diff --git a/DEPS b/DEPS
index b951f26..e1a20ba 100644
--- a/DEPS
+++ b/DEPS
@@ -40,7 +40,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'e8f28818a2c0fe967f9fc4cec4bb9dc78af78212',
+  'skia_revision': 'f90aa014d8639a0881b4cfb831b72eb0c8dfbbd7',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
diff --git a/android_webview/browser/deferred_gpu_command_service.cc b/android_webview/browser/deferred_gpu_command_service.cc
index 9cfd2ded7..2873d8c 100644
--- a/android_webview/browser/deferred_gpu_command_service.cc
+++ b/android_webview/browser/deferred_gpu_command_service.cc
@@ -13,10 +13,8 @@
 #include "base/trace_event/trace_event.h"
 #include "content/public/browser/gpu_utils.h"
 #include "content/public/common/content_switches.h"
-#include "gpu/command_buffer/service/framebuffer_completeness_cache.h"
 #include "gpu/command_buffer/service/gpu_preferences.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
-#include "gpu/command_buffer/service/shader_translator_cache.h"
 #include "gpu/command_buffer/service/sync_point_manager.h"
 #include "gpu/config/gpu_switches.h"
 #include "ui/gl/gl_switches.h"
@@ -156,24 +154,6 @@
 
 bool DeferredGpuCommandService::UseVirtualizedGLContexts() { return true; }
 
-scoped_refptr<gpu::gles2::ShaderTranslatorCache>
-DeferredGpuCommandService::shader_translator_cache() {
-  if (!shader_translator_cache_.get()) {
-    shader_translator_cache_ =
-        new gpu::gles2::ShaderTranslatorCache(gpu_preferences());
-  }
-  return shader_translator_cache_;
-}
-
-scoped_refptr<gpu::gles2::FramebufferCompletenessCache>
-DeferredGpuCommandService::framebuffer_completeness_cache() {
-  if (!framebuffer_completeness_cache_.get()) {
-    framebuffer_completeness_cache_ =
-        new gpu::gles2::FramebufferCompletenessCache;
-  }
-  return framebuffer_completeness_cache_;
-}
-
 gpu::SyncPointManager* DeferredGpuCommandService::sync_point_manager() {
   return sync_point_manager_.get();
 }
diff --git a/android_webview/browser/deferred_gpu_command_service.h b/android_webview/browser/deferred_gpu_command_service.h
index ed27efc4..20417222 100644
--- a/android_webview/browser/deferred_gpu_command_service.h
+++ b/android_webview/browser/deferred_gpu_command_service.h
@@ -48,10 +48,6 @@
   void ScheduleTask(const base::Closure& task) override;
   void ScheduleDelayedWork(const base::Closure& task) override;
   bool UseVirtualizedGLContexts() override;
-  scoped_refptr<gpu::gles2::ShaderTranslatorCache> shader_translator_cache()
-      override;
-  scoped_refptr<gpu::gles2::FramebufferCompletenessCache>
-  framebuffer_completeness_cache() override;
   gpu::SyncPointManager* sync_point_manager() override;
 
   void RunTasks();
@@ -82,9 +78,6 @@
   std::queue<std::pair<base::Time, base::Closure> > idle_tasks_;
 
   std::unique_ptr<gpu::SyncPointManager> sync_point_manager_;
-  scoped_refptr<gpu::gles2::ShaderTranslatorCache> shader_translator_cache_;
-  scoped_refptr<gpu::gles2::FramebufferCompletenessCache>
-      framebuffer_completeness_cache_;
   DISALLOW_COPY_AND_ASSIGN(DeferredGpuCommandService);
 };
 
diff --git a/ash/wm/system_gesture_event_filter_unittest.cc b/ash/wm/system_gesture_event_filter_unittest.cc
index 422297e..a77ff4af 100644
--- a/ash/wm/system_gesture_event_filter_unittest.cc
+++ b/ash/wm/system_gesture_event_filter_unittest.cc
@@ -344,11 +344,11 @@
   bounds = toplevel->GetNativeWindow()->bounds();
   // Swipe right and down starting with one finger.
   // Add another finger after 120ms and continue dragging.
-  // The window should move and the drag should be determined by the center
-  // point between the fingers.
+  // The window should not move (see crbug.com/363625) and drag should be
+  // determined by the delta of center point between the fingers.
   generator.GestureMultiFingerScrollWithDelays(kTouchPoints, points, delays, 15,
                                                kSteps, 150, 150);
-  bounds += gfx::Vector2d(150 + (points[1].x() - points[0].x()) / 2, 150);
+  bounds += gfx::Vector2d(150, 150);
   EXPECT_EQ(bounds.ToString(),
             toplevel->GetNativeWindow()->bounds().ToString());
 }
diff --git a/ash/wm/toplevel_window_event_handler_unittest.cc b/ash/wm/toplevel_window_event_handler_unittest.cc
index 4739631..c040e73 100644
--- a/ash/wm/toplevel_window_event_handler_unittest.cc
+++ b/ash/wm/toplevel_window_event_handler_unittest.cc
@@ -540,6 +540,146 @@
   EXPECT_FALSE(wm::GetWindowState(target.get())->IsMinimized());
 }
 
+TEST_F(ToplevelWindowEventHandlerTest, TwoFingerDragDifferentDelta) {
+  std::unique_ptr<aura::Window> target(CreateWindow(HTCAPTION));
+  ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
+                                     target.get());
+
+  const int kSteps = 10;
+  const int kTouchPoints = 2;
+  gfx::Point points[kTouchPoints] = {
+      gfx::Point(5, 5),   // Within caption.
+      gfx::Point(55, 5),  // Within caption.
+  };
+  gfx::Vector2d delta[kTouchPoints] = {
+      gfx::Vector2d(80, 80), gfx::Vector2d(20, 20),
+  };
+  int delay_adding_finger_ms[kTouchPoints] = {0, 0};
+  int delay_releasing_finger_ms[kTouchPoints] = {150, 150};
+
+  gfx::Rect bounds = target->bounds();
+  // Swipe right and down starting with two fingers. Two fingers have different
+  // moving deltas. The window position should move along the average vector of
+  // these two fingers.
+  generator.GestureMultiFingerScrollWithDelays(
+      kTouchPoints, points, delta, delay_adding_finger_ms,
+      delay_releasing_finger_ms, 15, kSteps);
+  bounds += gfx::Vector2d(50, 50);
+  EXPECT_EQ(bounds.ToString(), target->bounds().ToString());
+}
+
+TEST_F(ToplevelWindowEventHandlerTest, TwoFingerDragDelayAddFinger) {
+  std::unique_ptr<aura::Window> target(CreateWindow(HTCAPTION));
+  ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
+                                     target.get());
+
+  const int kSteps = 10;
+  const int kTouchPoints = 2;
+  gfx::Point points[kTouchPoints] = {
+      gfx::Point(5, 5),   // Within caption.
+      gfx::Point(55, 5),  // Within caption.
+  };
+  gfx::Vector2d delta[kTouchPoints] = {
+      gfx::Vector2d(50, 50), gfx::Vector2d(50, 50),
+  };
+  int delay_adding_finger_ms[kTouchPoints] = {0, 90};
+  int delay_releasing_finger_ms[kTouchPoints] = {150, 150};
+
+  gfx::Rect bounds = target->bounds();
+  // Swipe right and down starting with one fingers. Add another finger at 90ms
+  // and continue dragging. The drag should continue without interrupt.
+  generator.GestureMultiFingerScrollWithDelays(
+      kTouchPoints, points, delta, delay_adding_finger_ms,
+      delay_releasing_finger_ms, 15, kSteps);
+  bounds += gfx::Vector2d(50, 50);
+  EXPECT_EQ(bounds.ToString(), target->bounds().ToString());
+}
+
+TEST_F(ToplevelWindowEventHandlerTest, TwoFingerDragDelayReleaseFinger) {
+  std::unique_ptr<aura::Window> target(CreateWindow(HTCAPTION));
+  ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
+                                     target.get());
+
+  const int kSteps = 10;
+  const int kTouchPoints = 2;
+  gfx::Point points[kTouchPoints] = {
+      gfx::Point(5, 5),   // Within caption.
+      gfx::Point(55, 5),  // Within caption.
+  };
+  gfx::Vector2d delta[kTouchPoints] = {
+      gfx::Vector2d(50, 50), gfx::Vector2d(50, 50),
+  };
+  int delay_adding_finger_ms[kTouchPoints] = {0, 0};
+  int delay_releasing_finger_ms[kTouchPoints] = {150, 90};
+
+  gfx::Rect bounds = target->bounds();
+  // Swipe right and down starting with two fingers. Remove one finger at 90ms
+  // and continue dragging. The drag should continue without interrupt.
+  generator.GestureMultiFingerScrollWithDelays(
+      kTouchPoints, points, delta, delay_adding_finger_ms,
+      delay_releasing_finger_ms, 15, kSteps);
+  bounds += gfx::Vector2d(50, 50);
+  EXPECT_EQ(bounds.ToString(), target->bounds().ToString());
+}
+
+TEST_F(ToplevelWindowEventHandlerTest,
+       TwoFingerDragDelayAdd2ndAndRelease2ndFinger) {
+  std::unique_ptr<aura::Window> target(CreateWindow(HTCAPTION));
+  ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
+                                     target.get());
+
+  const int kSteps = 10;
+  const int kTouchPoints = 2;
+  gfx::Point points[kTouchPoints] = {
+      gfx::Point(5, 5),   // Within caption.
+      gfx::Point(55, 5),  // Within caption.
+  };
+  gfx::Vector2d delta[kTouchPoints] = {
+      gfx::Vector2d(50, 50), gfx::Vector2d(50, 50),
+  };
+  int delay_adding_finger_ms[kTouchPoints] = {0, 30};
+  int delay_releasing_finger_ms[kTouchPoints] = {150, 120};
+
+  gfx::Rect bounds = target->bounds();
+  // Swipe right and down starting with one fingers. Add second finger at 30ms,
+  // continue dragging, release second finger at 120ms and continue dragging.
+  // The drag should continue without interrupt.
+  generator.GestureMultiFingerScrollWithDelays(
+      kTouchPoints, points, delta, delay_adding_finger_ms,
+      delay_releasing_finger_ms, 15, kSteps);
+  bounds += gfx::Vector2d(50, 50);
+  EXPECT_EQ(bounds.ToString(), target->bounds().ToString());
+}
+
+TEST_F(ToplevelWindowEventHandlerTest,
+       TwoFingerDragDelayAdd2ndAndRelease1stFinger) {
+  std::unique_ptr<aura::Window> target(CreateWindow(HTCAPTION));
+  ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
+                                     target.get());
+
+  const int kSteps = 10;
+  const int kTouchPoints = 2;
+  gfx::Point points[kTouchPoints] = {
+      gfx::Point(5, 5),   // Within caption.
+      gfx::Point(55, 5),  // Within caption.
+  };
+  gfx::Vector2d delta[kTouchPoints] = {
+      gfx::Vector2d(50, 50), gfx::Vector2d(50, 50),
+  };
+  int delay_adding_finger_ms[kTouchPoints] = {0, 30};
+  int delay_releasing_finger_ms[kTouchPoints] = {120, 150};
+
+  gfx::Rect bounds = target->bounds();
+  // Swipe right and down starting with one fingers. Add second finger at 30ms,
+  // continue dragging, release first finger at 120ms and continue dragging.
+  // The drag should continue without interrupt.
+  generator.GestureMultiFingerScrollWithDelays(
+      kTouchPoints, points, delta, delay_adding_finger_ms,
+      delay_releasing_finger_ms, 15, kSteps);
+  bounds += gfx::Vector2d(50, 50);
+  EXPECT_EQ(bounds.ToString(), target->bounds().ToString());
+}
+
 TEST_F(ToplevelWindowEventHandlerTest, GestureDragToRestore) {
   std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
       new TestWindowDelegate(HTCAPTION), 0, gfx::Rect(10, 20, 30, 40)));
diff --git a/ash/wm/wm_toplevel_window_event_handler.cc b/ash/wm/wm_toplevel_window_event_handler.cc
index e400861..7e67f4cd 100644
--- a/ash/wm/wm_toplevel_window_event_handler.cc
+++ b/ash/wm/wm_toplevel_window_event_handler.cc
@@ -258,6 +258,9 @@
     }
     case ui::ET_GESTURE_BEGIN: {
       if (event->details().touch_points() == 1) {
+        first_finger_touch_point_ = event->location();
+        aura::Window::ConvertPointToTarget(target, target->parent(),
+                                           &first_finger_touch_point_);
         first_finger_hittest_ =
             GetNonClientComponent(target, event->location());
       } else if (window_resizer_.get()) {
@@ -275,9 +278,7 @@
             GetNonClientComponent(target, event->location());
         if (CanStartTwoFingerMove(target, first_finger_hittest_,
                                   second_finger_hittest)) {
-          gfx::Point location_in_parent =
-              event->details().bounding_box().CenterPoint();
-          AttemptToStartDrag(target, location_in_parent, HTCAPTION,
+          AttemptToStartDrag(target, first_finger_touch_point_, HTCAPTION,
                              ::wm::WINDOW_MOVE_SOURCE_TOUCH, EndClosure());
           event->StopPropagation();
         }
diff --git a/ash/wm/wm_toplevel_window_event_handler.h b/ash/wm/wm_toplevel_window_event_handler.h
index 7394283f..58dc1f55 100644
--- a/ash/wm/wm_toplevel_window_event_handler.h
+++ b/ash/wm/wm_toplevel_window_event_handler.h
@@ -105,6 +105,10 @@
   // touched the screen. |first_finger_hittest_| is one of ui/base/hit_test.h
   int first_finger_hittest_;
 
+  // The point for the first finger at the time that it initially touched the
+  // screen.
+  gfx::Point first_finger_touch_point_;
+
   // The window bounds when the drag was started. When a window is minimized,
   // maximized or snapped via a swipe/fling gesture, the restore bounds should
   // be set to the bounds of the window when the drag was started.
diff --git a/build/android/pylib/utils/logging_utils.py b/build/android/pylib/utils/logging_utils.py
index 2c2eabf..41c61338 100644
--- a/build/android/pylib/utils/logging_utils.py
+++ b/build/android/pylib/utils/logging_utils.py
@@ -11,9 +11,37 @@
 _COLORAMA_PATH = os.path.join(
     host_paths.DIR_SOURCE_ROOT, 'third_party', 'colorama', 'src')
 
-with host_paths.SysPath(_COLORAMA_PATH):
+with host_paths.SysPath(_COLORAMA_PATH, position=0):
   import colorama
 
+
+class _ColorFormatter(logging.Formatter):
+  # pylint does not see members added dynamically in the constructor.
+  # pylint: disable=no-member
+  color_map = {
+    logging.DEBUG: colorama.Fore.CYAN,
+    logging.WARNING: colorama.Fore.YELLOW,
+    logging.ERROR: colorama.Fore.RED,
+    logging.CRITICAL: colorama.Back.RED + colorama.Style.BRIGHT,
+  }
+
+  def __init__(self, wrapped_formatter=None):
+    """Wraps a |logging.Formatter| and adds color."""
+    super(_ColorFormatter, self).__init__(self)
+    self._wrapped_formatter = wrapped_formatter or logging.Formatter()
+
+  #override
+  def format(self, record):
+    message = self._wrapped_formatter.format(record)
+    return self.Colorize(message, record.levelno)
+
+  def Colorize(self, message, log_level):
+    try:
+      return self.color_map[log_level] + message + colorama.Style.RESET_ALL
+    except KeyError:
+      return message
+
+
 class ColorStreamHandler(logging.StreamHandler):
   """Handler that can be used to colorize logging output.
 
@@ -29,18 +57,10 @@
     logging.info('message')
 
   """
-  # pylint does not see members added dynamically in the constructor.
-  # pylint: disable=no-member
-  color_map = {
-    logging.DEBUG: colorama.Fore.CYAN,
-    logging.WARNING: colorama.Fore.YELLOW,
-    logging.ERROR: colorama.Fore.RED,
-    logging.CRITICAL: colorama.Back.RED + colorama.Style.BRIGHT,
-  }
-
   def __init__(self, force_color=False):
     super(ColorStreamHandler, self).__init__()
     self.force_color = force_color
+    self.setFormatter(logging.Formatter())
 
   @property
   def is_tty(self):
@@ -48,17 +68,10 @@
     return isatty and isatty()
 
   #override
-  def format(self, record):
-    message = logging.StreamHandler.format(self, record)
+  def setFormatter(self, formatter):
     if self.force_color or self.is_tty:
-      return self.Colorize(message, record.levelno)
-    return message
-
-  def Colorize(self, message, log_level):
-    try:
-      return self.color_map[log_level] + message + colorama.Style.RESET_ALL
-    except KeyError:
-      return message
+      formatter = _ColorFormatter(formatter)
+    super(ColorStreamHandler, self).setFormatter(formatter)
 
   @staticmethod
   def MakeDefault(force_color=False):
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index 0b053e2d..3753483 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -41,6 +41,7 @@
 from pylib.results import json_results
 from pylib.results import report_results
 from pylib.utils import logdog_helper
+from pylib.utils import logging_utils
 
 from py_utils import contextlib_ext
 
@@ -187,7 +188,11 @@
 
 def ProcessCommonOptions(args):
   """Processes and handles all common options."""
-  run_tests_helper.SetLogLevel(args.verbose_count)
+  run_tests_helper.SetLogLevel(args.verbose_count, add_handler=False)
+  handler = logging_utils.ColorStreamHandler()
+  handler.setFormatter(run_tests_helper.CustomFormatter())
+  logging.getLogger().addHandler(handler)
+
   constants.SetBuildType(args.build_type)
   if args.output_directory:
     constants.SetOutputDirectory(args.output_directory)
diff --git a/build/android/test_runner.pydeps b/build/android/test_runner.pydeps
index db43088..63326874 100644
--- a/build/android/test_runner.pydeps
+++ b/build/android/test_runner.pydeps
@@ -115,6 +115,12 @@
 ../../third_party/catapult/tracing/tracing_build/__init__.py
 ../../third_party/catapult/tracing/tracing_build/trace2html.py
 ../../third_party/catapult/tracing/tracing_project.py
+../../third_party/colorama/src/colorama/__init__.py
+../../third_party/colorama/src/colorama/ansi.py
+../../third_party/colorama/src/colorama/ansitowin32.py
+../../third_party/colorama/src/colorama/initialise.py
+../../third_party/colorama/src/colorama/win32.py
+../../third_party/colorama/src/colorama/winterm.py
 ../../third_party/jinja2/__init__.py
 ../../third_party/jinja2/_compat.py
 ../../third_party/jinja2/bccache.py
@@ -200,6 +206,7 @@
 pylib/utils/dexdump.py
 pylib/utils/google_storage_helper.py
 pylib/utils/logdog_helper.py
+pylib/utils/logging_utils.py
 pylib/utils/proguard.py
 pylib/utils/repo_utils.py
 pylib/valgrind_tools.py
diff --git a/build/config/sanitizers/sanitizers.gni b/build/config/sanitizers/sanitizers.gni
index 076206a..f59770a 100644
--- a/build/config/sanitizers/sanitizers.gni
+++ b/build/config/sanitizers/sanitizers.gni
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/config/chrome_build.gni")
+import("//build/config/chromecast_build.gni")
 import("//build/toolchain/toolchain.gni")
 
 declare_args() {
@@ -142,8 +143,9 @@
   # buildtools/third_party/libc++abi) instead of stdlibc++ as standard library.
   # This is intended to be used for instrumented builds.
   use_custom_libcxx =
-      (is_asan && is_linux && !is_chromeos) || is_tsan || is_msan || is_ubsan ||
-      is_ubsan_security || (use_libfuzzer && !is_mac) || use_afl
+      (is_asan && is_linux && !is_chromeos &&
+       (!is_chromecast || is_cast_desktop_build)) || is_tsan || is_msan ||
+      is_ubsan || is_ubsan_security || (use_libfuzzer && !is_mac) || use_afl
 
   # Enable -fsanitize-coverage.
   use_sanitizer_coverage =
diff --git a/chrome/VERSION b/chrome/VERSION
index 7eea030..8383d27 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=61
 MINOR=0
-BUILD=3130
+BUILD=3131
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 3fc38b8..ae511f7b 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -177,6 +177,7 @@
     "//components/crash/android:java",
     "//components/dom_distiller/content/browser/android:dom_distiller_content_java",
     "//components/dom_distiller/core/android:dom_distiller_core_java",
+    "//components/download/public:public_java",
     "//components/feature_engagement_tracker:feature_engagement_tracker_java",
     "//components/gcm_driver/android:gcm_driver_java",
     "//components/gcm_driver/instance_id/android:instance_id_driver_java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/service/DownloadBackgroundTask.java b/chrome/android/java/src/org/chromium/chrome/browser/download/service/DownloadBackgroundTask.java
new file mode 100644
index 0000000..6ff490f
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/service/DownloadBackgroundTask.java
@@ -0,0 +1,124 @@
+// 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.download.service;
+
+import android.content.Context;
+
+import org.chromium.base.Callback;
+import org.chromium.base.annotations.JNINamespace;
+import org.chromium.chrome.browser.background_task_scheduler.NativeBackgroundTask;
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.components.background_task_scheduler.TaskParameters;
+import org.chromium.components.download.DownloadTaskType;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Entry point for the download service to perform desired action when the task is fired by the
+ * scheduler. The scheduled task is executed for the regular profile and also for incognito profile
+ * if an incognito profile exists.
+ */
+@JNINamespace("download::android")
+public class DownloadBackgroundTask extends NativeBackgroundTask {
+    // Helper class to track the number of pending {@link TaskFinishedCallback}s.
+    private static class PendingTaskCounter {
+        // Number of tasks in progress.
+        public int numPendingCallbacks;
+
+        // Whether at least one of the tasks needs reschedule.
+        public boolean needsReschedule;
+    }
+
+    // Keeps track of in progress tasks which haven't invoked their {@link TaskFinishedCallback}s.
+    private Map<Integer, PendingTaskCounter> mPendingTaskCounters = new HashMap<>();
+
+    @Override
+    protected int onStartTaskBeforeNativeLoaded(
+            Context context, TaskParameters taskParameters, TaskFinishedCallback callback) {
+        return NativeBackgroundTask.LOAD_NATIVE;
+    }
+
+    @Override
+    protected void onStartTaskWithNative(
+            Context context, TaskParameters taskParameters, final TaskFinishedCallback callback) {
+        // In case of future upgrades, we would need to build an intent for the old version and
+        // validate that this code still works. This would require decoupling this immediate class
+        // from native as well.
+        @DownloadTaskType
+        final int taskType =
+                taskParameters.getExtras().getInt(DownloadTaskScheduler.EXTRA_TASK_TYPE);
+
+        Callback<Boolean> wrappedCallback = new Callback<Boolean>() {
+            @Override
+            public void onResult(Boolean needsReschedule) {
+                boolean noPendingCallbacks =
+                        decrementPendingCallbackCount(taskType, needsReschedule);
+                if (noPendingCallbacks) {
+                    callback.taskFinished(mPendingTaskCounters.get(taskType).needsReschedule);
+                    mPendingTaskCounters.remove(taskType);
+                }
+            }
+        };
+
+        Profile profile = Profile.getLastUsedProfile().getOriginalProfile();
+        incrementPendingCallbackCount(taskType);
+        nativeStartBackgroundTask(profile, taskType, wrappedCallback);
+
+        if (profile.hasOffTheRecordProfile()) {
+            incrementPendingCallbackCount(taskType);
+            nativeStartBackgroundTask(profile.getOffTheRecordProfile(), taskType, wrappedCallback);
+        }
+    }
+
+    private void incrementPendingCallbackCount(@DownloadTaskType int taskType) {
+        PendingTaskCounter taskCounter = mPendingTaskCounters.containsKey(taskType)
+                ? mPendingTaskCounters.get(taskType)
+                : new PendingTaskCounter();
+        taskCounter.numPendingCallbacks++;
+        mPendingTaskCounters.put(taskType, taskCounter);
+    }
+
+    /** @return Whether or not there are no more pending callbacks and we can notify the system. */
+    private boolean decrementPendingCallbackCount(
+            @DownloadTaskType int taskType, boolean needsRescuedule) {
+        PendingTaskCounter taskCounter = mPendingTaskCounters.get(taskType);
+        assert taskCounter != null && taskCounter.numPendingCallbacks > 0;
+
+        taskCounter.numPendingCallbacks = Math.max(0, taskCounter.numPendingCallbacks - 1);
+        taskCounter.needsReschedule |= needsRescuedule;
+        return taskCounter.numPendingCallbacks == 0;
+    }
+
+    @Override
+    protected boolean onStopTaskBeforeNativeLoaded(Context context, TaskParameters taskParameters) {
+        return true;
+    }
+
+    @Override
+    protected boolean onStopTaskWithNative(Context context, TaskParameters taskParameters) {
+        @DownloadTaskType
+        int taskType = taskParameters.getExtras().getInt(DownloadTaskScheduler.EXTRA_TASK_TYPE);
+        mPendingTaskCounters.remove(taskType);
+
+        Profile profile = Profile.getLastUsedProfile().getOriginalProfile();
+        boolean needsReschedule = nativeStopBackgroundTask(profile, taskType);
+
+        if (profile.hasOffTheRecordProfile()) {
+            needsReschedule |= nativeStopBackgroundTask(profile.getOffTheRecordProfile(), taskType);
+        }
+
+        return needsReschedule;
+    }
+
+    @Override
+    public void reschedule(Context context) {
+        // TODO(shaktisahu): Called when system asks us to schedule the task again. (crbug/730786)
+    }
+
+    private native void nativeStartBackgroundTask(
+            Profile profile, int taskType, Callback<Boolean> callback);
+    private native boolean nativeStopBackgroundTask(Profile profile, int taskType);
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/service/DownloadTaskScheduler.java b/chrome/android/java/src/org/chromium/chrome/browser/download/service/DownloadTaskScheduler.java
new file mode 100644
index 0000000..4b5b642
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/service/DownloadTaskScheduler.java
@@ -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.
+
+package org.chromium.chrome.browser.download.service;
+
+import android.os.Bundle;
+
+import org.chromium.base.ContextUtils;
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+import org.chromium.components.background_task_scheduler.BackgroundTaskScheduler;
+import org.chromium.components.background_task_scheduler.BackgroundTaskSchedulerFactory;
+import org.chromium.components.background_task_scheduler.TaskIds;
+import org.chromium.components.background_task_scheduler.TaskInfo;
+import org.chromium.components.download.DownloadTaskType;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A background task scheduler that schedules various types of jobs with the system with certain
+ * conditions as requested by the download service.
+ */
+@JNINamespace("download::android")
+public class DownloadTaskScheduler {
+    public static final String EXTRA_TASK_TYPE = "extra_task_type";
+
+    @CalledByNative
+    private static void scheduleTask(@DownloadTaskType int taskType, boolean requiresCharging,
+            boolean requiresUnmeteredNetwork, long windowStartTimeSeconds,
+            long windowEndTimeSeconds) {
+        Bundle bundle = new Bundle();
+        bundle.putInt(EXTRA_TASK_TYPE, taskType);
+        BackgroundTaskScheduler scheduler = BackgroundTaskSchedulerFactory.getScheduler();
+        TaskInfo taskInfo =
+                TaskInfo.createOneOffTask(getTaskId(taskType), DownloadBackgroundTask.class,
+                                TimeUnit.SECONDS.toMillis(windowStartTimeSeconds),
+                                TimeUnit.SECONDS.toMillis(windowEndTimeSeconds))
+                        .setRequiredNetworkType(
+                                getRequiredNetworkType(taskType, requiresUnmeteredNetwork))
+                        .setRequiresCharging(requiresCharging)
+                        .setUpdateCurrent(true)
+                        .setIsPersisted(true)
+                        .setExtras(bundle)
+                        .build();
+        scheduler.schedule(ContextUtils.getApplicationContext(), taskInfo);
+    }
+
+    @CalledByNative
+    private static void cancelTask(@DownloadTaskType int taskType) {
+        BackgroundTaskScheduler scheduler = BackgroundTaskSchedulerFactory.getScheduler();
+        scheduler.cancel(ContextUtils.getApplicationContext(), getTaskId(taskType));
+    }
+
+    private static int getTaskId(@DownloadTaskType int taskType) {
+        switch (taskType) {
+            case DownloadTaskType.DOWNLOAD_TASK:
+                return TaskIds.DOWNLOAD_SERVICE_JOB_ID;
+            case DownloadTaskType.CLEANUP_TASK:
+                return TaskIds.DOWNLOAD_CLEANUP_JOB_ID;
+            default:
+                assert false;
+                return -1;
+        }
+    }
+
+    private static int getRequiredNetworkType(
+            @DownloadTaskType int taskType, boolean requiresUnmeteredNetwork) {
+        if (taskType != DownloadTaskType.DOWNLOAD_TASK) return TaskInfo.NETWORK_TYPE_NONE;
+
+        return requiresUnmeteredNetwork ? TaskInfo.NETWORK_TYPE_UNMETERED
+                                        : TaskInfo.NETWORK_TYPE_ANY;
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentAppBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentAppBridge.java
index bd25589..fd6f120 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentAppBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentAppBridge.java
@@ -4,8 +4,13 @@
 
 package org.chromium.chrome.browser.payments;
 
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.SuppressFBWarnings;
+import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.payments.mojom.PaymentDetailsModifier;
 import org.chromium.payments.mojom.PaymentItem;
@@ -62,13 +67,19 @@
 
     @CalledByNative
     private static void addInstrument(List<PaymentInstrument> instruments, WebContents webContents,
-            long swRegistrationId, String instrumentId, String label, String[] methodNameArray) {
+            long swRegistrationId, String instrumentId, String label, String[] methodNameArray,
+            Bitmap icon) {
+        Context context = ChromeActivity.fromWebContents(webContents);
+        if (context == null) return;
+
         Set<String> methodNames = new HashSet<String>();
         for (int i = 0; i < methodNameArray.length; i++) {
             methodNames.add(methodNameArray[i]);
         }
-        instruments.add(new ServiceWorkerPaymentInstrument(
-                webContents, swRegistrationId, instrumentId, label, methodNames));
+
+        instruments.add(
+                new ServiceWorkerPaymentInstrument(webContents, swRegistrationId, instrumentId,
+                        label, methodNames, new BitmapDrawable(context.getResources(), icon)));
     }
 
     @CalledByNative
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentInstrument.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentInstrument.java
index c3d56c05..4579a9c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentInstrument.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentInstrument.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.payments;
 
+import android.graphics.drawable.Drawable;
+
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.payments.mojom.PaymentDetailsModifier;
 import org.chromium.payments.mojom.PaymentItem;
@@ -39,11 +41,12 @@
      * @param instrumentId      The unique id of the payment instrument.
      * @param label             The label of the payment instrument.
      * @param methodNames       A set of payment method names supported by the payment instrument.
+     * @param icon              The drawable icon of the payment instrument.
      */
     public ServiceWorkerPaymentInstrument(WebContents webContents, long swRegistrationId,
-            String instrumentId, String label, Set<String> methodNames) {
+            String instrumentId, String label, Set<String> methodNames, Drawable icon) {
         super(Long.toString(swRegistrationId) + "#" + instrumentId, label, null /* sublabel */,
-                null /* icon */);
+                icon);
         mWebContents = webContents;
         mSWRegistrationId = swRegistrationId;
         mInstrumentId = instrumentId;
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index 074ad45..66e2a78c 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -345,6 +345,8 @@
   "java/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorFactory.java",
   "java/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorNotificationBridgeUi.java",
   "java/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorNotificationBridgeUiFactory.java",
+  "java/src/org/chromium/chrome/browser/download/service/DownloadBackgroundTask.java",
+  "java/src/org/chromium/chrome/browser/download/service/DownloadTaskScheduler.java",
   "java/src/org/chromium/chrome/browser/download/ui/BackendItems.java",
   "java/src/org/chromium/chrome/browser/download/ui/BackendProvider.java",
   "java/src/org/chromium/chrome/browser/download/ui/DeletedFileTracker.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java
index dbba560a..458c1d6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java
@@ -65,16 +65,18 @@
                             instruments.add(new ServiceWorkerPaymentInstrument(webContents,
                                     0 /* swRegistrationId */, "new" /* instrumentId */,
                                     "Create BobPay account" /* label */,
-                                    new HashSet<String>(Arrays.asList("https://bobpay.com",
-                                            "basic-card")) /* methodNames */));
+                                    new HashSet<String>(Arrays.asList(
+                                            "https://bobpay.com", "basic-card")) /* methodNames */,
+                                    null /* icon*/));
                         }
 
                         if (instrumentPresence == TWO_OPTIONS) {
                             instruments.add(new ServiceWorkerPaymentInstrument(webContents,
                                     0 /* swRegistrationId */, "existing" /* instrumentId */,
                                     "Existing BobPay account" /* label */,
-                                    new HashSet<String>(Arrays.asList("https://bobpay.com",
-                                            "basic-card")) /* methodNames */));
+                                    new HashSet<String>(Arrays.asList(
+                                            "https://bobpay.com", "basic-card")) /* methodNames */,
+                                    null /* icon */));
                         }
 
                         callback.onPaymentAppCreated(
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 6fefe12a..7023bef 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -379,6 +379,8 @@
     "download/download_target_determiner_delegate.h",
     "download/download_target_info.cc",
     "download/download_target_info.h",
+    "download/download_task_scheduler_impl.cc",
+    "download/download_task_scheduler_impl.h",
     "download/download_ui_controller.cc",
     "download/download_ui_controller.h",
     "download/drag_download_item.h",
@@ -2925,6 +2927,10 @@
       "android/download/intercept_download_resource_throttle.h",
       "android/download/items/offline_content_aggregator_factory_android.cc",
       "android/download/items/offline_content_aggregator_factory_android.h",
+      "android/download/service/download_background_task.cc",
+      "android/download/service/download_background_task.h",
+      "android/download/service/download_task_scheduler.cc",
+      "android/download/service/download_task_scheduler.h",
       "android/download/ui/thumbnail_provider.cc",
       "android/download/ui/thumbnail_provider.h",
       "android/favicon_helper.cc",
@@ -4211,6 +4217,8 @@
       "../android/java/src/org/chromium/chrome/browser/download/DownloadItem.java",
       "../android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java",
       "../android/java/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorFactory.java",
+      "../android/java/src/org/chromium/chrome/browser/download/service/DownloadBackgroundTask.java",
+      "../android/java/src/org/chromium/chrome/browser/download/service/DownloadTaskScheduler.java",
       "../android/java/src/org/chromium/chrome/browser/download/ui/ThumbnailProviderImpl.java",
       "../android/java/src/org/chromium/chrome/browser/engagement/SiteEngagementService.java",
       "../android/java/src/org/chromium/chrome/browser/favicon/FaviconHelper.java",
diff --git a/chrome/browser/android/chrome_jni_registrar.cc b/chrome/browser/android/chrome_jni_registrar.cc
index 8b2178a..ceb6e72 100644
--- a/chrome/browser/android/chrome_jni_registrar.cc
+++ b/chrome/browser/android/chrome_jni_registrar.cc
@@ -48,6 +48,7 @@
 #include "chrome/browser/android/download/download_controller.h"
 #include "chrome/browser/android/download/download_manager_service.h"
 #include "chrome/browser/android/download/items/offline_content_aggregator_factory_android.h"
+#include "chrome/browser/android/download/service/download_background_task.h"
 #include "chrome/browser/android/download/ui/thumbnail_provider.h"
 #include "chrome/browser/android/favicon_helper.h"
 #include "chrome/browser/android/feature_engagement_tracker/feature_engagement_tracker_factory_android.h"
@@ -308,6 +309,8 @@
     {"DomDistillerServiceFactory",
      dom_distiller::android::DomDistillerServiceFactoryAndroid::Register},
     {"DomDistillerTabUtils", RegisterDomDistillerTabUtils},
+    {"DownloadBackgroundTask",
+     download::android::RegisterDownloadBackgroundTask},
     {"DownloadController", DownloadController::RegisterDownloadController},
     {"DownloadManagerService",
      DownloadManagerService::RegisterDownloadManagerService},
diff --git a/chrome/browser/android/download/service/download_background_task.cc b/chrome/browser/android/download/service/download_background_task.cc
new file mode 100644
index 0000000..9ad0bccf
--- /dev/null
+++ b/chrome/browser/android/download/service/download_background_task.cc
@@ -0,0 +1,67 @@
+// 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/android/download/service/download_background_task.h"
+
+#include "base/android/callback_android.h"
+#include "base/callback_forward.h"
+#include "chrome/browser/download/download_service_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_android.h"
+#include "components/download/public/download_service.h"
+#include "content/public/browser/browser_context.h"
+#include "jni/DownloadBackgroundTask_jni.h"
+
+using base::android::JavaParamRef;
+
+namespace download {
+namespace android {
+
+// static
+bool RegisterDownloadBackgroundTask(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
+
+void CallTaskFinishedCallback(const base::android::JavaRef<jobject>& j_callback,
+                              bool needs_reschedule) {
+  RunCallbackAndroid(j_callback, needs_reschedule);
+}
+
+// static
+void StartBackgroundTask(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& jcaller,
+    const base::android::JavaParamRef<jobject>& jprofile,
+    jint task_type,
+    const base::android::JavaParamRef<jobject>& jcallback) {
+  Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile);
+  DCHECK(profile);
+
+  TaskFinishedCallback finish_callback =
+      base::Bind(&CallTaskFinishedCallback,
+                 base::android::ScopedJavaGlobalRef<jobject>(jcallback));
+
+  DownloadService* download_service =
+      DownloadServiceFactory::GetForBrowserContext(profile);
+  download_service->OnStartScheduledTask(
+      static_cast<DownloadTaskType>(task_type), finish_callback);
+}
+
+// static
+jboolean StopBackgroundTask(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& jcaller,
+    const base::android::JavaParamRef<jobject>& jprofile,
+    jint task_type) {
+  Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile);
+  DCHECK(profile);
+
+  DownloadService* download_service =
+      DownloadServiceFactory::GetForBrowserContext(profile);
+  return download_service->OnStopScheduledTask(
+      static_cast<DownloadTaskType>(task_type));
+}
+
+}  // namespace android
+}  // namespace download
diff --git a/chrome/browser/android/download/service/download_background_task.h b/chrome/browser/android/download/service/download_background_task.h
new file mode 100644
index 0000000..730abf5
--- /dev/null
+++ b/chrome/browser/android/download/service/download_background_task.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 CHROME_BROWSER_ANDROID_DOWNLOAD_SERVICE_DOWNLOAD_BACKGROUND_TASK_H_
+#define CHROME_BROWSER_ANDROID_DOWNLOAD_SERVICE_DOWNLOAD_BACKGROUND_TASK_H_
+
+#include <jni.h>
+#include <memory>
+
+#include "base/android/jni_android.h"
+#include "base/macros.h"
+
+namespace download {
+namespace android {
+
+bool RegisterDownloadBackgroundTask(JNIEnv* env);
+
+}  // namespace android
+}  // namespace download
+
+#endif  // CHROME_BROWSER_ANDROID_DOWNLOAD_SERVICE_DOWNLOAD_BACKGROUND_TASK_H_
diff --git a/chrome/browser/android/download/service/download_task_scheduler.cc b/chrome/browser/android/download/service/download_task_scheduler.cc
new file mode 100644
index 0000000..6a5a078
--- /dev/null
+++ b/chrome/browser/android/download/service/download_task_scheduler.cc
@@ -0,0 +1,34 @@
+// 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/android/download/service/download_task_scheduler.h"
+
+#include "base/android/jni_android.h"
+#include "jni/DownloadTaskScheduler_jni.h"
+
+namespace download {
+namespace android {
+
+DownloadTaskScheduler::DownloadTaskScheduler() = default;
+
+DownloadTaskScheduler::~DownloadTaskScheduler() = default;
+
+void DownloadTaskScheduler::ScheduleTask(DownloadTaskType task_type,
+                                         bool require_unmetered_network,
+                                         bool require_charging,
+                                         long window_start_time_seconds,
+                                         long window_end_time_seconds) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  Java_DownloadTaskScheduler_scheduleTask(
+      env, static_cast<jint>(task_type), require_unmetered_network,
+      require_charging, window_start_time_seconds, window_end_time_seconds);
+}
+
+void DownloadTaskScheduler::CancelTask(DownloadTaskType task_type) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  Java_DownloadTaskScheduler_cancelTask(env, static_cast<jint>(task_type));
+}
+
+}  // namespace android
+}  // namespace download
diff --git a/chrome/browser/android/download/service/download_task_scheduler.h b/chrome/browser/android/download/service/download_task_scheduler.h
new file mode 100644
index 0000000..7e0e73b
--- /dev/null
+++ b/chrome/browser/android/download/service/download_task_scheduler.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 CHROME_BROWSER_ANDROID_DOWNLOAD_SERVICE_DOWNLOAD_TASK_SCHEDULER_H_
+#define CHROME_BROWSER_ANDROID_DOWNLOAD_SERVICE_DOWNLOAD_TASK_SCHEDULER_H_
+
+#include <jni.h>
+#include <memory>
+
+#include "base/macros.h"
+#include "components/download/public/download_task_types.h"
+#include "components/download/public/task_scheduler.h"
+
+namespace download {
+namespace android {
+
+// DownloadTaskScheduler is the utility class to schedule various types of
+// background tasks with the OS as of when required by the download service.
+class DownloadTaskScheduler : public TaskScheduler {
+ public:
+  DownloadTaskScheduler();
+  ~DownloadTaskScheduler();
+
+  // TaskScheduler implementation.
+  void ScheduleTask(DownloadTaskType task_type,
+                    bool require_unmetered_network,
+                    bool require_charging,
+                    long window_start_time_seconds,
+                    long window_end_time_seconds) override;
+  void CancelTask(DownloadTaskType task_type) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DownloadTaskScheduler);
+};
+
+}  // namespace android
+}  // namespace download
+
+#endif  // CHROME_BROWSER_ANDROID_DOWNLOAD_SERVICE_DOWNLOAD_TASK_SCHEDULER_H_
diff --git a/chrome/browser/android/payments/service_worker_payment_app_bridge.cc b/chrome/browser/android/payments/service_worker_payment_app_bridge.cc
index 6fd1d02f..98a4f22 100644
--- a/chrome/browser/android/payments/service_worker_payment_app_bridge.cc
+++ b/chrome/browser/android/payments/service_worker_payment_app_bridge.cc
@@ -16,6 +16,7 @@
 #include "content/public/browser/stored_payment_instrument.h"
 #include "content/public/browser/web_contents.h"
 #include "jni/ServiceWorkerPaymentAppBridge_jni.h"
+#include "ui/gfx/android/java_bitmap.h"
 
 namespace {
 
@@ -49,7 +50,8 @@
           env, java_instruments, jweb_contents, instrument->registration_id,
           ConvertUTF8ToJavaString(env, instrument->instrument_key),
           ConvertUTF8ToJavaString(env, instrument->name),
-          ToJavaArrayOfStrings(env, instrument->enabled_methods));
+          ToJavaArrayOfStrings(env, instrument->enabled_methods),
+          gfx::ConvertToJavaBitmap(instrument->icon.get()));
     }
     Java_ServiceWorkerPaymentAppBridge_onPaymentAppCreated(
         env, java_instruments, jweb_contents, jcallback);
diff --git a/chrome/browser/chromeos/printing/specifics_translation_unittest.cc b/chrome/browser/chromeos/printing/specifics_translation_unittest.cc
index 36765a1..5c6fb48 100644
--- a/chrome/browser/chromeos/printing/specifics_translation_unittest.cc
+++ b/chrome/browser/chromeos/printing/specifics_translation_unittest.cc
@@ -13,17 +13,17 @@
 
 namespace {
 
-const char id[] = "UNIQUE_ID";
-const char display_name[] = "Best Printer Ever";
-const char description[] = "The green one";
-const char manufacturer[] = "Manufacturer";
-const char model[] = "MODEL";
-const char uri[] = "ipps://notaprinter.chromium.org/ipp/print";
-const char uuid[] = "UUIDUUIDUUID";
+constexpr char kId[] = "UNIQUE_ID";
+constexpr char kDisplayName[] = "Best Printer Ever";
+constexpr char kDescription[] = "The green one";
+constexpr char kManufacturer[] = "Manufacturer";
+constexpr char kModel[] = "MODEL";
+constexpr char kUri[] = "ipps://notaprinter.chromium.org/ipp/print";
+constexpr char kUuid[] = "UUIDUUIDUUID";
 const base::Time kUpdateTime = base::Time::FromInternalValue(22114455660000);
 
-const char kUserSuppliedPPD[] = "file://foo/bar/baz/eeaaaffccdd00";
-const char effective_make_and_model[] = "Manufacturer Model T1000";
+constexpr char kUserSuppliedPPD[] = "file://foo/bar/baz/eeaaaffccdd00";
+constexpr char kEffectiveMakeAndModel[] = "Manufacturer Model T1000";
 
 }  // namespace
 
@@ -32,71 +32,71 @@
 
 TEST(SpecificsTranslationTest, SpecificsToPrinter) {
   sync_pb::PrinterSpecifics specifics;
-  specifics.set_id(id);
-  specifics.set_display_name(display_name);
-  specifics.set_description(description);
-  specifics.set_manufacturer(manufacturer);
-  specifics.set_model(model);
-  specifics.set_uri(uri);
-  specifics.set_uuid(uuid);
+  specifics.set_id(kId);
+  specifics.set_display_name(kDisplayName);
+  specifics.set_description(kDescription);
+  specifics.set_manufacturer(kManufacturer);
+  specifics.set_model(kModel);
+  specifics.set_uri(kUri);
+  specifics.set_uuid(kUuid);
   specifics.set_updated_timestamp(kUpdateTime.ToJavaTime());
 
   sync_pb::PrinterPPDReference ppd;
-  ppd.set_effective_make_and_model(effective_make_and_model);
+  ppd.set_effective_make_and_model(kEffectiveMakeAndModel);
   *specifics.mutable_ppd_reference() = ppd;
 
   std::unique_ptr<Printer> result = SpecificsToPrinter(specifics);
-  EXPECT_EQ(id, result->id());
-  EXPECT_EQ(display_name, result->display_name());
-  EXPECT_EQ(description, result->description());
-  EXPECT_EQ(manufacturer, result->manufacturer());
-  EXPECT_EQ(model, result->model());
-  EXPECT_EQ(uri, result->uri());
-  EXPECT_EQ(uuid, result->uuid());
+  EXPECT_EQ(kId, result->id());
+  EXPECT_EQ(kDisplayName, result->display_name());
+  EXPECT_EQ(kDescription, result->description());
+  EXPECT_EQ(kManufacturer, result->manufacturer());
+  EXPECT_EQ(kModel, result->model());
+  EXPECT_EQ(kUri, result->uri());
+  EXPECT_EQ(kUuid, result->uuid());
   EXPECT_EQ(kUpdateTime, result->last_updated());
 
-  EXPECT_EQ(effective_make_and_model,
+  EXPECT_EQ(kEffectiveMakeAndModel,
             result->ppd_reference().effective_make_and_model);
   EXPECT_FALSE(result->IsIppEverywhere());
 }
 
 TEST(SpecificsTranslationTest, PrinterToSpecifics) {
   Printer printer;
-  printer.set_id(id);
-  printer.set_display_name(display_name);
-  printer.set_description(description);
-  printer.set_manufacturer(manufacturer);
-  printer.set_model(model);
-  printer.set_uri(uri);
-  printer.set_uuid(uuid);
+  printer.set_id(kId);
+  printer.set_display_name(kDisplayName);
+  printer.set_description(kDescription);
+  printer.set_manufacturer(kManufacturer);
+  printer.set_model(kModel);
+  printer.set_uri(kUri);
+  printer.set_uuid(kUuid);
 
   Printer::PpdReference ppd;
-  ppd.effective_make_and_model = effective_make_and_model;
+  ppd.effective_make_and_model = kEffectiveMakeAndModel;
   *printer.mutable_ppd_reference() = ppd;
 
   std::unique_ptr<sync_pb::PrinterSpecifics> result =
       PrinterToSpecifics(printer);
-  EXPECT_EQ(id, result->id());
-  EXPECT_EQ(display_name, result->display_name());
-  EXPECT_EQ(description, result->description());
-  EXPECT_EQ(manufacturer, result->manufacturer());
-  EXPECT_EQ(model, result->model());
-  EXPECT_EQ(uri, result->uri());
-  EXPECT_EQ(uuid, result->uuid());
+  EXPECT_EQ(kId, result->id());
+  EXPECT_EQ(kDisplayName, result->display_name());
+  EXPECT_EQ(kDescription, result->description());
+  EXPECT_EQ(kManufacturer, result->manufacturer());
+  EXPECT_EQ(kModel, result->model());
+  EXPECT_EQ(kUri, result->uri());
+  EXPECT_EQ(kUuid, result->uuid());
 
-  EXPECT_EQ(effective_make_and_model,
+  EXPECT_EQ(kEffectiveMakeAndModel,
             result->ppd_reference().effective_make_and_model());
 }
 
 TEST(SpecificsTranslationTest, SpecificsToPrinterRoundTrip) {
   Printer printer;
-  printer.set_id(id);
-  printer.set_display_name(display_name);
-  printer.set_description(description);
-  printer.set_manufacturer(manufacturer);
-  printer.set_model(model);
-  printer.set_uri(uri);
-  printer.set_uuid(uuid);
+  printer.set_id(kId);
+  printer.set_display_name(kDisplayName);
+  printer.set_description(kDescription);
+  printer.set_manufacturer(kManufacturer);
+  printer.set_model(kModel);
+  printer.set_uri(kUri);
+  printer.set_uuid(kUuid);
 
   Printer::PpdReference ppd;
   ppd.autoconf = true;
@@ -105,13 +105,13 @@
   std::unique_ptr<sync_pb::PrinterSpecifics> temp = PrinterToSpecifics(printer);
   std::unique_ptr<Printer> result = SpecificsToPrinter(*temp);
 
-  EXPECT_EQ(id, result->id());
-  EXPECT_EQ(display_name, result->display_name());
-  EXPECT_EQ(description, result->description());
-  EXPECT_EQ(manufacturer, result->manufacturer());
-  EXPECT_EQ(model, result->model());
-  EXPECT_EQ(uri, result->uri());
-  EXPECT_EQ(uuid, result->uuid());
+  EXPECT_EQ(kId, result->id());
+  EXPECT_EQ(kDisplayName, result->display_name());
+  EXPECT_EQ(kDescription, result->description());
+  EXPECT_EQ(kManufacturer, result->manufacturer());
+  EXPECT_EQ(kModel, result->model());
+  EXPECT_EQ(kUri, result->uri());
+  EXPECT_EQ(kUuid, result->uuid());
 
   EXPECT_TRUE(result->ppd_reference().effective_make_and_model.empty());
   EXPECT_TRUE(result->ppd_reference().autoconf);
@@ -119,17 +119,17 @@
 
 TEST(SpecificsTranslationTest, MergePrinterToSpecifics) {
   sync_pb::PrinterSpecifics original;
-  original.set_id(id);
+  original.set_id(kId);
   original.mutable_ppd_reference()->set_autoconf(true);
 
-  Printer printer(id);
+  Printer printer(kId);
   printer.mutable_ppd_reference()->effective_make_and_model =
-      effective_make_and_model;
+      kEffectiveMakeAndModel;
 
   MergePrinterToSpecifics(printer, &original);
 
-  EXPECT_EQ(id, original.id());
-  EXPECT_EQ(effective_make_and_model,
+  EXPECT_EQ(kId, original.id());
+  EXPECT_EQ(kEffectiveMakeAndModel,
             original.ppd_reference().effective_make_and_model());
 
   // Verify that autoconf is cleared.
@@ -139,7 +139,7 @@
 // Tests that the autoconf value overrides other PpdReference fields.
 TEST(SpecificsTranslationTest, AutoconfOverrides) {
   sync_pb::PrinterSpecifics original;
-  original.set_id(id);
+  original.set_id(kId);
   auto* ppd_reference = original.mutable_ppd_reference();
   ppd_reference->set_autoconf(true);
   ppd_reference->set_user_supplied_ppd_url(kUserSuppliedPPD);
@@ -155,10 +155,10 @@
 // autoconf is false.
 TEST(SpecificsTranslationTest, UserSuppliedOverrides) {
   sync_pb::PrinterSpecifics original;
-  original.set_id(id);
+  original.set_id(kId);
   auto* ppd_reference = original.mutable_ppd_reference();
   ppd_reference->set_user_supplied_ppd_url(kUserSuppliedPPD);
-  ppd_reference->set_effective_make_and_model(effective_make_and_model);
+  ppd_reference->set_effective_make_and_model(kEffectiveMakeAndModel);
 
   auto printer = SpecificsToPrinter(original);
 
diff --git a/chrome/browser/download/download_service_factory.cc b/chrome/browser/download/download_service_factory.cc
index 41a2f7a..05a415bc 100644
--- a/chrome/browser/download/download_service_factory.cc
+++ b/chrome/browser/download/download_service_factory.cc
@@ -10,15 +10,21 @@
 #include "base/sequenced_task_runner.h"
 #include "base/task_scheduler/post_task.h"
 #include "base/task_scheduler/task_traits.h"
+#include "chrome/browser/download/download_task_scheduler_impl.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_constants.h"
 #include "components/download/content/factory/download_service_factory.h"
 #include "components/download/public/clients.h"
 #include "components/download/public/download_service.h"
+#include "components/download/public/task_scheduler.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "content/public/browser/browser_context.h"
 
+#if defined(OS_ANDROID)
+#include "chrome/browser/android/download/service/download_task_scheduler.h"
+#endif
+
 // static
 DownloadServiceFactory* DownloadServiceFactory::GetInstance() {
   return base::Singleton<DownloadServiceFactory>::get();
@@ -56,8 +62,17 @@
       base::CreateSequencedTaskRunnerWithTraits(
           {base::MayBlock(), base::TaskPriority::BACKGROUND});
 
+  std::unique_ptr<download::TaskScheduler> task_scheduler;
+
+#if defined(OS_ANDROID)
+  task_scheduler = base::MakeUnique<download::android::DownloadTaskScheduler>();
+#else
+  task_scheduler = base::MakeUnique<DownloadTaskSchedulerImpl>(context);
+#endif
+
   return download::CreateDownloadService(std::move(clients), download_manager,
-                                         storage_dir, background_task_runner);
+                                         storage_dir, background_task_runner,
+                                         std::move(task_scheduler));
 }
 
 content::BrowserContext* DownloadServiceFactory::GetBrowserContextToUse(
diff --git a/chrome/browser/download/download_task_scheduler_impl.cc b/chrome/browser/download/download_task_scheduler_impl.cc
new file mode 100644
index 0000000..32a9386
--- /dev/null
+++ b/chrome/browser/download/download_task_scheduler_impl.cc
@@ -0,0 +1,61 @@
+// 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/download/download_task_scheduler_impl.h"
+
+#include "base/bind.h"
+#include "base/cancelable_callback.h"
+#include "base/sequenced_task_runner.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/task_scheduler/task_traits.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
+#include "chrome/browser/download/download_service_factory.h"
+#include "components/download/public/download_service.h"
+#include "content/public/browser/browser_context.h"
+
+DownloadTaskSchedulerImpl::DownloadTaskSchedulerImpl(
+    content::BrowserContext* context)
+    : context_(context), weak_factory_(this) {}
+
+DownloadTaskSchedulerImpl::~DownloadTaskSchedulerImpl() = default;
+
+void DownloadTaskSchedulerImpl::ScheduleTask(
+    download::DownloadTaskType task_type,
+    bool require_unmetered_network,
+    bool require_charging,
+    long window_start_time_seconds,
+    long window_end_time_seconds) {
+  // We only rely on this for cleanup tasks. Since this doesn't restart Chrome,
+  // for download tasks it doesn't do much and we handle them outside of task
+  // scheduler.
+  if (task_type != download::DownloadTaskType::CLEANUP_TASK)
+    return;
+
+  scheduled_tasks_[task_type].Reset(
+      base::Bind(&DownloadTaskSchedulerImpl::RunScheduledTask,
+                 weak_factory_.GetWeakPtr(), task_type));
+  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+      FROM_HERE, scheduled_tasks_[task_type].callback(),
+      base::TimeDelta::FromSeconds(window_start_time_seconds));
+}
+
+void DownloadTaskSchedulerImpl::CancelTask(
+    download::DownloadTaskType task_type) {
+  scheduled_tasks_[task_type].Cancel();
+}
+
+void DownloadTaskSchedulerImpl::RunScheduledTask(
+    download::DownloadTaskType task_type) {
+  download::DownloadService* download_service =
+      DownloadServiceFactory::GetForBrowserContext(context_);
+  download_service->OnStartScheduledTask(
+      task_type, base::Bind(&DownloadTaskSchedulerImpl::OnTaskFinished,
+                            weak_factory_.GetWeakPtr()));
+}
+
+void DownloadTaskSchedulerImpl::OnTaskFinished(bool reschedule) {
+  // TODO(shaktisahu): Cache the original scheduling params and re-post task in
+  // case it needs reschedule.
+}
diff --git a/chrome/browser/download/download_task_scheduler_impl.h b/chrome/browser/download/download_task_scheduler_impl.h
new file mode 100644
index 0000000..6fa5d969
--- /dev/null
+++ b/chrome/browser/download/download_task_scheduler_impl.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 CHROME_BROWSER_DOWNLOAD_DOWNLOAD_TASK_SCHEDULER_IMPL_H_
+#define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_TASK_SCHEDULER_IMPL_H_
+
+#include <map>
+
+#include "base/cancelable_callback.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "components/download/public/task_scheduler.h"
+
+namespace content {
+class BrowserContext;
+}  // namespace content
+
+// A TaskScheduler implementation that doesn't do anything but posts the task
+// after the specified delay.
+// If Chrome is shut down, the implementation will not automatically restart it.
+class DownloadTaskSchedulerImpl : public download::TaskScheduler {
+ public:
+  explicit DownloadTaskSchedulerImpl(content::BrowserContext* context);
+  ~DownloadTaskSchedulerImpl();
+
+  // TaskScheduler implementation.
+  void ScheduleTask(download::DownloadTaskType task_type,
+                    bool require_unmetered_network,
+                    bool require_charging,
+                    long window_start_time_seconds,
+                    long window_end_time_seconds) override;
+  void CancelTask(download::DownloadTaskType task_type) override;
+
+ private:
+  void RunScheduledTask(download::DownloadTaskType task_type);
+  void OnTaskFinished(bool reschedule);
+
+  content::BrowserContext* context_;
+
+  // Keeps track of scheduled tasks so that they can be cancelled.
+  std::map<download::DownloadTaskType, base::CancelableClosure>
+      scheduled_tasks_;
+
+  base::WeakPtrFactory<DownloadTaskSchedulerImpl> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(DownloadTaskSchedulerImpl);
+};
+
+#endif  // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_TASK_SCHEDULER_IMPL_H_
diff --git a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html
index 968ca1b7..9fd16e3 100644
--- a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html
+++ b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html
@@ -205,7 +205,7 @@
           <div class="start">
             <div class="label">$i18n{printerQueue}</div>
             <div class="secondary">
-              <paper-input no-label-float label="ipp/print" 
+              <paper-input no-label-float label="ipp/print"
                   value="{{newPrinter.printerQueue}}">
               </paper-input>
             </div>
@@ -228,7 +228,7 @@
           <paper-button class="secondary-button"
               on-tap="switchToDiscoveryDialog_">
             $i18n{discoverPrintersButtonText}
-          </paper-button> 
+          </paper-button>
         </div>
         <div>  <!-- Right group -->
           <paper-button class="cancel-button secondary-button"
@@ -236,7 +236,7 @@
             $i18n{cancelButtonText}
           </paper-button>
           <paper-button class="action-button"
-              on-tap="switchToManufacturerDialog_"
+              on-tap="addPressed_"
               disabled="[[!newPrinter.printerName]]">
             $i18n{addPrinterButtonText}
           </paper-button>
diff --git a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js
index 8e1d7de44..52099fa 100644
--- a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js
+++ b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js
@@ -40,6 +40,7 @@
 function getEmptyPrinter_() {
   return {
     printerAddress: '',
+    printerAutoconf: false,
     printerDescription: '',
     printerId: '',
     printerManufacturer: '',
@@ -169,13 +170,13 @@
   },
 
   /** @private */
-  switchToManufacturerDialog_: function() {
+  addPressed_: function() {
     // Set the default printer queue to be "ipp/print".
-    if (!this.newPrinter.printerQueue)
+    if (!this.newPrinter.printerQueue) {
       this.set('newPrinter.printerQueue', 'ipp/print');
-
+    }
     this.$$('add-printer-dialog').close();
-    this.fire('open-manufacturer-model-dialog');
+    this.fire('open-configuring-printer-dialog');
   },
 
   /** @private */
@@ -416,6 +417,46 @@
   },
 
   /** @private */
+  addPrinter_: function() {
+    settings.CupsPrintersBrowserProxyImpl.getInstance().
+       addCupsPrinter(this.newPrinter);
+  },
+
+  /** @private */
+  switchToManufacturerDialog_: function() {
+    this.$$('add-printer-configuring-dialog').close();
+    this.fire('open-manufacturer-model-dialog');
+  },
+
+  /**
+   * Handler for getPrinterInfo success.
+   * @param {!PrinterMakeModel} info
+   * @private
+   * */
+  onPrinterFound_: function(info) {
+    this.newPrinter.printerAutoconf = info.autoconf;
+    this.newPrinter.printerManufacturer = info.manufacturer;
+    this.newPrinter.printerModel = info.model;
+
+    // Add the printer if it's configurable. Otherwise, forward to the
+    // manufacturer dialog.
+    if (this.newPrinter.printerAutoconf) {
+      this.addPrinter_();
+    } else {
+      this.switchToManufacturerDialog_();
+    }
+  },
+
+  /**
+   * Handler for getPrinterInfo failure.
+   * @param {*} rejected
+   * @private
+   */
+  infoFailed_: function(rejected) {
+    this.switchToManufacturerDialog_();
+  },
+
+  /** @private */
   openConfiguringPrinterDialog_: function() {
     this.switchDialog_(
         this.currentDialog_, AddPrinterDialogs.CONFIGURING,
@@ -423,13 +464,25 @@
     if (this.previousDialog_ == AddPrinterDialogs.DISCOVERY) {
       this.configuringDialogTitle =
           loadTimeData.getString('addPrintersNearbyTitle');
-      settings.CupsPrintersBrowserProxyImpl.getInstance().addCupsPrinter(
-          this.newPrinter);
-    } else if (this.previousDialog_ == AddPrinterDialogs.MANUFACTURER) {
+      this.addPrinter_();
+    } else if (
+        this.previousDialog_ == AddPrinterDialogs.MANUFACTURER) {
       this.configuringDialogTitle =
           loadTimeData.getString('addPrintersManuallyTitle');
-      settings.CupsPrintersBrowserProxyImpl.getInstance().addCupsPrinter(
-          this.newPrinter);
+      this.addPrinter_();
+    } else if (this.previousDialog_ == AddPrinterDialogs.MANUALLY) {
+      this.configuringDialogTitle =
+          loadTimeData.getString('addPrintersManuallyTitle');
+      if (this.newPrinter.printerProtocol == 'ipp' ||
+          this.newPrinter.printerProtocol == 'ipps') {
+        settings.CupsPrintersBrowserProxyImpl.getInstance().
+            getPrinterInfo(this.newPrinter).
+            then(
+                this.onPrinterFound_.bind(this), this.infoFailed_.bind(this));
+      } else {
+        // Defer the switch until all the elements are drawn.
+        this.async(this.switchToManufacturerDialog_.bind(this));
+      }
     }
   },
 
diff --git a/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js b/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js
index c02a562..3af40d9 100644
--- a/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js
+++ b/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js
@@ -10,6 +10,7 @@
 /**
  * @typedef {{
  *   printerAddress: string,
+ *   printerAutoconf: boolean,
  *   printerDescription: string,
  *   printerId: string,
  *   printerManufacturer: string,
@@ -46,6 +47,22 @@
  */
 var ModelsInfo;
 
+/**
+ * @typedef {{
+ *   manufacturer: string,
+ *   model: string,
+ *   autoconf: boolean
+ * }}
+ */
+var PrinterMakeModel;
+
+/**
+ * @typedef {{
+ *   message: string
+ * }}
+ */
+var QueryFailure;
+
 cr.define('settings', function() {
   /** @interface */
   function CupsPrintersBrowserProxy() {}
@@ -93,6 +110,12 @@
      * @return {!Promise<!ModelsInfo>}
      */
     getCupsPrinterModelsList: function(manufacturer) {},
+
+    /**
+     * @param {!CupsPrinterInfo} newPrinter
+     * @return {!Promise<!PrinterMakeModel>}
+     */
+    getPrinterInfo: function(newPrinter) {},
   };
 
   /**
@@ -147,6 +170,11 @@
     getCupsPrinterModelsList: function(manufacturer) {
       return cr.sendWithPromise('getCupsPrinterModelsList', manufacturer);
     },
+
+    /** @override */
+    getPrinterInfo: function(newPrinter) {
+      return cr.sendWithPromise('getPrinterInfo', newPrinter);
+    },
   };
 
   return {
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.cc b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
index 866d8fd..fdb621c 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
@@ -55,15 +55,8 @@
   if (content_settings()) {
     CleanUpExpiredVerdicts();
     UMA_HISTOGRAM_COUNTS_1000(
-        "PasswordProtection.NumberOfCachedVerdictBeforeShutdown."
-        "PasswordOnFocus",
-        GetStoredVerdictCount(
-            LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
-    UMA_HISTOGRAM_COUNTS_1000(
-        "PasswordProtection.NumberOfCachedVerdictBeforeShutdown."
-        "ProtectedPasswordEntry",
-        GetStoredVerdictCount(
-            LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
+        "PasswordProtection.NumberOfCachedVerdictBeforeShutdown",
+        GetStoredVerdictCount());
   }
 }
 
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc b/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
index f496f390..a30d126 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
@@ -75,7 +75,6 @@
   }
 
   void CacheVerdict(const GURL& url,
-                    LoginReputationClientRequest::TriggerType trigger_type,
                     LoginReputationClientResponse* verdict,
                     const base::Time& receive_time) override {}
 
diff --git a/chrome/browser/translate/chrome_translate_client.cc b/chrome/browser/translate/chrome_translate_client.cc
index 7aadf49d..ad257ad 100644
--- a/chrome/browser/translate/chrome_translate_client.cc
+++ b/chrome/browser/translate/chrome_translate_client.cc
@@ -90,9 +90,12 @@
   // If entry is null, we don't record the page.
   // The navigation entry can be null in situations like download or initial
   // blank page.
-  if (entry != nullptr) {
+  DCHECK(web_contents);
+  if (entry != nullptr &&
+      TranslateService::IsTranslatableURL(entry->GetVirtualURL())) {
     user_event_service->RecordUserEvent(
-        translate::ConstructLanguageDetectionEvent(details));
+        translate::ConstructLanguageDetectionEvent(
+            entry->GetTimestamp().ToInternalValue(), details));
   }
 }
 
diff --git a/chrome/browser/translate/chrome_translate_client.h b/chrome/browser/translate/chrome_translate_client.h
index da171a3..141350f 100644
--- a/chrome/browser/translate/chrome_translate_client.h
+++ b/chrome/browser/translate/chrome_translate_client.h
@@ -113,6 +113,10 @@
  private:
   explicit ChromeTranslateClient(content::WebContents* web_contents);
   friend class content::WebContentsUserData<ChromeTranslateClient>;
+  FRIEND_TEST_ALL_PREFIXES(ChromeTranslateClientTest,
+                           LanguageEventShouldRecord);
+  FRIEND_TEST_ALL_PREFIXES(ChromeTranslateClientTest,
+                           LanguageEventShouldNotRecord);
 
   // content::WebContentsObserver implementation.
   void WebContentsDestroyed() override;
diff --git a/chrome/browser/translate/chrome_translate_client_unittest.cc b/chrome/browser/translate/chrome_translate_client_unittest.cc
new file mode 100644
index 0000000..1793d84
--- /dev/null
+++ b/chrome/browser/translate/chrome_translate_client_unittest.cc
@@ -0,0 +1,69 @@
+// 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/translate/chrome_translate_client.h"
+
+#include <memory>
+
+#include "base/command_line.h"
+#include "base/memory/ref_counted.h"
+#include "base/run_loop.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "chrome/browser/sync/user_event_service_factory.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "components/sync/user_events/fake_user_event_service.h"
+#include "components/translate/core/common/language_detection_details.h"
+#include "content/public/browser/web_contents.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+std::unique_ptr<KeyedService> BuildFakeUserEventService(
+    content::BrowserContext* context) {
+  return base::MakeUnique<syncer::FakeUserEventService>();
+}
+
+class ChromeTranslateClientTest : public ChromeRenderViewHostTestHarness {
+ public:
+  void SetUp() override {
+    ChromeRenderViewHostTestHarness::SetUp();
+    fake_user_event_service_ = static_cast<syncer::FakeUserEventService*>(
+        browser_sync::UserEventServiceFactory::GetInstance()
+            ->SetTestingFactoryAndUse(browser_context(),
+                                      &BuildFakeUserEventService));
+  }
+
+  void TearDown() override { ChromeRenderViewHostTestHarness::TearDown(); }
+
+ protected:
+  syncer::FakeUserEventService* GetUserEventService() {
+    return fake_user_event_service_;
+  }
+
+ private:
+  syncer::FakeUserEventService* fake_user_event_service_;
+};
+
+TEST_F(ChromeTranslateClientTest, LanguageEventShouldRecord) {
+  GURL url("http://yahoo.com");
+  NavigateAndCommit(url);
+  ChromeTranslateClient client(web_contents());
+  translate::LanguageDetectionDetails details;
+  details.cld_language = "en";
+  details.is_cld_reliable = true;
+  details.adopted_language = "en";
+  client.OnLanguageDetermined(details);
+  EXPECT_EQ(1ul, GetUserEventService()->GetRecordedUserEvents().size());
+}
+
+TEST_F(ChromeTranslateClientTest, LanguageEventShouldNotRecord) {
+  GURL url("about://blank");
+  NavigateAndCommit(url);
+  ChromeTranslateClient client(web_contents());
+  translate::LanguageDetectionDetails details;
+  details.cld_language = "en";
+  details.is_cld_reliable = true;
+  details.adopted_language = "en";
+  client.OnLanguageDetermined(details);
+  EXPECT_EQ(0u, GetUserEventService()->GetRecordedUserEvents().size());
+}
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc
index 6c0ece3..ed2397d 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc
@@ -337,9 +337,11 @@
       l10n_util::GetStringUTF16(IDS_BOOKMARK_AX_BUBBLE_FOLDER_LABEL));
   layout->AddView(parent_combobox_);
 
-  layout->AddPaddingRow(
-      kFixed,
-      provider->GetInsetsMetric(views::INSETS_DIALOG_CONTENTS).bottom());
+  if (provider->UseExtraDialogPadding()) {
+    layout->AddPaddingRow(
+        kFixed,
+        provider->GetInsetsMetric(views::INSETS_DIALOG_CONTENTS).bottom());
+  }
 
   AddChildView(bookmark_contents_view_);
 }
diff --git a/chrome/browser/ui/views/harmony/chrome_layout_provider.cc b/chrome/browser/ui/views/harmony/chrome_layout_provider.cc
index a66a6b4aa..1fd3548a 100644
--- a/chrome/browser/ui/views/harmony/chrome_layout_provider.cc
+++ b/chrome/browser/ui/views/harmony/chrome_layout_provider.cc
@@ -30,8 +30,6 @@
       return views::kMinimumButtonWidth;
     case DISTANCE_CONTROL_LIST_VERTICAL:
       return GetDistanceMetric(views::DISTANCE_UNRELATED_CONTROL_VERTICAL);
-    case DISTANCE_DIALOG_BUTTON_TOP:
-      return 0;
     case DISTANCE_RELATED_CONTROL_HORIZONTAL_SMALL:
       return views::kRelatedControlSmallHorizontalSpacing;
     case DISTANCE_RELATED_CONTROL_VERTICAL_SMALL:
diff --git a/chrome/browser/ui/views/harmony/chrome_layout_provider.h b/chrome/browser/ui/views/harmony/chrome_layout_provider.h
index 318cab5..5541639 100644
--- a/chrome/browser/ui/views/harmony/chrome_layout_provider.h
+++ b/chrome/browser/ui/views/harmony/chrome_layout_provider.h
@@ -17,8 +17,6 @@
   DISTANCE_BUTTON_MINIMUM_WIDTH = views::VIEWS_DISTANCE_END,
   // Vertical spacing between a list of multiple controls in one column.
   DISTANCE_CONTROL_LIST_VERTICAL,
-  // Spacing between a dialog button and the content above it.
-  DISTANCE_DIALOG_BUTTON_TOP,
   // Smaller horizontal spacing between other controls that are logically
   // related.
   DISTANCE_RELATED_CONTROL_HORIZONTAL_SMALL,
diff --git a/chrome/browser/ui/views/harmony/harmony_layout_provider.cc b/chrome/browser/ui/views/harmony/harmony_layout_provider.cc
index 365023c..2e108b4 100644
--- a/chrome/browser/ui/views/harmony/harmony_layout_provider.cc
+++ b/chrome/browser/ui/views/harmony/harmony_layout_provider.cc
@@ -17,6 +17,7 @@
 int HarmonyLayoutProvider::GetDistanceMetric(int metric) const {
   DCHECK_GE(metric, views::VIEWS_INSETS_MAX);
   switch (metric) {
+    case views::DISTANCE_BUBBLE_BUTTON_TOP_MARGIN:
     case views::DISTANCE_BUBBLE_CONTENTS_HORIZONTAL_MARGIN:
     case views::DISTANCE_BUBBLE_CONTENTS_VERTICAL_MARGIN:
     case views::DISTANCE_DIALOG_CONTENTS_HORIZONTAL_MARGIN:
@@ -42,8 +43,6 @@
       return kHarmonyLayoutUnit / 2;
     case views::DISTANCE_DIALOG_BUTTON_BOTTOM_MARGIN:
       return kHarmonyLayoutUnit;
-    case DISTANCE_DIALOG_BUTTON_TOP:
-      return kHarmonyLayoutUnit;
     case views::DISTANCE_DIALOG_BUTTON_MINIMUM_WIDTH:
     case DISTANCE_BUTTON_MINIMUM_WIDTH:
       // Minimum label size plus padding.
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
index e5d02eb..f8d13d1 100644
--- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/chromeos/printing/ppd_provider_factory.h"
 #include "chrome/browser/chromeos/printing/printer_configurer.h"
 #include "chrome/browser/chromeos/printing/printer_discoverer.h"
+#include "chrome/browser/chromeos/printing/printer_info.h"
 #include "chrome/browser/chromeos/printing/printers_manager_factory.h"
 #include "chrome/browser/download/download_prefs.h"
 #include "chrome/browser/profiles/profile.h"
@@ -45,6 +46,12 @@
 
 namespace {
 
+const char kIppScheme[] = "ipp";
+const char kIppsScheme[] = "ipps";
+
+const int kIppPort = 631;
+const int kIppsPort = 443;
+
 // These values are written to logs.  New enum values can be added, but existing
 // enums must never be renumbered or deleted and reused.
 enum PpdSourceForHistogram { kUser = 0, kScs = 1, kPpdSourceMax };
@@ -58,6 +65,7 @@
                             Printer::PrinterProtocol::kProtocolMax);
 }
 
+// Returns a JSON representation of |printer| as a CupsPrinterInfo.
 std::unique_ptr<base::DictionaryValue> GetPrinterInfo(const Printer& printer) {
   std::unique_ptr<base::DictionaryValue> printer_info =
       base::MakeUnique<base::DictionaryValue>();
@@ -98,6 +106,23 @@
   return printer_info;
 }
 
+// Extracts a sanitized value of printerQueeu from |printer_dict|.  Returns an
+// empty string if the value was not present in the dictionary.
+std::string GetPrinterQueue(const base::DictionaryValue& printer_dict) {
+  std::string queue;
+  if (!printer_dict.GetString("printerQueue", &queue)) {
+    return queue;
+  }
+
+  if (!queue.empty() && queue[0] == '/') {
+    // Strip the leading backslash. It is expected that this results in an
+    // empty string if the input is just a backslash.
+    queue = queue.substr(1);
+  }
+
+  return queue;
+}
+
 }  // namespace
 
 CupsPrintersHandler::CupsPrintersHandler(content::WebUI* webui)
@@ -127,6 +152,9 @@
       "addCupsPrinter", base::Bind(&CupsPrintersHandler::HandleAddCupsPrinter,
                                    base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
+      "getPrinterInfo", base::Bind(&CupsPrintersHandler::HandleGetPrinterInfo,
+                                   base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
       "getCupsPrinterManufacturersList",
       base::Bind(&CupsPrintersHandler::HandleGetCupsPrinterManufacturers,
                  base::Unretained(this)));
@@ -203,6 +231,90 @@
                             base::Bind(&base::DoNothing));
 }
 
+void CupsPrintersHandler::HandleGetPrinterInfo(const base::ListValue* args) {
+  DCHECK(args);
+  std::string callback_id;
+  if (!args->GetString(0, &callback_id)) {
+    NOTREACHED() << "Expected request for a promise";
+    return;
+  }
+
+  const base::DictionaryValue* printer_dict = nullptr;
+  if (!args->GetDictionary(1, &printer_dict)) {
+    NOTREACHED() << "Dictionary missing";
+    return;
+  }
+
+  AllowJavascript();
+
+  std::string printer_address;
+  if (!printer_dict->GetString("printerAddress", &printer_address)) {
+    NOTREACHED() << "Address missing";
+    return;
+  }
+
+  if (printer_address.empty()) {
+    // Run the failure callback.
+    OnPrinterInfo(callback_id, false, "", "", false);
+    return;
+  }
+
+  std::string printer_queue = GetPrinterQueue(*printer_dict);
+
+  std::string printer_protocol;
+  if (!printer_dict->GetString("printerProtocol", &printer_protocol)) {
+    NOTREACHED() << "Protocol missing";
+    return;
+  }
+
+  // Parse url to separate address and port. ParseStandardURL expects a scheme,
+  // so add the printer_protocol.
+  std::string printer_uri =
+      printer_protocol + url::kStandardSchemeSeparator + printer_address;
+  const char* uri_ptr = printer_uri.c_str();
+  url::Parsed parsed;
+  url::ParseStandardURL(uri_ptr, printer_uri.length(), &parsed);
+  base::StringPiece host(&printer_uri[parsed.host.begin], parsed.host.len);
+
+  int port = ParsePort(uri_ptr, parsed.port);
+  if (port == url::SpecialPort::PORT_UNSPECIFIED ||
+      port == url::SpecialPort::PORT_INVALID) {
+    // imply port from protocol
+    if (printer_protocol == kIppScheme) {
+      port = kIppPort;
+    } else if (printer_protocol == kIppsScheme) {
+      // ipps is ipp over https so it uses the https port.
+      port = kIppsPort;
+    } else {
+      NOTREACHED() << "Unrecognized protocol. Port was not set.";
+    }
+  }
+
+  ::chromeos::QueryIppPrinter(
+      host.as_string(), port, printer_queue,
+      base::Bind(&CupsPrintersHandler::OnPrinterInfo,
+                 weak_factory_.GetWeakPtr(), callback_id));
+}
+
+void CupsPrintersHandler::OnPrinterInfo(const std::string& callback_id,
+                                        bool success,
+                                        const std::string& make,
+                                        const std::string& model,
+                                        bool ipp_everywhere) {
+  if (!success) {
+    base::DictionaryValue reject;
+    reject.SetString("message", "Querying printer failed");
+    RejectJavascriptCallback(base::Value(callback_id), reject);
+    return;
+  }
+
+  base::DictionaryValue info;
+  info.SetString("manufacturer", make);
+  info.SetString("model", model);
+  info.SetBoolean("autoconf", ipp_everywhere);
+  ResolveJavascriptCallback(base::Value(callback_id), info);
+}
+
 void CupsPrintersHandler::HandleAddCupsPrinter(const base::ListValue* args) {
   AllowJavascript();
 
@@ -216,7 +328,6 @@
   std::string printer_model;
   std::string printer_address;
   std::string printer_protocol;
-  std::string printer_queue;
   std::string printer_ppd_path;
   CHECK(printer_dict->GetString("printerId", &printer_id));
   CHECK(printer_dict->GetString("printerName", &printer_name));
@@ -225,16 +336,18 @@
   CHECK(printer_dict->GetString("printerModel", &printer_model));
   CHECK(printer_dict->GetString("printerAddress", &printer_address));
   CHECK(printer_dict->GetString("printerProtocol", &printer_protocol));
-  // printerQueue might be null for a printer whose protocol is not 'LPD'.
-  printer_dict->GetString("printerQueue", &printer_queue);
 
-  // printerPPDPath might be null for an auto-discovered printer.
-  printer_dict->GetString("printerPPDPath", &printer_ppd_path);
-  std::string printer_uri = printer_protocol + "://" + printer_address;
+  std::string printer_queue = GetPrinterQueue(*printer_dict);
+
+  std::string printer_uri =
+      printer_protocol + url::kStandardSchemeSeparator + printer_address;
   if (!printer_queue.empty()) {
     printer_uri += "/" + printer_queue;
   }
 
+  // printerPPDPath might be null for an auto-discovered printer.
+  printer_dict->GetString("printerPPDPath", &printer_ppd_path);
+
   std::unique_ptr<Printer> printer = base::MakeUnique<Printer>(printer_id);
   printer->set_display_name(printer_name);
   printer->set_description(printer_description);
@@ -242,8 +355,13 @@
   printer->set_model(printer_model);
   printer->set_uri(printer_uri);
 
-  // Verify a valid ppd path is present.
-  if (!printer_ppd_path.empty()) {
+  bool autoconf = false;
+  printer_dict->GetBoolean("printerAutoconf", &autoconf);
+
+  // Verify that the printer is autoconf or a valid ppd path is present.
+  if (autoconf) {
+    printer->mutable_ppd_reference()->autoconf = true;
+  } else if (!printer_ppd_path.empty()) {
     RecordPpdSource(kUser);
     GURL tmp = net::FilePathToFileURL(base::FilePath(printer_ppd_path));
     if (!tmp.is_valid()) {
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
index 343daea..ee93a93 100644
--- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
@@ -49,6 +49,23 @@
   void HandleUpdateCupsPrinter(const base::ListValue* args);
   void HandleRemoveCupsPrinter(const base::ListValue* args);
 
+  // For a CupsPrinterInfo in |args|, retrieves the relevant PrinterInfo object
+  // using an IPP call to the printer.
+  void HandleGetPrinterInfo(const base::ListValue* args);
+
+  // Handles the callback for HandleGetPrinterInfo. |callback_id| is the
+  // identifier to resolve the correct Promise. |success| indicates if the
+  // query was successful. |make| is the detected printer manufacturer.
+  // |model| is the detected model. |ipp_everywhere| indicates if configuration
+  // using the CUPS IPP Everywhere driver should be attempted. If |success| is
+  // false, the values of |make|, |model| and |ipp_everywhere| are not
+  // specified.
+  void OnPrinterInfo(const std::string& callback_id,
+                     bool success,
+                     const std::string& make,
+                     const std::string& model,
+                     bool ipp_everywhere);
+
   void HandleAddCupsPrinter(const base::ListValue* args);
   void OnAddedPrinter(std::unique_ptr<Printer> printer,
                       chromeos::PrinterSetupResult result);
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 4622529..fe3d75d 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -3270,6 +3270,7 @@
     "../browser/thumbnails/content_based_thumbnailing_algorithm_unittest.cc",
     "../browser/thumbnails/simple_thumbnail_crop_unittest.cc",
     "../browser/thumbnails/thumbnail_service_unittest.cc",
+    "../browser/translate/chrome_translate_client_unittest.cc",
     "../browser/translate/language_model_factory_unittest.cc",
     "../browser/translate/translate_service_unittest.cc",
     "../browser/ui/android/tab_model/tab_model_list_unittest.cc",
diff --git a/chrome/test/data/webui/media_router/OWNERS b/chrome/test/data/webui/media_router/OWNERS
new file mode 100644
index 0000000..fda51ea
--- /dev/null
+++ b/chrome/test/data/webui/media_router/OWNERS
@@ -0,0 +1,3 @@
+file://chrome/browser/media/router/OWNERS
+
+# COMPONENT: Internals>Cast>UI
diff --git a/chrome/test/data/webui/settings/cups_printer_page_tests.js b/chrome/test/data/webui/settings/cups_printer_page_tests.js
index 715fd44..aa5d175 100644
--- a/chrome/test/data/webui/settings/cups_printer_page_tests.js
+++ b/chrome/test/data/webui/settings/cups_printer_page_tests.js
@@ -12,6 +12,7 @@
     'getCupsPrintersList',
     'getCupsPrinterManufacturersList',
     'getCupsPrinterModelsList',
+    'getPrinterInfo',
     'startDiscoveringPrinters',
     'stopDiscoveringPrinters',
   ]);
@@ -23,6 +24,7 @@
   printerList: [],
   manufacturers: [],
   models: [],
+  printerInfo: {},
 
   /** @override */
   getCupsPrintersList: function() {
@@ -43,6 +45,13 @@
   },
 
   /** @override */
+  getPrinterInfo: function(newPrinter) {
+    this.methodCalled('getPrinterInfo', newPrinter);
+    // Reject all calls for now.
+    return Promise.reject();
+  },
+
+  /** @override */
   startDiscoveringPrinters: function() {
     this.methodCalled('startDiscoveringPrinters');
   },
@@ -117,15 +126,20 @@
     // Now we should be in the manually add dialog.
     var addDialog = dialog.$$('add-printer-manually-dialog');
     assertTrue(!!addDialog);
-
     fillAddManuallyDialog(addDialog);
 
     MockInteractions.tap(addDialog.$$('.action-button'));
     Polymer.dom.flush();
+    // Configure is shown until getPrinterInfo is rejected.
+    assertTrue(!!dialog.$$('add-printer-configuring-dialog'));
 
-    // showing model selection
-    assertFalse(!!dialog.$$('add-printer-configuring-dialog'));
-    assertTrue(!!dialog.$$('add-printer-manufacturer-model-dialog'));
+    // Upon rejection, show model.
+    return cupsPrintersBrowserProxy.
+        whenCalled('getCupsPrinterManufacturersList').
+        then(function() {
+          // TODO(skau): Verify other dialogs are hidden.
+          assertTrue(!!dialog.$$('add-printer-manufacturer-model-dialog'));
+        });
   });
 
   /**
@@ -149,10 +163,11 @@
     MockInteractions.tap(addDialog.$$('.action-button'));
     Polymer.dom.flush();
 
-    var modelDialog = dialog.$$('add-printer-manufacturer-model-dialog');
-    assertTrue(!!modelDialog);
-
-    return cupsPrintersBrowserProxy.whenCalled(
-        'getCupsPrinterManufacturersList');
+    return cupsPrintersBrowserProxy.
+        whenCalled('getCupsPrinterManufacturersList').
+        then(function() {
+          var modelDialog = dialog.$$('add-printer-manufacturer-model-dialog');
+          assertTrue(!!modelDialog);
+        });
   });
 });
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java
index 77252d7c..287f06e7 100644
--- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java
+++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java
@@ -25,8 +25,10 @@
     static final int BACKGROUND_TASK_CHROME_MINIDUMP = 5;
     static final int BACKGROUND_TASK_OFFLINE_PAGES = 6;
     static final int BACKGROUND_TASK_OFFLINE_PREFETCH = 7;
+    static final int BACKGROUND_TASK_DOWNLOAD_SERVICE = 8;
+    static final int BACKGROUND_TASK_DOWNLOAD_CLEANUP = 9;
     // Keep this one at the end and increment appropriately when adding new tasks.
-    static final int BACKGROUND_TASK_COUNT = 8;
+    static final int BACKGROUND_TASK_COUNT = 10;
 
     static final String KEY_CACHED_UMA = "bts_cached_uma";
 
@@ -222,6 +224,10 @@
                 return BACKGROUND_TASK_OFFLINE_PAGES;
             case TaskIds.OFFLINE_PAGES_PREFETCH_JOB_ID:
                 return BACKGROUND_TASK_OFFLINE_PREFETCH;
+            case TaskIds.DOWNLOAD_SERVICE_JOB_ID:
+                return BACKGROUND_TASK_DOWNLOAD_SERVICE;
+            case TaskIds.DOWNLOAD_CLEANUP_JOB_ID:
+                return BACKGROUND_TASK_DOWNLOAD_CLEANUP;
             default:
                 assert false;
         }
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskIds.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskIds.java
index e4a39529..b9c4fe57 100644
--- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskIds.java
+++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskIds.java
@@ -20,6 +20,8 @@
     public static final int CHROME_MINIDUMP_UPLOADING_JOB_ID = 43;
     public static final int OFFLINE_PAGES_BACKGROUND_JOB_ID = 77;
     public static final int OFFLINE_PAGES_PREFETCH_JOB_ID = 78;
+    public static final int DOWNLOAD_SERVICE_JOB_ID = 53;
+    public static final int DOWNLOAD_CLEANUP_JOB_ID = 54;
 
     private TaskIds() {}
 }
diff --git a/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java b/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java
index 405ef75..94e3a1c6 100644
--- a/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java
+++ b/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java
@@ -67,7 +67,13 @@
         assertEquals(BackgroundTaskSchedulerUma.BACKGROUND_TASK_OFFLINE_PREFETCH,
                 BackgroundTaskSchedulerUma.toUmaEnumValueFromTaskId(
                         TaskIds.OFFLINE_PAGES_PREFETCH_JOB_ID));
-        assertEquals(BackgroundTaskSchedulerUma.BACKGROUND_TASK_COUNT, 8);
+        assertEquals(BackgroundTaskSchedulerUma.BACKGROUND_TASK_DOWNLOAD_SERVICE,
+                BackgroundTaskSchedulerUma.toUmaEnumValueFromTaskId(
+                        TaskIds.DOWNLOAD_SERVICE_JOB_ID));
+        assertEquals(BackgroundTaskSchedulerUma.BACKGROUND_TASK_DOWNLOAD_CLEANUP,
+                BackgroundTaskSchedulerUma.toUmaEnumValueFromTaskId(
+                        TaskIds.DOWNLOAD_CLEANUP_JOB_ID));
+        assertEquals(BackgroundTaskSchedulerUma.BACKGROUND_TASK_COUNT, 10);
     }
 
     @Test
diff --git a/components/content_settings/core/common/content_settings.cc b/components/content_settings/core/common/content_settings.cc
index 4bee639..2333fe25 100644
--- a/components/content_settings/core/common/content_settings.cc
+++ b/components/content_settings/core/common/content_settings.cc
@@ -57,7 +57,6 @@
     {CONTENT_SETTINGS_TYPE_PERMISSION_AUTOBLOCKER_DATA, 31},
     {CONTENT_SETTINGS_TYPE_ADS, 32},
     {CONTENT_SETTINGS_TYPE_ADS_DATA, 33},
-    {CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, 34},
 };
 
 int ContentSettingTypeToHistogramValue(ContentSettingsType content_setting,
diff --git a/components/download/components_unittests.filter b/components/download/components_unittests.filter
index dd85efe6..7c53bdc 100644
--- a/components/download/components_unittests.filter
+++ b/components/download/components_unittests.filter
@@ -1,8 +1,10 @@
+BatteryListenerTest.*
 DownloadDriverImplTest.*
 DownloadServiceClientSetTest.*
 DownloadServiceControllerImplTest.*
 DownloadServiceImplTest.*
 DownloadServiceEntryUtilsTest.*
 DownloadServiceModelImplTest.*
-BatteryListenerTest.*
-NetworkListenerTest.*
\ No newline at end of file
+DownloadStoreTest.*
+NetworkListenerTest.*
+ProtoConversionsTest.*
\ No newline at end of file
diff --git a/components/download/content/factory/download_service_factory.cc b/components/download/content/factory/download_service_factory.cc
index c768b245..bb2d7b97 100644
--- a/components/download/content/factory/download_service_factory.cc
+++ b/components/download/content/factory/download_service_factory.cc
@@ -25,7 +25,8 @@
     std::unique_ptr<DownloadClientMap> clients,
     content::DownloadManager* download_manager,
     const base::FilePath& storage_dir,
-    const scoped_refptr<base::SequencedTaskRunner>& background_task_runner) {
+    const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
+    std::unique_ptr<TaskScheduler> task_scheduler) {
   auto client_set = base::MakeUnique<ClientSet>(std::move(clients));
   auto config = Configuration::CreateFromFinch();
 
@@ -44,7 +45,8 @@
 
   auto controller = base::MakeUnique<ControllerImpl>(
       std::move(client_set), std::move(config), std::move(driver),
-      std::move(model), std::move(device_status_listener));
+      std::move(model), std::move(device_status_listener),
+      std::move(task_scheduler));
   return new DownloadServiceImpl(std::move(controller));
 }
 
diff --git a/components/download/content/factory/download_service_factory.h b/components/download/content/factory/download_service_factory.h
index 8f5120b..8df6dfe7 100644
--- a/components/download/content/factory/download_service_factory.h
+++ b/components/download/content/factory/download_service_factory.h
@@ -19,6 +19,7 @@
 namespace download {
 
 class DownloadService;
+class TaskScheduler;
 
 // |clients| is a map of DownloadClient -> std::unique_ptr<Client>.  This
 // represents all of the clients that are allowed to have requests made on
@@ -34,7 +35,8 @@
     std::unique_ptr<DownloadClientMap> clients,
     content::DownloadManager* download_manager,
     const base::FilePath& storage_dir,
-    const scoped_refptr<base::SequencedTaskRunner>& background_task_runner);
+    const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
+    std::unique_ptr<TaskScheduler> task_scheduler);
 
 }  // namespace download
 
diff --git a/components/download/internal/controller.h b/components/download/internal/controller.h
index 0ea3f736..26011a0b 100644
--- a/components/download/internal/controller.h
+++ b/components/download/internal/controller.h
@@ -9,6 +9,8 @@
 
 #include "base/macros.h"
 #include "components/download/public/clients.h"
+#include "components/download/public/download_service.h"
+#include "components/download/public/download_task_types.h"
 
 namespace download {
 
@@ -54,6 +56,13 @@
   // Otherwise returns DownloadClient::INVALID for an unowned entry.
   virtual DownloadClient GetOwnerOfDownload(const std::string& guid) = 0;
 
+  // See DownloadService::OnStartScheduledTask.
+  virtual void OnStartScheduledTask(DownloadTaskType task_type,
+                                    const TaskFinishedCallback& callback) = 0;
+
+  // See DownloadService::OnStopScheduledTask.
+  virtual bool OnStopScheduledTask(DownloadTaskType task_type) = 0;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(Controller);
 };
diff --git a/components/download/internal/controller_impl.cc b/components/download/internal/controller_impl.cc
index 38f73731..c5e6782 100644
--- a/components/download/internal/controller_impl.cc
+++ b/components/download/internal/controller_impl.cc
@@ -8,13 +8,13 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/callback_helpers.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/download/internal/client_set.h"
 #include "components/download/internal/config.h"
 #include "components/download/internal/entry.h"
 #include "components/download/internal/entry_utils.h"
 #include "components/download/internal/model.h"
-#include "components/download/internal/stats.h"
 
 namespace download {
 
@@ -23,12 +23,14 @@
     std::unique_ptr<Configuration> config,
     std::unique_ptr<DownloadDriver> driver,
     std::unique_ptr<Model> model,
-    std::unique_ptr<DeviceStatusListener> device_status_listener)
+    std::unique_ptr<DeviceStatusListener> device_status_listener,
+    std::unique_ptr<TaskScheduler> task_scheduler)
     : clients_(std::move(clients)),
       config_(std::move(config)),
       driver_(std::move(driver)),
       model_(std::move(model)),
-      device_status_listener_(std::move(device_status_listener)) {}
+      device_status_listener_(std::move(device_status_listener)),
+      task_scheduler_(std::move(task_scheduler)) {}
 
 ControllerImpl::~ControllerImpl() {
   device_status_listener_->Stop();
@@ -135,6 +137,57 @@
   return entry ? entry->client : DownloadClient::INVALID;
 }
 
+void ControllerImpl::OnStartScheduledTask(
+    DownloadTaskType task_type,
+    const TaskFinishedCallback& callback) {
+  task_finished_callbacks_[task_type] = callback;
+  if (!startup_status_.Complete()) {
+    return;
+  } else if (!startup_status_.Ok()) {
+    HandleTaskFinished(task_type, false,
+                       stats::ScheduledTaskStatus::ABORTED_ON_FAILED_INIT);
+    return;
+  }
+
+  ProcessScheduledTasks();
+}
+
+bool ControllerImpl::OnStopScheduledTask(DownloadTaskType task_type) {
+  HandleTaskFinished(task_type, false,
+                     stats::ScheduledTaskStatus::CANCELLED_ON_STOP);
+  return true;
+}
+
+void ControllerImpl::ProcessScheduledTasks() {
+  if (!startup_status_.Ok()) {
+    while (!task_finished_callbacks_.empty()) {
+      auto it = task_finished_callbacks_.begin();
+      HandleTaskFinished(it->first, false,
+                         stats::ScheduledTaskStatus::ABORTED_ON_FAILED_INIT);
+    }
+    return;
+  }
+
+  while (!task_finished_callbacks_.empty()) {
+    auto it = task_finished_callbacks_.begin();
+    // TODO(shaktisahu): Execute the scheduled task.
+
+    HandleTaskFinished(it->first, false,
+                       stats::ScheduledTaskStatus::COMPLETED_NORMALLY);
+  }
+}
+
+void ControllerImpl::HandleTaskFinished(DownloadTaskType task_type,
+                                        bool needs_reschedule,
+                                        stats::ScheduledTaskStatus status) {
+  if (status != stats::ScheduledTaskStatus::CANCELLED_ON_STOP) {
+    base::ResetAndReturn(&task_finished_callbacks_[task_type])
+        .Run(needs_reschedule);
+  }
+  stats::LogScheduledTaskStatus(task_type, status);
+  task_finished_callbacks_.erase(task_type);
+}
+
 void ControllerImpl::OnDriverReady(bool success) {
   DCHECK(!startup_status_.driver_ok.has_value());
   startup_status_.driver_ok = success;
@@ -205,6 +258,7 @@
   if (!startup_status_.Ok()) {
     // TODO(dtrainor): Recover here.  Try to clean up any disk state and, if
     // possible, any DownloadDriver data and continue with initialization?
+    ProcessScheduledTasks();
     return;
   }
 
@@ -216,6 +270,7 @@
   // TODO(dtrainor): Post this so that the initialization step is finalized
   // before Clients can take action.
   NotifyClientsOfStartup();
+  ProcessScheduledTasks();
 }
 
 void ControllerImpl::CancelOrphanedRequests() {
diff --git a/components/download/internal/controller_impl.h b/components/download/internal/controller_impl.h
index 3a1e2db..3e7a852 100644
--- a/components/download/internal/controller_impl.h
+++ b/components/download/internal/controller_impl.h
@@ -15,7 +15,9 @@
 #include "components/download/internal/model.h"
 #include "components/download/internal/scheduler/device_status_listener.h"
 #include "components/download/internal/startup_status.h"
+#include "components/download/internal/stats.h"
 #include "components/download/public/download_params.h"
+#include "components/download/public/task_scheduler.h"
 
 namespace download {
 
@@ -38,7 +40,8 @@
                  std::unique_ptr<Configuration> config,
                  std::unique_ptr<DownloadDriver> driver,
                  std::unique_ptr<Model> model,
-                 std::unique_ptr<DeviceStatusListener> device_status_listener);
+                 std::unique_ptr<DeviceStatusListener> device_status_listener,
+                 std::unique_ptr<TaskScheduler> task_scheduler);
   ~ControllerImpl() override;
 
   // Controller implementation.
@@ -51,6 +54,9 @@
   void ChangeDownloadCriteria(const std::string& guid,
                               const SchedulingParams& params) override;
   DownloadClient GetOwnerOfDownload(const std::string& guid) override;
+  void OnStartScheduledTask(DownloadTaskType task_type,
+                            const TaskFinishedCallback& callback) override;
+  bool OnStopScheduledTask(DownloadTaskType task_type) override;
 
  private:
   // DownloadDriver::Client implementation.
@@ -106,6 +112,14 @@
       DownloadParams::StartResult result,
       const DownloadParams::StartCallback& callback);
 
+  // Entry point for a scheduled task after the task is fired.
+  void ProcessScheduledTasks();
+
+  // Handles and clears any pending task finished callbacks.
+  void HandleTaskFinished(DownloadTaskType task_type,
+                          bool needs_reschedule,
+                          stats::ScheduledTaskStatus status);
+
   std::unique_ptr<ClientSet> clients_;
   std::unique_ptr<Configuration> config_;
 
@@ -113,10 +127,12 @@
   std::unique_ptr<DownloadDriver> driver_;
   std::unique_ptr<Model> model_;
   std::unique_ptr<DeviceStatusListener> device_status_listener_;
+  std::unique_ptr<TaskScheduler> task_scheduler_;
 
   // Internal state.
   StartupStatus startup_status_;
   std::map<std::string, DownloadParams::StartCallback> start_callbacks_;
+  std::map<DownloadTaskType, TaskFinishedCallback> task_finished_callbacks_;
 
   DISALLOW_COPY_AND_ASSIGN(ControllerImpl);
 };
diff --git a/components/download/internal/controller_impl_unittest.cc b/components/download/internal/controller_impl_unittest.cc
index f47aa27..6cecf73 100644
--- a/components/download/internal/controller_impl_unittest.cc
+++ b/components/download/internal/controller_impl_unittest.cc
@@ -31,6 +31,16 @@
 
 namespace {
 
+class MockTaskScheduler : public TaskScheduler {
+ public:
+  MockTaskScheduler() = default;
+  ~MockTaskScheduler() = default;
+
+  // TaskScheduler implementation.
+  MOCK_METHOD5(ScheduleTask, void(DownloadTaskType, bool, bool, long, long));
+  MOCK_METHOD1(CancelTask, void(DownloadTaskType));
+};
+
 class DownloadServiceControllerImplTest : public testing::Test {
  public:
   DownloadServiceControllerImplTest()
@@ -43,6 +53,7 @@
         base::Bind(&DownloadServiceControllerImplTest::StartCallback,
                    base::Unretained(this));
   }
+
   ~DownloadServiceControllerImplTest() override = default;
 
   void SetUp() override {
@@ -61,10 +72,12 @@
     auto client_set = base::MakeUnique<ClientSet>(std::move(clients));
     auto model = base::MakeUnique<ModelImpl>(std::move(store));
     auto device_status_listener = base::MakeUnique<TestDeviceStatusListener>();
+    auto task_scheduler = base::MakeUnique<MockTaskScheduler>();
 
     controller_ = base::MakeUnique<ControllerImpl>(
         std::move(client_set), std::move(config), std::move(driver),
-        std::move(model), std::move(device_status_listener));
+        std::move(model), std::move(device_status_listener),
+        std::move(task_scheduler));
   }
 
  protected:
diff --git a/components/download/internal/download_service_impl.cc b/components/download/internal/download_service_impl.cc
index 27519ebc..c88c550 100644
--- a/components/download/internal/download_service_impl.cc
+++ b/components/download/internal/download_service_impl.cc
@@ -17,6 +17,16 @@
 
 DownloadServiceImpl::~DownloadServiceImpl() = default;
 
+void DownloadServiceImpl::OnStartScheduledTask(
+    DownloadTaskType task_type,
+    const TaskFinishedCallback& callback) {
+  controller_->OnStartScheduledTask(task_type, callback);
+}
+
+bool DownloadServiceImpl::OnStopScheduledTask(DownloadTaskType task_type) {
+  return controller_->OnStopScheduledTask(task_type);
+}
+
 DownloadService::ServiceStatus DownloadServiceImpl::GetStatus() {
   if (!controller_->GetStartupStatus()->Complete())
     return DownloadService::ServiceStatus::STARTING_UP;
diff --git a/components/download/internal/download_service_impl.h b/components/download/internal/download_service_impl.h
index e9f8e89..ab755c37 100644
--- a/components/download/internal/download_service_impl.h
+++ b/components/download/internal/download_service_impl.h
@@ -25,6 +25,9 @@
   ~DownloadServiceImpl() override;
 
   // DownloadService implementation.
+  void OnStartScheduledTask(DownloadTaskType task_type,
+                            const TaskFinishedCallback& callback) override;
+  bool OnStopScheduledTask(DownloadTaskType task_type) override;
   ServiceStatus GetStatus() override;
   void StartDownload(const DownloadParams& download_params) override;
   void PauseDownload(const std::string& guid) override;
diff --git a/components/download/internal/stats.cc b/components/download/internal/stats.cc
index ac019b7..762204d 100644
--- a/components/download/internal/stats.cc
+++ b/components/download/internal/stats.cc
@@ -29,5 +29,10 @@
   // TODO(dtrainor): Log |action|.
 }
 
+void LogScheduledTaskStatus(DownloadTaskType task_type,
+                            ScheduledTaskStatus status) {
+  // TODO(shaktisahu): Log |task_type| and |status|.
+}
+
 }  // namespace stats
 }  // namespace download
diff --git a/components/download/internal/stats.h b/components/download/internal/stats.h
index 5142760..4ccae0c 100644
--- a/components/download/internal/stats.h
+++ b/components/download/internal/stats.h
@@ -7,6 +7,7 @@
 
 #include "components/download/public/clients.h"
 #include "components/download/public/download_params.h"
+#include "components/download/public/download_task_types.h"
 
 namespace download {
 
@@ -60,6 +61,18 @@
   COUNT = 4,
 };
 
+// Enum used by UMA metrics to log the status of scheduled tasks.
+enum class ScheduledTaskStatus {
+  // Startup failed and the task was not run.
+  ABORTED_ON_FAILED_INIT = 0,
+
+  // OnStopScheduledTask() was received before the task could be fired.
+  CANCELLED_ON_STOP = 1,
+
+  // Callback was run successfully after completion of the task.
+  COMPLETED_NORMALLY = 2,
+};
+
 // Logs the results of starting up the Controller.  Will log each failure reason
 // if |status| contains more than one initialization failure.
 void LogControllerStartupStatus(const StartupStatus& status);
@@ -75,6 +88,10 @@
 // cases.
 void LogModelOperationResult(ModelAction action, bool success);
 
+// Log statistics about the status of a TaskFinishedCallback.
+void LogScheduledTaskStatus(DownloadTaskType task_type,
+                            ScheduledTaskStatus status);
+
 }  // namespace stats
 }  // namespace download
 
diff --git a/components/download/internal/test/mock_controller.h b/components/download/internal/test/mock_controller.h
index d4ac200..5c5ff76 100644
--- a/components/download/internal/test/mock_controller.h
+++ b/components/download/internal/test/mock_controller.h
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_TEST_MOCK_CONTROLLER_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_TEST_MOCK_CONTROLLER_H_
+
 #include "base/macros.h"
 #include "components/download/internal/controller.h"
 #include "components/download/internal/startup_status.h"
@@ -26,6 +29,9 @@
   MOCK_METHOD2(ChangeDownloadCriteria,
                void(const std::string&, const SchedulingParams&));
   MOCK_METHOD1(GetOwnerOfDownload, DownloadClient(const std::string&));
+  MOCK_METHOD2(OnStartScheduledTask,
+               void(DownloadTaskType, const TaskFinishedCallback&));
+  MOCK_METHOD1(OnStopScheduledTask, bool(DownloadTaskType task_type));
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockController);
@@ -33,3 +39,5 @@
 
 }  // namespace test
 }  // namespace download
+
+#endif  // COMPONENTS_DOWNLOAD_INTERNAL_TEST_MOCK_CONTROLLER_H_
diff --git a/components/download/public/BUILD.gn b/components/download/public/BUILD.gn
index 5f013fd..016afe2 100644
--- a/components/download/public/BUILD.gn
+++ b/components/download/public/BUILD.gn
@@ -14,8 +14,10 @@
     "download_params.cc",
     "download_params.h",
     "download_service.h",
+    "download_task_types.h",
     "features.cc",
     "features.h",
+    "task_scheduler.h",
   ]
 
   deps = [
@@ -28,3 +30,22 @@
     "//url",
   ]
 }
+
+if (is_android) {
+  android_library("public_java") {
+    srcjar_deps = [ ":jni_enums" ]
+
+    deps = [
+      "//base:base_java",
+      "//third_party/android_tools:android_support_annotations_java",
+    ]
+  }
+
+  java_cpp_enum("jni_enums") {
+    visibility = [ "*" ]
+
+    sources = [
+      "download_task_types.h",
+    ]
+  }
+}
diff --git a/components/download/public/download_service.h b/components/download/public/download_service.h
index 37165c2..38c01a95 100644
--- a/components/download/public/download_service.h
+++ b/components/download/public/download_service.h
@@ -14,6 +14,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/sequenced_task_runner.h"
 #include "components/download/public/clients.h"
+#include "components/download/public/download_task_types.h"
 #include "components/keyed_service/core/keyed_service.h"
 
 namespace download {
@@ -22,6 +23,8 @@
 struct DownloadParams;
 struct SchedulingParams;
 
+using TaskFinishedCallback = base::Callback<void(bool)>;
+
 // A service responsible for helping facilitate the scheduling and downloading
 // of file content from the web.  See |DownloadParams| for more details on the
 // types of scheduling that can be achieved and the required input parameters
@@ -48,6 +51,20 @@
     UNAVAILABLE = 2,
   };
 
+  // Callback method to run by the service when a pre-scheduled task starts.
+  // This method is invoked on main thread and while it is running, the system
+  // holds a wakelock which is not released until either the |callback| is run
+  // or OnStopScheduledTask is invoked by the system. Do not call this method
+  // directly.
+  virtual void OnStartScheduledTask(DownloadTaskType task_type,
+                                    const TaskFinishedCallback& callback) = 0;
+
+  // Callback method to run by the service if the system decides to stop the
+  // task. Returns true if the task needs to be rescheduled. Any pending
+  // TaskFinishedCallback should be reset after this call. Do not call this
+  // method directly.
+  virtual bool OnStopScheduledTask(DownloadTaskType task_type) = 0;
+
   // Whether or not the DownloadService is currently available, initialized
   // successfully, and ready to be used.
   virtual ServiceStatus GetStatus() = 0;
diff --git a/components/download/public/download_task_types.h b/components/download/public/download_task_types.h
new file mode 100644
index 0000000..a26bc013
--- /dev/null
+++ b/components/download/public/download_task_types.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 COMPONENTS_DOWNLOAD_PUBLIC_DOWNLOAD_TASK_TYPES_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_DOWNLOAD_TASK_TYPES_H_
+
+namespace download {
+
+// A Java counterpart will be generated for this enum.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.download
+enum class DownloadTaskType {
+  // Task to invoke download service to take various download actions.
+  DOWNLOAD_TASK = 0,
+
+  // Task to remove unnecessary files from the system.
+  CLEANUP_TASK = 1,
+};
+
+}  // namespace download
+
+#endif  // COMPONENTS_DOWNLOAD_PUBLIC_DOWNLOAD_TASK_TYPES_H_
diff --git a/components/download/public/task_scheduler.h b/components/download/public/task_scheduler.h
new file mode 100644
index 0000000..0d5df15
--- /dev/null
+++ b/components/download/public/task_scheduler.h
@@ -0,0 +1,34 @@
+// 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 COMPONENTS_DOWNLOAD_PUBLIC_TASK_SCHEDULER_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_TASK_SCHEDULER_H_
+
+#include "components/download/public/download_task_types.h"
+
+namespace download {
+
+// A helper class backed by system APIs to schedule jobs in the background. The
+// tasks can run independently of each other as long as they have different
+// |task_type|. Scheduling another task of same |task_type| before the task is
+// fired will cancel the previous task.
+class TaskScheduler {
+ public:
+  // Schedules a task with the operating system. The system has the liberty of
+  // firing the task any time between |window_start_time_seconds| and
+  // |window_end_time_seconds|. If the trigger conditions are not met, the
+  // behavior is unknown.
+  virtual void ScheduleTask(DownloadTaskType task_type,
+                            bool require_unmetered_network,
+                            bool require_charging,
+                            long window_start_time_seconds,
+                            long window_end_time_seconds) = 0;
+
+  // Cancels a pre-scheduled task of type |task_type|.
+  virtual void CancelTask(DownloadTaskType task_type) = 0;
+};
+
+}  // namespace download
+
+#endif  // COMPONENTS_DOWNLOAD_PUBLIC_TASK_SCHEDULER_H_
diff --git a/components/payments/mojom/payment_app.mojom b/components/payments/mojom/payment_app.mojom
index f0bd4dd..6cb1980 100644
--- a/components/payments/mojom/payment_app.mojom
+++ b/components/payments/mojom/payment_app.mojom
@@ -14,14 +14,26 @@
   NOT_FOUND,
   NO_ACTIVE_WORKER,
   STORAGE_OPERATION_FAILED,
+  FETCH_INSTRUMENT_ICON_FAILED,
 };
 
+// This struct is provided to hold an image object from render side
+// (ImageObject.idl).
+struct ImageObject {
+  url.mojom.Url src;
+};
+
+// This struct is provided to hold a payment instrument from render
+// side (PaymentInstrument.idl).
 struct PaymentInstrument {
   string name;
+  array<ImageObject> icons;
   array<string> enabled_methods;
   string stringified_capabilities;
 };
 
+// This interface provides implementation of PaymentInstruments.idl
+// in render side.
 interface PaymentManager {
   Init(string service_worker_scope);
   DeletePaymentInstrument(string instrument_key)
@@ -38,6 +50,8 @@
       => (PaymentHandlerStatus status);
 };
 
+// This struct is provided to send payment request data to render side
+// (PaymentRequestEvent.idl).
 struct PaymentRequestEventData {
   url.mojom.Url top_level_origin;
   url.mojom.Url payment_request_origin;
@@ -48,6 +62,8 @@
   string instrument_key;
 };
 
+// This struct is provided to receive payment app response from render
+// side (PaymentAppResponse.idl).
 struct PaymentAppResponse {
   string method_name;
   string stringified_details;
diff --git a/components/safe_browsing/password_protection/password_protection_request.cc b/components/safe_browsing/password_protection/password_protection_request.cc
index f23e47e..909c848 100644
--- a/components/safe_browsing/password_protection/password_protection_request.cc
+++ b/components/safe_browsing/password_protection/password_protection_request.cc
@@ -36,14 +36,12 @@
       password_form_action_(password_form_action),
       password_form_frame_url_(password_form_frame_url),
       saved_domain_(saved_domain),
-      trigger_type_(type),
+      request_type_(type),
       password_field_exists_(password_field_exists),
       password_protection_service_(pps),
       request_timeout_in_ms_(request_timeout_in_ms),
       weakptr_factory_(this) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK(trigger_type_ == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE ||
-         trigger_type_ == LoginReputationClientRequest::PASSWORD_REUSE_EVENT);
 }
 
 PasswordProtectionRequest::~PasswordProtectionRequest() {
@@ -87,7 +85,7 @@
   std::unique_ptr<LoginReputationClientResponse> cached_response =
       base::MakeUnique<LoginReputationClientResponse>();
   auto verdict = password_protection_service_->GetCachedVerdict(
-      main_frame_url_, trigger_type_, cached_response.get());
+      main_frame_url_, cached_response.get());
   if (verdict != LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED)
     Finish(PasswordProtectionService::RESPONSE_ALREADY_CACHED,
            std::move(cached_response));
@@ -98,11 +96,11 @@
 void PasswordProtectionRequest::FillRequestProto() {
   request_proto_ = base::MakeUnique<LoginReputationClientRequest>();
   request_proto_->set_page_url(main_frame_url_.spec());
-  request_proto_->set_trigger_type(trigger_type_);
-  password_protection_service_->FillUserPopulation(trigger_type_,
+  request_proto_->set_trigger_type(request_type_);
+  password_protection_service_->FillUserPopulation(request_type_,
                                                    request_proto_.get());
   request_proto_->set_stored_verdict_cnt(
-      password_protection_service_->GetStoredVerdictCount(trigger_type_));
+      password_protection_service_->GetStoredVerdictCount());
   LoginReputationClientRequest::Frame* main_frame =
       request_proto_->add_frames();
   main_frame->set_url(main_frame_url_.spec());
@@ -110,7 +108,7 @@
   password_protection_service_->FillReferrerChain(
       main_frame_url_, -1 /* tab id not available */, main_frame);
 
-  switch (trigger_type_) {
+  switch (request_type_) {
     case LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE: {
       LoginReputationClientRequest::Frame::Form* password_form;
       if (password_form_frame_url_ == main_frame_url_) {
@@ -249,7 +247,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   tracker_.TryCancelAll();
 
-  if (trigger_type_ == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE) {
+  if (request_type_ == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE) {
     UMA_HISTOGRAM_ENUMERATION(kPasswordOnFocusRequestOutcomeHistogramName,
                               outcome, PasswordProtectionService::MAX_OUTCOME);
   } else {
@@ -258,7 +256,7 @@
   }
 
   if (outcome == PasswordProtectionService::SUCCEEDED && response) {
-    switch (trigger_type_) {
+    switch (request_type_) {
       case LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE:
         UMA_HISTOGRAM_ENUMERATION(
             "PasswordProtection.Verdict.PasswordFieldOnFocus",
diff --git a/components/safe_browsing/password_protection/password_protection_request.h b/components/safe_browsing/password_protection/password_protection_request.h
index 756a65d..721739b 100644
--- a/components/safe_browsing/password_protection/password_protection_request.h
+++ b/components/safe_browsing/password_protection/password_protection_request.h
@@ -74,8 +74,8 @@
 
   content::WebContents* web_contents() const { return web_contents_; }
 
-  LoginReputationClientRequest::TriggerType trigger_type() const {
-    return trigger_type_;
+  LoginReputationClientRequest::TriggerType request_type() const {
+    return request_type_;
   }
 
  private:
@@ -129,7 +129,7 @@
   const std::string saved_domain_;
 
   // If this request is for unfamiliar login page or for a password reuse event.
-  const LoginReputationClientRequest::TriggerType trigger_type_;
+  const LoginReputationClientRequest::TriggerType request_type_;
 
   // If there is a password field on the page.
   const bool password_field_exists_;
diff --git a/components/safe_browsing/password_protection/password_protection_service.cc b/components/safe_browsing/password_protection/password_protection_service.cc
index b24e456..c7ec2a9d 100644
--- a/components/safe_browsing/password_protection/password_protection_service.cc
+++ b/components/safe_browsing/password_protection/password_protection_service.cc
@@ -4,9 +4,6 @@
 
 #include "components/safe_browsing/password_protection/password_protection_service.h"
 
-#include <stddef.h>
-#include <string>
-
 #include "base/base64.h"
 #include "base/bind.h"
 #include "base/callback.h"
@@ -41,7 +38,6 @@
 const int kRequestTimeoutMs = 10000;
 const char kPasswordProtectionRequestUrl[] =
     "https://sb-ssl.google.com/safebrowsing/clientreport/login";
-const char kPasswordOnFocusCacheKey[] = "password_on_focus_cache_key";
 
 // Helper function to determine if the given origin matches content settings
 // map's patterns.
@@ -91,8 +87,7 @@
     scoped_refptr<net::URLRequestContextGetter> request_context_getter,
     HistoryService* history_service,
     HostContentSettingsMap* host_content_settings_map)
-    : stored_verdict_count_password_on_focus_(-1),
-      stored_verdict_count_password_entry_(-1),
+    : stored_verdict_count_(-1),
       database_manager_(database_manager),
       request_context_getter_(request_context_getter),
       history_service_observer_(this),
@@ -127,50 +122,24 @@
          hostname.find('.') != std::string::npos;
 }
 
-// We cache both types of pings under the same content settings type (
-// CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION). Since UNFAMILIAR_LOGING_PAGE
-// verdicts are only enabled on extended reporting users, we cache them one
-// layer lower in the content setting DictionaryValue than PASSWORD_REUSE_EVENT
-// verdicts.
-// In other words, to cache a UNFAMILIAR_LOGIN_PAGE verdict we needs two levels
-// of keys: (1) origin, (2) cache expression returned in verdict.
-// To cache a PASSWORD_REUSE_EVENT, three levels of keys are used:
-// (1) origin, (2) 2nd level key is always |kPasswordOnFocusCacheKey|,
-// (3) cache expression.
 LoginReputationClientResponse::VerdictType
 PasswordProtectionService::GetCachedVerdict(
     const GURL& url,
-    TriggerType trigger_type,
     LoginReputationClientResponse* out_response) {
-  DCHECK(trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE ||
-         trigger_type == LoginReputationClientRequest::PASSWORD_REUSE_EVENT);
-
   if (!url.is_valid())
     return LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED;
 
+  DCHECK(content_settings_);
+
   GURL hostname = GetHostNameWithHTTPScheme(url);
-  std::unique_ptr<base::DictionaryValue> cache_dictionary =
+  std::unique_ptr<base::DictionaryValue> verdict_dictionary =
       base::DictionaryValue::From(content_settings_->GetWebsiteSetting(
           hostname, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION,
           std::string(), nullptr));
-
-  if (!cache_dictionary.get() || cache_dictionary->empty())
+  // Return early if there is no verdict cached for this origin.
+  if (!verdict_dictionary.get() || verdict_dictionary->empty())
     return LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED;
 
-  base::DictionaryValue* verdict_dictionary = nullptr;
-  if (trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE) {
-    // All UNFAMILIAR_LOGIN_PAGE verdicts (a.k.a password on focus ping)
-    // are cached under |kPasswordOnFocusCacheKey|.
-    if (!cache_dictionary->HasKey(
-            base::StringPiece(kPasswordOnFocusCacheKey))) {
-      return LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED;
-    }
-    DCHECK(cache_dictionary->GetDictionaryWithoutPathExpansion(
-        base::StringPiece(kPasswordOnFocusCacheKey), &verdict_dictionary));
-  } else {
-    verdict_dictionary = cache_dictionary.get();
-  }
-
   std::vector<std::string> paths;
   GeneratePathVariantsWithoutQuery(url, &paths);
   int max_path_depth = -1;
@@ -179,12 +148,8 @@
   // For all the verdicts of the same origin, we key them by |cache_expression|.
   // Its corresponding value is a DictionaryValue contains its creation time and
   // the serialized verdict proto.
-  for (base::DictionaryValue::Iterator it(*verdict_dictionary); !it.IsAtEnd();
-       it.Advance()) {
-    if (trigger_type == LoginReputationClientRequest::PASSWORD_REUSE_EVENT &&
-        it.key() == base::StringPiece(kPasswordOnFocusCacheKey)) {
-      continue;
-    }
+  for (base::DictionaryValue::Iterator it(*verdict_dictionary.get());
+       !it.IsAtEnd(); it.Advance()) {
     base::DictionaryValue* verdict_entry = nullptr;
     CHECK(verdict_dictionary->GetDictionaryWithoutPathExpansion(
         it.key() /* cache_expression */, &verdict_entry));
@@ -215,66 +180,39 @@
 
 void PasswordProtectionService::CacheVerdict(
     const GURL& url,
-    TriggerType trigger_type,
     LoginReputationClientResponse* verdict,
     const base::Time& receive_time) {
   DCHECK(verdict);
   DCHECK(content_settings_);
-  DCHECK(trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE ||
-         trigger_type == LoginReputationClientRequest::PASSWORD_REUSE_EVENT);
 
   GURL hostname = GetHostNameWithHTTPScheme(url);
-  int* stored_verdict_count =
-      trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE
-          ? &stored_verdict_count_password_on_focus_
-          : &stored_verdict_count_password_entry_;
-  std::unique_ptr<base::DictionaryValue> cache_dictionary =
+  std::unique_ptr<base::DictionaryValue> verdict_dictionary =
       base::DictionaryValue::From(content_settings_->GetWebsiteSetting(
           hostname, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION,
           std::string(), nullptr));
 
-  if (!cache_dictionary.get())
-    cache_dictionary = base::MakeUnique<base::DictionaryValue>();
+  if (!verdict_dictionary.get())
+    verdict_dictionary = base::MakeUnique<base::DictionaryValue>();
 
   std::unique_ptr<base::DictionaryValue> verdict_entry =
       CreateDictionaryFromVerdict(verdict, receive_time);
 
-  base::DictionaryValue* verdict_dictionary = nullptr;
-  if (trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE) {
-    // All UNFAMILIAR_LOGIN_PAGE verdicts (a.k.a password on focus ping)
-    // are cached under |kPasswordOnFocusCacheKey|.
-    if (!cache_dictionary->HasKey(
-            base::StringPiece(kPasswordOnFocusCacheKey))) {
-      cache_dictionary->SetDictionaryWithoutPathExpansion(
-          base::StringPiece(kPasswordOnFocusCacheKey),
-          base::MakeUnique<base::DictionaryValue>());
-    }
-    DCHECK(cache_dictionary->GetDictionaryWithoutPathExpansion(
-        base::StringPiece(kPasswordOnFocusCacheKey), &verdict_dictionary));
-  } else {
-    verdict_dictionary = cache_dictionary.get();
-  }
-
   // Increases stored verdict count if we haven't seen this cache expression
   // before.
   if (!verdict_dictionary->HasKey(verdict->cache_expression()))
-    *stored_verdict_count = GetStoredVerdictCount(trigger_type) + 1;
+    stored_verdict_count_ = GetStoredVerdictCount() + 1;
   // If same cache_expression is already in this verdict_dictionary, we simply
   // override it.
   verdict_dictionary->SetWithoutPathExpansion(verdict->cache_expression(),
                                               std::move(verdict_entry));
   content_settings_->SetWebsiteSettingDefaultScope(
       hostname, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION,
-      std::string(), std::move(cache_dictionary));
+      std::string(), std::move(verdict_dictionary));
 }
 
 void PasswordProtectionService::CleanUpExpiredVerdicts() {
   DCHECK(content_settings_);
-
-  if (GetStoredVerdictCount(
-          LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE) <= 0 &&
-      GetStoredVerdictCount(
-          LoginReputationClientRequest::PASSWORD_REUSE_EVENT) <= 0)
+  if (GetStoredVerdictCount() <= 0)
     return;
 
   ContentSettingsForOneType password_protection_settings;
@@ -286,29 +224,44 @@
        password_protection_settings) {
     GURL primary_pattern_url = GURL(source.primary_pattern.ToString());
     // Find all verdicts associated with this origin.
-    std::unique_ptr<base::DictionaryValue> cache_dictionary =
+    std::unique_ptr<base::DictionaryValue> verdict_dictionary =
         base::DictionaryValue::From(content_settings_->GetWebsiteSetting(
             primary_pattern_url, GURL(),
             CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, std::string(), nullptr));
-    bool has_expired_password_on_focus_entry = RemoveExpiredVerdicts(
-        LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
-        cache_dictionary.get());
-    bool has_expired_password_reuse_entry = RemoveExpiredVerdicts(
-        LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
-        cache_dictionary.get());
+    std::vector<std::string> expired_keys;
+    for (base::DictionaryValue::Iterator it(*verdict_dictionary.get());
+         !it.IsAtEnd(); it.Advance()) {
+      base::DictionaryValue* verdict_entry = nullptr;
+      CHECK(verdict_dictionary->GetDictionaryWithoutPathExpansion(
+          it.key(), &verdict_entry));
+      int verdict_received_time;
+      LoginReputationClientResponse verdict;
+      CHECK(ParseVerdictEntry(verdict_entry, &verdict_received_time, &verdict));
 
-    if (cache_dictionary->size() == 0u) {
+      if (IsCacheExpired(verdict_received_time, verdict.cache_duration_sec())) {
+        // Since DictionaryValue::Iterator cannot be used to modify the
+        // dictionary, we record the keys of expired verdicts in |expired_keys|
+        // and remove them in the next for-loop.
+        expired_keys.push_back(it.key());
+      }
+    }
+
+    for (const std::string& key : expired_keys) {
+      verdict_dictionary->RemoveWithoutPathExpansion(key, nullptr);
+      stored_verdict_count_--;
+    }
+
+    if (verdict_dictionary->size() == 0u) {
       content_settings_->ClearSettingsForOneTypeWithPredicate(
           CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, base::Time(),
           base::Bind(&OriginMatchPrimaryPattern, primary_pattern_url));
-    } else if (has_expired_password_on_focus_entry ||
-               has_expired_password_reuse_entry) {
+    } else if (expired_keys.size() > 0u) {
       // Set the website setting of this origin with the updated
       // |verdict_diectionary|.
       content_settings_->SetWebsiteSettingDefaultScope(
           primary_pattern_url, GURL(),
           CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, std::string(),
-          std::move(cache_dictionary));
+          std::move(verdict_dictionary));
     }
   }
 }
@@ -319,15 +272,14 @@
     const GURL& password_form_action,
     const GURL& password_form_frame_url,
     const std::string& saved_domain,
-    TriggerType trigger_type,
+    LoginReputationClientRequest::TriggerType type,
     bool password_field_exists) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   scoped_refptr<PasswordProtectionRequest> request(
       new PasswordProtectionRequest(
           web_contents, main_frame_url, password_form_action,
-          password_form_frame_url, saved_domain, trigger_type,
-          password_field_exists, this, GetRequestTimeoutInMS()));
-
+          password_form_frame_url, saved_domain, type, password_field_exists,
+          this, GetRequestTimeoutInMS()));
   DCHECK(request);
   request->Start();
   requests_.insert(std::move(request));
@@ -380,11 +332,11 @@
 
   if (response) {
     if (!already_cached) {
-      CacheVerdict(request->main_frame_url(), request->trigger_type(),
-                   response.get(), base::Time::Now());
+      CacheVerdict(request->main_frame_url(), response.get(),
+                   base::Time::Now());
     }
 
-    if (request->trigger_type() ==
+    if (request->request_type() ==
             LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE &&
         response->verdict_type() == LoginReputationClientResponse::PHISHING &&
         base::FeatureList::IsEnabled(kPasswordProtectionInterstitial)) {
@@ -427,51 +379,30 @@
   return url.Resolve("?key=" + net::EscapeQueryParamValue(api_key, true));
 }
 
-int PasswordProtectionService::GetStoredVerdictCount(TriggerType trigger_type) {
+int PasswordProtectionService::GetStoredVerdictCount() {
   DCHECK(content_settings_);
-  DCHECK(trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE ||
-         trigger_type == LoginReputationClientRequest::PASSWORD_REUSE_EVENT);
-  int* stored_verdict_count =
-      trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE
-          ? &stored_verdict_count_password_on_focus_
-          : &stored_verdict_count_password_entry_;
   // If we have already computed this, return its value.
-  if (*stored_verdict_count >= 0)
-    return *stored_verdict_count;
+  if (stored_verdict_count_ >= 0)
+    return stored_verdict_count_;
 
   ContentSettingsForOneType password_protection_settings;
   content_settings_->GetSettingsForOneType(
       CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, std::string(),
       &password_protection_settings);
-  stored_verdict_count_password_on_focus_ = 0;
-  stored_verdict_count_password_entry_ = 0;
+  stored_verdict_count_ = 0;
   if (password_protection_settings.empty())
     return 0;
 
   for (const ContentSettingPatternSource& source :
        password_protection_settings) {
-    std::unique_ptr<base::DictionaryValue> cache_dictionary =
+    std::unique_ptr<base::DictionaryValue> verdict_dictionary =
         base::DictionaryValue::From(content_settings_->GetWebsiteSetting(
             GURL(source.primary_pattern.ToString()), GURL(),
             CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, std::string(), nullptr));
-    if (cache_dictionary.get() && !cache_dictionary->empty()) {
-      stored_verdict_count_password_entry_ +=
-          static_cast<int>(cache_dictionary->size());
-      if (cache_dictionary->HasKey(
-              base::StringPiece(kPasswordOnFocusCacheKey))) {
-        // Substracts 1 from password_entry count if |kPasswordOnFocusCacheKey|
-        // presents.
-        stored_verdict_count_password_entry_ -= 1;
-        base::DictionaryValue* password_on_focus_dict = nullptr;
-        cache_dictionary->GetDictionaryWithoutPathExpansion(
-            base::StringPiece(kPasswordOnFocusCacheKey),
-            &password_on_focus_dict);
-        stored_verdict_count_password_on_focus_ +=
-            static_cast<int>(password_on_focus_dict->size());
-      }
-    }
+    if (verdict_dictionary.get() && !verdict_dictionary->empty())
+      stored_verdict_count_ += static_cast<int>(verdict_dictionary->size());
   }
-  return *stored_verdict_count;
+  return stored_verdict_count_;
 }
 
 int PasswordProtectionService::GetRequestTimeoutInMS() {
@@ -479,7 +410,7 @@
 }
 
 void PasswordProtectionService::FillUserPopulation(
-    TriggerType trigger_type,
+    const LoginReputationClientRequest::TriggerType& request_type,
     LoginReputationClientRequest* request_proto) {
   ChromeUserPopulation* user_population = request_proto->mutable_population();
   user_population->set_user_population(
@@ -509,10 +440,8 @@
     bool expired,
     const history::URLRows& deleted_rows,
     const std::set<GURL>& favicon_urls) {
-  if (stored_verdict_count_password_on_focus_ <= 0 &&
-      stored_verdict_count_password_entry_ <= 0) {
+  if (stored_verdict_count_ <= 0)
     return;
-  }
 
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
@@ -534,8 +463,7 @@
   if (all_history) {
     content_settings_->ClearSettingsForOneType(
         CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION);
-    stored_verdict_count_password_on_focus_ = 0;
-    stored_verdict_count_password_entry_ = 0;
+    stored_verdict_count_ = 0;
     return;
   }
 
@@ -546,104 +474,24 @@
   for (const history::URLRow& row : deleted_rows) {
     if (!row.url().SchemeIsHTTPOrHTTPS())
       continue;
-
     GURL url_key = GetHostNameWithHTTPScheme(row.url());
-    stored_verdict_count_password_on_focus_ =
-        GetStoredVerdictCount(
-            LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE) -
-        GetVerdictCountForURL(
-            url_key, LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE);
-    stored_verdict_count_password_entry_ =
-        GetStoredVerdictCount(
-            LoginReputationClientRequest::PASSWORD_REUSE_EVENT) -
-        GetVerdictCountForURL(
-            url_key, LoginReputationClientRequest::PASSWORD_REUSE_EVENT);
+    std::unique_ptr<base::DictionaryValue> verdict_dictionary =
+        base::DictionaryValue::From(content_settings_->GetWebsiteSetting(
+            url_key, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION,
+            std::string(), nullptr));
+
+    // Move on if we have no cached verdict for this deleted history row.
+    if (!verdict_dictionary.get() || verdict_dictionary->empty())
+      continue;
+
+    int verdict_count = static_cast<int>(verdict_dictionary->size());
+    stored_verdict_count_ = GetStoredVerdictCount() - verdict_count;
     content_settings_->ClearSettingsForOneTypeWithPredicate(
         CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, base::Time(),
         base::Bind(&OriginMatchPrimaryPattern, url_key));
   }
 }
 
-int PasswordProtectionService::GetVerdictCountForURL(const GURL& url,
-                                                     TriggerType trigger_type) {
-  DCHECK(trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE ||
-         trigger_type == LoginReputationClientRequest::PASSWORD_REUSE_EVENT);
-  std::unique_ptr<base::DictionaryValue> cache_dictionary =
-      base::DictionaryValue::From(content_settings_->GetWebsiteSetting(
-          url, GURL(), CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION, std::string(),
-          nullptr));
-  if (!cache_dictionary.get() || cache_dictionary->empty())
-    return 0;
-
-  if (trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE) {
-    base::DictionaryValue* password_on_focus_dict = nullptr;
-    cache_dictionary->GetDictionaryWithoutPathExpansion(
-        base::StringPiece(kPasswordOnFocusCacheKey), &password_on_focus_dict);
-    return password_on_focus_dict ? password_on_focus_dict->size() : 0;
-  } else {
-    return cache_dictionary->HasKey(base::StringPiece(kPasswordOnFocusCacheKey))
-               ? cache_dictionary->size() - 1
-               : cache_dictionary->size();
-  }
-}
-
-bool PasswordProtectionService::RemoveExpiredVerdicts(
-    TriggerType trigger_type,
-    base::DictionaryValue* cache_dictionary) {
-  DCHECK(trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE ||
-         trigger_type == LoginReputationClientRequest::PASSWORD_REUSE_EVENT);
-  base::DictionaryValue* verdict_dictionary = nullptr;
-  if (trigger_type == LoginReputationClientRequest::PASSWORD_REUSE_EVENT) {
-    verdict_dictionary = cache_dictionary;
-  } else {
-    if (!cache_dictionary->GetDictionaryWithoutPathExpansion(
-            base::StringPiece(kPasswordOnFocusCacheKey), &verdict_dictionary)) {
-      return false;
-    }
-  }
-
-  if (!verdict_dictionary || verdict_dictionary->empty())
-    return false;
-
-  std::vector<std::string> expired_keys;
-  for (base::DictionaryValue::Iterator it(*verdict_dictionary); !it.IsAtEnd();
-       it.Advance()) {
-    if (trigger_type == LoginReputationClientRequest::PASSWORD_REUSE_EVENT &&
-        it.key() == std::string(kPasswordOnFocusCacheKey))
-      continue;
-
-    base::DictionaryValue* verdict_entry = nullptr;
-    CHECK(verdict_dictionary->GetDictionaryWithoutPathExpansion(
-        it.key(), &verdict_entry));
-    int verdict_received_time;
-    LoginReputationClientResponse verdict;
-    CHECK(ParseVerdictEntry(verdict_entry, &verdict_received_time, &verdict));
-
-    if (IsCacheExpired(verdict_received_time, verdict.cache_duration_sec())) {
-      // Since DictionaryValue::Iterator cannot be used to modify the
-      // dictionary, we record the keys of expired verdicts in |expired_keys|
-      // and remove them in the next for-loop.
-      expired_keys.push_back(it.key());
-    }
-  }
-
-  for (const std::string& key : expired_keys) {
-    verdict_dictionary->RemoveWithoutPathExpansion(key, nullptr);
-    if (trigger_type == LoginReputationClientRequest::PASSWORD_REUSE_EVENT)
-      stored_verdict_count_password_entry_--;
-    else
-      stored_verdict_count_password_on_focus_--;
-  }
-
-  if (trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE &&
-      verdict_dictionary->size() == 0U) {
-    cache_dictionary->RemoveWithoutPathExpansion(
-        base::StringPiece(kPasswordOnFocusCacheKey), nullptr);
-  }
-
-  return expired_keys.size() > 0U;
-}
-
 // static
 bool PasswordProtectionService::ParseVerdictEntry(
     base::DictionaryValue* verdict_entry,
diff --git a/components/safe_browsing/password_protection/password_protection_service.h b/components/safe_browsing/password_protection/password_protection_service.h
index 10036f4..89870aa 100644
--- a/components/safe_browsing/password_protection/password_protection_service.h
+++ b/components/safe_browsing/password_protection/password_protection_service.h
@@ -49,7 +49,6 @@
 // HostContentSettingsMap instance.
 class PasswordProtectionService : public history::HistoryServiceObserver {
  public:
-  using TriggerType = LoginReputationClientRequest::TriggerType;
   // The outcome of the request. These values are used for UMA.
   // DO NOT CHANGE THE ORDERING OF THESE VALUES.
   enum RequestOutcome {
@@ -88,13 +87,11 @@
   // any thread.
   LoginReputationClientResponse::VerdictType GetCachedVerdict(
       const GURL& url,
-      TriggerType trigger_type,
       LoginReputationClientResponse* out_response);
 
-  // Stores |verdict| in |settings| based on its |trigger_type|, |url|,
-  // |verdict| and |receive_time|.
+  // Stores |verdict| in |settings| based on |url|, |verdict| and
+  // |receive_time|.
   virtual void CacheVerdict(const GURL& url,
-                            TriggerType trigger_type,
                             LoginReputationClientResponse* verdict,
                             const base::Time& receive_time);
 
@@ -109,7 +106,7 @@
                     const GURL& password_form_action,
                     const GURL& password_form_frame_url,
                     const std::string& saved_domain,
-                    TriggerType trigger_type,
+                    LoginReputationClientRequest::TriggerType type,
                     bool password_field_exists);
 
   virtual void MaybeStartPasswordFieldOnFocusRequest(
@@ -155,9 +152,9 @@
   // the requests.
   void CancelPendingRequests();
 
-  // Gets the total number of verdicts of the specified |trigger_type| we cached
-  // for this profile. This counts both expired and active verdicts.
-  virtual int GetStoredVerdictCount(TriggerType trigger_type);
+  // Gets the total number of verdict (no matter expired or not) we cached for
+  // current active profile.
+  virtual int GetStoredVerdictCount();
 
   scoped_refptr<net::URLRequestContextGetter> request_context_getter() {
     return request_context_getter_;
@@ -176,8 +173,9 @@
       int event_tab_id,  // -1 if tab id is not available.
       LoginReputationClientRequest::Frame* frame) = 0;
 
-  void FillUserPopulation(TriggerType trigger_type,
-                          LoginReputationClientRequest* request_proto);
+  void FillUserPopulation(
+      const LoginReputationClientRequest::TriggerType& request_type,
+      LoginReputationClientRequest* request_proto);
 
   virtual bool IsExtendedReporting() = 0;
 
@@ -225,15 +223,6 @@
   void RemoveContentSettingsOnURLsDeleted(bool all_history,
                                           const history::URLRows& deleted_rows);
 
-  // Helper function called by RemoveContentSettingsOnURLsDeleted(..). It
-  // calculate the number of verdicts of |type| that associate with |url|.
-  int GetVerdictCountForURL(const GURL& url, TriggerType type);
-
-  // Remove verdict of |type| from |cache_dictionary|. Return false if no
-  // verdict removed, true otherwise.
-  bool RemoveExpiredVerdicts(TriggerType type,
-                             base::DictionaryValue* cache_dictionary);
-
   static bool ParseVerdictEntry(base::DictionaryValue* verdict_entry,
                                 int* out_verdict_received_time,
                                 LoginReputationClientResponse* out_verdict);
@@ -256,12 +245,8 @@
 
   static void RecordNoPingingReason(const base::Feature& feature,
                                     RequestOutcome reason);
-  // Number of verdict stored for this profile for password on focus pings.
-  int stored_verdict_count_password_on_focus_;
-
-  // Number of verdict stored for this profile for protected password entry
-  // pings.
-  int stored_verdict_count_password_entry_;
+  // Number of verdict stored for this profile.
+  int stored_verdict_count_;
 
   scoped_refptr<SafeBrowsingDatabaseManager> database_manager_;
 
diff --git a/components/safe_browsing/password_protection/password_protection_service_unittest.cc b/components/safe_browsing/password_protection/password_protection_service_unittest.cc
index 1baee7c..d297ef1 100644
--- a/components/safe_browsing/password_protection/password_protection_service_unittest.cc
+++ b/components/safe_browsing/password_protection/password_protection_service_unittest.cc
@@ -201,19 +201,18 @@
   }
 
   void CacheVerdict(const GURL& url,
-                    LoginReputationClientRequest::TriggerType trigger,
                     LoginReputationClientResponse::VerdictType verdict,
                     int cache_duration_sec,
                     const std::string& cache_expression,
                     const base::Time& verdict_received_time) {
     LoginReputationClientResponse response(
         CreateVerdictProto(verdict, cache_duration_sec, cache_expression));
-    password_protection_service_->CacheVerdict(url, trigger, &response,
+    password_protection_service_->CacheVerdict(url, &response,
                                                verdict_received_time);
   }
 
-  size_t GetStoredVerdictCount(LoginReputationClientRequest::TriggerType type) {
-    return password_protection_service_->GetStoredVerdictCount(type);
+  size_t GetStoredVerdictCount() {
+    return password_protection_service_->GetStoredVerdictCount();
   }
 
  protected:
@@ -305,173 +304,80 @@
       GURL("http://evil.com/worse/index.html"), cache_expression_with_slash));
 }
 
-TEST_F(PasswordProtectionServiceTest, TestCachePasswordReuseVerdicts) {
-  ASSERT_EQ(0U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
-
+TEST_F(PasswordProtectionServiceTest, TestCachedVerdicts) {
+  ASSERT_EQ(0U, GetStoredVerdictCount());
   // Assume each verdict has a TTL of 10 minutes.
   // Cache a verdict for http://www.test.com/foo/index.html
   CacheVerdict(GURL("http://www.test.com/foo/index.html"),
-               LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
                LoginReputationClientResponse::SAFE, 10 * 60, "test.com/foo",
                base::Time::Now());
 
-  EXPECT_EQ(1U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
+  EXPECT_EQ(1U, GetStoredVerdictCount());
 
   // Cache another verdict with the some origin and cache_expression should
   // override the cache.
   CacheVerdict(GURL("http://www.test.com/foo/index2.html"),
-               LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
                LoginReputationClientResponse::PHISHING, 10 * 60, "test.com/foo",
                base::Time::Now());
-  EXPECT_EQ(1U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
+  EXPECT_EQ(1U, GetStoredVerdictCount());
   LoginReputationClientResponse out_verdict;
-  EXPECT_EQ(
-      LoginReputationClientResponse::PHISHING,
-      password_protection_service_->GetCachedVerdict(
-          GURL("http://www.test.com/foo/index2.html"),
-          LoginReputationClientRequest::PASSWORD_REUSE_EVENT, &out_verdict));
+  EXPECT_EQ(LoginReputationClientResponse::PHISHING,
+            password_protection_service_->GetCachedVerdict(
+                GURL("http://www.test.com/foo/index2.html"), &out_verdict));
 
   // Cache another verdict with the same origin but different cache_expression
   // will not increase setting count, but will increase the number of verdicts
   // in the given origin.
   CacheVerdict(GURL("http://www.test.com/bar/index2.html"),
-               LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
                LoginReputationClientResponse::SAFE, 10 * 60, "test.com/bar",
                base::Time::Now());
-  EXPECT_EQ(2U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
-
-  // Now cache a UNFAMILIAR_LOGIN_PAGE verdict, stored verdict count for
-  // PASSWORD_REUSE_EVENT should be the same.
-  CacheVerdict(GURL("http://www.test.com/foobar/index3.html"),
-               LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
-               LoginReputationClientResponse::SAFE, 10 * 60, "test.com/foobar",
-               base::Time::Now());
-  EXPECT_EQ(2U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
-  EXPECT_EQ(1U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
-}
-
-TEST_F(PasswordProtectionServiceTest, TestCacheUnfamiliarLoginVerdicts) {
-  ASSERT_EQ(0U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
-
-  // Assume each verdict has a TTL of 10 minutes.
-  // Cache a verdict for http://www.test.com/foo/index.html
-  CacheVerdict(GURL("http://www.test.com/foo/index.html"),
-               LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
-               LoginReputationClientResponse::SAFE, 10 * 60, "test.com/foo",
-               base::Time::Now());
-
-  EXPECT_EQ(1U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
-
-  // Cache another verdict with the same origin but different cache_expression
-  // will not increase setting count, but will increase the number of verdicts
-  // in the given origin.
-  CacheVerdict(GURL("http://www.test.com/bar/index2.html"),
-               LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
-               LoginReputationClientResponse::SAFE, 10 * 60, "test.com/bar",
-               base::Time::Now());
-  EXPECT_EQ(2U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
-
-  // Now cache a PASSWORD_REUSE_EVENT verdict, stored verdict count for
-  // UNFAMILIAR_LOGIN_PAGE should be the same.
-  CacheVerdict(GURL("http://www.test.com/foobar/index3.html"),
-               LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
-               LoginReputationClientResponse::SAFE, 10 * 60, "test.com/foobar",
-               base::Time::Now());
-  EXPECT_EQ(2U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
-  EXPECT_EQ(1U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
+  EXPECT_EQ(2U, GetStoredVerdictCount());
 }
 
 TEST_F(PasswordProtectionServiceTest, TestGetCachedVerdicts) {
-  ASSERT_EQ(0U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
-  ASSERT_EQ(0U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
-  // Prepare 3 verdicts of the same origin with different cache expressions,
-  // one is expired, one is not, the other is of a different type.
+  ASSERT_EQ(0U, GetStoredVerdictCount());
+  // Prepare 2 verdicts of the same origin with different cache expressions,
+  // one is expired, the other is not.
   base::Time now = base::Time::Now();
   CacheVerdict(GURL("http://test.com/login.html"),
-               LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
                LoginReputationClientResponse::SAFE, 10 * 60, "test.com", now);
   CacheVerdict(
       GURL("http://test.com/def/index.jsp"),
-      LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
       LoginReputationClientResponse::PHISHING, 10 * 60, "test.com/def",
       base::Time::FromDoubleT(now.ToDoubleT() -
                               24.0 * 60.0 * 60.0));  // Yesterday, expired.
-  CacheVerdict(GURL("http://test.com/bar/login.html"),
-               LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
-               LoginReputationClientResponse::PHISHING, 10 * 60, "test.com/bar",
-               now);
-
-  ASSERT_EQ(2U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
-  ASSERT_EQ(1U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
+  ASSERT_EQ(2U, GetStoredVerdictCount());
 
   // Return VERDICT_TYPE_UNSPECIFIED if look up for a URL with unknown origin.
   LoginReputationClientResponse actual_verdict;
-  EXPECT_EQ(
-      LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
-      password_protection_service_->GetCachedVerdict(
-          GURL("http://www.unknown.com/"),
-          LoginReputationClientRequest::PASSWORD_REUSE_EVENT, &actual_verdict));
+  EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
+            password_protection_service_->GetCachedVerdict(
+                GURL("http://www.unknown.com/"), &actual_verdict));
 
   // Return SAFE if look up for a URL that matches "test.com" cache expression.
-  EXPECT_EQ(
-      LoginReputationClientResponse::SAFE,
-      password_protection_service_->GetCachedVerdict(
-          GURL("http://test.com/xyz/foo.jsp"),
-          LoginReputationClientRequest::PASSWORD_REUSE_EVENT, &actual_verdict));
+  EXPECT_EQ(LoginReputationClientResponse::SAFE,
+            password_protection_service_->GetCachedVerdict(
+                GURL("http://test.com/xyz/foo.jsp"), &actual_verdict));
 
   // Return VERDICT_TYPE_UNSPECIFIED if look up for a URL whose variants match
   // test.com/def, but the corresponding verdict is expired.
-  EXPECT_EQ(
-      LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
-      password_protection_service_->GetCachedVerdict(
-          GURL("http://test.com/def/ghi/index.html"),
-          LoginReputationClientRequest::PASSWORD_REUSE_EVENT, &actual_verdict));
+  EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
+            password_protection_service_->GetCachedVerdict(
+                GURL("http://test.com/def/ghi/index.html"), &actual_verdict));
 }
 
 TEST_F(PasswordProtectionServiceTest, TestRemoveCachedVerdictOnURLsDeleted) {
-  ASSERT_EQ(0U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
-  ASSERT_EQ(0U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
+  ASSERT_EQ(0U, GetStoredVerdictCount());
   // Prepare 2 verdicts. One is for origin "http://foo.com", and the other is
   // for "http://bar.com".
   base::Time now = base::Time::Now();
   CacheVerdict(GURL("http://foo.com/abc/index.jsp"),
-               LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
                LoginReputationClientResponse::LOW_REPUTATION, 10 * 60,
                "foo.com/abc", now);
   CacheVerdict(GURL("http://bar.com/index.jsp"),
-               LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
                LoginReputationClientResponse::PHISHING, 10 * 60, "bar.com",
                now);
-  ASSERT_EQ(2U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
-
-  CacheVerdict(GURL("http://foo.com/abc/index.jsp"),
-               LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
-               LoginReputationClientResponse::LOW_REPUTATION, 10 * 60,
-               "foo.com/abc", now);
-  CacheVerdict(GURL("http://bar.com/index.jsp"),
-               LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
-               LoginReputationClientResponse::PHISHING, 10 * 60, "bar.com",
-               now);
-  ASSERT_EQ(2U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
+  ASSERT_EQ(2U, GetStoredVerdictCount());
 
   // Delete a bar.com URL. Corresponding content setting keyed on
   // origin "http://bar.com" should be removed,
@@ -484,31 +390,17 @@
 
   password_protection_service_->RemoveContentSettingsOnURLsDeleted(
       false /* all_history */, deleted_urls);
-  EXPECT_EQ(1U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
-  EXPECT_EQ(1U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
-
+  EXPECT_EQ(1U, GetStoredVerdictCount());
   LoginReputationClientResponse actual_verdict;
-  EXPECT_EQ(
-      LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
-      password_protection_service_->GetCachedVerdict(
-          GURL("http://bar.com"),
-          LoginReputationClientRequest::PASSWORD_REUSE_EVENT, &actual_verdict));
   EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
             password_protection_service_->GetCachedVerdict(
-                GURL("http://bar.com"),
-                LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
-                &actual_verdict));
+                GURL("http://bar.com"), &actual_verdict));
 
   // If delete all history. All password protection content settings should be
   // gone.
   password_protection_service_->RemoveContentSettingsOnURLsDeleted(
       true /* all_history */, history::URLRows());
-  EXPECT_EQ(0U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
-  EXPECT_EQ(0U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
+  EXPECT_EQ(0U, GetStoredVerdictCount());
 }
 
 TEST_F(PasswordProtectionServiceTest, VerifyCanGetReputationOfURL) {
@@ -562,10 +454,8 @@
 
 TEST_F(PasswordProtectionServiceTest, TestNoRequestSentIfVerdictAlreadyCached) {
   histograms_.ExpectTotalCount(kPasswordOnFocusRequestOutcomeHistogramName, 0);
-  CacheVerdict(GURL(kTargetUrl),
-               LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
-               LoginReputationClientResponse::LOW_REPUTATION, 600,
-               GURL(kTargetUrl).host(), base::Time::Now());
+  CacheVerdict(GURL(kTargetUrl), LoginReputationClientResponse::LOW_REPUTATION,
+               600, GURL(kTargetUrl).host(), base::Time::Now());
   InitializeAndStartPasswordOnFocusRequest(false /* match whitelist */,
                                            10000 /* timeout in ms*/);
   base::RunLoop().RunUntilIdle();
@@ -672,87 +562,42 @@
 }
 
 TEST_F(PasswordProtectionServiceTest, TestCleanUpExpiredVerdict) {
-  // Prepare 4 verdicts for PASSWORD_REUSE_EVENT:
+  ASSERT_EQ(0U, GetStoredVerdictCount());
+  // Prepare 4 verdicts:
   // (1) "foo.com/abc" valid
   // (2) "foo.com/def" expired
   // (3) "bar.com/abc" expired
   // (4) "bar.com/def" expired
   base::Time now = base::Time::Now();
   CacheVerdict(GURL("https://foo.com/abc/index.jsp"),
-               LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
                LoginReputationClientResponse::LOW_REPUTATION, 10 * 60,
                "foo.com/abc", now);
   CacheVerdict(GURL("https://foo.com/def/index.jsp"),
-               LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
                LoginReputationClientResponse::LOW_REPUTATION, 0, "foo.com/def",
                now);
   CacheVerdict(GURL("https://bar.com/abc/index.jsp"),
-               LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
                LoginReputationClientResponse::PHISHING, 0, "bar.com/abc", now);
   CacheVerdict(GURL("https://bar.com/def/index.jsp"),
-               LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
                LoginReputationClientResponse::PHISHING, 0, "bar.com/def", now);
-  ASSERT_EQ(4U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
-
-  // Prepare 2 verdicts for UNFAMILIAR_LOGIN_PAGE:
-  // (1) "bar.com/def" valid
-  // (2) "bar.com/xyz" expired
-  CacheVerdict(GURL("https://bar.com/def/index.jsp"),
-               LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
-               LoginReputationClientResponse::SAFE, 10 * 60, "bar.com/def",
-               now);
-  CacheVerdict(GURL("https://bar.com/xyz/index.jsp"),
-               LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
-               LoginReputationClientResponse::PHISHING, 0, "bar.com/xyz", now);
-  ASSERT_EQ(2U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
+  ASSERT_EQ(4U, GetStoredVerdictCount());
 
   password_protection_service_->CleanUpExpiredVerdicts();
 
-  ASSERT_EQ(1U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::PASSWORD_REUSE_EVENT));
-  ASSERT_EQ(1U, GetStoredVerdictCount(
-                    LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE));
+  ASSERT_EQ(1U, GetStoredVerdictCount());
   LoginReputationClientResponse actual_verdict;
-  // Has cached PASSWORD_REUSE_EVENT verdict for foo.com/abc.
-  EXPECT_EQ(
-      LoginReputationClientResponse::LOW_REPUTATION,
-      password_protection_service_->GetCachedVerdict(
-          GURL("https://foo.com/abc/test.jsp"),
-          LoginReputationClientRequest::PASSWORD_REUSE_EVENT, &actual_verdict));
-  // No cached PASSWORD_REUSE_EVENT verdict for foo.com/def.
-  EXPECT_EQ(
-      LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
-      password_protection_service_->GetCachedVerdict(
-          GURL("https://foo.com/def/index.jsp"),
-          LoginReputationClientRequest::PASSWORD_REUSE_EVENT, &actual_verdict));
-  // No cached PASSWORD_REUSE_EVENT verdict for bar.com/abc.
-  EXPECT_EQ(
-      LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
-      password_protection_service_->GetCachedVerdict(
-          GURL("https://bar.com/abc/index.jsp"),
-          LoginReputationClientRequest::PASSWORD_REUSE_EVENT, &actual_verdict));
-  // No cached PASSWORD_REUSE_EVENT verdict for bar.com/def.
-  EXPECT_EQ(
-      LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
-      password_protection_service_->GetCachedVerdict(
-          GURL("https://bar.com/def/index.jsp"),
-          LoginReputationClientRequest::PASSWORD_REUSE_EVENT, &actual_verdict));
-
-  // Has cached UNFAMILIAR_LOGIN_PAGE verdict for bar.com/def.
-  EXPECT_EQ(LoginReputationClientResponse::SAFE,
+  // Has cached verdict for foo.com/abc.
+  EXPECT_EQ(LoginReputationClientResponse::LOW_REPUTATION,
             password_protection_service_->GetCachedVerdict(
-                GURL("https://bar.com/def/index.jsp"),
-                LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
-                &actual_verdict));
-
-  // No cached UNFAMILIAR_LOGIN_PAGE verdict for bar.com/xyz.
+                GURL("https://foo.com/abc/test.jsp"), &actual_verdict));
+  // No cached verdict for foo.com/def.
   EXPECT_EQ(LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
             password_protection_service_->GetCachedVerdict(
-                GURL("https://bar.com/xyz/index.jsp"),
-                LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE,
-                &actual_verdict));
+                GURL("https://foo.com/def/index.jsp"), &actual_verdict));
+  // Nothing in content setting for bar.com.
+  EXPECT_EQ(nullptr, content_setting_map_->GetWebsiteSetting(
+                         GURL("https://bar.com"), GURL(),
+                         CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION,
+                         std::string(), nullptr));
 }
 
 TEST_F(PasswordProtectionServiceTest, VerifyPasswordOnFocusRequestProto) {
diff --git a/components/sync/driver/sync_driver_switches.cc b/components/sync/driver/sync_driver_switches.cc
index bb9f136c..1b346e2 100644
--- a/components/sync/driver/sync_driver_switches.cc
+++ b/components/sync/driver/sync_driver_switches.cc
@@ -40,6 +40,14 @@
 const base::Feature kSyncUserEvents{"SyncUserEvents",
                                     base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Gates registration for user language detection events.
+const base::Feature kSyncUserLanguageDetectionEvents{
+    "SyncUserLanguageDetectionEvents", base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Gates registration for user translation events.
+const base::Feature kSyncUserTranslationEvents{
+    "SyncUserTranslationEvents", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Enables USS implementation of Autocomplete datatype.
 const base::Feature kSyncUSSAutocomplete{"SyncUSSAutocomplete",
                                          base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/sync/driver/sync_driver_switches.h b/components/sync/driver/sync_driver_switches.h
index e4597fd5..bce16be 100644
--- a/components/sync/driver/sync_driver_switches.h
+++ b/components/sync/driver/sync_driver_switches.h
@@ -21,6 +21,8 @@
 
 extern const base::Feature kSyncClearDataOnPassphraseEncryption;
 extern const base::Feature kSyncUserEvents;
+extern const base::Feature kSyncUserLanguageDetectionEvents;
+extern const base::Feature kSyncUserTranslationEvents;
 extern const base::Feature kSyncUSSAutocomplete;
 extern const base::Feature kSyncUSSTypedURL;
 extern const base::Feature kSyncUSSDeviceInfo;
diff --git a/components/translate/core/common/language_detection_logging_helper.cc b/components/translate/core/common/language_detection_logging_helper.cc
index e632bdfb..b98ae85 100644
--- a/components/translate/core/common/language_detection_logging_helper.cc
+++ b/components/translate/core/common/language_detection_logging_helper.cc
@@ -14,13 +14,14 @@
 namespace translate {
 
 std::unique_ptr<sync_pb::UserEventSpecifics> ConstructLanguageDetectionEvent(
+    const int64_t navigation_id,
     const LanguageDetectionDetails& details) {
   auto specifics = base::MakeUnique<sync_pb::UserEventSpecifics>();
   specifics->set_event_time_usec(base::Time::Now().ToInternalValue());
 
   // TODO(renjieliu): Revisit this field when the best way to identify
   // navigations is determined.
-  specifics->set_navigation_id(base::Time::Now().ToInternalValue());
+  specifics->set_navigation_id(navigation_id);
 
   sync_pb::LanguageDetection lang_detection;
   auto* const lang = lang_detection.add_detected_languages();
@@ -33,4 +34,5 @@
   *specifics->mutable_language_detection() = lang_detection;
   return specifics;
 }
+
 }  // namespace translate
\ No newline at end of file
diff --git a/components/translate/core/common/language_detection_logging_helper.h b/components/translate/core/common/language_detection_logging_helper.h
index d8f67bb..15ecaee5 100644
--- a/components/translate/core/common/language_detection_logging_helper.h
+++ b/components/translate/core/common/language_detection_logging_helper.h
@@ -15,7 +15,10 @@
 
 struct LanguageDetectionDetails;
 
+// Construct language detection based on navigation_id and language detection
+// details.
 std::unique_ptr<sync_pb::UserEventSpecifics> ConstructLanguageDetectionEvent(
+    int64_t navigation_id,
     const LanguageDetectionDetails& details);
 
 }  // namespace translate
diff --git a/components/translate/core/common/language_detection_logging_helper_unittest.cc b/components/translate/core/common/language_detection_logging_helper_unittest.cc
index 6dc27c0..c22a0ee0 100644
--- a/components/translate/core/common/language_detection_logging_helper_unittest.cc
+++ b/components/translate/core/common/language_detection_logging_helper_unittest.cc
@@ -24,8 +24,11 @@
   lang->set_language_code(details.cld_language);
   lang->set_is_reliable(details.is_cld_reliable);
   lang_detection.set_adopted_language_code(details.adopted_language);
+  const int64_t navigation_id = 1000000000000000LL;
   const std::unique_ptr<sync_pb::UserEventSpecifics> user_event =
-      ConstructLanguageDetectionEvent(details);
+      ConstructLanguageDetectionEvent(navigation_id, details);
+  // Expect the navigation id is correctly set.
+  EXPECT_EQ(user_event->navigation_id(), navigation_id);
   EXPECT_EQ(user_event->language_detection().SerializeAsString(),
             lang_detection.SerializeAsString());
 }
@@ -43,7 +46,9 @@
   lang->set_language_code(details.cld_language);
   lang->set_is_reliable(details.is_cld_reliable);
   const std::unique_ptr<sync_pb::UserEventSpecifics> user_event =
-      ConstructLanguageDetectionEvent(details);
+      ConstructLanguageDetectionEvent(100, details);
+  // Expect the navigation id is correctly set.
+  EXPECT_EQ(user_event->navigation_id(), 100);
   EXPECT_EQ(user_event->language_detection().SerializeAsString(),
             lang_detection.SerializeAsString());
 }
diff --git a/components/ukm/public/interfaces/ukm_interface.mojom b/components/ukm/public/interfaces/ukm_interface.mojom
index 0625916..4daeb839 100644
--- a/components/ukm/public/interfaces/ukm_interface.mojom
+++ b/components/ukm/public/interfaces/ukm_interface.mojom
@@ -19,4 +19,5 @@
 
 interface UkmRecorderInterface {
   AddEntry(UkmEntry entry);
+  UpdateSourceURL(int64 source_id, string url);
 };
diff --git a/components/ukm/public/mojo_ukm_recorder.cc b/components/ukm/public/mojo_ukm_recorder.cc
index 8d5af8f9..d62b1464 100644
--- a/components/ukm/public/mojo_ukm_recorder.cc
+++ b/components/ukm/public/mojo_ukm_recorder.cc
@@ -13,8 +13,7 @@
 MojoUkmRecorder::~MojoUkmRecorder() = default;
 
 void MojoUkmRecorder::UpdateSourceURL(SourceId source_id, const GURL& url) {
-  DCHECK(false);
-  // Not implemented yet, currently a no-op.
+  interface_->UpdateSourceURL(source_id, url.spec());
 }
 
 void MojoUkmRecorder::AddEntry(mojom::UkmEntryPtr entry) {
diff --git a/components/ukm/ukm_interface.cc b/components/ukm/ukm_interface.cc
index d89f613..99decf0 100644
--- a/components/ukm/ukm_interface.cc
+++ b/components/ukm/ukm_interface.cc
@@ -4,14 +4,30 @@
 
 #include "components/ukm/ukm_interface.h"
 
+#include "base/atomic_sequence_num.h"
 #include "base/memory/ptr_util.h"
 #include "components/ukm/public/ukm_recorder.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
+#include "url/gurl.h"
 
 namespace ukm {
 
-UkmInterface::UkmInterface(UkmRecorder* ukm_recorder)
-    : ukm_recorder_(ukm_recorder) {}
+namespace {
+
+// Map source ids from different instances into unique namespaces, so that
+// clients can create thier own IDs without having them collide.
+// This won't be necessary once we switch to using CoordinationUnitIDs.
+int64_t ConvertSourceId(int64_t source_id, int64_t instance_id) {
+  const int64_t low_bits = (INT64_C(1) << 32) - 1;
+  // Neither ID should get large enough to cause an issue, but explicitly
+  // discard down to 32 bits anyway.
+  return ((instance_id & low_bits) << 32) | (source_id & low_bits);
+}
+
+}  // namespace
+
+UkmInterface::UkmInterface(UkmRecorder* ukm_recorder, int64_t instance_id)
+    : ukm_recorder_(ukm_recorder), instance_id_(instance_id) {}
 
 UkmInterface::~UkmInterface() = default;
 
@@ -19,12 +35,21 @@
 void UkmInterface::Create(UkmRecorder* ukm_recorder,
                           const service_manager::BindSourceInfo& source_info,
                           mojom::UkmRecorderInterfaceRequest request) {
-  mojo::MakeStrongBinding(base::MakeUnique<UkmInterface>(ukm_recorder),
-                          std::move(request));
+  static base::StaticAtomicSequenceNumber seq;
+  mojo::MakeStrongBinding(
+      base::MakeUnique<UkmInterface>(ukm_recorder,
+                                     static_cast<int64_t>(seq.GetNext()) + 1),
+      std::move(request));
 }
 
 void UkmInterface::AddEntry(mojom::UkmEntryPtr ukm_entry) {
+  ukm_entry->source_id = ConvertSourceId(instance_id_, ukm_entry->source_id);
   ukm_recorder_->AddEntry(std::move(ukm_entry));
 }
 
+void UkmInterface::UpdateSourceURL(int64_t source_id, const std::string& url) {
+  ukm_recorder_->UpdateSourceURL(ConvertSourceId(instance_id_, source_id),
+                                 GURL(url));
+}
+
 }  // namespace ukm
diff --git a/components/ukm/ukm_interface.h b/components/ukm/ukm_interface.h
index 2f536fc..a3047738 100644
--- a/components/ukm/ukm_interface.h
+++ b/components/ukm/ukm_interface.h
@@ -17,7 +17,7 @@
 
 class UkmInterface : public mojom::UkmRecorderInterface {
  public:
-  explicit UkmInterface(UkmRecorder* ukm_recorder);
+  UkmInterface(UkmRecorder* ukm_recorder, int64_t instance_id);
   ~UkmInterface() override;
 
   static void Create(UkmRecorder* ukm_recorder,
@@ -27,8 +27,10 @@
  private:
   // ukm::mojom::UkmRecorderInterface:
   void AddEntry(mojom::UkmEntryPtr entry) override;
+  void UpdateSourceURL(int64_t source_id, const std::string& url) override;
 
   UkmRecorder* ukm_recorder_;
+  int64_t instance_id_;
 
   DISALLOW_COPY_AND_ASSIGN(UkmInterface);
 };
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 0c0fcbbb..0bc69e1 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -110,6 +110,7 @@
     "//services/catalog:constants",
     "//services/catalog/public/cpp",
     "//services/catalog/public/interfaces:constants",
+    "//services/data_decoder/public/cpp",
     "//services/data_decoder/public/interfaces",
     "//services/device:lib",
     "//services/device/public/interfaces",
@@ -1071,6 +1072,8 @@
     "payments/payment_app_database.h",
     "payments/payment_app_provider_impl.cc",
     "payments/payment_app_provider_impl.h",
+    "payments/payment_instrument_icon_fetcher.cc",
+    "payments/payment_instrument_icon_fetcher.h",
     "payments/payment_manager.cc",
     "payments/payment_manager.h",
     "permissions/permission_service_context.cc",
diff --git a/content/browser/DEPS b/content/browser/DEPS
index 530f0c0..437c816 100644
--- a/content/browser/DEPS
+++ b/content/browser/DEPS
@@ -22,6 +22,7 @@
 
   "+content/app/strings/grit",  # For generated headers
   "+content/public/browser",
+  "+device/base/synchronization",
   "+device/gamepad", # For gamepad API
   "+device/generic_sensor",  # For sensors service.
   "+device/geolocation",
diff --git a/content/browser/generic_sensor_browsertest.cc b/content/browser/generic_sensor_browsertest.cc
index 66375fe..8b3b9ee 100644
--- a/content/browser/generic_sensor_browsertest.cc
+++ b/content/browser/generic_sensor_browsertest.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/bind.h"
 #include "base/command_line.h"
 #include "base/macros.h"
-#include "base/memory/singleton.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/platform_thread.h"
 #include "build/build_config.h"
@@ -17,75 +17,150 @@
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
 #include "content/shell/browser/shell_javascript_dialog_manager.h"
-#include "device/generic_sensor/platform_sensor.h"
-#include "device/generic_sensor/platform_sensor_provider.h"
-#include "device/generic_sensor/sensor_provider_impl.h"
+#include "device/base/synchronization/one_writer_seqlock.h"
+#include "device/generic_sensor/public/cpp/platform_sensor_configuration.h"
+#include "device/generic_sensor/public/cpp/sensor_reading.h"
+#include "device/generic_sensor/public/interfaces/sensor.mojom.h"
+#include "device/generic_sensor/public/interfaces/sensor_provider.mojom.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "mojo/public/cpp/system/buffer.h"
+#include "services/device/public/interfaces/constants.mojom.h"
+#include "services/service_manager/public/cpp/service_context.h"
 
 namespace content {
 
 namespace {
 
-class FakeAmbientLightSensor : public device::PlatformSensor {
+class FakeAmbientLightSensor : public device::mojom::Sensor {
  public:
-  FakeAmbientLightSensor(mojo::ScopedSharedBufferMapping mapping,
-                         device::PlatformSensorProvider* provider)
-      : PlatformSensor(device::mojom::SensorType::AMBIENT_LIGHT,
-                       std::move(mapping),
-                       provider) {}
+  FakeAmbientLightSensor() {
+    shared_buffer_handle_ = mojo::SharedBufferHandle::Create(
+        sizeof(device::SensorReadingSharedBuffer) *
+        static_cast<uint64_t>(device::mojom::SensorType::LAST));
+  }
 
-  device::mojom::ReportingMode GetReportingMode() override {
+  ~FakeAmbientLightSensor() override = default;
+
+  // device::mojom::Sensor implemenation:
+  void AddConfiguration(
+      const device::PlatformSensorConfiguration& configuration,
+      AddConfigurationCallback callback) override {
+    std::move(callback).Run(true);
+    SensorReadingChanged();
+  }
+
+  void GetDefaultConfiguration(
+      GetDefaultConfigurationCallback callback) override {
+    std::move(callback).Run(GetDefaultConfiguration());
+  }
+
+  void RemoveConfiguration(
+      const device::PlatformSensorConfiguration& configuration,
+      RemoveConfigurationCallback callback) override {
+    std::move(callback).Run(true);
+  }
+
+  void Suspend() override {}
+  void Resume() override {}
+
+  device::PlatformSensorConfiguration GetDefaultConfiguration() {
+    return device::PlatformSensorConfiguration(60 /* frequency */);
+  }
+
+  device::mojom::ReportingMode GetReportingMode() {
     return device::mojom::ReportingMode::ON_CHANGE;
   }
 
-  bool StartSensor(
-      const device::PlatformSensorConfiguration& configuration) override {
+  double GetMaximumSupportedFrequency() { return 60.0; }
+  double GetMinimumSupportedFrequency() { return 1.0; }
+
+  device::mojom::SensorClientRequest GetClient() {
+    return mojo::MakeRequest(&client_);
+  }
+
+  mojo::ScopedSharedBufferHandle GetSharedBufferHandle() {
+    return shared_buffer_handle_->Clone(
+        mojo::SharedBufferHandle::AccessMode::READ_ONLY);
+  }
+
+  uint64_t GetBufferOffset() {
+    return device::SensorReadingSharedBuffer::GetOffset(
+        device::mojom::SensorType::AMBIENT_LIGHT);
+  }
+
+  void SensorReadingChanged() {
+    if (!shared_buffer_handle_.is_valid())
+      return;
+
+    mojo::ScopedSharedBufferMapping shared_buffer =
+        shared_buffer_handle_->MapAtOffset(
+            device::mojom::SensorInitParams::kReadBufferSizeForTests,
+            GetBufferOffset());
+
     device::SensorReading reading;
     reading.timestamp =
         (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
     reading.values[0] = 50;
-    UpdateSensorReading(reading, true);
-    return true;
+
+    device::SensorReadingSharedBuffer* buffer =
+        static_cast<device::SensorReadingSharedBuffer*>(shared_buffer.get());
+    auto& seqlock = buffer->seqlock.value();
+    seqlock.WriteBegin();
+    buffer->reading = reading;
+    seqlock.WriteEnd();
+
+    if (client_)
+      client_->SensorReadingChanged();
   }
 
-  void StopSensor() override {}
+ private:
+  mojo::ScopedSharedBufferHandle shared_buffer_handle_;
+  device::mojom::SensorClientPtr client_;
 
- protected:
-  ~FakeAmbientLightSensor() override = default;
-  bool CheckSensorConfiguration(
-      const device::PlatformSensorConfiguration& configuration) override {
-    return true;
-  }
-  device::PlatformSensorConfiguration GetDefaultConfiguration() override {
-    return device::PlatformSensorConfiguration(60 /* frequency */);
-  }
+  DISALLOW_COPY_AND_ASSIGN(FakeAmbientLightSensor);
 };
 
-class FakeSensorProvider : public device::PlatformSensorProvider {
+class FakeSensorProvider : public device::mojom::SensorProvider {
  public:
-  static FakeSensorProvider* GetInstance() {
-    return base::Singleton<FakeSensorProvider, base::LeakySingletonTraits<
-                                                   FakeSensorProvider>>::get();
-  }
-  FakeSensorProvider() = default;
+  FakeSensorProvider() : binding_(this) {}
   ~FakeSensorProvider() override = default;
 
- protected:
-  void CreateSensorInternal(device::mojom::SensorType type,
-                            mojo::ScopedSharedBufferMapping mapping,
-                            const CreateSensorCallback& callback) override {
-    // Create Sensors here.
+  void Bind(const service_manager::BindSourceInfo& source_info,
+            const std::string& interface_name,
+            mojo::ScopedMessagePipeHandle handle) {
+    DCHECK(!binding_.is_bound());
+    binding_.Bind(device::mojom::SensorProviderRequest(std::move(handle)));
+  }
+
+  // device::mojom::sensorProvider implementation.
+  void GetSensor(device::mojom::SensorType type,
+                 device::mojom::SensorRequest sensor_request,
+                 GetSensorCallback callback) override {
     switch (type) {
       case device::mojom::SensorType::AMBIENT_LIGHT: {
-        scoped_refptr<device::PlatformSensor> sensor =
-            new FakeAmbientLightSensor(std::move(mapping), this);
-        callback.Run(std::move(sensor));
+        auto sensor = base::MakeUnique<FakeAmbientLightSensor>();
+
+        auto init_params = device::mojom::SensorInitParams::New();
+        init_params->memory = sensor->GetSharedBufferHandle();
+        init_params->buffer_offset = sensor->GetBufferOffset();
+        init_params->default_configuration = sensor->GetDefaultConfiguration();
+        init_params->maximum_frequency = sensor->GetMaximumSupportedFrequency();
+        init_params->minimum_frequency = sensor->GetMinimumSupportedFrequency();
+
+        std::move(callback).Run(std::move(init_params), sensor->GetClient());
+        mojo::MakeStrongBinding(std::move(sensor), std::move(sensor_request));
         break;
       }
       default:
         NOTIMPLEMENTED();
-        callback.Run(nullptr);
     }
   }
+
+ private:
+  mojo::Binding<device::mojom::SensorProvider> binding_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeSensorProvider);
 };
 
 class GenericSensorBrowserTest : public ContentBrowserTest {
@@ -94,31 +169,37 @@
       : io_loop_finished_event_(
             base::WaitableEvent::ResetPolicy::AUTOMATIC,
             base::WaitableEvent::InitialState::NOT_SIGNALED) {
-    // TODO(darktears): remove when the GenericSensor feature goes stable.
     base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
     cmd_line->AppendSwitchASCII(switches::kEnableFeatures, "GenericSensor");
   }
 
   void SetUpOnMainThread() override {
+    fake_sensor_provider_ = base::MakeUnique<FakeSensorProvider>();
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
-        base::Bind(&GenericSensorBrowserTest::SetUpOnIOThread,
+        base::Bind(&GenericSensorBrowserTest::SetBinderOnIOThread,
                    base::Unretained(this)));
+
     io_loop_finished_event_.Wait();
   }
 
-  void SetUpOnIOThread() {
-    device::PlatformSensorProvider::SetProviderForTesting(
-        FakeSensorProvider::GetInstance());
+  void SetBinderOnIOThread() {
+    // Because Device Service also runs in this process(browser process), here
+    // we can directly set our binder to intercept interface requests against
+    // it.
+    service_manager::ServiceContext::SetGlobalBinderForTesting(
+        device::mojom::kServiceName, device::mojom::SensorProvider::Name_,
+        base::Bind(&FakeSensorProvider::Bind,
+                   base::Unretained(fake_sensor_provider_.get())));
+
     io_loop_finished_event_.Signal();
   }
 
-  void TearDown() override {
-    device::PlatformSensorProvider::SetProviderForTesting(nullptr);
-  }
-
- public:
+ private:
   base::WaitableEvent io_loop_finished_event_;
+  std::unique_ptr<FakeSensorProvider> fake_sensor_provider_;
+
+  DISALLOW_COPY_AND_ASSIGN(GenericSensorBrowserTest);
 };
 
 IN_PROC_BROWSER_TEST_F(GenericSensorBrowserTest, AmbientLightSensorTest) {
diff --git a/content/browser/payments/payment_app.proto b/content/browser/payments/payment_app.proto
index c2eadb6..78a0a23 100644
--- a/content/browser/payments/payment_app.proto
+++ b/content/browser/payments/payment_app.proto
@@ -13,6 +13,10 @@
   optional string key = 2;
 }
 
+message StoredPaymentInstrumentImageObject {
+  optional string src = 1;
+}
+
 message StoredPaymentInstrumentProto {
   optional int64 registration_id = 1;
   optional string instrument_key = 2;
@@ -20,4 +24,6 @@
   optional string name = 4;
   repeated string enabled_methods = 5;
   optional string stringified_capabilities = 6;
+  repeated StoredPaymentInstrumentImageObject icons = 7;
+  optional string decoded_instrument_icon = 8;
 }
diff --git a/content/browser/payments/payment_app_database.cc b/content/browser/payments/payment_app_database.cc
index 5c58b9b..c1c1bf8 100644
--- a/content/browser/payments/payment_app_database.cc
+++ b/content/browser/payments/payment_app_database.cc
@@ -7,6 +7,7 @@
 #include <map>
 #include <utility>
 
+#include "base/base64.h"
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "base/optional.h"
@@ -16,6 +17,8 @@
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/browser/service_worker/service_worker_registration.h"
 #include "content/public/browser/browser_thread.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/image/image.h"
 
 namespace content {
 namespace {
@@ -58,6 +61,10 @@
 
   PaymentInstrumentPtr instrument = PaymentInstrument::New();
   instrument->name = instrument_proto.name();
+  for (const auto& icon : instrument_proto.icons()) {
+    instrument->icons.emplace_back(
+        payments::mojom::ImageObject::New(GURL(icon.src())));
+  }
   for (const auto& method : instrument_proto.enabled_methods())
     instrument->enabled_methods.push_back(method);
   instrument->stringified_capabilities =
@@ -78,6 +85,18 @@
   instrument->instrument_key = instrument_proto.instrument_key();
   instrument->origin = GURL(instrument_proto.origin());
   instrument->name = instrument_proto.name();
+
+  if (!instrument_proto.decoded_instrument_icon().empty()) {
+    std::string icon_raw_data;
+    base::Base64Decode(instrument_proto.decoded_instrument_icon(),
+                       &icon_raw_data);
+    // Note that the icon has been decoded to PNG raw data regardless of the
+    // original icon format that was downloaded.
+    gfx::Image icon_image = gfx::Image::CreateFrom1xPNGBytes(
+        reinterpret_cast<const unsigned char*>(icon_raw_data.data()),
+        icon_raw_data.size());
+    instrument->icon = base::MakeUnique<SkBitmap>(icon_image.AsBitmap());
+  }
   for (const auto& method : instrument_proto.enabled_methods())
     instrument->enabled_methods.push_back(method);
 
@@ -166,12 +185,46 @@
     WritePaymentInstrumentCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
+  if (instrument->icons.size() > 0) {
+    instrument_icon_fetcher_ =
+        base::MakeRefCounted<PaymentInstrumentIconFetcher>();
+    instrument_icon_fetcher_->Start(
+        instrument->icons, service_worker_context_,
+        base::Bind(&PaymentAppDatabase::DidFetchedPaymentInstrumentIcon,
+                   weak_ptr_factory_.GetWeakPtr(), scope, instrument_key,
+                   base::Passed(std::move(instrument)),
+                   base::Passed(std::move(callback))));
+  } else {
+    service_worker_context_->FindReadyRegistrationForPattern(
+        scope,
+        base::Bind(
+            &PaymentAppDatabase::DidFindRegistrationToWritePaymentInstrument,
+            weak_ptr_factory_.GetWeakPtr(), instrument_key,
+            base::Passed(std::move(instrument)), std::string(),
+            base::Passed(std::move(callback))));
+  }
+}
+
+void PaymentAppDatabase::DidFetchedPaymentInstrumentIcon(
+    const GURL& scope,
+    const std::string& instrument_key,
+    payments::mojom::PaymentInstrumentPtr instrument,
+    WritePaymentInstrumentCallback callback,
+    const std::string& icon) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  instrument_icon_fetcher_ = nullptr;
+  if (icon.empty()) {
+    std::move(callback).Run(PaymentHandlerStatus::FETCH_INSTRUMENT_ICON_FAILED);
+    return;
+  }
+
   service_worker_context_->FindReadyRegistrationForPattern(
       scope,
       base::Bind(
           &PaymentAppDatabase::DidFindRegistrationToWritePaymentInstrument,
           weak_ptr_factory_.GetWeakPtr(), instrument_key,
-          base::Passed(std::move(instrument)),
+          base::Passed(std::move(instrument)), icon,
           base::Passed(std::move(callback))));
 }
 
@@ -371,6 +424,7 @@
 void PaymentAppDatabase::DidFindRegistrationToWritePaymentInstrument(
     const std::string& instrument_key,
     PaymentInstrumentPtr instrument,
+    const std::string& decoded_instrument_icon,
     WritePaymentInstrumentCallback callback,
     ServiceWorkerStatusCode status,
     scoped_refptr<ServiceWorkerRegistration> registration) {
@@ -381,6 +435,7 @@
   }
 
   StoredPaymentInstrumentProto instrument_proto;
+  instrument_proto.set_decoded_instrument_icon(decoded_instrument_icon);
   instrument_proto.set_registration_id(registration->id());
   instrument_proto.set_instrument_key(instrument_key);
   instrument_proto.set_origin(registration->pattern().GetOrigin().spec());
@@ -388,6 +443,11 @@
   for (const auto& method : instrument->enabled_methods) {
     instrument_proto.add_enabled_methods(method);
   }
+  for (const auto& image_object : instrument->icons) {
+    StoredPaymentInstrumentImageObject* image_object_proto =
+        instrument_proto.add_icons();
+    image_object_proto->set_src(image_object->src.spec());
+  }
   instrument_proto.set_stringified_capabilities(
       instrument->stringified_capabilities);
 
diff --git a/content/browser/payments/payment_app_database.h b/content/browser/payments/payment_app_database.h
index 0016850..230db47a 100644
--- a/content/browser/payments/payment_app_database.h
+++ b/content/browser/payments/payment_app_database.h
@@ -12,6 +12,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "components/payments/mojom/payment_app.mojom.h"
+#include "content/browser/payments/payment_instrument_icon_fetcher.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/browser/service_worker/service_worker_registration.h"
 #include "content/common/content_export.h"
@@ -122,12 +123,21 @@
   void DidFindRegistrationToWritePaymentInstrument(
       const std::string& instrument_key,
       payments::mojom::PaymentInstrumentPtr instrument,
+      const std::string& decoded_instrument_icon,
       WritePaymentInstrumentCallback callback,
       ServiceWorkerStatusCode status,
       scoped_refptr<ServiceWorkerRegistration> registration);
   void DidWritePaymentInstrument(WritePaymentInstrumentCallback callback,
                                  ServiceWorkerStatusCode status);
 
+  // PaymentInstrumentIconFetcherCallback.
+  void DidFetchedPaymentInstrumentIcon(
+      const GURL& scope,
+      const std::string& instrument_key,
+      payments::mojom::PaymentInstrumentPtr instrument,
+      WritePaymentInstrumentCallback callback,
+      const std::string& icon);
+
   // ClearPaymentInstruments callbacks
   void DidFindRegistrationToClearPaymentInstruments(
       const GURL& scope,
@@ -142,6 +152,7 @@
   void DidClearPaymentInstruments(ClearPaymentInstrumentsCallback callback,
                                   ServiceWorkerStatusCode status);
 
+  scoped_refptr<PaymentInstrumentIconFetcher> instrument_icon_fetcher_;
   scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
   base::WeakPtrFactory<PaymentAppDatabase> weak_ptr_factory_;
 
diff --git a/content/browser/payments/payment_instrument_icon_fetcher.cc b/content/browser/payments/payment_instrument_icon_fetcher.cc
new file mode 100644
index 0000000..a4ccdd97
--- /dev/null
+++ b/content/browser/payments/payment_instrument_icon_fetcher.cc
@@ -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.
+
+#include "content/browser/payments/payment_instrument_icon_fetcher.h"
+
+#include "base/base64.h"
+#include "base/bind_helpers.h"
+#include "content/browser/storage_partition_impl.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/common/service_manager_connection.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_status_code.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/data_decoder/public/cpp/decode_image.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/image/image.h"
+
+namespace content {
+
+namespace {
+
+net::NetworkTrafficAnnotationTag g_traffic_annotation =
+    net::DefineNetworkTrafficAnnotation("payment_instrument_icon_fetcher", R"(
+        semantics {
+          sender: "Web Payments"
+          description:
+            "Chromium downloads payment instrument icons when registering
+             payment instruments."
+          trigger:
+            "When user navigates to a website to register web payment apps."
+          data:
+            "URL of the required icon to fetch. No user information is sent."
+          destination: WEBSITE
+        }
+        policy {
+          cookies_allowed: false
+          setting:
+            "This feature cannot be disabled in settings. Users can refuse
+             to install web payment apps."
+          policy_exception_justification: "Not implemented."
+        })");
+
+}  // namespace
+
+PaymentInstrumentIconFetcher::PaymentInstrumentIconFetcher()
+    : checking_image_object_index_(0) {}
+PaymentInstrumentIconFetcher::~PaymentInstrumentIconFetcher() {}
+
+void PaymentInstrumentIconFetcher::Start(
+    const std::vector<payments::mojom::ImageObjectPtr>& image_objects,
+    scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
+    PaymentInstrumentIconFetcherCallback callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  for (const auto& obj : image_objects) {
+    image_objects_.emplace_back(payments::mojom::ImageObject::New(obj->src));
+  }
+  DCHECK_GT(image_objects_.size(), 0U);
+
+  callback_ = std::move(callback);
+
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      base::BindOnce(&PaymentInstrumentIconFetcher::StartFromUIThread, this,
+                     std::move(service_worker_context)));
+}
+
+void PaymentInstrumentIconFetcher::StartFromUIThread(
+    scoped_refptr<ServiceWorkerContextWrapper> service_worker_context) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  url_request_context_getter_ =
+      service_worker_context->storage_partition()->GetURLRequestContext();
+  if (!url_request_context_getter_) {
+    PostCallbackToIOThread(std::string());
+    return;
+  }
+
+  FetchIcon();
+}
+
+void PaymentInstrumentIconFetcher::FetchIcon() {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  if (checking_image_object_index_ >= image_objects_.size()) {
+    PostCallbackToIOThread(std::string());
+    return;
+  }
+
+  GURL* icon_src_url = &(image_objects_[checking_image_object_index_]->src);
+  if (!icon_src_url->is_valid()) {
+    checking_image_object_index_++;
+    FetchIcon();
+    return;
+  }
+
+  fetcher_ = net::URLFetcher::Create(*icon_src_url, net::URLFetcher::GET, this,
+                                     g_traffic_annotation);
+  fetcher_->SetRequestContext(url_request_context_getter_.get());
+  fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
+                         net::LOAD_DO_NOT_SAVE_COOKIES);
+  fetcher_->SetStopOnRedirect(true);
+  fetcher_->Start();
+}
+
+void PaymentInstrumentIconFetcher::OnURLFetchComplete(
+    const net::URLFetcher* source) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  DCHECK_EQ(fetcher_.get(), source);
+  std::unique_ptr<net::URLFetcher> free_fetcher = std::move(fetcher_);
+
+  std::string data;
+  if (!(source->GetStatus().is_success() &&
+        source->GetResponseCode() == net::HTTP_OK &&
+        source->GetResponseAsString(&data))) {
+    checking_image_object_index_++;
+    FetchIcon();
+    return;
+  }
+
+  service_manager::mojom::ConnectorRequest connector_request;
+  std::unique_ptr<service_manager::Connector> connector =
+      service_manager::Connector::Create(&connector_request);
+  content::ServiceManagerConnection::GetForProcess()
+      ->GetConnector()
+      ->BindConnectorRequest(std::move(connector_request));
+
+  std::vector<uint8_t> image_data(data.begin(), data.end());
+  data_decoder::DecodeImage(
+      connector.get(), image_data, data_decoder::mojom::ImageCodec::DEFAULT,
+      false, data_decoder::kDefaultMaxSizeInBytes, gfx::Size(),
+      base::Bind(&PaymentInstrumentIconFetcher::DecodeImageCallback, this));
+}
+
+void PaymentInstrumentIconFetcher::DecodeImageCallback(const SkBitmap& bitmap) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  if (bitmap.drawsNothing()) {
+    checking_image_object_index_++;
+    FetchIcon();
+    return;
+  }
+
+  gfx::Image decoded_image = gfx::Image::CreateFrom1xBitmap(bitmap);
+  scoped_refptr<base::RefCountedMemory> raw_data = decoded_image.As1xPNGBytes();
+  std::string base_64;
+  base::Base64Encode(
+      base::StringPiece(raw_data->front_as<char>(), raw_data->size()),
+      &base_64);
+
+  PostCallbackToIOThread(base_64);
+}
+
+void PaymentInstrumentIconFetcher::PostCallbackToIOThread(
+    const std::string& decoded_data) {
+  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+                          base::BindOnce(std::move(callback_), decoded_data));
+}
+
+}  // namespace content
diff --git a/content/browser/payments/payment_instrument_icon_fetcher.h b/content/browser/payments/payment_instrument_icon_fetcher.h
new file mode 100644
index 0000000..a4fc3958
--- /dev/null
+++ b/content/browser/payments/payment_instrument_icon_fetcher.h
@@ -0,0 +1,76 @@
+// 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 CONTENT_BROWSER_PAYMENTS_PAYMENT_INSTRUMENT_ICON_FETCHER_H_
+#define CONTENT_BROWSER_PAYMENTS_PAYMENT_INSTRUMENT_ICON_FETCHER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "components/payments/mojom/payment_app.mojom.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "net/url_request/url_fetcher.h"
+#include "net/url_request/url_fetcher_delegate.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+namespace content {
+
+class PaymentInstrumentIconFetcher
+    : public base::RefCountedThreadSafe<PaymentInstrumentIconFetcher>,
+      private net::URLFetcherDelegate {
+ public:
+  using PaymentInstrumentIconFetcherCallback =
+      base::OnceCallback<void(const std::string&)>;
+
+  PaymentInstrumentIconFetcher();
+
+  // Starts fetching and decoding payment instrument icon from online. The
+  // result will be send back through |callback|.
+  // TODO(gogerald): Right now, we return the first fetchable and decodable icon
+  // with smallest available size. We may add more logic to choose appropriate
+  // icon according to icon size and our usage.
+  void Start(const std::vector<payments::mojom::ImageObjectPtr>& image_objects,
+             scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
+             PaymentInstrumentIconFetcherCallback callback);
+
+ private:
+  friend class base::RefCountedThreadSafe<PaymentInstrumentIconFetcher>;
+  ~PaymentInstrumentIconFetcher() override;
+
+  void StartFromUIThread(
+      scoped_refptr<ServiceWorkerContextWrapper> service_worker_context);
+  void PostCallbackToIOThread(const std::string& decoded_data);
+
+  // data_decoder::mojom::ImageDecoder::DecodeImageCallback.
+  void DecodeImageCallback(const SkBitmap& bitmap);
+
+  // Override net::URLFetcherDelegate.
+  void OnURLFetchComplete(const net::URLFetcher* source) override;
+
+  void FetchIcon();
+
+  // Declared set of image objects of the payment instrument.
+  std::vector<payments::mojom::ImageObjectPtr> image_objects_;
+
+  // The index of the currently checking image object in image_objects_.
+  size_t checking_image_object_index_;
+
+  // The callback to notify after complete.
+  PaymentInstrumentIconFetcherCallback callback_;
+
+  // The url request context getter for fetching icon from online.
+  scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
+
+  // The url fetcher to fetch raw icon from online.
+  std::unique_ptr<net::URLFetcher> fetcher_;
+
+  DISALLOW_COPY_AND_ASSIGN(PaymentInstrumentIconFetcher);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_PAYMENTS_PAYMENT_INSTRUMENT_ICON_FETCHER_H_
\ No newline at end of file
diff --git a/content/public/browser/stored_payment_instrument.h b/content/public/browser/stored_payment_instrument.h
index 858e2c5..5c0f64d 100644
--- a/content/public/browser/stored_payment_instrument.h
+++ b/content/public/browser/stored_payment_instrument.h
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "content/common/content_export.h"
+#include "third_party/skia/include/core/SkBitmap.h"
 #include "url/gurl.h"
 
 namespace content {
@@ -32,6 +33,9 @@
   // Label for this payment instrument.
   std::string name;
 
+  // Decoded icon for this payment instrument.
+  std::unique_ptr<SkBitmap> icon;
+
   // A list of one or more payment method identifiers of the payment methods
   // supported by this payment instrument.
   std::vector<std::string> enabled_methods;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 9837f8b0..063ca757 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -4064,11 +4064,8 @@
   if (request.GetPreviewsState() != WebURLRequest::kPreviewsUnspecified)
     return request.GetPreviewsState() & WebURLRequest::kClientLoFiOn;
 
-  if (!(previews_state_ & CLIENT_LOFI_ON))
+  if (!IsClientLoFiActiveForFrame())
     return false;
-  if (previews_state_ & (PREVIEWS_OFF | PREVIEWS_NO_TRANSFORM)) {
-    return false;
-  }
 
   // Even if this frame is using Server Lo-Fi, https:// images won't be handled
   // by Server Lo-Fi since their requests won't be sent to the Data Saver proxy,
@@ -4078,6 +4075,15 @@
   return true;
 }
 
+bool RenderFrameImpl::IsClientLoFiActiveForFrame() {
+  if (!(previews_state_ & CLIENT_LOFI_ON))
+    return false;
+  if (previews_state_ & (PREVIEWS_OFF | PREVIEWS_NO_TRANSFORM)) {
+    return false;
+  }
+  return true;
+}
+
 void RenderFrameImpl::AbortClientNavigation() {
   Send(new FrameHostMsg_AbortNavigation(routing_id_));
 }
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index f9efacf6..d64f3ce 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -584,6 +584,7 @@
   void DidChangeThemeColor() override;
   void DispatchLoad() override;
   blink::WebEffectiveConnectionType GetEffectiveConnectionType() override;
+  bool IsClientLoFiActiveForFrame() override;
   bool ShouldUseClientLoFiForRequest(const blink::WebURLRequest&) override;
   void AbortClientNavigation() override;
   void DidChangeSelection(bool is_empty_selection) override;
diff --git a/content/renderer/render_frame_impl_browsertest.cc b/content/renderer/render_frame_impl_browsertest.cc
index deff2df1..b7d0598 100644
--- a/content/renderer/render_frame_impl_browsertest.cc
+++ b/content/renderer/render_frame_impl_browsertest.cc
@@ -488,6 +488,38 @@
   }
 }
 
+TEST_F(RenderFrameImplTest, IsClientLoFiActiveForFrame) {
+  const struct {
+    PreviewsState frame_previews_state;
+    bool expected_is_client_lo_fi_active_for_frame;
+  } tests[] = {
+      // With no previews enabled for the frame, no previews should be
+      // activated.
+      {PREVIEWS_UNSPECIFIED, false},
+
+      // Server Lo-Fi should not make Client Lo-Fi active.
+      {SERVER_LOFI_ON, false},
+
+      // PREVIEWS_NO_TRANSFORM and PREVIEWS_OFF should
+      // take precedence over Client Lo-Fi.
+      {CLIENT_LOFI_ON | PREVIEWS_NO_TRANSFORM, false},
+      {CLIENT_LOFI_ON | PREVIEWS_OFF, false},
+
+      // Otherwise, if Client Lo-Fi is enabled on its own or with
+      // SERVER_LOFI_ON, then it is active for the frame.
+      {CLIENT_LOFI_ON, true},
+      {CLIENT_LOFI_ON | SERVER_LOFI_ON, true},
+  };
+
+  for (const auto& test : tests) {
+    SetPreviewsState(frame(), test.frame_previews_state);
+
+    EXPECT_EQ(test.expected_is_client_lo_fi_active_for_frame,
+              frame()->IsClientLoFiActiveForFrame())
+        << (&test - tests);
+  }
+}
+
 TEST_F(RenderFrameImplTest, ShouldUseClientLoFiForRequest) {
   const struct {
     PreviewsState frame_previews_state;
diff --git a/extensions/common/api/bluetooth_low_energy.idl b/extensions/common/api/bluetooth_low_energy.idl
index b35cd98..f0641f57 100644
--- a/extensions/common/api/bluetooth_low_energy.idl
+++ b/extensions/common/api/bluetooth_low_energy.idl
@@ -254,6 +254,12 @@
 
     // Get all the GATT services that were discovered on the remote device with
     // the given device address.
+    //
+    // <em>Note:</em> If service discovery is not yet complete on the device,
+    // this API will return a subset (possibly empty) of services. A work around
+    // is to add a time based delay and/or call repeatedly until the expected
+    // number of services is returned.
+    //
     // |deviceAddress|: The Bluetooth address of the remote device whose GATT
     // services should be returned.
     // |callback|: Called with the list of requested Service objects.
diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc
index beba5c0..abbf784 100644
--- a/gpu/command_buffer/service/context_group.cc
+++ b/gpu/command_buffer/service/context_group.cc
@@ -16,7 +16,6 @@
 #include "gpu/command_buffer/service/framebuffer_manager.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h"
 #include "gpu/command_buffer/service/gpu_preferences.h"
-#include "gpu/command_buffer/service/mailbox_manager_impl.h"
 #include "gpu/command_buffer/service/path_manager.h"
 #include "gpu/command_buffer/service/program_manager.h"
 #include "gpu/command_buffer/service/progress_reporter.h"
@@ -62,11 +61,10 @@
 
 ContextGroup::ContextGroup(
     const GpuPreferences& gpu_preferences,
-    const scoped_refptr<MailboxManager>& mailbox_manager,
+    MailboxManager* mailbox_manager,
     const scoped_refptr<MemoryTracker>& memory_tracker,
-    const scoped_refptr<ShaderTranslatorCache>& shader_translator_cache,
-    const scoped_refptr<FramebufferCompletenessCache>&
-        framebuffer_completeness_cache,
+    ShaderTranslatorCache* shader_translator_cache,
+    FramebufferCompletenessCache* framebuffer_completeness_cache,
     const scoped_refptr<FeatureInfo>& feature_info,
     bool bind_generates_resource,
     ImageManager* image_manager,
@@ -118,8 +116,7 @@
       discardable_manager_(discardable_manager) {
   DCHECK(discardable_manager);
   DCHECK(feature_info_);
-  if (!mailbox_manager_.get())
-    mailbox_manager_ = new MailboxManagerImpl;
+  DCHECK(mailbox_manager_);
   transfer_buffer_manager_ =
       base::MakeUnique<TransferBufferManager>(memory_tracker_.get());
 }
diff --git a/gpu/command_buffer/service/context_group.h b/gpu/command_buffer/service/context_group.h
index 3f9073e..98d864d5 100644
--- a/gpu/command_buffer/service/context_group.h
+++ b/gpu/command_buffer/service/context_group.h
@@ -57,20 +57,18 @@
 // resources.
 class GPU_EXPORT ContextGroup : public base::RefCounted<ContextGroup> {
  public:
-  ContextGroup(
-      const GpuPreferences& gpu_preferences,
-      const scoped_refptr<MailboxManager>& mailbox_manager,
-      const scoped_refptr<MemoryTracker>& memory_tracker,
-      const scoped_refptr<ShaderTranslatorCache>& shader_translator_cache,
-      const scoped_refptr<FramebufferCompletenessCache>&
-          framebuffer_completeness_cache,
-      const scoped_refptr<FeatureInfo>& feature_info,
-      bool bind_generates_resource,
-      ImageManager* image_manager,
-      gpu::ImageFactory* image_factory,
-      ProgressReporter* progress_reporter,
-      const GpuFeatureInfo& gpu_feature_info,
-      ServiceDiscardableManager* discardable_manager);
+  ContextGroup(const GpuPreferences& gpu_preferences,
+               MailboxManager* mailbox_manager,
+               const scoped_refptr<MemoryTracker>& memory_tracker,
+               ShaderTranslatorCache* shader_translator_cache,
+               FramebufferCompletenessCache* framebuffer_completeness_cache,
+               const scoped_refptr<FeatureInfo>& feature_info,
+               bool bind_generates_resource,
+               ImageManager* image_manager,
+               gpu::ImageFactory* image_factory,
+               ProgressReporter* progress_reporter,
+               const GpuFeatureInfo& gpu_feature_info,
+               ServiceDiscardableManager* discardable_manager);
 
   // This should only be called by GLES2Decoder. This must be paired with a
   // call to destroy if it succeeds.
@@ -83,20 +81,16 @@
   // It should only be called by GLES2Decoder.
   void Destroy(GLES2Decoder* decoder, bool have_context);
 
-  MailboxManager* mailbox_manager() const {
-    return mailbox_manager_.get();
-  }
+  MailboxManager* mailbox_manager() const { return mailbox_manager_; }
 
-  MemoryTracker* memory_tracker() const {
-    return memory_tracker_.get();
-  }
+  MemoryTracker* memory_tracker() const { return memory_tracker_.get(); }
 
   ShaderTranslatorCache* shader_translator_cache() const {
-    return shader_translator_cache_.get();
+    return shader_translator_cache_;
   }
 
   FramebufferCompletenessCache* framebuffer_completeness_cache() const {
-    return framebuffer_completeness_cache_.get();
+    return framebuffer_completeness_cache_;
   }
 
   bool bind_generates_resource() {
@@ -252,10 +246,10 @@
   void ReportProgress();
 
   const GpuPreferences& gpu_preferences_;
-  scoped_refptr<MailboxManager> mailbox_manager_;
+  MailboxManager* mailbox_manager_;
   scoped_refptr<MemoryTracker> memory_tracker_;
-  scoped_refptr<ShaderTranslatorCache> shader_translator_cache_;
-  scoped_refptr<FramebufferCompletenessCache> framebuffer_completeness_cache_;
+  ShaderTranslatorCache* shader_translator_cache_;
+  FramebufferCompletenessCache* framebuffer_completeness_cache_;
   std::unique_ptr<TransferBufferManager> transfer_buffer_manager_;
 
   bool enforce_gl_minimums_;
diff --git a/gpu/command_buffer/service/context_group_unittest.cc b/gpu/command_buffer/service/context_group_unittest.cc
index 3ef61f90..dada3dc9 100644
--- a/gpu/command_buffer/service/context_group_unittest.cc
+++ b/gpu/command_buffer/service/context_group_unittest.cc
@@ -12,7 +12,7 @@
 #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h"
 #include "gpu/command_buffer/service/gpu_service_test.h"
 #include "gpu/command_buffer/service/image_manager.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/mailbox_manager_impl.h"
 #include "gpu/command_buffer/service/service_discardable_manager.h"
 #include "gpu/command_buffer/service/test_helper.h"
 #include "gpu/command_buffer/service/texture_manager.h"
@@ -46,8 +46,8 @@
     decoder_.reset(new MockGLES2Decoder(&command_buffer_service_));
     scoped_refptr<FeatureInfo> feature_info = new FeatureInfo;
     group_ = scoped_refptr<ContextGroup>(new ContextGroup(
-        gpu_preferences_, nullptr /* mailbox_manager */,
-        nullptr /* memory_tracker */, nullptr /* shader_translator_cache */,
+        gpu_preferences_, &mailbox_manager_, nullptr /* memory_tracker */,
+        nullptr /* shader_translator_cache */,
         nullptr /* framebuffer_completeness_cache */, feature_info,
         kBindGeneratesResource, &image_manager_, nullptr /* image_factory */,
         nullptr /* progress_reporter */, GpuFeatureInfo(),
@@ -58,6 +58,7 @@
   ImageManager image_manager_;
   ServiceDiscardableManager discardable_manager_;
   FakeCommandBufferServiceBase command_buffer_service_;
+  MailboxManagerImpl mailbox_manager_;
   std::unique_ptr<MockGLES2Decoder> decoder_;
   scoped_refptr<ContextGroup> group_;
 };
diff --git a/gpu/command_buffer/service/framebuffer_completeness_cache.h b/gpu/command_buffer/service/framebuffer_completeness_cache.h
index 932aa62..dd26bf69 100644
--- a/gpu/command_buffer/service/framebuffer_completeness_cache.h
+++ b/gpu/command_buffer/service/framebuffer_completeness_cache.h
@@ -9,7 +9,6 @@
 
 #include "base/containers/hash_tables.h"
 #include "base/macros.h"
-#include "base/memory/ref_counted.h"
 #include "gpu/gpu_export.h"
 
 namespace gpu {
@@ -18,20 +17,15 @@
 // Refcounted wrapper for a hash_set of framebuffer format signatures
 // representing framebuffer configurations that are reported by the GL
 // driver as complete according to glCheckFramebufferStatusEXT.
-class GPU_EXPORT FramebufferCompletenessCache
-    : public base::RefCounted<FramebufferCompletenessCache> {
+class GPU_EXPORT FramebufferCompletenessCache {
  public:
   FramebufferCompletenessCache();
+  ~FramebufferCompletenessCache();
 
   bool IsComplete(const std::string& signature) const;
   void SetComplete(const std::string& signature);
 
- protected:
-  virtual ~FramebufferCompletenessCache();
-
  private:
-  friend class base::RefCounted<FramebufferCompletenessCache>;
-
   typedef base::hash_set<std::string> Map;
 
   Map cache_;
diff --git a/gpu/command_buffer/service/framebuffer_manager.cc b/gpu/command_buffer/service/framebuffer_manager.cc
index e803262..e2333d1 100644
--- a/gpu/command_buffer/service/framebuffer_manager.cc
+++ b/gpu/command_buffer/service/framebuffer_manager.cc
@@ -318,8 +318,7 @@
 FramebufferManager::FramebufferManager(
     uint32_t max_draw_buffers,
     uint32_t max_color_attachments,
-    const scoped_refptr<FramebufferCompletenessCache>&
-        framebuffer_combo_complete_cache)
+    FramebufferCompletenessCache* framebuffer_combo_complete_cache)
     : framebuffer_state_change_count_(1),
       framebuffer_count_(0),
       have_context_(true),
diff --git a/gpu/command_buffer/service/framebuffer_manager.h b/gpu/command_buffer/service/framebuffer_manager.h
index 182032b9..09ab0923 100644
--- a/gpu/command_buffer/service/framebuffer_manager.h
+++ b/gpu/command_buffer/service/framebuffer_manager.h
@@ -317,10 +317,10 @@
 // so we can correctly clear them.
 class GPU_EXPORT FramebufferManager {
  public:
-  FramebufferManager(uint32_t max_draw_buffers,
-                     uint32_t max_color_attachments,
-                     const scoped_refptr<FramebufferCompletenessCache>&
-                         framebuffer_combo_complete_cache);
+  FramebufferManager(
+      uint32_t max_draw_buffers,
+      uint32_t max_color_attachments,
+      FramebufferCompletenessCache* framebuffer_combo_complete_cache);
   ~FramebufferManager();
 
   // Must call before destruction.
@@ -360,7 +360,7 @@
   void StopTracking(Framebuffer* framebuffer);
 
   FramebufferCompletenessCache* GetFramebufferComboCompleteCache() {
-    return framebuffer_combo_complete_cache_.get();
+    return framebuffer_combo_complete_cache_;
   }
 
   // Info for each framebuffer in the system.
@@ -381,7 +381,7 @@
   uint32_t max_draw_buffers_;
   uint32_t max_color_attachments_;
 
-  scoped_refptr<FramebufferCompletenessCache> framebuffer_combo_complete_cache_;
+  FramebufferCompletenessCache* framebuffer_combo_complete_cache_;
 
   DISALLOW_COPY_AND_ASSIGN(FramebufferManager);
 };
diff --git a/gpu/command_buffer/service/framebuffer_manager_unittest.cc b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
index 1ebaeda..ebe5fc8 100644
--- a/gpu/command_buffer/service/framebuffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/framebuffer_manager_unittest.cc
@@ -119,7 +119,7 @@
       : context_type_(context_type),
         manager_(kMaxDrawBuffers,
                  kMaxColorAttachments,
-                 new FramebufferCompletenessCache),
+                 &framebuffer_completeness_cache_),
         feature_info_(new FeatureInfo()) {
     texture_manager_.reset(new TextureManager(
         nullptr, feature_info_.get(), kMaxTextureSize, kMaxCubemapSize,
@@ -158,6 +158,7 @@
   }
 
   ContextType context_type_;
+  FramebufferCompletenessCache framebuffer_completeness_cache_;
   FramebufferManager manager_;
   Framebuffer* framebuffer_;
   scoped_refptr<FeatureInfo> feature_info_;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
index 24723e6..420dd28 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
@@ -357,7 +357,7 @@
   ClientServiceMap<GLuint, GLuint> vertex_array_id_map_;
 
   // Mailboxes
-  scoped_refptr<MailboxManager> mailbox_manager_;
+  MailboxManager* mailbox_manager_;
 
   // State tracking of currently bound 2D textures (client IDs)
   size_t active_texture_unit_;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
index 4dfe0539f..bda9206 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -126,7 +126,8 @@
       cached_depth_mask_(true),
       cached_stencil_front_mask_(static_cast<GLuint>(-1)),
       cached_stencil_back_mask_(static_cast<GLuint>(-1)),
-      shader_language_version_(100) {
+      shader_language_version_(100),
+      shader_translator_cache_(gpu_preferences_) {
   memset(immediate_buffer_, 0xEE, sizeof(immediate_buffer_));
 }
 
@@ -208,9 +209,8 @@
   }
 
   group_ = scoped_refptr<ContextGroup>(new ContextGroup(
-      gpu_preferences_, nullptr /* mailbox_manager */, memory_tracker_,
-      new ShaderTranslatorCache(gpu_preferences_),
-      new FramebufferCompletenessCache, feature_info,
+      gpu_preferences_, &mailbox_manager_, memory_tracker_,
+      &shader_translator_cache_, &framebuffer_completeness_cache_, feature_info,
       normalized_init.bind_generates_resource, &image_manager_,
       nullptr /* image_factory */, nullptr /* progress_reporter */,
       GpuFeatureInfo(), &discardable_manager_));
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
index d268fc1..8d717f8 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
@@ -22,6 +22,7 @@
 #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h"
 #include "gpu/command_buffer/service/gpu_preferences.h"
 #include "gpu/command_buffer/service/image_manager.h"
+#include "gpu/command_buffer/service/mailbox_manager_impl.h"
 #include "gpu/command_buffer/service/program_manager.h"
 #include "gpu/command_buffer/service/query_manager.h"
 #include "gpu/command_buffer/service/renderbuffer_manager.h"
@@ -767,7 +768,10 @@
   void SetupInitStateManualExpectationsForDoLineWidth(GLfloat width);
 
   GpuPreferences gpu_preferences_;
-  gles2::ImageManager image_manager_;
+  MailboxManagerImpl mailbox_manager_;
+  ShaderTranslatorCache shader_translator_cache_;
+  FramebufferCompletenessCache framebuffer_completeness_cache_;
+  ImageManager image_manager_;
   ServiceDiscardableManager discardable_manager_;
   scoped_refptr<ContextGroup> group_;
   MockGLStates gl_states_;
diff --git a/gpu/command_buffer/service/mailbox_manager.cc b/gpu/command_buffer/service/mailbox_manager.cc
index 629b269..be559781 100644
--- a/gpu/command_buffer/service/mailbox_manager.cc
+++ b/gpu/command_buffer/service/mailbox_manager.cc
@@ -5,6 +5,7 @@
 #include "gpu/command_buffer/service/mailbox_manager.h"
 
 #include "base/command_line.h"
+#include "base/memory/ptr_util.h"
 #include "gpu/command_buffer/service/gpu_preferences.h"
 #include "gpu/command_buffer/service/mailbox_manager_impl.h"
 #include "gpu/command_buffer/service/mailbox_manager_sync.h"
@@ -13,11 +14,11 @@
 namespace gles2 {
 
 // static
-scoped_refptr<MailboxManager> MailboxManager::Create(
+std::unique_ptr<MailboxManager> MailboxManager::Create(
     const GpuPreferences& gpu_preferences) {
   if (gpu_preferences.enable_threaded_texture_mailboxes)
-    return scoped_refptr<MailboxManager>(new MailboxManagerSync);
-  return scoped_refptr<MailboxManager>(new MailboxManagerImpl);
+    return base::MakeUnique<MailboxManagerSync>();
+  return base::MakeUnique<MailboxManagerImpl>();
 }
 
 }  // namespage gles2
diff --git a/gpu/command_buffer/service/mailbox_manager.h b/gpu/command_buffer/service/mailbox_manager.h
index 1d9ce635..3c7234c 100644
--- a/gpu/command_buffer/service/mailbox_manager.h
+++ b/gpu/command_buffer/service/mailbox_manager.h
@@ -5,8 +5,9 @@
 #ifndef GPU_COMMAND_BUFFER_SERVICE_MAILBOX_MANAGER_H_
 #define GPU_COMMAND_BUFFER_SERVICE_MAILBOX_MANAGER_H_
 
+#include <memory>
+
 #include "base/macros.h"
-#include "base/memory/ref_counted.h"
 #include "gpu/command_buffer/common/mailbox.h"
 #include "gpu/gpu_export.h"
 
@@ -20,10 +21,9 @@
 class TextureBase;
 
 // Manages resources scoped beyond the context or context group level.
-class GPU_EXPORT MailboxManager : public base::RefCounted<MailboxManager> {
+class GPU_EXPORT MailboxManager {
  public:
-  static scoped_refptr<MailboxManager> Create(
-      const GpuPreferences& gpu_preferences);
+  virtual ~MailboxManager() {}
 
   // Look up the texture definition from the named mailbox.
   virtual TextureBase* ConsumeTexture(const Mailbox& mailbox) = 0;
@@ -41,14 +41,8 @@
   // Destroy any mailbox that reference the given texture.
   virtual void TextureDeleted(TextureBase* texture) = 0;
 
- protected:
-  MailboxManager() {}
-  virtual ~MailboxManager() {}
-
- private:
-  friend class base::RefCounted<MailboxManager>;
-
-  DISALLOW_COPY_AND_ASSIGN(MailboxManager);
+  static std::unique_ptr<MailboxManager> Create(
+      const GpuPreferences& gpu_preferences);
 };
 
 }  // namespage gles2
diff --git a/gpu/command_buffer/service/mailbox_manager_impl.h b/gpu/command_buffer/service/mailbox_manager_impl.h
index ff3d4a80..7cde11d9 100644
--- a/gpu/command_buffer/service/mailbox_manager_impl.h
+++ b/gpu/command_buffer/service/mailbox_manager_impl.h
@@ -24,6 +24,7 @@
 class GPU_EXPORT MailboxManagerImpl : public MailboxManager {
  public:
   MailboxManagerImpl();
+  ~MailboxManagerImpl() override;
 
   // MailboxManager implementation:
   TextureBase* ConsumeTexture(const Mailbox& mailbox) override;
@@ -33,12 +34,7 @@
   void PullTextureUpdates(const SyncToken& token) override {}
   void TextureDeleted(TextureBase* texture) override;
 
- protected:
-  ~MailboxManagerImpl() override;
-
  private:
-  friend class base::RefCounted<MailboxManager>;
-
   void InsertTexture(const Mailbox& mailbox, TextureBase* texture);
 
   // This is a bidirectional map between mailbox and textures. We can have
diff --git a/gpu/command_buffer/service/mailbox_manager_sync.h b/gpu/command_buffer/service/mailbox_manager_sync.h
index a1a64aaa..33f4e36 100644
--- a/gpu/command_buffer/service/mailbox_manager_sync.h
+++ b/gpu/command_buffer/service/mailbox_manager_sync.h
@@ -27,6 +27,7 @@
 class GPU_EXPORT MailboxManagerSync : public MailboxManager {
  public:
   MailboxManagerSync();
+  ~MailboxManagerSync() override;
 
   // MailboxManager implementation:
   Texture* ConsumeTexture(const Mailbox& mailbox) override;
@@ -37,12 +38,8 @@
   void TextureDeleted(TextureBase* texture) override;
 
  private:
-  friend class base::RefCounted<MailboxManager>;
-
   static bool SkipTextureWorkarounds(const Texture* texture);
 
-  ~MailboxManagerSync() override;
-
   class TextureGroup : public base::RefCounted<TextureGroup> {
    public:
     explicit TextureGroup(const TextureDefinition& definition);
diff --git a/gpu/command_buffer/service/mailbox_manager_unittest.cc b/gpu/command_buffer/service/mailbox_manager_unittest.cc
index a1935883..711b890 100644
--- a/gpu/command_buffer/service/mailbox_manager_unittest.cc
+++ b/gpu/command_buffer/service/mailbox_manager_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/macros.h"
+#include "base/memory/ptr_util.h"
 #include "gpu/command_buffer/common/sync_token.h"
 #include "gpu/command_buffer/service/feature_info.h"
 #include "gpu/command_buffer/service/gpu_service_test.h"
@@ -33,14 +34,14 @@
   void SetUp() override {
     GpuServiceTest::SetUp();
     feature_info_ = new FeatureInfo;
-    manager_ = new MailboxManagerImpl;
+    manager_ = base::MakeUnique<MailboxManagerImpl>();
     DCHECK(!manager_->UsesSync());
   }
 
   virtual void SetUpWithSynchronizer() {
     GpuServiceTest::SetUp();
     feature_info_ = new FeatureInfo;
-    manager_ = new MailboxManagerSync();
+    manager_ = base::MakeUnique<MailboxManagerSync>();
     DCHECK(manager_->UsesSync());
   }
 
@@ -82,7 +83,7 @@
 
   void DestroyTexture(TextureBase* texture) { delete texture; }
 
-  scoped_refptr<MailboxManager> manager_;
+  std::unique_ptr<MailboxManager> manager_;
 
  private:
   scoped_refptr<FeatureInfo> feature_info_;
@@ -195,7 +196,7 @@
  protected:
   void SetUp() override {
     MailboxManagerTest::SetUpWithSynchronizer();
-    manager2_ = new MailboxManagerSync();
+    manager2_ = base::MakeUnique<MailboxManagerSync>();
     context_ = new gl::GLContextStub();
     surface_ = new gl::GLSurfaceStub();
     context_->MakeCurrent(surface_.get());
@@ -250,7 +251,7 @@
     MailboxManagerTest::TearDown();
   }
 
-  scoped_refptr<MailboxManager> manager2_;
+  std::unique_ptr<MailboxManager> manager2_;
   scoped_refptr<gl::GLContext> context_;
   scoped_refptr<gl::GLSurface> surface_;
 
diff --git a/gpu/command_buffer/service/service_discardable_manager_unittest.cc b/gpu/command_buffer/service/service_discardable_manager_unittest.cc
index 6cdffaf..9ddcb12 100644
--- a/gpu/command_buffer/service/service_discardable_manager_unittest.cc
+++ b/gpu/command_buffer/service/service_discardable_manager_unittest.cc
@@ -8,7 +8,7 @@
 #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h"
 #include "gpu/command_buffer/service/gpu_service_test.h"
 #include "gpu/command_buffer/service/image_manager.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/mailbox_manager_impl.h"
 #include "gpu/command_buffer/service/memory_tracking.h"
 #include "gpu/command_buffer/service/mocks.h"
 #include "gpu/command_buffer/service/test_helper.h"
@@ -69,10 +69,10 @@
     GpuServiceTest::SetUp();
     decoder_.reset(new MockGLES2Decoder(&command_buffer_service_));
     feature_info_ = new FeatureInfo();
-    context_group_ = scoped_refptr<ContextGroup>(
-        new ContextGroup(gpu_preferences_, nullptr, nullptr, nullptr, nullptr,
-                         feature_info_, false, &image_manager_, nullptr,
-                         nullptr, GpuFeatureInfo(), &discardable_manager_));
+    context_group_ = scoped_refptr<ContextGroup>(new ContextGroup(
+        gpu_preferences_, &mailbox_manager_, nullptr, nullptr, nullptr,
+        feature_info_, false, &image_manager_, nullptr, nullptr,
+        GpuFeatureInfo(), &discardable_manager_));
     TestHelper::SetupContextGroupInitExpectations(
         gl_.get(), DisallowedFeatures(), "", "", CONTEXT_TYPE_OPENGLES2, false);
     context_group_->Initialize(decoder_.get(), CONTEXT_TYPE_OPENGLES2,
@@ -113,7 +113,8 @@
         .RetiresOnSaturation();
   }
 
-  gles2::ImageManager image_manager_;
+  MailboxManagerImpl mailbox_manager_;
+  ImageManager image_manager_;
   ServiceDiscardableManager discardable_manager_;
   GpuPreferences gpu_preferences_;
   scoped_refptr<FeatureInfo> feature_info_;
diff --git a/gpu/command_buffer/service/shader_translator_cache.h b/gpu/command_buffer/service/shader_translator_cache.h
index 67b9158d..b764b75 100644
--- a/gpu/command_buffer/service/shader_translator_cache.h
+++ b/gpu/command_buffer/service/shader_translator_cache.h
@@ -27,10 +27,10 @@
 // TODO(backer): Investigate using glReleaseShaderCompiler as an alternative to
 // to this cache.
 class GPU_EXPORT ShaderTranslatorCache
-    : public base::RefCounted<ShaderTranslatorCache>,
-      public NON_EXPORTED_BASE(ShaderTranslator::DestructionObserver) {
+    : public NON_EXPORTED_BASE(ShaderTranslator::DestructionObserver) {
  public:
   explicit ShaderTranslatorCache(const GpuPreferences& gpu_preferences);
+  ~ShaderTranslatorCache() override;
 
   // ShaderTranslator::DestructionObserver implementation
   void OnDestruct(ShaderTranslator* translator) override;
@@ -43,9 +43,7 @@
       ShCompileOptions driver_bug_workarounds);
 
  private:
-  friend class base::RefCounted<ShaderTranslatorCache>;
   friend class ShaderTranslatorCacheTest_InitParamComparable_Test;
-  ~ShaderTranslatorCache() override;
 
   // Parameters passed into ShaderTranslator::Init
   struct ShaderTranslatorInitParams {
diff --git a/gpu/command_buffer/tests/fuzzer_main.cc b/gpu/command_buffer/tests/fuzzer_main.cc
index 551364d0..f7d8f48 100644
--- a/gpu/command_buffer/tests/fuzzer_main.cc
+++ b/gpu/command_buffer/tests/fuzzer_main.cc
@@ -90,12 +90,21 @@
     "GL_OES_texture_half_float_linear";
 #endif
 
+GpuPreferences GetGpuPreferences() {
+  GpuPreferences preferences;
+#if defined(GPU_FUZZER_USE_PASSTHROUGH_CMD_DECODER)
+  preferences.use_passthrough_cmd_decoder = true;
+#endif
+  return preferences;
+}
+
 class CommandBufferSetup {
  public:
   CommandBufferSetup()
       : atexit_manager_(),
-        mailbox_manager_(new gles2::MailboxManagerImpl),
-        share_group_(new gl::GLShareGroup) {
+        gpu_preferences_(GetGpuPreferences()),
+        share_group_(new gl::GLShareGroup),
+        translator_cache_(gpu_preferences_) {
     logging::SetMinLogLevel(logging::LOG_FATAL);
     base::CommandLine::Init(0, NULL);
 
@@ -104,7 +113,6 @@
 
 #if defined(GPU_FUZZER_USE_PASSTHROUGH_CMD_DECODER)
     command_line->AppendSwitch(switches::kUsePassthroughCmdDecoder);
-    gpu_preferences_.use_passthrough_cmd_decoder = true;
     recreate_context_ = true;
 #endif
 
@@ -133,9 +141,6 @@
     InitContext();
     gl::GLSurfaceTestSupport::InitializeOneOffWithMockBindings();
 #endif  // defined(GPU_FUZZER_USE_STUB)
-
-    translator_cache_ = new gles2::ShaderTranslatorCache(gpu_preferences_);
-    completeness_cache_ = new gles2::FramebufferCompletenessCache;
   }
 
   void InitDecoder() {
@@ -147,8 +152,8 @@
     scoped_refptr<gles2::FeatureInfo> feature_info =
         new gles2::FeatureInfo();
     scoped_refptr<gles2::ContextGroup> context_group = new gles2::ContextGroup(
-        gpu_preferences_, mailbox_manager_.get(), nullptr /* memory_tracker */,
-        translator_cache_, completeness_cache_, feature_info,
+        gpu_preferences_, &mailbox_manager_, nullptr /* memory_tracker */,
+        &translator_cache_, &completeness_cache_, feature_info,
         true /* bind_generates_resource */, &image_manager_,
         nullptr /* image_factory */, nullptr /* progress_reporter */,
         GpuFeatureInfo(), &discardable_manager_);
@@ -264,7 +269,7 @@
 
   GpuPreferences gpu_preferences_;
 
-  scoped_refptr<gles2::MailboxManager> mailbox_manager_;
+  gles2::MailboxManagerImpl mailbox_manager_;
   scoped_refptr<gl::GLShareGroup> share_group_;
   SyncPointManager sync_point_manager_;
   gles2::ImageManager image_manager_;
@@ -274,8 +279,8 @@
   scoped_refptr<gl::GLSurface> surface_;
   scoped_refptr<gl::GLContext> context_;
 
-  scoped_refptr<gles2::ShaderTranslatorCache> translator_cache_;
-  scoped_refptr<gles2::FramebufferCompletenessCache> completeness_cache_;
+  gles2::ShaderTranslatorCache translator_cache_;
+  gles2::FramebufferCompletenessCache completeness_cache_;
 
   std::unique_ptr<CommandBufferDirect> command_buffer_;
 
diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc
index 5fa84d47..795052a3 100644
--- a/gpu/command_buffer/tests/gl_manager.cc
+++ b/gpu/command_buffer/tests/gl_manager.cc
@@ -31,7 +31,6 @@
 #include "gpu/command_buffer/service/gl_context_virtual.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
-#include "gpu/command_buffer/service/mailbox_manager_impl.h"
 #include "gpu/command_buffer/service/memory_tracking.h"
 #include "gpu/command_buffer/service/service_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -257,11 +256,12 @@
   InitializeGpuPreferencesForTestingFromCommandLine(command_line,
                                                     &gpu_preferences_);
 
-  gles2::MailboxManager* mailbox_manager = NULL;
   if (options.share_mailbox_manager) {
-    mailbox_manager = options.share_mailbox_manager->mailbox_manager();
+    mailbox_manager_ = options.share_mailbox_manager->mailbox_manager();
   } else if (options.share_group_manager) {
-    mailbox_manager = options.share_group_manager->mailbox_manager();
+    mailbox_manager_ = options.share_group_manager->mailbox_manager();
+  } else {
+    mailbox_manager_ = &owned_mailbox_manager_;
   }
 
   gl::GLShareGroup* share_group = NULL;
@@ -285,8 +285,6 @@
     real_gl_context = options.virtual_manager->context();
   }
 
-  mailbox_manager_ =
-      mailbox_manager ? mailbox_manager : new gles2::MailboxManagerImpl;
   share_group_ = share_group ? share_group : new gl::GLShareGroup;
 
   gles2::ContextCreationAttribHelper attribs;
@@ -305,15 +303,16 @@
   attribs.offscreen_framebuffer_size = options.size;
   attribs.buffer_preserved = options.preserve_backbuffer;
   attribs.bind_generates_resource = options.bind_generates_resource;
+  translator_cache_ =
+      base::MakeUnique<gles2::ShaderTranslatorCache>(gpu_preferences_);
 
   if (!context_group) {
     GpuDriverBugWorkarounds gpu_driver_bug_workaround(&command_line);
     scoped_refptr<gles2::FeatureInfo> feature_info =
         new gles2::FeatureInfo(command_line, gpu_driver_bug_workaround);
     context_group = new gles2::ContextGroup(
-        gpu_preferences_, mailbox_manager_.get(), nullptr /* memory_tracker */,
-        new gpu::gles2::ShaderTranslatorCache(gpu_preferences_),
-        new gpu::gles2::FramebufferCompletenessCache, feature_info,
+        gpu_preferences_, mailbox_manager_, nullptr /* memory_tracker */,
+        translator_cache_.get(), &completeness_cache_, feature_info,
         options.bind_generates_resource, &image_manager_, options.image_factory,
         nullptr /* progress_reporter */, GpuFeatureInfo(),
         &discardable_manager_);
diff --git a/gpu/command_buffer/tests/gl_manager.h b/gpu/command_buffer/tests/gl_manager.h
index 2cc2dea..01f8c80 100644
--- a/gpu/command_buffer/tests/gl_manager.h
+++ b/gpu/command_buffer/tests/gl_manager.h
@@ -16,6 +16,7 @@
 #include "gpu/command_buffer/service/feature_info.h"
 #include "gpu/command_buffer/service/gpu_preferences.h"
 #include "gpu/command_buffer/service/image_manager.h"
+#include "gpu/command_buffer/service/mailbox_manager_impl.h"
 #include "gpu/command_buffer/service/service_discardable_manager.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/gpu_memory_buffer.h"
@@ -109,9 +110,7 @@
     return decoder_.get();
   }
 
-  gles2::MailboxManager* mailbox_manager() const {
-    return mailbox_manager_.get();
-  }
+  gles2::MailboxManager* mailbox_manager() const { return mailbox_manager_; }
 
   gl::GLShareGroup* share_group() const { return share_group_.get(); }
 
@@ -155,7 +154,12 @@
 
   gpu::GpuPreferences gpu_preferences_;
 
-  scoped_refptr<gles2::MailboxManager> mailbox_manager_;
+  gles2::MailboxManagerImpl owned_mailbox_manager_;
+  gles2::ImageManager image_manager_;
+  ServiceDiscardableManager discardable_manager_;
+  std::unique_ptr<gles2::ShaderTranslatorCache> translator_cache_;
+  gles2::FramebufferCompletenessCache completeness_cache_;
+  gles2::MailboxManager* mailbox_manager_ = nullptr;
   scoped_refptr<gl::GLShareGroup> share_group_;
   std::unique_ptr<CommandBufferDirect> command_buffer_;
   std::unique_ptr<gles2::GLES2Decoder> decoder_;
@@ -165,9 +169,6 @@
   std::unique_ptr<TransferBuffer> transfer_buffer_;
   std::unique_ptr<gles2::GLES2Implementation> gles2_implementation_;
 
-  gles2::ImageManager image_manager_;
-  ServiceDiscardableManager discardable_manager_;
-
   uint64_t next_fence_sync_release_ = 1;
 
   bool use_iosurface_memory_buffers_ = false;
diff --git a/gpu/gles2_conform_support/egl/context.cc b/gpu/gles2_conform_support/egl/context.cc
index 39613b68..d61fabb 100644
--- a/gpu/gles2_conform_support/egl/context.cc
+++ b/gpu/gles2_conform_support/egl/context.cc
@@ -14,7 +14,6 @@
 #include "gpu/command_buffer/client/transfer_buffer.h"
 #include "gpu/command_buffer/service/context_group.h"
 #include "gpu/command_buffer/service/image_manager.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
 #include "gpu/command_buffer/service/memory_tracking.h"
 #include "gpu/command_buffer/service/service_discardable_manager.h"
 #include "gpu/command_buffer/service/transfer_buffer_manager.h"
@@ -54,7 +53,8 @@
       config_(config),
       is_current_in_some_thread_(false),
       is_destroyed_(false),
-      gpu_driver_bug_workarounds_(base::CommandLine::ForCurrentProcess()) {}
+      gpu_driver_bug_workarounds_(base::CommandLine::ForCurrentProcess()),
+      translator_cache_(gpu::GpuPreferences()) {}
 
 Context::~Context() {
   // We might not have a surface, so we must lose the context.  Cleanup will
@@ -258,10 +258,8 @@
   scoped_refptr<gpu::gles2::FeatureInfo> feature_info(
       new gpu::gles2::FeatureInfo(gpu_driver_bug_workarounds_));
   scoped_refptr<gpu::gles2::ContextGroup> group(new gpu::gles2::ContextGroup(
-      gpu_preferences_, nullptr /* mailbox_manager */,
-      nullptr /* memory_tracker */,
-      new gpu::gles2::ShaderTranslatorCache(gpu_preferences_),
-      new gpu::gles2::FramebufferCompletenessCache, feature_info, true,
+      gpu::GpuPreferences(), &mailbox_manager_, nullptr /* memory_tracker */,
+      &translator_cache_, &completeness_cache_, feature_info, true,
       &image_manager_, nullptr /* image_factory */,
       nullptr /* progress_reporter */, gpu::GpuFeatureInfo(),
       &discardable_manager_));
diff --git a/gpu/gles2_conform_support/egl/context.h b/gpu/gles2_conform_support/egl/context.h
index f90ad445..f0bb5d53 100644
--- a/gpu/gles2_conform_support/egl/context.h
+++ b/gpu/gles2_conform_support/egl/context.h
@@ -16,6 +16,7 @@
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
 #include "gpu/command_buffer/service/gpu_preferences.h"
 #include "gpu/command_buffer/service/image_manager.h"
+#include "gpu/command_buffer/service/mailbox_manager_impl.h"
 #include "gpu/command_buffer/service/service_discardable_manager.h"
 #include "gpu/config/gpu_driver_bug_workarounds.h"
 #include "ui/gfx/native_widget_types.h"
@@ -104,11 +105,16 @@
   const Config* config_;
   bool is_current_in_some_thread_;
   bool is_destroyed_;
-  gpu::GpuPreferences gpu_preferences_;
   const gpu::GpuDriverBugWorkarounds gpu_driver_bug_workarounds_;
   std::unique_ptr<gpu::TransferBufferManager> transfer_buffer_manager_;
   std::unique_ptr<gpu::CommandBufferDirect> command_buffer_;
   std::unique_ptr<gpu::gles2::GLES2CmdHelper> gles2_cmd_helper_;
+
+  gpu::gles2::MailboxManagerImpl mailbox_manager_;
+  gpu::gles2::ImageManager image_manager_;
+  gpu::ServiceDiscardableManager discardable_manager_;
+  gpu::gles2::ShaderTranslatorCache translator_cache_;
+  gpu::gles2::FramebufferCompletenessCache completeness_cache_;
   std::unique_ptr<gpu::gles2::GLES2Decoder> decoder_;
   std::unique_ptr<gpu::TransferBuffer> transfer_buffer_;
 
@@ -116,9 +122,6 @@
 
   std::unique_ptr<gpu::gles2::GLES2Interface> client_gl_context_;
 
-  gpu::gles2::ImageManager image_manager_;
-  gpu::ServiceDiscardableManager discardable_manager_;
-
   DISALLOW_COPY_AND_ASSIGN(Context);
 };
 
diff --git a/gpu/ipc/gpu_in_process_thread_service.cc b/gpu/ipc/gpu_in_process_thread_service.cc
index b21b864..d1aedd6 100644
--- a/gpu/ipc/gpu_in_process_thread_service.cc
+++ b/gpu/ipc/gpu_in_process_thread_service.cc
@@ -30,24 +30,6 @@
   return true;
 }
 
-scoped_refptr<gpu::gles2::ShaderTranslatorCache>
-GpuInProcessThreadService::shader_translator_cache() {
-  if (!shader_translator_cache_) {
-    shader_translator_cache_ = make_scoped_refptr(
-        new gpu::gles2::ShaderTranslatorCache(gpu_preferences()));
-  }
-  return shader_translator_cache_;
-}
-
-scoped_refptr<gpu::gles2::FramebufferCompletenessCache>
-GpuInProcessThreadService::framebuffer_completeness_cache() {
-  if (!framebuffer_completeness_cache_.get()) {
-    framebuffer_completeness_cache_ =
-        make_scoped_refptr(new gpu::gles2::FramebufferCompletenessCache);
-  }
-  return framebuffer_completeness_cache_;
-}
-
 gpu::SyncPointManager* GpuInProcessThreadService::sync_point_manager() {
   return sync_point_manager_;
 }
diff --git a/gpu/ipc/gpu_in_process_thread_service.h b/gpu/ipc/gpu_in_process_thread_service.h
index eb77ee27..fdf2703 100644
--- a/gpu/ipc/gpu_in_process_thread_service.h
+++ b/gpu/ipc/gpu_in_process_thread_service.h
@@ -30,10 +30,6 @@
   void ScheduleTask(const base::Closure& task) override;
   void ScheduleDelayedWork(const base::Closure& task) override;
   bool UseVirtualizedGLContexts() override;
-  scoped_refptr<gpu::gles2::ShaderTranslatorCache> shader_translator_cache()
-      override;
-  scoped_refptr<gpu::gles2::FramebufferCompletenessCache>
-  framebuffer_completeness_cache() override;
   gpu::SyncPointManager* sync_point_manager() override;
   void AddRef() const override;
   void Release() const override;
@@ -47,9 +43,6 @@
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
 
   gpu::SyncPointManager* sync_point_manager_;  // Non-owning.
-  scoped_refptr<gpu::gles2::ShaderTranslatorCache> shader_translator_cache_;
-  scoped_refptr<gpu::gles2::FramebufferCompletenessCache>
-      framebuffer_completeness_cache_;
 
   DISALLOW_COPY_AND_ASSIGN(GpuInProcessThreadService);
 };
diff --git a/gpu/ipc/in_process_command_buffer.cc b/gpu/ipc/in_process_command_buffer.cc
index 4f70fead..3b28b89a 100644
--- a/gpu/ipc/in_process_command_buffer.cc
+++ b/gpu/ipc/in_process_command_buffer.cc
@@ -32,12 +32,10 @@
 #include "gpu/command_buffer/service/gl_context_virtual.h"
 #include "gpu/command_buffer/service/gpu_preferences.h"
 #include "gpu/command_buffer/service/image_factory.h"
-#include "gpu/command_buffer/service/image_manager.h"
 #include "gpu/command_buffer/service/mailbox_manager.h"
 #include "gpu/command_buffer/service/memory_program_cache.h"
 #include "gpu/command_buffer/service/memory_tracking.h"
 #include "gpu/command_buffer/service/query_manager.h"
-#include "gpu/command_buffer/service/service_discardable_manager.h"
 #include "gpu/command_buffer/service/service_utils.h"
 #include "gpu/command_buffer/service/sync_point_manager.h"
 #include "gpu/command_buffer/service/transfer_buffer_manager.h"
@@ -126,15 +124,28 @@
 }  // anonyous namespace
 
 InProcessCommandBuffer::Service::Service(const GpuPreferences& gpu_preferences)
-    : gpu_preferences_(gpu_preferences),
-      gpu_driver_bug_workarounds_(base::CommandLine::ForCurrentProcess()) {}
+    : Service(gpu_preferences, nullptr, nullptr) {}
 
 InProcessCommandBuffer::Service::Service(
     gpu::gles2::MailboxManager* mailbox_manager,
     scoped_refptr<gl::GLShareGroup> share_group)
-    : gpu_driver_bug_workarounds_(base::CommandLine::ForCurrentProcess()),
+    : Service(GpuPreferences(), mailbox_manager, share_group) {}
+
+InProcessCommandBuffer::Service::Service(
+    const GpuPreferences& gpu_preferences,
+    gpu::gles2::MailboxManager* mailbox_manager,
+    scoped_refptr<gl::GLShareGroup> share_group)
+    : gpu_preferences_(gpu_preferences),
+      gpu_driver_bug_workarounds_(base::CommandLine::ForCurrentProcess()),
       mailbox_manager_(mailbox_manager),
-      share_group_(share_group) {}
+      share_group_(share_group),
+      shader_translator_cache_(gpu_preferences_) {
+  if (!mailbox_manager_) {
+    // TODO(piman): have embedders own the mailbox manager.
+    owned_mailbox_manager_ = gles2::MailboxManager::Create(gpu_preferences_);
+    mailbox_manager_ = owned_mailbox_manager_.get();
+  }
+}
 
 InProcessCommandBuffer::Service::~Service() {}
 
@@ -153,14 +164,6 @@
   return share_group_;
 }
 
-scoped_refptr<gles2::MailboxManager>
-InProcessCommandBuffer::Service::mailbox_manager() {
-  if (!mailbox_manager_.get()) {
-    mailbox_manager_ = gles2::MailboxManager::Create(gpu_preferences());
-  }
-  return mailbox_manager_;
-}
-
 gpu::gles2::ProgramCache* InProcessCommandBuffer::Service::program_cache() {
   if (!program_cache_.get() &&
       (gl::g_current_gl_driver->ext.b_GL_ARB_get_program_binary ||
@@ -178,20 +181,6 @@
   return program_cache_.get();
 }
 
-gles2::ImageManager* InProcessCommandBuffer::Service::image_manager() {
-  if (!image_manager_)
-    image_manager_.reset(new gles2::ImageManager());
-  return image_manager_.get();
-}
-
-ServiceDiscardableManager*
-InProcessCommandBuffer::Service::discardable_manager() {
-  if (!discardable_manager_) {
-    discardable_manager_.reset(new ServiceDiscardableManager());
-  }
-  return discardable_manager_.get();
-}
-
 InProcessCommandBuffer::InProcessCommandBuffer(
     const scoped_refptr<Service>& service)
     : command_buffer_id_(CommandBufferId::FromUnsafeValue(
diff --git a/gpu/ipc/in_process_command_buffer.h b/gpu/ipc/in_process_command_buffer.h
index a058e16..d36f0c71 100644
--- a/gpu/ipc/in_process_command_buffer.h
+++ b/gpu/ipc/in_process_command_buffer.h
@@ -29,6 +29,8 @@
 #include "gpu/command_buffer/service/context_group.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
 #include "gpu/command_buffer/service/gpu_preferences.h"
+#include "gpu/command_buffer/service/image_manager.h"
+#include "gpu/command_buffer/service/service_discardable_manager.h"
 #include "gpu/config/gpu_driver_bug_workarounds.h"
 #include "gpu/gpu_export.h"
 #include "gpu/ipc/service/image_transport_surface_delegate.h"
@@ -187,7 +189,7 @@
   // The serializer interface to the GPU service (i.e. thread).
   class Service {
    public:
-    Service(const gpu::GpuPreferences& gpu_preferences);
+    explicit Service(const gpu::GpuPreferences& gpu_preferences);
     Service(gles2::MailboxManager* mailbox_manager,
             scoped_refptr<gl::GLShareGroup> share_group);
 
@@ -204,30 +206,42 @@
     virtual void ScheduleDelayedWork(const base::Closure& task) = 0;
 
     virtual bool UseVirtualizedGLContexts() = 0;
-    virtual scoped_refptr<gles2::ShaderTranslatorCache>
-    shader_translator_cache() = 0;
-    virtual scoped_refptr<gles2::FramebufferCompletenessCache>
-    framebuffer_completeness_cache() = 0;
     virtual SyncPointManager* sync_point_manager() = 0;
+    virtual bool BlockThreadOnWaitSyncToken() const = 0;
+
     const GpuPreferences& gpu_preferences();
     const GpuDriverBugWorkarounds& gpu_driver_bug_workarounds();
     scoped_refptr<gl::GLShareGroup> share_group();
-    scoped_refptr<gles2::MailboxManager> mailbox_manager();
+    gles2::MailboxManager* mailbox_manager() { return mailbox_manager_; }
     gles2::ProgramCache* program_cache();
-    gles2::ImageManager* image_manager();
-    ServiceDiscardableManager* discardable_manager();
-    virtual bool BlockThreadOnWaitSyncToken() const = 0;
+    gles2::ImageManager* image_manager() { return &image_manager_; }
+    ServiceDiscardableManager* discardable_manager() {
+      return &discardable_manager_;
+    }
+    gles2::ShaderTranslatorCache* shader_translator_cache() {
+      return &shader_translator_cache_;
+    }
+    gles2::FramebufferCompletenessCache* framebuffer_completeness_cache() {
+      return &framebuffer_completeness_cache_;
+    }
 
    protected:
+    Service(const gpu::GpuPreferences& gpu_preferences,
+            gles2::MailboxManager* mailbox_manager,
+            scoped_refptr<gl::GLShareGroup> share_group);
+
     const GpuPreferences gpu_preferences_;
     const GpuDriverBugWorkarounds gpu_driver_bug_workarounds_;
-    scoped_refptr<gles2::MailboxManager> mailbox_manager_;
+    std::unique_ptr<gles2::MailboxManager> owned_mailbox_manager_;
+    gles2::MailboxManager* mailbox_manager_ = nullptr;
     scoped_refptr<gl::GLShareGroup> share_group_;
     std::unique_ptr<gles2::ProgramCache> program_cache_;
     // No-op default initialization is used in in-process mode.
     GpuProcessActivityFlags activity_flags_;
-    std::unique_ptr<gles2::ImageManager> image_manager_;
-    std::unique_ptr<ServiceDiscardableManager> discardable_manager_;
+    gles2::ImageManager image_manager_;
+    ServiceDiscardableManager discardable_manager_;
+    gles2::ShaderTranslatorCache shader_translator_cache_;
+    gles2::FramebufferCompletenessCache framebuffer_completeness_cache_;
   };
 
  private:
diff --git a/gpu/ipc/service/gpu_channel.cc b/gpu/ipc/service/gpu_channel.cc
index bcae75e..c6a1efb 100644
--- a/gpu/ipc/service/gpu_channel.cc
+++ b/gpu/ipc/service/gpu_channel.cc
@@ -797,10 +797,7 @@
     GpuChannelManager* gpu_channel_manager,
     Scheduler* scheduler,
     SyncPointManager* sync_point_manager,
-    GpuWatchdogThread* watchdog,
     scoped_refptr<gl::GLShareGroup> share_group,
-    scoped_refptr<gles2::MailboxManager> mailbox_manager,
-    ServiceDiscardableManager* discardable_manager,
     scoped_refptr<PreemptionFlag> preempting_flag,
     scoped_refptr<PreemptionFlag> preempted_flag,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
@@ -818,15 +815,11 @@
       task_runner_(task_runner),
       io_task_runner_(io_task_runner),
       share_group_(share_group),
-      mailbox_manager_(mailbox_manager),
       image_manager_(new gles2::ImageManager()),
-      watchdog_(watchdog),
-      discardable_manager_(discardable_manager),
       is_gpu_host_(is_gpu_host),
       weak_factory_(this) {
   DCHECK(gpu_channel_manager_);
   DCHECK(client_id_);
-  DCHECK(discardable_manager_);
 
   if (!scheduler_) {
     message_queue_ = new GpuChannelMessageQueue(
diff --git a/gpu/ipc/service/gpu_channel.h b/gpu/ipc/service/gpu_channel.h
index a6953e23..74d474e 100644
--- a/gpu/ipc/service/gpu_channel.h
+++ b/gpu/ipc/service/gpu_channel.h
@@ -46,7 +46,6 @@
 class GpuChannelManager;
 class GpuChannelMessageFilter;
 class GpuChannelMessageQueue;
-class GpuWatchdogThread;
 
 class GPU_EXPORT FilteredSender : public IPC::Sender {
  public:
@@ -84,10 +83,7 @@
   GpuChannel(GpuChannelManager* gpu_channel_manager,
              Scheduler* scheduler,
              SyncPointManager* sync_point_manager,
-             GpuWatchdogThread* watchdog,
              scoped_refptr<gl::GLShareGroup> share_group,
-             scoped_refptr<gles2::MailboxManager> mailbox_manager,
-             ServiceDiscardableManager* discardable_manager_,
              scoped_refptr<PreemptionFlag> preempting_flag,
              scoped_refptr<PreemptionFlag> preempted_flag,
              scoped_refptr<base::SingleThreadTaskRunner> task_runner,
@@ -114,14 +110,8 @@
 
   SyncPointManager* sync_point_manager() const { return sync_point_manager_; }
 
-  GpuWatchdogThread* watchdog() const { return watchdog_; }
-
   gles2::ImageManager* image_manager() const { return image_manager_.get(); }
 
-  const scoped_refptr<gles2::MailboxManager>& mailbox_manager() const {
-    return mailbox_manager_;
-  }
-
   const scoped_refptr<base::SingleThreadTaskRunner>& task_runner() const {
     return task_runner_;
   }
@@ -157,10 +147,6 @@
 
   gl::GLShareGroup* share_group() const { return share_group_.get(); }
 
-  ServiceDiscardableManager* discardable_manager() const {
-    return discardable_manager_;
-  }
-
   GpuCommandBufferStub* LookupCommandBuffer(int32_t route_id);
 
   void LoseAllContexts();
@@ -275,14 +261,8 @@
   // process use.
   scoped_refptr<gl::GLShareGroup> share_group_;
 
-  scoped_refptr<gles2::MailboxManager> mailbox_manager_;
-
   std::unique_ptr<gles2::ImageManager> image_manager_;
 
-  GpuWatchdogThread* const watchdog_;
-
-  ServiceDiscardableManager* discardable_manager_;
-
   const bool is_gpu_host_;
 
   // Member variables should appear before the WeakPtrFactory, to ensure that
diff --git a/gpu/ipc/service/gpu_channel_manager.cc b/gpu/ipc/service/gpu_channel_manager.cc
index a0bde422..7a9a4c9c 100644
--- a/gpu/ipc/service/gpu_channel_manager.cc
+++ b/gpu/ipc/service/gpu_channel_manager.cc
@@ -21,7 +21,6 @@
 #include "gpu/command_buffer/service/memory_program_cache.h"
 #include "gpu/command_buffer/service/preemption_flag.h"
 #include "gpu/command_buffer/service/scheduler.h"
-#include "gpu/command_buffer/service/shader_translator_cache.h"
 #include "gpu/command_buffer/service/sync_point_manager.h"
 #include "gpu/ipc/common/gpu_messages.h"
 #include "gpu/ipc/service/gpu_channel.h"
@@ -67,6 +66,7 @@
       gpu_memory_manager_(this),
       scheduler_(scheduler),
       sync_point_manager_(sync_point_manager),
+      shader_translator_cache_(gpu_preferences_),
       gpu_memory_buffer_factory_(gpu_memory_buffer_factory),
       gpu_feature_info_(gpu_feature_info),
       exiting_for_lost_context_(false),
@@ -102,21 +102,6 @@
   return program_cache_.get();
 }
 
-gles2::ShaderTranslatorCache* GpuChannelManager::shader_translator_cache() {
-  if (!shader_translator_cache_.get()) {
-    shader_translator_cache_ =
-        new gles2::ShaderTranslatorCache(gpu_preferences_);
-  }
-  return shader_translator_cache_.get();
-}
-
-gles2::FramebufferCompletenessCache*
-GpuChannelManager::framebuffer_completeness_cache() {
-  if (!framebuffer_completeness_cache_.get())
-    framebuffer_completeness_cache_ = new gles2::FramebufferCompletenessCache;
-  return framebuffer_completeness_cache_.get();
-}
-
 void GpuChannelManager::RemoveChannel(int client_id) {
   delegate_->DidDestroyChannel(client_id);
   gpu_channels_.erase(client_id);
@@ -131,8 +116,7 @@
                                                 uint64_t client_tracing_id,
                                                 bool is_gpu_host) {
   std::unique_ptr<GpuChannel> gpu_channel = base::MakeUnique<GpuChannel>(
-      this, scheduler_, sync_point_manager_, watchdog_, share_group_,
-      mailbox_manager_, &discardable_manager_,
+      this, scheduler_, sync_point_manager_, share_group_,
       is_gpu_host ? preemption_flag_ : nullptr,
       is_gpu_host ? nullptr : preemption_flag_, task_runner_, io_task_runner_,
       client_id, client_tracing_id, is_gpu_host);
diff --git a/gpu/ipc/service/gpu_channel_manager.h b/gpu/ipc/service/gpu_channel_manager.h
index 1aebaed2..b5a0463 100644
--- a/gpu/ipc/service/gpu_channel_manager.h
+++ b/gpu/ipc/service/gpu_channel_manager.h
@@ -22,6 +22,7 @@
 #include "gpu/command_buffer/common/constants.h"
 #include "gpu/command_buffer/service/gpu_preferences.h"
 #include "gpu/command_buffer/service/service_discardable_manager.h"
+#include "gpu/command_buffer/service/shader_translator_cache.h"
 #include "gpu/config/gpu_driver_bug_workarounds.h"
 #include "gpu/config/gpu_feature_info.h"
 #include "gpu/gpu_export.h"
@@ -43,10 +44,8 @@
 class SyncPointManager;
 struct SyncToken;
 namespace gles2 {
-class FramebufferCompletenessCache;
 class MailboxManager;
 class ProgramCache;
-class ShaderTranslatorCache;
 }
 }
 
@@ -75,6 +74,7 @@
   ~GpuChannelManager();
 
   GpuChannelManagerDelegate* delegate() const { return delegate_; }
+  GpuWatchdogThread* watchdog() const { return watchdog_; }
 
   GpuChannel* EstablishChannel(int client_id,
                                uint64_t client_tracing_id,
@@ -100,9 +100,16 @@
     return gpu_driver_bug_workarounds_;
   }
   const GpuFeatureInfo& gpu_feature_info() const { return gpu_feature_info_; }
+  ServiceDiscardableManager* discardable_manager() {
+    return &discardable_manager_;
+  }
   gles2::ProgramCache* program_cache();
-  gles2::ShaderTranslatorCache* shader_translator_cache();
-  gles2::FramebufferCompletenessCache* framebuffer_completeness_cache();
+  gles2::ShaderTranslatorCache* shader_translator_cache() {
+    return &shader_translator_cache_;
+  }
+  gles2::FramebufferCompletenessCache* framebuffer_completeness_cache() {
+    return &framebuffer_completeness_cache_;
+  }
 
   GpuMemoryManager* gpu_memory_manager() { return &gpu_memory_manager_; }
 
@@ -120,9 +127,7 @@
 
   bool is_exiting_for_lost_context() { return exiting_for_lost_context_; }
 
-  gles2::MailboxManager* mailbox_manager() const {
-    return mailbox_manager_.get();
-  }
+  gles2::MailboxManager* mailbox_manager() { return mailbox_manager_.get(); }
 
   gl::GLShareGroup* share_group() const { return share_group_.get(); }
 
@@ -156,15 +161,14 @@
 
   scoped_refptr<PreemptionFlag> preemption_flag_;
 
-  scoped_refptr<gles2::MailboxManager> mailbox_manager_;
+  std::unique_ptr<gles2::MailboxManager> mailbox_manager_;
   GpuMemoryManager gpu_memory_manager_;
   Scheduler* scheduler_;
   // SyncPointManager guaranteed to outlive running MessageLoop.
   SyncPointManager* sync_point_manager_;
   std::unique_ptr<gles2::ProgramCache> program_cache_;
-  scoped_refptr<gles2::ShaderTranslatorCache> shader_translator_cache_;
-  scoped_refptr<gles2::FramebufferCompletenessCache>
-      framebuffer_completeness_cache_;
+  gles2::ShaderTranslatorCache shader_translator_cache_;
+  gles2::FramebufferCompletenessCache framebuffer_completeness_cache_;
   scoped_refptr<gl::GLSurface> default_offscreen_surface_;
   GpuMemoryBufferFactory* const gpu_memory_buffer_factory_;
   GpuFeatureInfo gpu_feature_info_;
diff --git a/gpu/ipc/service/gpu_command_buffer_stub.cc b/gpu/ipc/service/gpu_command_buffer_stub.cc
index c5f6a811..8c5705e8 100644
--- a/gpu/ipc/service/gpu_command_buffer_stub.cc
+++ b/gpu/ipc/service/gpu_command_buffer_stub.cc
@@ -570,7 +570,7 @@
     gpu::GpuMemoryBufferFactory* gmb_factory =
         channel_->gpu_channel_manager()->gpu_memory_buffer_factory();
     context_group_ = new gles2::ContextGroup(
-        manager->gpu_preferences(), channel_->mailbox_manager(),
+        manager->gpu_preferences(), manager->mailbox_manager(),
         new GpuCommandBufferMemoryTracker(
             channel_, command_buffer_id_.GetUnsafeValue(),
             init_params.attribs.context_type, channel_->task_runner()),
@@ -578,8 +578,8 @@
         manager->framebuffer_completeness_cache(), feature_info,
         init_params.attribs.bind_generates_resource, channel_->image_manager(),
         gmb_factory ? gmb_factory->AsImageFactory() : nullptr,
-        channel_->watchdog() /* progress_reporter */,
-        manager->gpu_feature_info(), channel_->discardable_manager());
+        manager->watchdog() /* progress_reporter */,
+        manager->gpu_feature_info(), manager->discardable_manager());
   }
 
 #if defined(OS_MACOSX)
@@ -595,7 +595,7 @@
 
   // MailboxManagerSync synchronization correctness currently depends on having
   // only a single context. See crbug.com/510243 for details.
-  use_virtualized_gl_context_ |= channel_->mailbox_manager()->UsesSync();
+  use_virtualized_gl_context_ |= manager->mailbox_manager()->UsesSync();
 
   bool offscreen = (surface_handle_ == kNullSurfaceHandle);
   gl::GLSurface* default_surface = manager->GetDefaultOffscreenSurface();
@@ -838,8 +838,9 @@
 
 CommandBufferServiceClient::CommandBatchProcessedResult
 GpuCommandBufferStub::OnCommandBatchProcessed() {
-  if (channel_->watchdog())
-    channel_->watchdog()->CheckArmed();
+  GpuWatchdogThread* watchdog = channel_->gpu_channel_manager()->watchdog();
+  if (watchdog)
+    watchdog->CheckArmed();
   bool pause = false;
   if (channel_->scheduler()) {
     pause = channel_->scheduler()->ShouldYield(sequence_id_);
diff --git a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
index 21910c4..bd63303 100644
--- a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
+++ b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
@@ -39,7 +39,7 @@
 			<string>Disable Request Mobile Site</string>
 			<key>Key</key>
 			<string>RequestMobileSiteDisabled</string>
-			<key>Default</key>
+			<key>DefaultValue</key>
 			<false/>
 		</dict>
 		<dict>
diff --git a/ios/web_view/internal/cwv_web_view.mm b/ios/web_view/internal/cwv_web_view.mm
index 616defce..5954eb0 100644
--- a/ios/web_view/internal/cwv_web_view.mm
+++ b/ios/web_view/internal/cwv_web_view.mm
@@ -87,6 +87,8 @@
 - (void)updateNavigationAvailability;
 // Updates the URLs exposed through |lastCommittedURL| and |visibleURL|.
 - (void)updateCurrentURLs;
+// Updates |title| property.
+- (void)updateTitle;
 
 @end
 
@@ -239,7 +241,7 @@
 }
 
 - (void)webStateDidChangeTitle:(web::WebState*)webState {
-  self.title = base::SysUTF16ToNSString(_webState->GetTitle());
+  [self updateTitle];
 }
 
 - (void)renderProcessGoneForWebState:(web::WebState*)webState {
@@ -373,6 +375,12 @@
   _translationController.webState = _webState.get();
 
   [self addInternalWebViewAsSubview];
+
+  [self updateNavigationAvailability];
+  [self updateCurrentURLs];
+  [self updateTitle];
+  self.loading = NO;
+  self.estimatedProgress = 0.0;
 }
 
 // Adds the web view provided by |_webState| as a subview unless it has already.
@@ -398,4 +406,8 @@
   self.visibleURL = net::NSURLWithGURL(_webState->GetVisibleURL());
 }
 
+- (void)updateTitle {
+  self.title = base::SysUTF16ToNSString(_webState->GetTitle());
+}
+
 @end
diff --git a/ios/web_view/test/BUILD.gn b/ios/web_view/test/BUILD.gn
index 1b25eda..70620cb 100644
--- a/ios/web_view/test/BUILD.gn
+++ b/ios/web_view/test/BUILD.gn
@@ -17,6 +17,7 @@
   testonly = true
   sources = [
     "chrome_web_view_kvo_inttest.mm",
+    "chrome_web_view_restorable_state_inttest.mm",
     "chrome_web_view_test.h",
     "chrome_web_view_test.mm",
     "observer.h",
diff --git a/ios/web_view/test/chrome_web_view_restorable_state_inttest.mm b/ios/web_view/test/chrome_web_view_restorable_state_inttest.mm
new file mode 100644
index 0000000..7c17e25b
--- /dev/null
+++ b/ios/web_view/test/chrome_web_view_restorable_state_inttest.mm
@@ -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.
+
+#import <ChromeWebView/ChromeWebView.h>
+
+#import "ios/web_view/test/chrome_web_view_test.h"
+#include "testing/gtest_mac.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+
+// Creates web view for testing.
+CWVWebView* CreateWebView() {
+  return [[CWVWebView alloc]
+      initWithFrame:CGRectMake(0, 0, 50, 50)
+      configuration:[CWVWebViewConfiguration defaultConfiguration]];
+}
+
+// Creates a new web view and restores its state from |source_web_view|.
+CWVWebView* CreateWebViewWithState(CWVWebView* source_web_view) {
+  NSMutableData* data = [[NSMutableData alloc] init];
+  NSKeyedArchiver* archiver =
+      [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
+  [source_web_view encodeRestorableStateWithCoder:archiver];
+  [archiver finishEncoding];
+  NSKeyedUnarchiver* unarchiver =
+      [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
+  CWVWebView* result = CreateWebView();
+  [result decodeRestorableStateWithCoder:unarchiver];
+  return result;
+}
+
+}  // namespace
+
+namespace ios_web_view {
+
+// Tests encodeRestorableStateWithCoder: and decodeRestorableStateWithCoder:
+// methods.
+typedef ios_web_view::ChromeWebViewTest ChromeWebViewRestorableStateTest;
+TEST_F(ChromeWebViewRestorableStateTest, EncodeDecode) {
+  // Create web view that will be used as a source for state restoration.
+  CWVWebView* web_view = CreateWebView();
+
+  // Load 2 URLs to create non-default state.
+  ASSERT_FALSE(web_view.lastCommittedURL);
+  ASSERT_FALSE(web_view.visibleURL);
+  ASSERT_FALSE(web_view.canGoBack);
+  ASSERT_FALSE(web_view.canGoForward);
+  LoadUrl(web_view, [NSURL URLWithString:@"about:newtab"]);
+  ASSERT_NSEQ(@"about:newtab", web_view.lastCommittedURL.absoluteString);
+  ASSERT_NSEQ(@"about:newtab", web_view.visibleURL.absoluteString);
+  LoadUrl(web_view, [NSURL URLWithString:@"about:blank"]);
+  ASSERT_NSEQ(@"about:blank", web_view.lastCommittedURL.absoluteString);
+  ASSERT_NSEQ(@"about:blank", web_view.visibleURL.absoluteString);
+  ASSERT_TRUE(web_view.canGoBack);
+  ASSERT_FALSE(web_view.canGoForward);
+
+  // Create second web view and restore its state from the first web view.
+  CWVWebView* restored_web_view = CreateWebViewWithState(web_view);
+
+  // Verify that the state has been restored correctly.
+  EXPECT_NSEQ(@"about:blank",
+              restored_web_view.lastCommittedURL.absoluteString);
+  EXPECT_NSEQ(@"about:blank", restored_web_view.visibleURL.absoluteString);
+  EXPECT_TRUE(web_view.canGoBack);
+  EXPECT_FALSE(web_view.canGoForward);
+}
+
+}  // namespace ios_web_view
diff --git a/media/gpu/dxva_video_decode_accelerator_win.cc b/media/gpu/dxva_video_decode_accelerator_win.cc
index 764a7c2..34f72c09 100644
--- a/media/gpu/dxva_video_decode_accelerator_win.cc
+++ b/media/gpu/dxva_video_decode_accelerator_win.cc
@@ -1629,9 +1629,14 @@
     }
   }
 
+  // Each picture buffer can store a sample, plus one in
+  // pending_output_samples_. The decoder adds this number to the number of
+  // reference pictures it expects to need and uses that to determine the
+  // array size of the output texture.
+  const int kMaxOutputSamples = kNumPictureBuffers + 1;
   attributes->SetUINT32(MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT_PROGRESSIVE,
-                        kNumPictureBuffers);
-  attributes->SetUINT32(MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT, kNumPictureBuffers);
+                        kMaxOutputSamples);
+  attributes->SetUINT32(MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT, kMaxOutputSamples);
 
   auto* gl_context = get_gl_context_cb_.Run();
   RETURN_ON_FAILURE(gl_context, "Couldn't get GL context", false);
@@ -2077,6 +2082,9 @@
     base::AutoLock lock(decoder_lock_);
     sample_count = pending_output_samples_.size();
   }
+  size_t stale_output_picture_buffers_size =
+      stale_output_picture_buffers_.size();
+  PictureBufferMechanism mechanism = GetPictureBufferMechanism();
 
   base::debug::Alias(&last_exception_code);
   base::debug::Alias(&last_unhandled_error);
@@ -2086,6 +2094,8 @@
   base::debug::Alias(&perf_frequency.QuadPart);
   base::debug::Alias(&output_array_size);
   base::debug::Alias(&sample_count);
+  base::debug::Alias(&stale_output_picture_buffers_size);
+  base::debug::Alias(&mechanism);
   decoder_thread_.Stop();
 }
 
diff --git a/media/renderers/renderer_impl.cc b/media/renderers/renderer_impl.cc
index d2386f6..d36e948 100644
--- a/media/renderers/renderer_impl.cc
+++ b/media/renderers/renderer_impl.cc
@@ -167,17 +167,13 @@
   }
 
   cdm_context_ = cdm_context;
+  cdm_attached_cb.Run(true);
 
-  if (state_ != STATE_INIT_PENDING_CDM) {
-    cdm_attached_cb.Run(true);
+  if (state_ != STATE_INIT_PENDING_CDM)
     return;
-  }
 
   DCHECK(!init_cb_.is_null());
   state_ = STATE_INITIALIZING;
-  // |cdm_attached_cb| will be fired after initialization finishes.
-  pending_cdm_attached_cb_ = cdm_attached_cb;
-
   InitializeAudioRenderer();
 }
 
@@ -334,10 +330,6 @@
 
 void RendererImpl::FinishInitialization(PipelineStatus status) {
   DCHECK(!init_cb_.is_null());
-
-  if (!pending_cdm_attached_cb_.is_null())
-    base::ResetAndReturn(&pending_cdm_attached_cb_).Run(status == PIPELINE_OK);
-
   base::ResetAndReturn(&init_cb_).Run(status);
 }
 
diff --git a/media/renderers/renderer_impl.h b/media/renderers/renderer_impl.h
index aae8b52..7e78749 100644
--- a/media/renderers/renderer_impl.h
+++ b/media/renderers/renderer_impl.h
@@ -214,7 +214,6 @@
   bool video_ended_;
 
   CdmContext* cdm_context_;
-  CdmAttachedCB pending_cdm_attached_cb_;
 
   bool underflow_disabled_for_testing_;
   bool clockless_video_playback_enabled_for_testing_;
diff --git a/media/renderers/renderer_impl_unittest.cc b/media/renderers/renderer_impl_unittest.cc
index 6075b8f..c5ff649 100644
--- a/media/renderers/renderer_impl_unittest.cc
+++ b/media/renderers/renderer_impl_unittest.cc
@@ -372,7 +372,7 @@
 
   // SetCdm() will trigger the initialization to start. But it will not complete
   // because the |video_renderer_| is not returning the initialization callback.
-  SetCdmAndExpect(false);
+  SetCdmAndExpect(true);
   EXPECT_EQ(PIPELINE_OK, initialization_status_);
 
   Destroy();
@@ -455,7 +455,7 @@
   // Initialization is pending until CDM is set.
   EXPECT_EQ(PIPELINE_OK, initialization_status_);
 
-  SetCdmAndExpect(false);
+  SetCdmAndExpect(true);
   EXPECT_EQ(PIPELINE_ERROR_INITIALIZATION_FAILED, initialization_status_);
 }
 
diff --git a/net/cert/x509_certificate_nss.cc b/net/cert/x509_certificate_nss.cc
index 4f3339f..4f5baa3 100644
--- a/net/cert/x509_certificate_nss.cc
+++ b/net/cert/x509_certificate_nss.cc
@@ -26,15 +26,189 @@
 
 namespace net {
 
-bool X509Certificate::Initialize() {
-  serial_number_ = x509_util::ParseSerialNumber(cert_handle_);
+namespace {
 
-  return (
-      !serial_number_.empty() &&
-      x509_util::ParsePrincipal(&cert_handle_->subject, &subject_) &&
-      x509_util::ParsePrincipal(&cert_handle_->issuer, &issuer_) &&
-      x509_util::ParseDate(&cert_handle_->validity.notBefore, &valid_start_) &&
-      x509_util::ParseDate(&cert_handle_->validity.notAfter, &valid_expiry_));
+// Callback for CERT_DecodeCertPackage(), used in
+// CreateOSCertHandlesFromBytes().
+SECStatus PR_CALLBACK CollectCertsCallback(void* arg,
+                                           SECItem** certs,
+                                           int num_certs) {
+  X509Certificate::OSCertHandles* results =
+      reinterpret_cast<X509Certificate::OSCertHandles*>(arg);
+
+  for (int i = 0; i < num_certs; ++i) {
+    X509Certificate::OSCertHandle handle =
+        X509Certificate::CreateOSCertHandleFromBytes(
+            reinterpret_cast<char*>(certs[i]->data), certs[i]->len);
+    if (handle)
+      results->push_back(handle);
+  }
+
+  return SECSuccess;
+}
+
+// Parses the Principal attribute from |name| and outputs the result in
+// |principal|. Returns true on success.
+bool ParsePrincipal(CERTName* name, CertPrincipal* principal) {
+// Starting in NSS 3.15, CERTGetNameFunc takes a const CERTName* argument.
+#if NSS_VMINOR >= 15
+  typedef char* (*CERTGetNameFunc)(const CERTName* name);
+#else
+  typedef char* (*CERTGetNameFunc)(CERTName * name);
+#endif
+
+  // TODO(jcampan): add business_category and serial_number.
+  // TODO(wtc): NSS has the CERT_GetOrgName, CERT_GetOrgUnitName, and
+  // CERT_GetDomainComponentName functions, but they return only the most
+  // general (the first) RDN.  NSS doesn't have a function for the street
+  // address.
+  static const SECOidTag kOIDs[] = {
+      SEC_OID_AVA_STREET_ADDRESS, SEC_OID_AVA_ORGANIZATION_NAME,
+      SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME, SEC_OID_AVA_DC};
+
+  std::vector<std::string>* values[] = {
+      &principal->street_addresses, &principal->organization_names,
+      &principal->organization_unit_names, &principal->domain_components};
+  DCHECK_EQ(arraysize(kOIDs), arraysize(values));
+
+  CERTRDN** rdns = name->rdns;
+  for (size_t rdn = 0; rdns[rdn]; ++rdn) {
+    CERTAVA** avas = rdns[rdn]->avas;
+    for (size_t pair = 0; avas[pair] != 0; ++pair) {
+      SECOidTag tag = CERT_GetAVATag(avas[pair]);
+      for (size_t oid = 0; oid < arraysize(kOIDs); ++oid) {
+        if (kOIDs[oid] == tag) {
+          SECItem* decode_item = CERT_DecodeAVAValue(&avas[pair]->value);
+          if (!decode_item)
+            return false;
+          // TODO(wtc): Pass decode_item to CERT_RFC1485_EscapeAndQuote.
+          std::string value(reinterpret_cast<char*>(decode_item->data),
+                            decode_item->len);
+          values[oid]->push_back(value);
+          SECITEM_FreeItem(decode_item, PR_TRUE);
+          break;
+        }
+      }
+    }
+  }
+
+  // Get CN, L, S, and C.
+  CERTGetNameFunc get_name_funcs[4] = {CERT_GetCommonName, CERT_GetLocalityName,
+                                       CERT_GetStateName, CERT_GetCountryName};
+  std::string* single_values[4] = {
+      &principal->common_name, &principal->locality_name,
+      &principal->state_or_province_name, &principal->country_name};
+  for (size_t i = 0; i < arraysize(get_name_funcs); ++i) {
+    char* value = get_name_funcs[i](name);
+    if (value) {
+      single_values[i]->assign(value);
+      PORT_Free(value);
+    }
+  }
+
+  return true;
+}
+
+// Parses the date from |der_date| and outputs the result in |result|.
+// Returns true on success.
+bool ParseDate(const SECItem* der_date, base::Time* result) {
+  PRTime prtime;
+  SECStatus rv = DER_DecodeTimeChoice(&prtime, der_date);
+  if (rv != SECSuccess)
+    return false;
+  *result = crypto::PRTimeToBaseTime(prtime);
+  return true;
+}
+
+// Parses the serial number from |certificate|.
+std::string ParseSerialNumber(const CERTCertificate* certificate) {
+  return std::string(reinterpret_cast<char*>(certificate->serialNumber.data),
+                     certificate->serialNumber.len);
+}
+
+typedef std::unique_ptr<CERTName,
+                        crypto::NSSDestroyer<CERTName, CERT_DestroyName>>
+    ScopedCERTName;
+
+// Create a new CERTName object from its encoded representation.
+// |arena| is the allocation pool to use.
+// |data| points to a DER-encoded X.509 DistinguishedName.
+// Return a new CERTName pointer on success, or NULL.
+CERTName* CreateCertNameFromEncoded(PLArenaPool* arena,
+                                    const base::StringPiece& data) {
+  if (!arena)
+    return NULL;
+
+  ScopedCERTName name(PORT_ArenaZNew(arena, CERTName));
+  if (!name.get())
+    return NULL;
+
+  SECItem item;
+  item.len = static_cast<unsigned int>(data.length());
+  item.data = reinterpret_cast<unsigned char*>(const_cast<char*>(data.data()));
+
+  SECStatus rv = SEC_ASN1DecodeItem(arena, name.get(),
+                                    SEC_ASN1_GET(CERT_NameTemplate), &item);
+  if (rv != SECSuccess)
+    return NULL;
+
+  return name.release();
+}
+
+// Create a list of CERTName objects from a list of DER-encoded X.509
+// DistinguishedName items. All objects are created in a given arena.
+// |encoded_issuers| is the list of encoded DNs.
+// |arena| is the arena used for all allocations.
+// |out| will receive the result list on success.
+// Return true on success. On failure, the caller must free the
+// intermediate CERTName objects pushed to |out|.
+bool GetIssuersFromEncodedList(const std::vector<std::string>& encoded_issuers,
+                               PLArenaPool* arena,
+                               std::vector<CERTName*>* out) {
+  std::vector<CERTName*> result;
+  for (size_t n = 0; n < encoded_issuers.size(); ++n) {
+    CERTName* name = CreateCertNameFromEncoded(arena, encoded_issuers[n]);
+    if (name != NULL)
+      result.push_back(name);
+  }
+
+  if (result.size() == encoded_issuers.size()) {
+    out->swap(result);
+    return true;
+  }
+
+  for (size_t n = 0; n < result.size(); ++n)
+    CERT_DestroyName(result[n]);
+  return false;
+}
+
+// Returns true iff a certificate is issued by any of the issuers listed
+// by name in |valid_issuers|.
+// |cert_chain| is the certificate's chain.
+// |valid_issuers| is a list of strings, where each string contains
+// a DER-encoded X.509 Distinguished Name.
+bool IsCertificateIssuedBy(const std::vector<CERTCertificate*>& cert_chain,
+                           const std::vector<CERTName*>& valid_issuers) {
+  for (size_t n = 0; n < cert_chain.size(); ++n) {
+    CERTName* cert_issuer = &cert_chain[n]->issuer;
+    for (size_t i = 0; i < valid_issuers.size(); ++i) {
+      if (CERT_CompareName(valid_issuers[i], cert_issuer) == SECEqual)
+        return true;
+    }
+  }
+  return false;
+}
+
+}  // namespace
+
+bool X509Certificate::Initialize() {
+  serial_number_ = ParseSerialNumber(cert_handle_);
+
+  return (!serial_number_.empty() &&
+          ParsePrincipal(&cert_handle_->subject, &subject_) &&
+          ParsePrincipal(&cert_handle_->issuer, &issuer_) &&
+          ParseDate(&cert_handle_->validity.notBefore, &valid_start_) &&
+          ParseDate(&cert_handle_->validity.notAfter, &valid_expiry_));
 }
 
 std::string X509Certificate::GetDefaultNickname(CertType type) const {
@@ -92,7 +266,54 @@
 bool X509Certificate::GetSubjectAltName(
     std::vector<std::string>* dns_names,
     std::vector<std::string>* ip_addrs) const {
-  return x509_util::GetSubjectAltName(cert_handle_, dns_names, ip_addrs);
+  if (dns_names)
+    dns_names->clear();
+  if (ip_addrs)
+    ip_addrs->clear();
+
+  SECItem alt_name;
+  SECStatus rv = CERT_FindCertExtension(
+      cert_handle_, SEC_OID_X509_SUBJECT_ALT_NAME, &alt_name);
+  if (rv != SECSuccess)
+    return false;
+
+  crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
+
+  CERTGeneralName* alt_name_list;
+  alt_name_list = CERT_DecodeAltNameExtension(arena.get(), &alt_name);
+  SECITEM_FreeItem(&alt_name, PR_FALSE);
+
+  bool has_san = false;
+  CERTGeneralName* name = alt_name_list;
+  while (name) {
+    // DNSName and IPAddress are encoded as IA5String and OCTET STRINGs
+    // respectively, both of which can be byte copied from
+    // SECItemType::data into the appropriate output vector.
+    if (name->type == certDNSName) {
+      has_san = true;
+      if (dns_names) {
+        dns_names->push_back(
+            std::string(reinterpret_cast<char*>(name->name.other.data),
+                        name->name.other.len));
+      }
+    } else if (name->type == certIPAddress) {
+      has_san = true;
+      if (ip_addrs) {
+        ip_addrs->push_back(
+            std::string(reinterpret_cast<char*>(name->name.other.data),
+                        name->name.other.len));
+      }
+    }
+    // Fast path: Found at least one subjectAltName and the caller doesn't
+    // need the actual values.
+    if (has_san && !ip_addrs && !dns_names)
+      return true;
+
+    name = CERT_GetNextGeneralName(name);
+    if (name == alt_name_list)
+      break;
+  }
+  return has_san;
 }
 
 bool X509Certificate::IsIssuedByEncoded(
@@ -106,12 +327,10 @@
   // Convert encoded issuers to scoped CERTName* list.
   std::vector<CERTName*> issuers;
   crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-  if (!x509_util::GetIssuersFromEncodedList(valid_issuers,
-                                            arena.get(),
-                                            &issuers)) {
+  if (!GetIssuersFromEncodedList(valid_issuers, arena.get(), &issuers)) {
     return false;
   }
-  return x509_util::IsCertificateIssuedBy(cert_chain, issuers);
+  return IsCertificateIssuedBy(cert_chain, issuers);
 }
 
 // static
@@ -167,7 +386,38 @@
     const char* data,
     size_t length,
     Format format) {
-  return x509_util::CreateOSCertHandlesFromBytes(data, length, format);
+  X509Certificate::OSCertHandles results;
+
+  crypto::EnsureNSSInit();
+
+  if (!NSS_IsInitialized())
+    return results;
+
+  switch (format) {
+    case X509Certificate::FORMAT_SINGLE_CERTIFICATE: {
+      X509Certificate::OSCertHandle handle =
+          X509Certificate::CreateOSCertHandleFromBytes(data, length);
+      if (handle)
+        results.push_back(handle);
+      break;
+    }
+    case X509Certificate::FORMAT_PKCS7: {
+      // Make a copy since CERT_DecodeCertPackage may modify it
+      std::vector<char> data_copy(data, data + length);
+
+      SECStatus result = CERT_DecodeCertPackage(
+          data_copy.data(), base::checked_cast<int>(data_copy.size()),
+          CollectCertsCallback, &results);
+      if (result != SECSuccess)
+        results.clear();
+      break;
+    }
+    default:
+      NOTREACHED() << "Certificate format " << format << " unimplemented";
+      break;
+  }
+
+  return results;
 }
 
 // static
@@ -221,7 +471,12 @@
 // static
 X509Certificate::OSCertHandle X509Certificate::ReadOSCertHandleFromPickle(
     base::PickleIterator* pickle_iter) {
-  return x509_util::ReadOSCertHandleFromPickle(pickle_iter);
+  const char* data;
+  int length;
+  if (!pickle_iter->ReadData(&data, &length))
+    return NULL;
+
+  return CreateOSCertHandleFromBytes(data, length);
 }
 
 // static
@@ -236,7 +491,34 @@
 void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle,
                                        size_t* size_bits,
                                        PublicKeyType* type) {
-  x509_util::GetPublicKeyInfo(cert_handle, size_bits, type);
+  // Since we might fail, set the output parameters to default values first.
+  *type = X509Certificate::kPublicKeyTypeUnknown;
+  *size_bits = 0;
+
+  crypto::ScopedSECKEYPublicKey key(CERT_ExtractPublicKey(cert_handle));
+  if (!key.get())
+    return;
+
+  *size_bits = SECKEY_PublicKeyStrengthInBits(key.get());
+
+  switch (key->keyType) {
+    case rsaKey:
+      *type = X509Certificate::kPublicKeyTypeRSA;
+      break;
+    case dsaKey:
+      *type = X509Certificate::kPublicKeyTypeDSA;
+      break;
+    case dhKey:
+      *type = X509Certificate::kPublicKeyTypeDH;
+      break;
+    case ecKey:
+      *type = X509Certificate::kPublicKeyTypeECDSA;
+      break;
+    default:
+      *type = X509Certificate::kPublicKeyTypeUnknown;
+      *size_bits = 0;
+      break;
+  }
 }
 
 // static
diff --git a/net/cert/x509_util_nss.cc b/net/cert/x509_util_nss.cc
index 1175bd80..13d7e36 100644
--- a/net/cert/x509_util_nss.cc
+++ b/net/cert/x509_util_nss.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "net/cert/x509_util_nss.h"
+
 #include <cert.h>  // Must be included before certdb.h
 #include <certdb.h>
 #include <cryptohi.h>
@@ -12,22 +14,9 @@
 #include <secmod.h>
 #include <secport.h>
 
-#include <memory>
-
-#include "base/debug/leak_annotations.h"
 #include "base/logging.h"
-#include "base/memory/singleton.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/pickle.h"
 #include "base/strings/stringprintf.h"
-#include "crypto/ec_private_key.h"
-#include "crypto/nss_util.h"
-#include "crypto/nss_util_internal.h"
-#include "crypto/rsa_private_key.h"
 #include "crypto/scoped_nss_types.h"
-#include "net/cert/x509_certificate.h"
-#include "net/cert/x509_util.h"
-#include "net/cert/x509_util_nss.h"
 
 namespace net {
 
@@ -37,184 +26,10 @@
 const uint8_t kUpnOid[] = {0x2b, 0x6,  0x1,  0x4, 0x1,
                            0x82, 0x37, 0x14, 0x2, 0x3};
 
-// Callback for CERT_DecodeCertPackage(), used in
-// CreateOSCertHandlesFromBytes().
-SECStatus PR_CALLBACK CollectCertsCallback(void* arg,
-                                           SECItem** certs,
-                                           int num_certs) {
-  X509Certificate::OSCertHandles* results =
-      reinterpret_cast<X509Certificate::OSCertHandles*>(arg);
-
-  for (int i = 0; i < num_certs; ++i) {
-    X509Certificate::OSCertHandle handle =
-        X509Certificate::CreateOSCertHandleFromBytes(
-            reinterpret_cast<char*>(certs[i]->data), certs[i]->len);
-    if (handle)
-      results->push_back(handle);
-  }
-
-  return SECSuccess;
-}
-
-typedef std::unique_ptr<CERTName,
-                        crypto::NSSDestroyer<CERTName, CERT_DestroyName>>
-    ScopedCERTName;
-
-// Create a new CERTName object from its encoded representation.
-// |arena| is the allocation pool to use.
-// |data| points to a DER-encoded X.509 DistinguishedName.
-// Return a new CERTName pointer on success, or NULL.
-CERTName* CreateCertNameFromEncoded(PLArenaPool* arena,
-                                    const base::StringPiece& data) {
-  if (!arena)
-    return NULL;
-
-  ScopedCERTName name(PORT_ArenaZNew(arena, CERTName));
-  if (!name.get())
-    return NULL;
-
-  SECItem item;
-  item.len = static_cast<unsigned int>(data.length());
-  item.data = reinterpret_cast<unsigned char*>(const_cast<char*>(data.data()));
-
-  SECStatus rv = SEC_ASN1DecodeItem(arena, name.get(),
-                                    SEC_ASN1_GET(CERT_NameTemplate), &item);
-  if (rv != SECSuccess)
-    return NULL;
-
-  return name.release();
-}
-
 }  // namespace
 
 namespace x509_util {
 
-bool ParsePrincipal(CERTName* name, CertPrincipal* principal) {
-// Starting in NSS 3.15, CERTGetNameFunc takes a const CERTName* argument.
-#if NSS_VMINOR >= 15
-  typedef char* (*CERTGetNameFunc)(const CERTName* name);
-#else
-  typedef char* (*CERTGetNameFunc)(CERTName * name);
-#endif
-
-  // TODO(jcampan): add business_category and serial_number.
-  // TODO(wtc): NSS has the CERT_GetOrgName, CERT_GetOrgUnitName, and
-  // CERT_GetDomainComponentName functions, but they return only the most
-  // general (the first) RDN.  NSS doesn't have a function for the street
-  // address.
-  static const SECOidTag kOIDs[] = {
-      SEC_OID_AVA_STREET_ADDRESS, SEC_OID_AVA_ORGANIZATION_NAME,
-      SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME, SEC_OID_AVA_DC};
-
-  std::vector<std::string>* values[] = {
-      &principal->street_addresses, &principal->organization_names,
-      &principal->organization_unit_names, &principal->domain_components};
-  DCHECK_EQ(arraysize(kOIDs), arraysize(values));
-
-  CERTRDN** rdns = name->rdns;
-  for (size_t rdn = 0; rdns[rdn]; ++rdn) {
-    CERTAVA** avas = rdns[rdn]->avas;
-    for (size_t pair = 0; avas[pair] != 0; ++pair) {
-      SECOidTag tag = CERT_GetAVATag(avas[pair]);
-      for (size_t oid = 0; oid < arraysize(kOIDs); ++oid) {
-        if (kOIDs[oid] == tag) {
-          SECItem* decode_item = CERT_DecodeAVAValue(&avas[pair]->value);
-          if (!decode_item)
-            return false;
-          // TODO(wtc): Pass decode_item to CERT_RFC1485_EscapeAndQuote.
-          std::string value(reinterpret_cast<char*>(decode_item->data),
-                            decode_item->len);
-          values[oid]->push_back(value);
-          SECITEM_FreeItem(decode_item, PR_TRUE);
-          break;
-        }
-      }
-    }
-  }
-
-  // Get CN, L, S, and C.
-  CERTGetNameFunc get_name_funcs[4] = {CERT_GetCommonName, CERT_GetLocalityName,
-                                       CERT_GetStateName, CERT_GetCountryName};
-  std::string* single_values[4] = {
-      &principal->common_name, &principal->locality_name,
-      &principal->state_or_province_name, &principal->country_name};
-  for (size_t i = 0; i < arraysize(get_name_funcs); ++i) {
-    char* value = get_name_funcs[i](name);
-    if (value) {
-      single_values[i]->assign(value);
-      PORT_Free(value);
-    }
-  }
-
-  return true;
-}
-
-bool ParseDate(const SECItem* der_date, base::Time* result) {
-  PRTime prtime;
-  SECStatus rv = DER_DecodeTimeChoice(&prtime, der_date);
-  if (rv != SECSuccess)
-    return false;
-  *result = crypto::PRTimeToBaseTime(prtime);
-  return true;
-}
-
-std::string ParseSerialNumber(const CERTCertificate* certificate) {
-  return std::string(reinterpret_cast<char*>(certificate->serialNumber.data),
-                     certificate->serialNumber.len);
-}
-
-bool GetSubjectAltName(CERTCertificate* cert_handle,
-                       std::vector<std::string>* dns_names,
-                       std::vector<std::string>* ip_addrs) {
-  if (dns_names)
-    dns_names->clear();
-  if (ip_addrs)
-    ip_addrs->clear();
-
-  SECItem alt_name;
-  SECStatus rv = CERT_FindCertExtension(
-      cert_handle, SEC_OID_X509_SUBJECT_ALT_NAME, &alt_name);
-  if (rv != SECSuccess)
-    return false;
-
-  crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-
-  CERTGeneralName* alt_name_list;
-  alt_name_list = CERT_DecodeAltNameExtension(arena.get(), &alt_name);
-  SECITEM_FreeItem(&alt_name, PR_FALSE);
-
-  bool has_san = false;
-  CERTGeneralName* name = alt_name_list;
-  while (name) {
-    // DNSName and IPAddress are encoded as IA5String and OCTET STRINGs
-    // respectively, both of which can be byte copied from
-    // SECItemType::data into the appropriate output vector.
-    if (name->type == certDNSName) {
-      has_san = true;
-      if (dns_names) {
-        dns_names->push_back(
-            std::string(reinterpret_cast<char*>(name->name.other.data),
-                        name->name.other.len));
-      }
-    } else if (name->type == certIPAddress) {
-      has_san = true;
-      if (ip_addrs) {
-        ip_addrs->push_back(
-            std::string(reinterpret_cast<char*>(name->name.other.data),
-                        name->name.other.len));
-      }
-    }
-    // Fast path: Found at least one subjectAltName and the caller doesn't
-    // need the actual values.
-    if (has_san && !ip_addrs && !dns_names)
-      return true;
-
-    name = CERT_GetNextGeneralName(name);
-    if (name == alt_name_list)
-      break;
-  }
-  return has_san;
-}
 
 void GetRFC822SubjectAltNames(CERTCertificate* cert_handle,
                               std::vector<std::string>* names) {
@@ -284,119 +99,6 @@
   }
 }
 
-X509Certificate::OSCertHandles CreateOSCertHandlesFromBytes(
-    const char* data,
-    size_t length,
-    X509Certificate::Format format) {
-  X509Certificate::OSCertHandles results;
-
-  crypto::EnsureNSSInit();
-
-  if (!NSS_IsInitialized())
-    return results;
-
-  switch (format) {
-    case X509Certificate::FORMAT_SINGLE_CERTIFICATE: {
-      X509Certificate::OSCertHandle handle =
-          X509Certificate::CreateOSCertHandleFromBytes(data, length);
-      if (handle)
-        results.push_back(handle);
-      break;
-    }
-    case X509Certificate::FORMAT_PKCS7: {
-      // Make a copy since CERT_DecodeCertPackage may modify it
-      std::vector<char> data_copy(data, data + length);
-
-      SECStatus result = CERT_DecodeCertPackage(
-          data_copy.data(), base::checked_cast<int>(data_copy.size()),
-          CollectCertsCallback, &results);
-      if (result != SECSuccess)
-        results.clear();
-      break;
-    }
-    default:
-      NOTREACHED() << "Certificate format " << format << " unimplemented";
-      break;
-  }
-
-  return results;
-}
-
-X509Certificate::OSCertHandle ReadOSCertHandleFromPickle(
-    base::PickleIterator* pickle_iter) {
-  const char* data;
-  int length;
-  if (!pickle_iter->ReadData(&data, &length))
-    return NULL;
-
-  return X509Certificate::CreateOSCertHandleFromBytes(data, length);
-}
-
-void GetPublicKeyInfo(CERTCertificate* handle,
-                      size_t* size_bits,
-                      X509Certificate::PublicKeyType* type) {
-  // Since we might fail, set the output parameters to default values first.
-  *type = X509Certificate::kPublicKeyTypeUnknown;
-  *size_bits = 0;
-
-  crypto::ScopedSECKEYPublicKey key(CERT_ExtractPublicKey(handle));
-  if (!key.get())
-    return;
-
-  *size_bits = SECKEY_PublicKeyStrengthInBits(key.get());
-
-  switch (key->keyType) {
-    case rsaKey:
-      *type = X509Certificate::kPublicKeyTypeRSA;
-      break;
-    case dsaKey:
-      *type = X509Certificate::kPublicKeyTypeDSA;
-      break;
-    case dhKey:
-      *type = X509Certificate::kPublicKeyTypeDH;
-      break;
-    case ecKey:
-      *type = X509Certificate::kPublicKeyTypeECDSA;
-      break;
-    default:
-      *type = X509Certificate::kPublicKeyTypeUnknown;
-      *size_bits = 0;
-      break;
-  }
-}
-
-bool GetIssuersFromEncodedList(const std::vector<std::string>& encoded_issuers,
-                               PLArenaPool* arena,
-                               std::vector<CERTName*>* out) {
-  std::vector<CERTName*> result;
-  for (size_t n = 0; n < encoded_issuers.size(); ++n) {
-    CERTName* name = CreateCertNameFromEncoded(arena, encoded_issuers[n]);
-    if (name != NULL)
-      result.push_back(name);
-  }
-
-  if (result.size() == encoded_issuers.size()) {
-    out->swap(result);
-    return true;
-  }
-
-  for (size_t n = 0; n < result.size(); ++n)
-    CERT_DestroyName(result[n]);
-  return false;
-}
-
-bool IsCertificateIssuedBy(const std::vector<CERTCertificate*>& cert_chain,
-                           const std::vector<CERTName*>& valid_issuers) {
-  for (size_t n = 0; n < cert_chain.size(); ++n) {
-    CERTName* cert_issuer = &cert_chain[n]->issuer;
-    for (size_t i = 0; i < valid_issuers.size(); ++i) {
-      if (CERT_CompareName(valid_issuers[i], cert_issuer) == SECEqual)
-        return true;
-    }
-  }
-  return false;
-}
-
 std::string GetUniqueNicknameForSlot(const std::string& nickname,
                                      const SECItem* subject,
                                      PK11SlotInfo* slot) {
diff --git a/net/cert/x509_util_nss.h b/net/cert/x509_util_nss.h
index b5dfe795..7acabdf29 100644
--- a/net/cert/x509_util_nss.h
+++ b/net/cert/x509_util_nss.h
@@ -10,44 +10,16 @@
 #include <string>
 #include <vector>
 
-#include "base/time/time.h"
 #include "net/base/net_export.h"
-#include "net/cert/x509_certificate.h"
-
-namespace base {
-class PickleIterator;
-}
 
 typedef struct CERTCertificateStr CERTCertificate;
-typedef struct CERTNameStr CERTName;
 typedef struct PK11SlotInfoStr PK11SlotInfo;
-typedef struct PLArenaPool PLArenaPool;
 typedef struct SECItemStr SECItem;
 
 namespace net {
 
 namespace x509_util {
 
-// Parses the Principal attribute from |name| and outputs the result in
-// |principal|. Returns true on success.
-bool ParsePrincipal(CERTName* name, CertPrincipal* principal);
-
-// Parses the date from |der_date| and outputs the result in |result|.
-// Returns true on success.
-bool ParseDate(const SECItem* der_date, base::Time* result);
-
-// Parses the serial number from |certificate|.
-std::string ParseSerialNumber(const CERTCertificate* certificate);
-
-// Gets the dNSName and iPAddress name fields from the subjectAltName
-// extension of |cert_handle|.
-// If |dns_names| is non-null, each dNSName will be stored in |*dns_names|.
-// If |ip_addrs| is non-null, each iPAddress will be stored in |*ip_addrs|.
-// Returns true if any dNSName or iPAddress was present.
-bool GetSubjectAltName(CERTCertificate* cert_handle,
-                       std::vector<std::string>* dns_names,
-                       std::vector<std::string>* ip_addrs);
-
 // Stores the values of all rfc822Name subjectAltNames from |cert_handle|
 // into |names|. If no names are present, clears |names|.
 // WARNING: This method does not validate that the rfc822Name is
@@ -77,45 +49,6 @@
 NET_EXPORT void GetUPNSubjectAltNames(CERTCertificate* cert_handle,
                                       std::vector<std::string>* names);
 
-// Creates all possible OS certificate handles from |data| encoded in a specific
-// |format|. Returns an empty collection on failure.
-X509Certificate::OSCertHandles CreateOSCertHandlesFromBytes(
-    const char* data,
-    size_t length,
-    X509Certificate::Format format);
-
-// Reads a single certificate from |pickle_iter| and returns a platform-specific
-// certificate handle. Returns an invalid handle, NULL, on failure.
-X509Certificate::OSCertHandle ReadOSCertHandleFromPickle(
-    base::PickleIterator* pickle_iter);
-
-// Sets |*size_bits| to be the length of the public key in bits, and sets
-// |*type| to one of the |PublicKeyType| values. In case of
-// |kPublicKeyTypeUnknown|, |*size_bits| will be set to 0.
-void GetPublicKeyInfo(CERTCertificate* handle,
-                      size_t* size_bits,
-                      X509Certificate::PublicKeyType* type);
-
-// Create a list of CERTName objects from a list of DER-encoded X.509
-// DistinguishedName items. All objects are created in a given arena.
-// |encoded_issuers| is the list of encoded DNs.
-// |arena| is the arena used for all allocations.
-// |out| will receive the result list on success.
-// Return true on success. On failure, the caller must free the
-// intermediate CERTName objects pushed to |out|.
-bool GetIssuersFromEncodedList(
-    const std::vector<std::string>& issuers,
-    PLArenaPool* arena,
-    std::vector<CERTName*>* out);
-
-// Returns true iff a certificate is issued by any of the issuers listed
-// by name in |valid_issuers|.
-// |cert_chain| is the certificate's chain.
-// |valid_issuers| is a list of strings, where each string contains
-// a DER-encoded X.509 Distinguished Name.
-bool IsCertificateIssuedBy(const std::vector<CERTCertificate*>& cert_chain,
-                           const std::vector<CERTName*>& valid_issuers);
-
 // Generates a unique nickname for |slot|, returning |nickname| if it is
 // already unique.
 //
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index afabf3b..0354406 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1571,6 +1571,10 @@
 crbug.com/732829 css3/blending/mix-blend-mode-isolated-group-3.html [ NeedsManualRebaseline ]
 crbug.com/732829 css3/blending/mix-blend-mode-simple-text.html [ NeedsManualRebaseline ]
 crbug.com/732829 svg/filters/feBlend-all-modes.html [ NeedsManualRebaseline ]
+crbug.com/732829 css3/blending/svg-blend-color.html [ NeedsManualRebaseline ]
+crbug.com/732829 css3/blending/svg-blend-hue.html [ NeedsManualRebaseline ]
+crbug.com/732829 css3/blending/svg-blend-luminosity.html [ NeedsManualRebaseline ]
+crbug.com/732829 css3/blending/svg-blend-saturation.html [ NeedsManualRebaseline ]
 
 
 # Mac10.10-specific failures that still need triaging.
diff --git a/third_party/WebKit/LayoutTests/W3CImportExpectations b/third_party/WebKit/LayoutTests/W3CImportExpectations
index f8043c5e..53d73ef 100644
--- a/third_party/WebKit/LayoutTests/W3CImportExpectations
+++ b/third_party/WebKit/LayoutTests/W3CImportExpectations
@@ -398,7 +398,7 @@
 ## Owners: bsheedy@chromium.org
 # external/wpt/webvr [ Pass ]
 external/wpt/wai-aria [ Skip ]
-## Owners: suzyh@chromium.org
+## Owners: meade@chromium.org
 # external/wpt/web-animations [ Pass ]
 ## Owners: hongchan@chromium.org, rtoy@chromium.org
 # external/wpt/webaudio [ Pass ]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/ranges/Range-insertNode-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/ranges/Range-insertNode-expected.txt
deleted file mode 100644
index 41ddbab..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/dom/ranges/Range-insertNode-expected.txt
+++ /dev/null
@@ -1,1676 +0,0 @@
-This is a testharness.js-based test.
-Found 1672 tests; 1671 PASS, 1 FAIL, 0 TIMEOUT, 0 NOTRUN.
-PASS 0,0: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node paras[0] 
-PASS 0,0: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node paras[0] 
-PASS 0,1: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node paras[0].firstChild 
-PASS 0,1: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node paras[0].firstChild 
-PASS 0,2: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node paras[1].firstChild 
-PASS 0,2: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node paras[1].firstChild 
-PASS 0,3: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node foreignPara1 
-PASS 0,3: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node foreignPara1 
-PASS 0,4: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node foreignPara1.firstChild 
-PASS 0,4: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node foreignPara1.firstChild 
-PASS 0,5: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node detachedPara1 
-PASS 0,5: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node detachedPara1 
-PASS 0,6: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node detachedPara1.firstChild 
-PASS 0,6: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node detachedPara1.firstChild 
-PASS 0,7: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node document 
-PASS 0,7: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node document 
-PASS 0,8: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node detachedDiv 
-PASS 0,8: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node detachedDiv 
-PASS 0,9: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node foreignDoc 
-PASS 0,9: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node foreignDoc 
-PASS 0,10: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node foreignPara2 
-PASS 0,10: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node foreignPara2 
-PASS 0,11: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node xmlDoc 
-PASS 0,11: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node xmlDoc 
-PASS 0,12: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node xmlElement 
-PASS 0,12: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node xmlElement 
-PASS 0,13: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node detachedTextNode 
-PASS 0,13: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node detachedTextNode 
-PASS 0,14: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node foreignTextNode 
-PASS 0,14: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node foreignTextNode 
-PASS 0,15: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node processingInstruction 
-PASS 0,15: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node processingInstruction 
-PASS 0,16: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node detachedProcessingInstruction 
-PASS 0,16: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node detachedProcessingInstruction 
-PASS 0,17: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node comment 
-PASS 0,17: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node comment 
-PASS 0,18: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node detachedComment 
-PASS 0,18: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node detachedComment 
-PASS 0,19: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node docfrag 
-PASS 0,19: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node docfrag 
-PASS 0,20: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node doctype 
-PASS 0,20: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node doctype 
-PASS 0,21: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node foreignDoctype 
-PASS 0,21: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node foreignDoctype 
-PASS 1,0: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node paras[0] 
-PASS 1,0: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node paras[0] 
-PASS 1,1: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node paras[0].firstChild 
-PASS 1,1: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node paras[0].firstChild 
-PASS 1,2: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node paras[1].firstChild 
-PASS 1,2: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node paras[1].firstChild 
-PASS 1,3: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node foreignPara1 
-PASS 1,3: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node foreignPara1 
-PASS 1,4: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node foreignPara1.firstChild 
-PASS 1,4: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node foreignPara1.firstChild 
-PASS 1,5: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node detachedPara1 
-PASS 1,5: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node detachedPara1 
-PASS 1,6: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node detachedPara1.firstChild 
-PASS 1,6: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node detachedPara1.firstChild 
-PASS 1,7: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node document 
-PASS 1,7: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node document 
-PASS 1,8: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node detachedDiv 
-PASS 1,8: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node detachedDiv 
-PASS 1,9: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node foreignDoc 
-PASS 1,9: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node foreignDoc 
-PASS 1,10: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node foreignPara2 
-PASS 1,10: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node foreignPara2 
-PASS 1,11: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node xmlDoc 
-PASS 1,11: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node xmlDoc 
-PASS 1,12: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node xmlElement 
-PASS 1,12: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node xmlElement 
-PASS 1,13: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node detachedTextNode 
-PASS 1,13: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node detachedTextNode 
-PASS 1,14: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node foreignTextNode 
-PASS 1,14: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node foreignTextNode 
-PASS 1,15: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node processingInstruction 
-PASS 1,15: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node processingInstruction 
-PASS 1,16: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node detachedProcessingInstruction 
-PASS 1,16: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node detachedProcessingInstruction 
-PASS 1,17: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node comment 
-PASS 1,17: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node comment 
-PASS 1,18: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node detachedComment 
-PASS 1,18: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node detachedComment 
-PASS 1,19: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node docfrag 
-PASS 1,19: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node docfrag 
-PASS 1,20: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node doctype 
-PASS 1,20: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node doctype 
-PASS 1,21: resulting DOM for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node foreignDoctype 
-PASS 1,21: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node foreignDoctype 
-PASS 2,0: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node paras[0] 
-PASS 2,0: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node paras[0] 
-PASS 2,1: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node paras[0].firstChild 
-PASS 2,1: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node paras[0].firstChild 
-PASS 2,2: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node paras[1].firstChild 
-PASS 2,2: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node paras[1].firstChild 
-PASS 2,3: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node foreignPara1 
-PASS 2,3: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node foreignPara1 
-PASS 2,4: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node foreignPara1.firstChild 
-PASS 2,4: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node foreignPara1.firstChild 
-PASS 2,5: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node detachedPara1 
-PASS 2,5: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node detachedPara1 
-PASS 2,6: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node detachedPara1.firstChild 
-PASS 2,6: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node detachedPara1.firstChild 
-PASS 2,7: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node document 
-PASS 2,7: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node document 
-PASS 2,8: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node detachedDiv 
-PASS 2,8: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node detachedDiv 
-PASS 2,9: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node foreignDoc 
-PASS 2,9: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node foreignDoc 
-PASS 2,10: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node foreignPara2 
-PASS 2,10: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node foreignPara2 
-PASS 2,11: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node xmlDoc 
-PASS 2,11: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node xmlDoc 
-PASS 2,12: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node xmlElement 
-PASS 2,12: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node xmlElement 
-PASS 2,13: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node detachedTextNode 
-PASS 2,13: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node detachedTextNode 
-PASS 2,14: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node foreignTextNode 
-PASS 2,14: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node foreignTextNode 
-PASS 2,15: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node processingInstruction 
-PASS 2,15: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node processingInstruction 
-PASS 2,16: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node detachedProcessingInstruction 
-PASS 2,16: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node detachedProcessingInstruction 
-PASS 2,17: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node comment 
-PASS 2,17: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node comment 
-PASS 2,18: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node detachedComment 
-PASS 2,18: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node detachedComment 
-PASS 2,19: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node docfrag 
-PASS 2,19: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node docfrag 
-PASS 2,20: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node doctype 
-PASS 2,20: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node doctype 
-PASS 2,21: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node foreignDoctype 
-PASS 2,21: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node foreignDoctype 
-PASS 3,0: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node paras[0] 
-PASS 3,0: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node paras[0] 
-PASS 3,1: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node paras[0].firstChild 
-PASS 3,1: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node paras[0].firstChild 
-PASS 3,2: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node paras[1].firstChild 
-PASS 3,2: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node paras[1].firstChild 
-PASS 3,3: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node foreignPara1 
-PASS 3,3: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node foreignPara1 
-PASS 3,4: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node foreignPara1.firstChild 
-PASS 3,4: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node foreignPara1.firstChild 
-PASS 3,5: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node detachedPara1 
-PASS 3,5: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node detachedPara1 
-PASS 3,6: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node detachedPara1.firstChild 
-PASS 3,6: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node detachedPara1.firstChild 
-PASS 3,7: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node document 
-PASS 3,7: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node document 
-PASS 3,8: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node detachedDiv 
-PASS 3,8: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node detachedDiv 
-PASS 3,9: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node foreignDoc 
-PASS 3,9: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node foreignDoc 
-PASS 3,10: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node foreignPara2 
-PASS 3,10: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node foreignPara2 
-PASS 3,11: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node xmlDoc 
-PASS 3,11: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node xmlDoc 
-PASS 3,12: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node xmlElement 
-PASS 3,12: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node xmlElement 
-PASS 3,13: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node detachedTextNode 
-PASS 3,13: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node detachedTextNode 
-PASS 3,14: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node foreignTextNode 
-PASS 3,14: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node foreignTextNode 
-PASS 3,15: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node processingInstruction 
-PASS 3,15: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node processingInstruction 
-PASS 3,16: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node detachedProcessingInstruction 
-PASS 3,16: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node detachedProcessingInstruction 
-PASS 3,17: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node comment 
-PASS 3,17: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node comment 
-PASS 3,18: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node detachedComment 
-PASS 3,18: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node detachedComment 
-PASS 3,19: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node docfrag 
-PASS 3,19: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node docfrag 
-PASS 3,20: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node doctype 
-PASS 3,20: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node doctype 
-PASS 3,21: resulting DOM for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node foreignDoctype 
-PASS 3,21: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node foreignDoctype 
-PASS 4,0: resulting DOM for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node paras[0] 
-PASS 4,0: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node paras[0] 
-PASS 4,1: resulting DOM for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node paras[0].firstChild 
-PASS 4,1: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node paras[0].firstChild 
-PASS 4,2: resulting DOM for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node paras[1].firstChild 
-PASS 4,2: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node paras[1].firstChild 
-PASS 4,3: resulting DOM for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node foreignPara1 
-PASS 4,3: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node foreignPara1 
-PASS 4,4: resulting DOM for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node foreignPara1.firstChild 
-PASS 4,4: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node foreignPara1.firstChild 
-PASS 4,5: resulting DOM for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node detachedPara1 
-PASS 4,5: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node detachedPara1 
-PASS 4,6: resulting DOM for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node detachedPara1.firstChild 
-PASS 4,6: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node detachedPara1.firstChild 
-PASS 4,7: resulting DOM for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node document 
-PASS 4,7: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node document 
-PASS 4,8: resulting DOM for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node detachedDiv 
-PASS 4,8: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node detachedDiv 
-PASS 4,9: resulting DOM for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node foreignDoc 
-PASS 4,9: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node foreignDoc 
-PASS 4,10: resulting DOM for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node foreignPara2 
-PASS 4,10: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node foreignPara2 
-PASS 4,11: resulting DOM for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node xmlDoc 
-PASS 4,11: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node xmlDoc 
-PASS 4,12: resulting DOM for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node xmlElement 
-PASS 4,12: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node xmlElement 
-PASS 4,13: resulting DOM for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node detachedTextNode 
-PASS 4,13: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node detachedTextNode 
-PASS 4,14: resulting DOM for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node foreignTextNode 
-PASS 4,14: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node foreignTextNode 
-PASS 4,15: resulting DOM for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node processingInstruction 
-PASS 4,15: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node processingInstruction 
-PASS 4,16: resulting DOM for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node detachedProcessingInstruction 
-PASS 4,16: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node detachedProcessingInstruction 
-PASS 4,17: resulting DOM for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node comment 
-PASS 4,17: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node comment 
-PASS 4,18: resulting DOM for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node detachedComment 
-PASS 4,18: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node detachedComment 
-PASS 4,19: resulting DOM for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node docfrag 
-PASS 4,19: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node docfrag 
-PASS 4,20: resulting DOM for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node doctype 
-PASS 4,20: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node doctype 
-PASS 4,21: resulting DOM for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node foreignDoctype 
-PASS 4,21: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node foreignDoctype 
-PASS 5,0: resulting DOM for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node paras[0] 
-PASS 5,0: resulting range position for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node paras[0] 
-PASS 5,1: resulting DOM for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node paras[0].firstChild 
-PASS 5,1: resulting range position for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node paras[0].firstChild 
-PASS 5,2: resulting DOM for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node paras[1].firstChild 
-PASS 5,2: resulting range position for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node paras[1].firstChild 
-PASS 5,3: resulting DOM for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node foreignPara1 
-PASS 5,3: resulting range position for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node foreignPara1 
-PASS 5,4: resulting DOM for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node foreignPara1.firstChild 
-PASS 5,4: resulting range position for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node foreignPara1.firstChild 
-PASS 5,5: resulting DOM for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node detachedPara1 
-PASS 5,5: resulting range position for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node detachedPara1 
-PASS 5,6: resulting DOM for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node detachedPara1.firstChild 
-PASS 5,6: resulting range position for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node detachedPara1.firstChild 
-PASS 5,7: resulting DOM for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node document 
-PASS 5,7: resulting range position for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node document 
-PASS 5,8: resulting DOM for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node detachedDiv 
-PASS 5,8: resulting range position for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node detachedDiv 
-PASS 5,9: resulting DOM for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node foreignDoc 
-PASS 5,9: resulting range position for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node foreignDoc 
-PASS 5,10: resulting DOM for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node foreignPara2 
-PASS 5,10: resulting range position for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node foreignPara2 
-PASS 5,11: resulting DOM for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node xmlDoc 
-PASS 5,11: resulting range position for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node xmlDoc 
-PASS 5,12: resulting DOM for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node xmlElement 
-PASS 5,12: resulting range position for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node xmlElement 
-PASS 5,13: resulting DOM for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node detachedTextNode 
-PASS 5,13: resulting range position for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node detachedTextNode 
-PASS 5,14: resulting DOM for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node foreignTextNode 
-PASS 5,14: resulting range position for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node foreignTextNode 
-PASS 5,15: resulting DOM for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node processingInstruction 
-PASS 5,15: resulting range position for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node processingInstruction 
-PASS 5,16: resulting DOM for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node detachedProcessingInstruction 
-PASS 5,16: resulting range position for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node detachedProcessingInstruction 
-PASS 5,17: resulting DOM for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node comment 
-PASS 5,17: resulting range position for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node comment 
-PASS 5,18: resulting DOM for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node detachedComment 
-PASS 5,18: resulting range position for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node detachedComment 
-PASS 5,19: resulting DOM for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node docfrag 
-PASS 5,19: resulting range position for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node docfrag 
-PASS 5,20: resulting DOM for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node doctype 
-PASS 5,20: resulting range position for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node doctype 
-PASS 5,21: resulting DOM for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node foreignDoctype 
-PASS 5,21: resulting range position for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node foreignDoctype 
-PASS 6,0: resulting DOM for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node paras[0] 
-PASS 6,0: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node paras[0] 
-PASS 6,1: resulting DOM for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node paras[0].firstChild 
-PASS 6,1: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node paras[0].firstChild 
-PASS 6,2: resulting DOM for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node paras[1].firstChild 
-PASS 6,2: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node paras[1].firstChild 
-PASS 6,3: resulting DOM for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node foreignPara1 
-PASS 6,3: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node foreignPara1 
-PASS 6,4: resulting DOM for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node foreignPara1.firstChild 
-PASS 6,4: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node foreignPara1.firstChild 
-PASS 6,5: resulting DOM for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node detachedPara1 
-PASS 6,5: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node detachedPara1 
-PASS 6,6: resulting DOM for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node detachedPara1.firstChild 
-PASS 6,6: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node detachedPara1.firstChild 
-PASS 6,7: resulting DOM for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node document 
-PASS 6,7: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node document 
-PASS 6,8: resulting DOM for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node detachedDiv 
-PASS 6,8: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node detachedDiv 
-PASS 6,9: resulting DOM for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node foreignDoc 
-PASS 6,9: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node foreignDoc 
-PASS 6,10: resulting DOM for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node foreignPara2 
-PASS 6,10: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node foreignPara2 
-PASS 6,11: resulting DOM for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node xmlDoc 
-PASS 6,11: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node xmlDoc 
-PASS 6,12: resulting DOM for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node xmlElement 
-PASS 6,12: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node xmlElement 
-PASS 6,13: resulting DOM for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node detachedTextNode 
-PASS 6,13: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node detachedTextNode 
-PASS 6,14: resulting DOM for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node foreignTextNode 
-PASS 6,14: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node foreignTextNode 
-PASS 6,15: resulting DOM for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node processingInstruction 
-PASS 6,15: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node processingInstruction 
-PASS 6,16: resulting DOM for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node detachedProcessingInstruction 
-PASS 6,16: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node detachedProcessingInstruction 
-PASS 6,17: resulting DOM for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node comment 
-PASS 6,17: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node comment 
-PASS 6,18: resulting DOM for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node detachedComment 
-PASS 6,18: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node detachedComment 
-PASS 6,19: resulting DOM for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node docfrag 
-PASS 6,19: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node docfrag 
-PASS 6,20: resulting DOM for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node doctype 
-PASS 6,20: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node doctype 
-PASS 6,21: resulting DOM for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node foreignDoctype 
-PASS 6,21: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node foreignDoctype 
-PASS 7,0: resulting DOM for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node paras[0] 
-PASS 7,0: resulting range position for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node paras[0] 
-PASS 7,1: resulting DOM for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node paras[0].firstChild 
-PASS 7,1: resulting range position for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node paras[0].firstChild 
-PASS 7,2: resulting DOM for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node paras[1].firstChild 
-PASS 7,2: resulting range position for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node paras[1].firstChild 
-PASS 7,3: resulting DOM for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node foreignPara1 
-PASS 7,3: resulting range position for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node foreignPara1 
-PASS 7,4: resulting DOM for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node foreignPara1.firstChild 
-PASS 7,4: resulting range position for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node foreignPara1.firstChild 
-PASS 7,5: resulting DOM for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node detachedPara1 
-PASS 7,5: resulting range position for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node detachedPara1 
-PASS 7,6: resulting DOM for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node detachedPara1.firstChild 
-PASS 7,6: resulting range position for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node detachedPara1.firstChild 
-PASS 7,7: resulting DOM for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node document 
-PASS 7,7: resulting range position for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node document 
-PASS 7,8: resulting DOM for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node detachedDiv 
-PASS 7,8: resulting range position for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node detachedDiv 
-PASS 7,9: resulting DOM for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node foreignDoc 
-PASS 7,9: resulting range position for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node foreignDoc 
-PASS 7,10: resulting DOM for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node foreignPara2 
-PASS 7,10: resulting range position for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node foreignPara2 
-PASS 7,11: resulting DOM for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node xmlDoc 
-PASS 7,11: resulting range position for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node xmlDoc 
-PASS 7,12: resulting DOM for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node xmlElement 
-PASS 7,12: resulting range position for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node xmlElement 
-PASS 7,13: resulting DOM for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node detachedTextNode 
-PASS 7,13: resulting range position for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node detachedTextNode 
-PASS 7,14: resulting DOM for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node foreignTextNode 
-PASS 7,14: resulting range position for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node foreignTextNode 
-PASS 7,15: resulting DOM for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node processingInstruction 
-PASS 7,15: resulting range position for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node processingInstruction 
-PASS 7,16: resulting DOM for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node detachedProcessingInstruction 
-PASS 7,16: resulting range position for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node detachedProcessingInstruction 
-PASS 7,17: resulting DOM for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node comment 
-PASS 7,17: resulting range position for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node comment 
-PASS 7,18: resulting DOM for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node detachedComment 
-PASS 7,18: resulting range position for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node detachedComment 
-PASS 7,19: resulting DOM for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node docfrag 
-PASS 7,19: resulting range position for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node docfrag 
-PASS 7,20: resulting DOM for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node doctype 
-PASS 7,20: resulting range position for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node doctype 
-PASS 7,21: resulting DOM for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node foreignDoctype 
-PASS 7,21: resulting range position for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node foreignDoctype 
-PASS 8,0: resulting DOM for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node paras[0] 
-PASS 8,0: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node paras[0] 
-PASS 8,1: resulting DOM for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node paras[0].firstChild 
-PASS 8,1: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node paras[0].firstChild 
-PASS 8,2: resulting DOM for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node paras[1].firstChild 
-PASS 8,2: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node paras[1].firstChild 
-PASS 8,3: resulting DOM for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node foreignPara1 
-PASS 8,3: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node foreignPara1 
-PASS 8,4: resulting DOM for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node foreignPara1.firstChild 
-PASS 8,4: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node foreignPara1.firstChild 
-PASS 8,5: resulting DOM for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node detachedPara1 
-PASS 8,5: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node detachedPara1 
-PASS 8,6: resulting DOM for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node detachedPara1.firstChild 
-PASS 8,6: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node detachedPara1.firstChild 
-PASS 8,7: resulting DOM for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node document 
-PASS 8,7: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node document 
-PASS 8,8: resulting DOM for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node detachedDiv 
-PASS 8,8: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node detachedDiv 
-PASS 8,9: resulting DOM for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node foreignDoc 
-PASS 8,9: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node foreignDoc 
-PASS 8,10: resulting DOM for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node foreignPara2 
-PASS 8,10: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node foreignPara2 
-PASS 8,11: resulting DOM for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node xmlDoc 
-PASS 8,11: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node xmlDoc 
-PASS 8,12: resulting DOM for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node xmlElement 
-PASS 8,12: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node xmlElement 
-PASS 8,13: resulting DOM for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node detachedTextNode 
-PASS 8,13: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node detachedTextNode 
-PASS 8,14: resulting DOM for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node foreignTextNode 
-PASS 8,14: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node foreignTextNode 
-PASS 8,15: resulting DOM for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node processingInstruction 
-PASS 8,15: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node processingInstruction 
-PASS 8,16: resulting DOM for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node detachedProcessingInstruction 
-PASS 8,16: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node detachedProcessingInstruction 
-PASS 8,17: resulting DOM for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node comment 
-PASS 8,17: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node comment 
-PASS 8,18: resulting DOM for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node detachedComment 
-PASS 8,18: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node detachedComment 
-PASS 8,19: resulting DOM for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node docfrag 
-PASS 8,19: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node docfrag 
-PASS 8,20: resulting DOM for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node doctype 
-PASS 8,20: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node doctype 
-PASS 8,21: resulting DOM for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node foreignDoctype 
-PASS 8,21: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node foreignDoctype 
-PASS 9,0: resulting DOM for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node paras[0] 
-PASS 9,0: resulting range position for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node paras[0] 
-PASS 9,1: resulting DOM for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node paras[0].firstChild 
-PASS 9,1: resulting range position for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node paras[0].firstChild 
-PASS 9,2: resulting DOM for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node paras[1].firstChild 
-PASS 9,2: resulting range position for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node paras[1].firstChild 
-PASS 9,3: resulting DOM for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node foreignPara1 
-PASS 9,3: resulting range position for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node foreignPara1 
-PASS 9,4: resulting DOM for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node foreignPara1.firstChild 
-PASS 9,4: resulting range position for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node foreignPara1.firstChild 
-PASS 9,5: resulting DOM for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node detachedPara1 
-PASS 9,5: resulting range position for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node detachedPara1 
-PASS 9,6: resulting DOM for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node detachedPara1.firstChild 
-PASS 9,6: resulting range position for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node detachedPara1.firstChild 
-PASS 9,7: resulting DOM for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node document 
-PASS 9,7: resulting range position for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node document 
-PASS 9,8: resulting DOM for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node detachedDiv 
-PASS 9,8: resulting range position for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node detachedDiv 
-PASS 9,9: resulting DOM for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node foreignDoc 
-PASS 9,9: resulting range position for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node foreignDoc 
-PASS 9,10: resulting DOM for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node foreignPara2 
-PASS 9,10: resulting range position for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node foreignPara2 
-PASS 9,11: resulting DOM for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node xmlDoc 
-PASS 9,11: resulting range position for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node xmlDoc 
-PASS 9,12: resulting DOM for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node xmlElement 
-PASS 9,12: resulting range position for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node xmlElement 
-PASS 9,13: resulting DOM for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node detachedTextNode 
-PASS 9,13: resulting range position for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node detachedTextNode 
-PASS 9,14: resulting DOM for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node foreignTextNode 
-PASS 9,14: resulting range position for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node foreignTextNode 
-PASS 9,15: resulting DOM for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node processingInstruction 
-PASS 9,15: resulting range position for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node processingInstruction 
-PASS 9,16: resulting DOM for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node detachedProcessingInstruction 
-PASS 9,16: resulting range position for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node detachedProcessingInstruction 
-PASS 9,17: resulting DOM for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node comment 
-PASS 9,17: resulting range position for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node comment 
-PASS 9,18: resulting DOM for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node detachedComment 
-PASS 9,18: resulting range position for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node detachedComment 
-PASS 9,19: resulting DOM for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node docfrag 
-PASS 9,19: resulting range position for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node docfrag 
-PASS 9,20: resulting DOM for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node doctype 
-PASS 9,20: resulting range position for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node doctype 
-PASS 9,21: resulting DOM for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node foreignDoctype 
-PASS 9,21: resulting range position for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node foreignDoctype 
-PASS 10,0: resulting DOM for range [document.documentElement, 0, document.documentElement, 1], node paras[0] 
-PASS 10,0: resulting range position for range [document.documentElement, 0, document.documentElement, 1], node paras[0] 
-PASS 10,1: resulting DOM for range [document.documentElement, 0, document.documentElement, 1], node paras[0].firstChild 
-PASS 10,1: resulting range position for range [document.documentElement, 0, document.documentElement, 1], node paras[0].firstChild 
-PASS 10,2: resulting DOM for range [document.documentElement, 0, document.documentElement, 1], node paras[1].firstChild 
-PASS 10,2: resulting range position for range [document.documentElement, 0, document.documentElement, 1], node paras[1].firstChild 
-PASS 10,3: resulting DOM for range [document.documentElement, 0, document.documentElement, 1], node foreignPara1 
-PASS 10,3: resulting range position for range [document.documentElement, 0, document.documentElement, 1], node foreignPara1 
-PASS 10,4: resulting DOM for range [document.documentElement, 0, document.documentElement, 1], node foreignPara1.firstChild 
-PASS 10,4: resulting range position for range [document.documentElement, 0, document.documentElement, 1], node foreignPara1.firstChild 
-PASS 10,5: resulting DOM for range [document.documentElement, 0, document.documentElement, 1], node detachedPara1 
-PASS 10,5: resulting range position for range [document.documentElement, 0, document.documentElement, 1], node detachedPara1 
-PASS 10,6: resulting DOM for range [document.documentElement, 0, document.documentElement, 1], node detachedPara1.firstChild 
-PASS 10,6: resulting range position for range [document.documentElement, 0, document.documentElement, 1], node detachedPara1.firstChild 
-PASS 10,7: resulting DOM for range [document.documentElement, 0, document.documentElement, 1], node document 
-PASS 10,7: resulting range position for range [document.documentElement, 0, document.documentElement, 1], node document 
-PASS 10,8: resulting DOM for range [document.documentElement, 0, document.documentElement, 1], node detachedDiv 
-PASS 10,8: resulting range position for range [document.documentElement, 0, document.documentElement, 1], node detachedDiv 
-PASS 10,9: resulting DOM for range [document.documentElement, 0, document.documentElement, 1], node foreignDoc 
-PASS 10,9: resulting range position for range [document.documentElement, 0, document.documentElement, 1], node foreignDoc 
-PASS 10,10: resulting DOM for range [document.documentElement, 0, document.documentElement, 1], node foreignPara2 
-PASS 10,10: resulting range position for range [document.documentElement, 0, document.documentElement, 1], node foreignPara2 
-PASS 10,11: resulting DOM for range [document.documentElement, 0, document.documentElement, 1], node xmlDoc 
-PASS 10,11: resulting range position for range [document.documentElement, 0, document.documentElement, 1], node xmlDoc 
-PASS 10,12: resulting DOM for range [document.documentElement, 0, document.documentElement, 1], node xmlElement 
-PASS 10,12: resulting range position for range [document.documentElement, 0, document.documentElement, 1], node xmlElement 
-PASS 10,13: resulting DOM for range [document.documentElement, 0, document.documentElement, 1], node detachedTextNode 
-PASS 10,13: resulting range position for range [document.documentElement, 0, document.documentElement, 1], node detachedTextNode 
-PASS 10,14: resulting DOM for range [document.documentElement, 0, document.documentElement, 1], node foreignTextNode 
-PASS 10,14: resulting range position for range [document.documentElement, 0, document.documentElement, 1], node foreignTextNode 
-PASS 10,15: resulting DOM for range [document.documentElement, 0, document.documentElement, 1], node processingInstruction 
-PASS 10,15: resulting range position for range [document.documentElement, 0, document.documentElement, 1], node processingInstruction 
-PASS 10,16: resulting DOM for range [document.documentElement, 0, document.documentElement, 1], node detachedProcessingInstruction 
-PASS 10,16: resulting range position for range [document.documentElement, 0, document.documentElement, 1], node detachedProcessingInstruction 
-PASS 10,17: resulting DOM for range [document.documentElement, 0, document.documentElement, 1], node comment 
-PASS 10,17: resulting range position for range [document.documentElement, 0, document.documentElement, 1], node comment 
-PASS 10,18: resulting DOM for range [document.documentElement, 0, document.documentElement, 1], node detachedComment 
-PASS 10,18: resulting range position for range [document.documentElement, 0, document.documentElement, 1], node detachedComment 
-PASS 10,19: resulting DOM for range [document.documentElement, 0, document.documentElement, 1], node docfrag 
-PASS 10,19: resulting range position for range [document.documentElement, 0, document.documentElement, 1], node docfrag 
-PASS 10,20: resulting DOM for range [document.documentElement, 0, document.documentElement, 1], node doctype 
-PASS 10,20: resulting range position for range [document.documentElement, 0, document.documentElement, 1], node doctype 
-PASS 10,21: resulting DOM for range [document.documentElement, 0, document.documentElement, 1], node foreignDoctype 
-PASS 10,21: resulting range position for range [document.documentElement, 0, document.documentElement, 1], node foreignDoctype 
-PASS 11,0: resulting DOM for range [document.documentElement, 0, document.documentElement, 2], node paras[0] 
-PASS 11,0: resulting range position for range [document.documentElement, 0, document.documentElement, 2], node paras[0] 
-PASS 11,1: resulting DOM for range [document.documentElement, 0, document.documentElement, 2], node paras[0].firstChild 
-PASS 11,1: resulting range position for range [document.documentElement, 0, document.documentElement, 2], node paras[0].firstChild 
-PASS 11,2: resulting DOM for range [document.documentElement, 0, document.documentElement, 2], node paras[1].firstChild 
-PASS 11,2: resulting range position for range [document.documentElement, 0, document.documentElement, 2], node paras[1].firstChild 
-PASS 11,3: resulting DOM for range [document.documentElement, 0, document.documentElement, 2], node foreignPara1 
-PASS 11,3: resulting range position for range [document.documentElement, 0, document.documentElement, 2], node foreignPara1 
-PASS 11,4: resulting DOM for range [document.documentElement, 0, document.documentElement, 2], node foreignPara1.firstChild 
-PASS 11,4: resulting range position for range [document.documentElement, 0, document.documentElement, 2], node foreignPara1.firstChild 
-PASS 11,5: resulting DOM for range [document.documentElement, 0, document.documentElement, 2], node detachedPara1 
-PASS 11,5: resulting range position for range [document.documentElement, 0, document.documentElement, 2], node detachedPara1 
-PASS 11,6: resulting DOM for range [document.documentElement, 0, document.documentElement, 2], node detachedPara1.firstChild 
-PASS 11,6: resulting range position for range [document.documentElement, 0, document.documentElement, 2], node detachedPara1.firstChild 
-PASS 11,7: resulting DOM for range [document.documentElement, 0, document.documentElement, 2], node document 
-PASS 11,7: resulting range position for range [document.documentElement, 0, document.documentElement, 2], node document 
-PASS 11,8: resulting DOM for range [document.documentElement, 0, document.documentElement, 2], node detachedDiv 
-PASS 11,8: resulting range position for range [document.documentElement, 0, document.documentElement, 2], node detachedDiv 
-PASS 11,9: resulting DOM for range [document.documentElement, 0, document.documentElement, 2], node foreignDoc 
-PASS 11,9: resulting range position for range [document.documentElement, 0, document.documentElement, 2], node foreignDoc 
-PASS 11,10: resulting DOM for range [document.documentElement, 0, document.documentElement, 2], node foreignPara2 
-PASS 11,10: resulting range position for range [document.documentElement, 0, document.documentElement, 2], node foreignPara2 
-PASS 11,11: resulting DOM for range [document.documentElement, 0, document.documentElement, 2], node xmlDoc 
-PASS 11,11: resulting range position for range [document.documentElement, 0, document.documentElement, 2], node xmlDoc 
-PASS 11,12: resulting DOM for range [document.documentElement, 0, document.documentElement, 2], node xmlElement 
-PASS 11,12: resulting range position for range [document.documentElement, 0, document.documentElement, 2], node xmlElement 
-PASS 11,13: resulting DOM for range [document.documentElement, 0, document.documentElement, 2], node detachedTextNode 
-PASS 11,13: resulting range position for range [document.documentElement, 0, document.documentElement, 2], node detachedTextNode 
-PASS 11,14: resulting DOM for range [document.documentElement, 0, document.documentElement, 2], node foreignTextNode 
-PASS 11,14: resulting range position for range [document.documentElement, 0, document.documentElement, 2], node foreignTextNode 
-PASS 11,15: resulting DOM for range [document.documentElement, 0, document.documentElement, 2], node processingInstruction 
-PASS 11,15: resulting range position for range [document.documentElement, 0, document.documentElement, 2], node processingInstruction 
-PASS 11,16: resulting DOM for range [document.documentElement, 0, document.documentElement, 2], node detachedProcessingInstruction 
-PASS 11,16: resulting range position for range [document.documentElement, 0, document.documentElement, 2], node detachedProcessingInstruction 
-PASS 11,17: resulting DOM for range [document.documentElement, 0, document.documentElement, 2], node comment 
-PASS 11,17: resulting range position for range [document.documentElement, 0, document.documentElement, 2], node comment 
-PASS 11,18: resulting DOM for range [document.documentElement, 0, document.documentElement, 2], node detachedComment 
-PASS 11,18: resulting range position for range [document.documentElement, 0, document.documentElement, 2], node detachedComment 
-PASS 11,19: resulting DOM for range [document.documentElement, 0, document.documentElement, 2], node docfrag 
-PASS 11,19: resulting range position for range [document.documentElement, 0, document.documentElement, 2], node docfrag 
-PASS 11,20: resulting DOM for range [document.documentElement, 0, document.documentElement, 2], node doctype 
-PASS 11,20: resulting range position for range [document.documentElement, 0, document.documentElement, 2], node doctype 
-PASS 11,21: resulting DOM for range [document.documentElement, 0, document.documentElement, 2], node foreignDoctype 
-PASS 11,21: resulting range position for range [document.documentElement, 0, document.documentElement, 2], node foreignDoctype 
-PASS 12,0: resulting DOM for range [document.documentElement, 1, document.documentElement, 2], node paras[0] 
-PASS 12,0: resulting range position for range [document.documentElement, 1, document.documentElement, 2], node paras[0] 
-PASS 12,1: resulting DOM for range [document.documentElement, 1, document.documentElement, 2], node paras[0].firstChild 
-PASS 12,1: resulting range position for range [document.documentElement, 1, document.documentElement, 2], node paras[0].firstChild 
-PASS 12,2: resulting DOM for range [document.documentElement, 1, document.documentElement, 2], node paras[1].firstChild 
-PASS 12,2: resulting range position for range [document.documentElement, 1, document.documentElement, 2], node paras[1].firstChild 
-PASS 12,3: resulting DOM for range [document.documentElement, 1, document.documentElement, 2], node foreignPara1 
-PASS 12,3: resulting range position for range [document.documentElement, 1, document.documentElement, 2], node foreignPara1 
-PASS 12,4: resulting DOM for range [document.documentElement, 1, document.documentElement, 2], node foreignPara1.firstChild 
-PASS 12,4: resulting range position for range [document.documentElement, 1, document.documentElement, 2], node foreignPara1.firstChild 
-PASS 12,5: resulting DOM for range [document.documentElement, 1, document.documentElement, 2], node detachedPara1 
-PASS 12,5: resulting range position for range [document.documentElement, 1, document.documentElement, 2], node detachedPara1 
-PASS 12,6: resulting DOM for range [document.documentElement, 1, document.documentElement, 2], node detachedPara1.firstChild 
-PASS 12,6: resulting range position for range [document.documentElement, 1, document.documentElement, 2], node detachedPara1.firstChild 
-PASS 12,7: resulting DOM for range [document.documentElement, 1, document.documentElement, 2], node document 
-PASS 12,7: resulting range position for range [document.documentElement, 1, document.documentElement, 2], node document 
-PASS 12,8: resulting DOM for range [document.documentElement, 1, document.documentElement, 2], node detachedDiv 
-PASS 12,8: resulting range position for range [document.documentElement, 1, document.documentElement, 2], node detachedDiv 
-PASS 12,9: resulting DOM for range [document.documentElement, 1, document.documentElement, 2], node foreignDoc 
-PASS 12,9: resulting range position for range [document.documentElement, 1, document.documentElement, 2], node foreignDoc 
-PASS 12,10: resulting DOM for range [document.documentElement, 1, document.documentElement, 2], node foreignPara2 
-PASS 12,10: resulting range position for range [document.documentElement, 1, document.documentElement, 2], node foreignPara2 
-PASS 12,11: resulting DOM for range [document.documentElement, 1, document.documentElement, 2], node xmlDoc 
-PASS 12,11: resulting range position for range [document.documentElement, 1, document.documentElement, 2], node xmlDoc 
-PASS 12,12: resulting DOM for range [document.documentElement, 1, document.documentElement, 2], node xmlElement 
-PASS 12,12: resulting range position for range [document.documentElement, 1, document.documentElement, 2], node xmlElement 
-PASS 12,13: resulting DOM for range [document.documentElement, 1, document.documentElement, 2], node detachedTextNode 
-PASS 12,13: resulting range position for range [document.documentElement, 1, document.documentElement, 2], node detachedTextNode 
-PASS 12,14: resulting DOM for range [document.documentElement, 1, document.documentElement, 2], node foreignTextNode 
-PASS 12,14: resulting range position for range [document.documentElement, 1, document.documentElement, 2], node foreignTextNode 
-PASS 12,15: resulting DOM for range [document.documentElement, 1, document.documentElement, 2], node processingInstruction 
-PASS 12,15: resulting range position for range [document.documentElement, 1, document.documentElement, 2], node processingInstruction 
-PASS 12,16: resulting DOM for range [document.documentElement, 1, document.documentElement, 2], node detachedProcessingInstruction 
-PASS 12,16: resulting range position for range [document.documentElement, 1, document.documentElement, 2], node detachedProcessingInstruction 
-PASS 12,17: resulting DOM for range [document.documentElement, 1, document.documentElement, 2], node comment 
-PASS 12,17: resulting range position for range [document.documentElement, 1, document.documentElement, 2], node comment 
-PASS 12,18: resulting DOM for range [document.documentElement, 1, document.documentElement, 2], node detachedComment 
-PASS 12,18: resulting range position for range [document.documentElement, 1, document.documentElement, 2], node detachedComment 
-PASS 12,19: resulting DOM for range [document.documentElement, 1, document.documentElement, 2], node docfrag 
-PASS 12,19: resulting range position for range [document.documentElement, 1, document.documentElement, 2], node docfrag 
-PASS 12,20: resulting DOM for range [document.documentElement, 1, document.documentElement, 2], node doctype 
-PASS 12,20: resulting range position for range [document.documentElement, 1, document.documentElement, 2], node doctype 
-PASS 12,21: resulting DOM for range [document.documentElement, 1, document.documentElement, 2], node foreignDoctype 
-PASS 12,21: resulting range position for range [document.documentElement, 1, document.documentElement, 2], node foreignDoctype 
-PASS 13,0: resulting DOM for range [document.head, 1, document.head, 1], node paras[0] 
-PASS 13,0: resulting range position for range [document.head, 1, document.head, 1], node paras[0] 
-PASS 13,1: resulting DOM for range [document.head, 1, document.head, 1], node paras[0].firstChild 
-PASS 13,1: resulting range position for range [document.head, 1, document.head, 1], node paras[0].firstChild 
-PASS 13,2: resulting DOM for range [document.head, 1, document.head, 1], node paras[1].firstChild 
-PASS 13,2: resulting range position for range [document.head, 1, document.head, 1], node paras[1].firstChild 
-PASS 13,3: resulting DOM for range [document.head, 1, document.head, 1], node foreignPara1 
-PASS 13,3: resulting range position for range [document.head, 1, document.head, 1], node foreignPara1 
-PASS 13,4: resulting DOM for range [document.head, 1, document.head, 1], node foreignPara1.firstChild 
-PASS 13,4: resulting range position for range [document.head, 1, document.head, 1], node foreignPara1.firstChild 
-PASS 13,5: resulting DOM for range [document.head, 1, document.head, 1], node detachedPara1 
-PASS 13,5: resulting range position for range [document.head, 1, document.head, 1], node detachedPara1 
-PASS 13,6: resulting DOM for range [document.head, 1, document.head, 1], node detachedPara1.firstChild 
-PASS 13,6: resulting range position for range [document.head, 1, document.head, 1], node detachedPara1.firstChild 
-PASS 13,7: resulting DOM for range [document.head, 1, document.head, 1], node document 
-PASS 13,7: resulting range position for range [document.head, 1, document.head, 1], node document 
-PASS 13,8: resulting DOM for range [document.head, 1, document.head, 1], node detachedDiv 
-PASS 13,8: resulting range position for range [document.head, 1, document.head, 1], node detachedDiv 
-PASS 13,9: resulting DOM for range [document.head, 1, document.head, 1], node foreignDoc 
-PASS 13,9: resulting range position for range [document.head, 1, document.head, 1], node foreignDoc 
-PASS 13,10: resulting DOM for range [document.head, 1, document.head, 1], node foreignPara2 
-PASS 13,10: resulting range position for range [document.head, 1, document.head, 1], node foreignPara2 
-PASS 13,11: resulting DOM for range [document.head, 1, document.head, 1], node xmlDoc 
-PASS 13,11: resulting range position for range [document.head, 1, document.head, 1], node xmlDoc 
-PASS 13,12: resulting DOM for range [document.head, 1, document.head, 1], node xmlElement 
-PASS 13,12: resulting range position for range [document.head, 1, document.head, 1], node xmlElement 
-PASS 13,13: resulting DOM for range [document.head, 1, document.head, 1], node detachedTextNode 
-PASS 13,13: resulting range position for range [document.head, 1, document.head, 1], node detachedTextNode 
-PASS 13,14: resulting DOM for range [document.head, 1, document.head, 1], node foreignTextNode 
-PASS 13,14: resulting range position for range [document.head, 1, document.head, 1], node foreignTextNode 
-PASS 13,15: resulting DOM for range [document.head, 1, document.head, 1], node processingInstruction 
-PASS 13,15: resulting range position for range [document.head, 1, document.head, 1], node processingInstruction 
-PASS 13,16: resulting DOM for range [document.head, 1, document.head, 1], node detachedProcessingInstruction 
-PASS 13,16: resulting range position for range [document.head, 1, document.head, 1], node detachedProcessingInstruction 
-PASS 13,17: resulting DOM for range [document.head, 1, document.head, 1], node comment 
-PASS 13,17: resulting range position for range [document.head, 1, document.head, 1], node comment 
-PASS 13,18: resulting DOM for range [document.head, 1, document.head, 1], node detachedComment 
-PASS 13,18: resulting range position for range [document.head, 1, document.head, 1], node detachedComment 
-PASS 13,19: resulting DOM for range [document.head, 1, document.head, 1], node docfrag 
-PASS 13,19: resulting range position for range [document.head, 1, document.head, 1], node docfrag 
-PASS 13,20: resulting DOM for range [document.head, 1, document.head, 1], node doctype 
-PASS 13,20: resulting range position for range [document.head, 1, document.head, 1], node doctype 
-PASS 13,21: resulting DOM for range [document.head, 1, document.head, 1], node foreignDoctype 
-PASS 13,21: resulting range position for range [document.head, 1, document.head, 1], node foreignDoctype 
-PASS 14,0: resulting DOM for range [document.body, 4, document.body, 5], node paras[0] 
-PASS 14,0: resulting range position for range [document.body, 4, document.body, 5], node paras[0] 
-PASS 14,1: resulting DOM for range [document.body, 4, document.body, 5], node paras[0].firstChild 
-PASS 14,1: resulting range position for range [document.body, 4, document.body, 5], node paras[0].firstChild 
-PASS 14,2: resulting DOM for range [document.body, 4, document.body, 5], node paras[1].firstChild 
-PASS 14,2: resulting range position for range [document.body, 4, document.body, 5], node paras[1].firstChild 
-PASS 14,3: resulting DOM for range [document.body, 4, document.body, 5], node foreignPara1 
-PASS 14,3: resulting range position for range [document.body, 4, document.body, 5], node foreignPara1 
-PASS 14,4: resulting DOM for range [document.body, 4, document.body, 5], node foreignPara1.firstChild 
-PASS 14,4: resulting range position for range [document.body, 4, document.body, 5], node foreignPara1.firstChild 
-PASS 14,5: resulting DOM for range [document.body, 4, document.body, 5], node detachedPara1 
-PASS 14,5: resulting range position for range [document.body, 4, document.body, 5], node detachedPara1 
-PASS 14,6: resulting DOM for range [document.body, 4, document.body, 5], node detachedPara1.firstChild 
-PASS 14,6: resulting range position for range [document.body, 4, document.body, 5], node detachedPara1.firstChild 
-PASS 14,7: resulting DOM for range [document.body, 4, document.body, 5], node document 
-PASS 14,7: resulting range position for range [document.body, 4, document.body, 5], node document 
-PASS 14,8: resulting DOM for range [document.body, 4, document.body, 5], node detachedDiv 
-PASS 14,8: resulting range position for range [document.body, 4, document.body, 5], node detachedDiv 
-PASS 14,9: resulting DOM for range [document.body, 4, document.body, 5], node foreignDoc 
-PASS 14,9: resulting range position for range [document.body, 4, document.body, 5], node foreignDoc 
-PASS 14,10: resulting DOM for range [document.body, 4, document.body, 5], node foreignPara2 
-PASS 14,10: resulting range position for range [document.body, 4, document.body, 5], node foreignPara2 
-PASS 14,11: resulting DOM for range [document.body, 4, document.body, 5], node xmlDoc 
-PASS 14,11: resulting range position for range [document.body, 4, document.body, 5], node xmlDoc 
-PASS 14,12: resulting DOM for range [document.body, 4, document.body, 5], node xmlElement 
-PASS 14,12: resulting range position for range [document.body, 4, document.body, 5], node xmlElement 
-PASS 14,13: resulting DOM for range [document.body, 4, document.body, 5], node detachedTextNode 
-PASS 14,13: resulting range position for range [document.body, 4, document.body, 5], node detachedTextNode 
-PASS 14,14: resulting DOM for range [document.body, 4, document.body, 5], node foreignTextNode 
-PASS 14,14: resulting range position for range [document.body, 4, document.body, 5], node foreignTextNode 
-PASS 14,15: resulting DOM for range [document.body, 4, document.body, 5], node processingInstruction 
-PASS 14,15: resulting range position for range [document.body, 4, document.body, 5], node processingInstruction 
-PASS 14,16: resulting DOM for range [document.body, 4, document.body, 5], node detachedProcessingInstruction 
-PASS 14,16: resulting range position for range [document.body, 4, document.body, 5], node detachedProcessingInstruction 
-PASS 14,17: resulting DOM for range [document.body, 4, document.body, 5], node comment 
-PASS 14,17: resulting range position for range [document.body, 4, document.body, 5], node comment 
-PASS 14,18: resulting DOM for range [document.body, 4, document.body, 5], node detachedComment 
-PASS 14,18: resulting range position for range [document.body, 4, document.body, 5], node detachedComment 
-PASS 14,19: resulting DOM for range [document.body, 4, document.body, 5], node docfrag 
-PASS 14,19: resulting range position for range [document.body, 4, document.body, 5], node docfrag 
-PASS 14,20: resulting DOM for range [document.body, 4, document.body, 5], node doctype 
-PASS 14,20: resulting range position for range [document.body, 4, document.body, 5], node doctype 
-PASS 14,21: resulting DOM for range [document.body, 4, document.body, 5], node foreignDoctype 
-PASS 14,21: resulting range position for range [document.body, 4, document.body, 5], node foreignDoctype 
-PASS 15,0: resulting DOM for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node paras[0] 
-PASS 15,0: resulting range position for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node paras[0] 
-PASS 15,1: resulting DOM for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node paras[0].firstChild 
-PASS 15,1: resulting range position for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node paras[0].firstChild 
-PASS 15,2: resulting DOM for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node paras[1].firstChild 
-PASS 15,2: resulting range position for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node paras[1].firstChild 
-PASS 15,3: resulting DOM for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node foreignPara1 
-PASS 15,3: resulting range position for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node foreignPara1 
-PASS 15,4: resulting DOM for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node foreignPara1.firstChild 
-PASS 15,4: resulting range position for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node foreignPara1.firstChild 
-PASS 15,5: resulting DOM for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node detachedPara1 
-PASS 15,5: resulting range position for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node detachedPara1 
-PASS 15,6: resulting DOM for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node detachedPara1.firstChild 
-PASS 15,6: resulting range position for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node detachedPara1.firstChild 
-PASS 15,7: resulting DOM for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node document 
-PASS 15,7: resulting range position for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node document 
-PASS 15,8: resulting DOM for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node detachedDiv 
-PASS 15,8: resulting range position for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node detachedDiv 
-PASS 15,9: resulting DOM for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node foreignDoc 
-PASS 15,9: resulting range position for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node foreignDoc 
-PASS 15,10: resulting DOM for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node foreignPara2 
-PASS 15,10: resulting range position for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node foreignPara2 
-PASS 15,11: resulting DOM for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node xmlDoc 
-PASS 15,11: resulting range position for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node xmlDoc 
-PASS 15,12: resulting DOM for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node xmlElement 
-PASS 15,12: resulting range position for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node xmlElement 
-PASS 15,13: resulting DOM for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node detachedTextNode 
-PASS 15,13: resulting range position for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node detachedTextNode 
-PASS 15,14: resulting DOM for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node foreignTextNode 
-PASS 15,14: resulting range position for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node foreignTextNode 
-PASS 15,15: resulting DOM for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node processingInstruction 
-PASS 15,15: resulting range position for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node processingInstruction 
-PASS 15,16: resulting DOM for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node detachedProcessingInstruction 
-PASS 15,16: resulting range position for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node detachedProcessingInstruction 
-PASS 15,17: resulting DOM for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node comment 
-PASS 15,17: resulting range position for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node comment 
-PASS 15,18: resulting DOM for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node detachedComment 
-PASS 15,18: resulting range position for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node detachedComment 
-PASS 15,19: resulting DOM for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node docfrag 
-PASS 15,19: resulting range position for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node docfrag 
-PASS 15,20: resulting DOM for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node doctype 
-PASS 15,20: resulting range position for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node doctype 
-PASS 15,21: resulting DOM for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node foreignDoctype 
-PASS 15,21: resulting range position for range [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node foreignDoctype 
-PASS 16,0: resulting DOM for range [paras[0], 0, paras[0], 1], node paras[0] 
-PASS 16,0: resulting range position for range [paras[0], 0, paras[0], 1], node paras[0] 
-PASS 16,1: resulting DOM for range [paras[0], 0, paras[0], 1], node paras[0].firstChild 
-PASS 16,1: resulting range position for range [paras[0], 0, paras[0], 1], node paras[0].firstChild 
-PASS 16,2: resulting DOM for range [paras[0], 0, paras[0], 1], node paras[1].firstChild 
-PASS 16,2: resulting range position for range [paras[0], 0, paras[0], 1], node paras[1].firstChild 
-PASS 16,3: resulting DOM for range [paras[0], 0, paras[0], 1], node foreignPara1 
-PASS 16,3: resulting range position for range [paras[0], 0, paras[0], 1], node foreignPara1 
-PASS 16,4: resulting DOM for range [paras[0], 0, paras[0], 1], node foreignPara1.firstChild 
-PASS 16,4: resulting range position for range [paras[0], 0, paras[0], 1], node foreignPara1.firstChild 
-PASS 16,5: resulting DOM for range [paras[0], 0, paras[0], 1], node detachedPara1 
-PASS 16,5: resulting range position for range [paras[0], 0, paras[0], 1], node detachedPara1 
-PASS 16,6: resulting DOM for range [paras[0], 0, paras[0], 1], node detachedPara1.firstChild 
-PASS 16,6: resulting range position for range [paras[0], 0, paras[0], 1], node detachedPara1.firstChild 
-PASS 16,7: resulting DOM for range [paras[0], 0, paras[0], 1], node document 
-PASS 16,7: resulting range position for range [paras[0], 0, paras[0], 1], node document 
-PASS 16,8: resulting DOM for range [paras[0], 0, paras[0], 1], node detachedDiv 
-PASS 16,8: resulting range position for range [paras[0], 0, paras[0], 1], node detachedDiv 
-PASS 16,9: resulting DOM for range [paras[0], 0, paras[0], 1], node foreignDoc 
-PASS 16,9: resulting range position for range [paras[0], 0, paras[0], 1], node foreignDoc 
-PASS 16,10: resulting DOM for range [paras[0], 0, paras[0], 1], node foreignPara2 
-PASS 16,10: resulting range position for range [paras[0], 0, paras[0], 1], node foreignPara2 
-PASS 16,11: resulting DOM for range [paras[0], 0, paras[0], 1], node xmlDoc 
-PASS 16,11: resulting range position for range [paras[0], 0, paras[0], 1], node xmlDoc 
-PASS 16,12: resulting DOM for range [paras[0], 0, paras[0], 1], node xmlElement 
-PASS 16,12: resulting range position for range [paras[0], 0, paras[0], 1], node xmlElement 
-PASS 16,13: resulting DOM for range [paras[0], 0, paras[0], 1], node detachedTextNode 
-PASS 16,13: resulting range position for range [paras[0], 0, paras[0], 1], node detachedTextNode 
-PASS 16,14: resulting DOM for range [paras[0], 0, paras[0], 1], node foreignTextNode 
-PASS 16,14: resulting range position for range [paras[0], 0, paras[0], 1], node foreignTextNode 
-PASS 16,15: resulting DOM for range [paras[0], 0, paras[0], 1], node processingInstruction 
-PASS 16,15: resulting range position for range [paras[0], 0, paras[0], 1], node processingInstruction 
-PASS 16,16: resulting DOM for range [paras[0], 0, paras[0], 1], node detachedProcessingInstruction 
-PASS 16,16: resulting range position for range [paras[0], 0, paras[0], 1], node detachedProcessingInstruction 
-PASS 16,17: resulting DOM for range [paras[0], 0, paras[0], 1], node comment 
-PASS 16,17: resulting range position for range [paras[0], 0, paras[0], 1], node comment 
-PASS 16,18: resulting DOM for range [paras[0], 0, paras[0], 1], node detachedComment 
-PASS 16,18: resulting range position for range [paras[0], 0, paras[0], 1], node detachedComment 
-PASS 16,19: resulting DOM for range [paras[0], 0, paras[0], 1], node docfrag 
-PASS 16,19: resulting range position for range [paras[0], 0, paras[0], 1], node docfrag 
-PASS 16,20: resulting DOM for range [paras[0], 0, paras[0], 1], node doctype 
-PASS 16,20: resulting range position for range [paras[0], 0, paras[0], 1], node doctype 
-PASS 16,21: resulting DOM for range [paras[0], 0, paras[0], 1], node foreignDoctype 
-PASS 16,21: resulting range position for range [paras[0], 0, paras[0], 1], node foreignDoctype 
-PASS 17,0: resulting DOM for range [detachedPara1, 0, detachedPara1, 1], node paras[0] 
-PASS 17,0: resulting range position for range [detachedPara1, 0, detachedPara1, 1], node paras[0] 
-PASS 17,1: resulting DOM for range [detachedPara1, 0, detachedPara1, 1], node paras[0].firstChild 
-PASS 17,1: resulting range position for range [detachedPara1, 0, detachedPara1, 1], node paras[0].firstChild 
-PASS 17,2: resulting DOM for range [detachedPara1, 0, detachedPara1, 1], node paras[1].firstChild 
-PASS 17,2: resulting range position for range [detachedPara1, 0, detachedPara1, 1], node paras[1].firstChild 
-PASS 17,3: resulting DOM for range [detachedPara1, 0, detachedPara1, 1], node foreignPara1 
-PASS 17,3: resulting range position for range [detachedPara1, 0, detachedPara1, 1], node foreignPara1 
-PASS 17,4: resulting DOM for range [detachedPara1, 0, detachedPara1, 1], node foreignPara1.firstChild 
-PASS 17,4: resulting range position for range [detachedPara1, 0, detachedPara1, 1], node foreignPara1.firstChild 
-PASS 17,5: resulting DOM for range [detachedPara1, 0, detachedPara1, 1], node detachedPara1 
-PASS 17,5: resulting range position for range [detachedPara1, 0, detachedPara1, 1], node detachedPara1 
-PASS 17,6: resulting DOM for range [detachedPara1, 0, detachedPara1, 1], node detachedPara1.firstChild 
-PASS 17,6: resulting range position for range [detachedPara1, 0, detachedPara1, 1], node detachedPara1.firstChild 
-PASS 17,7: resulting DOM for range [detachedPara1, 0, detachedPara1, 1], node document 
-PASS 17,7: resulting range position for range [detachedPara1, 0, detachedPara1, 1], node document 
-PASS 17,8: resulting DOM for range [detachedPara1, 0, detachedPara1, 1], node detachedDiv 
-PASS 17,8: resulting range position for range [detachedPara1, 0, detachedPara1, 1], node detachedDiv 
-PASS 17,9: resulting DOM for range [detachedPara1, 0, detachedPara1, 1], node foreignDoc 
-PASS 17,9: resulting range position for range [detachedPara1, 0, detachedPara1, 1], node foreignDoc 
-PASS 17,10: resulting DOM for range [detachedPara1, 0, detachedPara1, 1], node foreignPara2 
-PASS 17,10: resulting range position for range [detachedPara1, 0, detachedPara1, 1], node foreignPara2 
-PASS 17,11: resulting DOM for range [detachedPara1, 0, detachedPara1, 1], node xmlDoc 
-PASS 17,11: resulting range position for range [detachedPara1, 0, detachedPara1, 1], node xmlDoc 
-PASS 17,12: resulting DOM for range [detachedPara1, 0, detachedPara1, 1], node xmlElement 
-PASS 17,12: resulting range position for range [detachedPara1, 0, detachedPara1, 1], node xmlElement 
-PASS 17,13: resulting DOM for range [detachedPara1, 0, detachedPara1, 1], node detachedTextNode 
-PASS 17,13: resulting range position for range [detachedPara1, 0, detachedPara1, 1], node detachedTextNode 
-PASS 17,14: resulting DOM for range [detachedPara1, 0, detachedPara1, 1], node foreignTextNode 
-PASS 17,14: resulting range position for range [detachedPara1, 0, detachedPara1, 1], node foreignTextNode 
-PASS 17,15: resulting DOM for range [detachedPara1, 0, detachedPara1, 1], node processingInstruction 
-PASS 17,15: resulting range position for range [detachedPara1, 0, detachedPara1, 1], node processingInstruction 
-PASS 17,16: resulting DOM for range [detachedPara1, 0, detachedPara1, 1], node detachedProcessingInstruction 
-PASS 17,16: resulting range position for range [detachedPara1, 0, detachedPara1, 1], node detachedProcessingInstruction 
-PASS 17,17: resulting DOM for range [detachedPara1, 0, detachedPara1, 1], node comment 
-PASS 17,17: resulting range position for range [detachedPara1, 0, detachedPara1, 1], node comment 
-PASS 17,18: resulting DOM for range [detachedPara1, 0, detachedPara1, 1], node detachedComment 
-PASS 17,18: resulting range position for range [detachedPara1, 0, detachedPara1, 1], node detachedComment 
-PASS 17,19: resulting DOM for range [detachedPara1, 0, detachedPara1, 1], node docfrag 
-PASS 17,19: resulting range position for range [detachedPara1, 0, detachedPara1, 1], node docfrag 
-PASS 17,20: resulting DOM for range [detachedPara1, 0, detachedPara1, 1], node doctype 
-PASS 17,20: resulting range position for range [detachedPara1, 0, detachedPara1, 1], node doctype 
-PASS 17,21: resulting DOM for range [detachedPara1, 0, detachedPara1, 1], node foreignDoctype 
-PASS 17,21: resulting range position for range [detachedPara1, 0, detachedPara1, 1], node foreignDoctype 
-PASS 18,0: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node paras[0] 
-PASS 18,0: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node paras[0] 
-PASS 18,1: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node paras[0].firstChild 
-PASS 18,1: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node paras[0].firstChild 
-PASS 18,2: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node paras[1].firstChild 
-PASS 18,2: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node paras[1].firstChild 
-PASS 18,3: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node foreignPara1 
-PASS 18,3: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node foreignPara1 
-PASS 18,4: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node foreignPara1.firstChild 
-PASS 18,4: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node foreignPara1.firstChild 
-PASS 18,5: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node detachedPara1 
-PASS 18,5: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node detachedPara1 
-PASS 18,6: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node detachedPara1.firstChild 
-PASS 18,6: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node detachedPara1.firstChild 
-PASS 18,7: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node document 
-PASS 18,7: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node document 
-PASS 18,8: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node detachedDiv 
-PASS 18,8: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node detachedDiv 
-PASS 18,9: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node foreignDoc 
-PASS 18,9: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node foreignDoc 
-PASS 18,10: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node foreignPara2 
-PASS 18,10: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node foreignPara2 
-PASS 18,11: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node xmlDoc 
-PASS 18,11: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node xmlDoc 
-PASS 18,12: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node xmlElement 
-PASS 18,12: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node xmlElement 
-PASS 18,13: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node detachedTextNode 
-PASS 18,13: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node detachedTextNode 
-PASS 18,14: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node foreignTextNode 
-PASS 18,14: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node foreignTextNode 
-PASS 18,15: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node processingInstruction 
-PASS 18,15: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node processingInstruction 
-PASS 18,16: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node detachedProcessingInstruction 
-PASS 18,16: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node detachedProcessingInstruction 
-PASS 18,17: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node comment 
-PASS 18,17: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node comment 
-PASS 18,18: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node detachedComment 
-PASS 18,18: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node detachedComment 
-PASS 18,19: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node docfrag 
-PASS 18,19: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node docfrag 
-PASS 18,20: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node doctype 
-PASS 18,20: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node doctype 
-PASS 18,21: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node foreignDoctype 
-PASS 18,21: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 0], node foreignDoctype 
-PASS 19,0: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node paras[0] 
-PASS 19,0: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node paras[0] 
-PASS 19,1: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node paras[0].firstChild 
-PASS 19,1: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node paras[0].firstChild 
-PASS 19,2: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node paras[1].firstChild 
-PASS 19,2: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node paras[1].firstChild 
-PASS 19,3: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node foreignPara1 
-PASS 19,3: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node foreignPara1 
-PASS 19,4: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node foreignPara1.firstChild 
-PASS 19,4: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node foreignPara1.firstChild 
-PASS 19,5: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node detachedPara1 
-PASS 19,5: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node detachedPara1 
-PASS 19,6: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node detachedPara1.firstChild 
-PASS 19,6: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node detachedPara1.firstChild 
-PASS 19,7: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node document 
-PASS 19,7: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node document 
-PASS 19,8: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node detachedDiv 
-PASS 19,8: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node detachedDiv 
-PASS 19,9: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node foreignDoc 
-PASS 19,9: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node foreignDoc 
-PASS 19,10: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node foreignPara2 
-PASS 19,10: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node foreignPara2 
-PASS 19,11: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node xmlDoc 
-PASS 19,11: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node xmlDoc 
-PASS 19,12: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node xmlElement 
-PASS 19,12: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node xmlElement 
-PASS 19,13: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node detachedTextNode 
-PASS 19,13: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node detachedTextNode 
-PASS 19,14: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node foreignTextNode 
-PASS 19,14: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node foreignTextNode 
-PASS 19,15: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node processingInstruction 
-PASS 19,15: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node processingInstruction 
-PASS 19,16: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node detachedProcessingInstruction 
-PASS 19,16: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node detachedProcessingInstruction 
-PASS 19,17: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node comment 
-PASS 19,17: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node comment 
-PASS 19,18: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node detachedComment 
-PASS 19,18: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node detachedComment 
-PASS 19,19: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node docfrag 
-PASS 19,19: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node docfrag 
-PASS 19,20: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node doctype 
-PASS 19,20: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node doctype 
-PASS 19,21: resulting DOM for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node foreignDoctype 
-PASS 19,21: resulting range position for range [paras[0].firstChild, 0, paras[1].firstChild, 8], node foreignDoctype 
-PASS 20,0: resulting DOM for range [paras[0].firstChild, 3, paras[3], 1], node paras[0] 
-PASS 20,0: resulting range position for range [paras[0].firstChild, 3, paras[3], 1], node paras[0] 
-PASS 20,1: resulting DOM for range [paras[0].firstChild, 3, paras[3], 1], node paras[0].firstChild 
-PASS 20,1: resulting range position for range [paras[0].firstChild, 3, paras[3], 1], node paras[0].firstChild 
-PASS 20,2: resulting DOM for range [paras[0].firstChild, 3, paras[3], 1], node paras[1].firstChild 
-PASS 20,2: resulting range position for range [paras[0].firstChild, 3, paras[3], 1], node paras[1].firstChild 
-PASS 20,3: resulting DOM for range [paras[0].firstChild, 3, paras[3], 1], node foreignPara1 
-PASS 20,3: resulting range position for range [paras[0].firstChild, 3, paras[3], 1], node foreignPara1 
-PASS 20,4: resulting DOM for range [paras[0].firstChild, 3, paras[3], 1], node foreignPara1.firstChild 
-PASS 20,4: resulting range position for range [paras[0].firstChild, 3, paras[3], 1], node foreignPara1.firstChild 
-PASS 20,5: resulting DOM for range [paras[0].firstChild, 3, paras[3], 1], node detachedPara1 
-PASS 20,5: resulting range position for range [paras[0].firstChild, 3, paras[3], 1], node detachedPara1 
-PASS 20,6: resulting DOM for range [paras[0].firstChild, 3, paras[3], 1], node detachedPara1.firstChild 
-PASS 20,6: resulting range position for range [paras[0].firstChild, 3, paras[3], 1], node detachedPara1.firstChild 
-PASS 20,7: resulting DOM for range [paras[0].firstChild, 3, paras[3], 1], node document 
-PASS 20,7: resulting range position for range [paras[0].firstChild, 3, paras[3], 1], node document 
-PASS 20,8: resulting DOM for range [paras[0].firstChild, 3, paras[3], 1], node detachedDiv 
-PASS 20,8: resulting range position for range [paras[0].firstChild, 3, paras[3], 1], node detachedDiv 
-PASS 20,9: resulting DOM for range [paras[0].firstChild, 3, paras[3], 1], node foreignDoc 
-PASS 20,9: resulting range position for range [paras[0].firstChild, 3, paras[3], 1], node foreignDoc 
-PASS 20,10: resulting DOM for range [paras[0].firstChild, 3, paras[3], 1], node foreignPara2 
-PASS 20,10: resulting range position for range [paras[0].firstChild, 3, paras[3], 1], node foreignPara2 
-PASS 20,11: resulting DOM for range [paras[0].firstChild, 3, paras[3], 1], node xmlDoc 
-PASS 20,11: resulting range position for range [paras[0].firstChild, 3, paras[3], 1], node xmlDoc 
-PASS 20,12: resulting DOM for range [paras[0].firstChild, 3, paras[3], 1], node xmlElement 
-PASS 20,12: resulting range position for range [paras[0].firstChild, 3, paras[3], 1], node xmlElement 
-PASS 20,13: resulting DOM for range [paras[0].firstChild, 3, paras[3], 1], node detachedTextNode 
-PASS 20,13: resulting range position for range [paras[0].firstChild, 3, paras[3], 1], node detachedTextNode 
-PASS 20,14: resulting DOM for range [paras[0].firstChild, 3, paras[3], 1], node foreignTextNode 
-PASS 20,14: resulting range position for range [paras[0].firstChild, 3, paras[3], 1], node foreignTextNode 
-PASS 20,15: resulting DOM for range [paras[0].firstChild, 3, paras[3], 1], node processingInstruction 
-PASS 20,15: resulting range position for range [paras[0].firstChild, 3, paras[3], 1], node processingInstruction 
-PASS 20,16: resulting DOM for range [paras[0].firstChild, 3, paras[3], 1], node detachedProcessingInstruction 
-PASS 20,16: resulting range position for range [paras[0].firstChild, 3, paras[3], 1], node detachedProcessingInstruction 
-PASS 20,17: resulting DOM for range [paras[0].firstChild, 3, paras[3], 1], node comment 
-PASS 20,17: resulting range position for range [paras[0].firstChild, 3, paras[3], 1], node comment 
-PASS 20,18: resulting DOM for range [paras[0].firstChild, 3, paras[3], 1], node detachedComment 
-PASS 20,18: resulting range position for range [paras[0].firstChild, 3, paras[3], 1], node detachedComment 
-PASS 20,19: resulting DOM for range [paras[0].firstChild, 3, paras[3], 1], node docfrag 
-PASS 20,19: resulting range position for range [paras[0].firstChild, 3, paras[3], 1], node docfrag 
-PASS 20,20: resulting DOM for range [paras[0].firstChild, 3, paras[3], 1], node doctype 
-PASS 20,20: resulting range position for range [paras[0].firstChild, 3, paras[3], 1], node doctype 
-PASS 20,21: resulting DOM for range [paras[0].firstChild, 3, paras[3], 1], node foreignDoctype 
-PASS 20,21: resulting range position for range [paras[0].firstChild, 3, paras[3], 1], node foreignDoctype 
-PASS 21,0: resulting DOM for range [paras[0], 0, paras[0].firstChild, 7], node paras[0] 
-PASS 21,0: resulting range position for range [paras[0], 0, paras[0].firstChild, 7], node paras[0] 
-PASS 21,1: resulting DOM for range [paras[0], 0, paras[0].firstChild, 7], node paras[0].firstChild 
-FAIL 21,1: resulting range position for range [paras[0], 0, paras[0].firstChild, 7], node paras[0].firstChild assert_equals: Unexpected endOffset after insertNode() expected 1 but got 7
-PASS 21,2: resulting DOM for range [paras[0], 0, paras[0].firstChild, 7], node paras[1].firstChild 
-PASS 21,2: resulting range position for range [paras[0], 0, paras[0].firstChild, 7], node paras[1].firstChild 
-PASS 21,3: resulting DOM for range [paras[0], 0, paras[0].firstChild, 7], node foreignPara1 
-PASS 21,3: resulting range position for range [paras[0], 0, paras[0].firstChild, 7], node foreignPara1 
-PASS 21,4: resulting DOM for range [paras[0], 0, paras[0].firstChild, 7], node foreignPara1.firstChild 
-PASS 21,4: resulting range position for range [paras[0], 0, paras[0].firstChild, 7], node foreignPara1.firstChild 
-PASS 21,5: resulting DOM for range [paras[0], 0, paras[0].firstChild, 7], node detachedPara1 
-PASS 21,5: resulting range position for range [paras[0], 0, paras[0].firstChild, 7], node detachedPara1 
-PASS 21,6: resulting DOM for range [paras[0], 0, paras[0].firstChild, 7], node detachedPara1.firstChild 
-PASS 21,6: resulting range position for range [paras[0], 0, paras[0].firstChild, 7], node detachedPara1.firstChild 
-PASS 21,7: resulting DOM for range [paras[0], 0, paras[0].firstChild, 7], node document 
-PASS 21,7: resulting range position for range [paras[0], 0, paras[0].firstChild, 7], node document 
-PASS 21,8: resulting DOM for range [paras[0], 0, paras[0].firstChild, 7], node detachedDiv 
-PASS 21,8: resulting range position for range [paras[0], 0, paras[0].firstChild, 7], node detachedDiv 
-PASS 21,9: resulting DOM for range [paras[0], 0, paras[0].firstChild, 7], node foreignDoc 
-PASS 21,9: resulting range position for range [paras[0], 0, paras[0].firstChild, 7], node foreignDoc 
-PASS 21,10: resulting DOM for range [paras[0], 0, paras[0].firstChild, 7], node foreignPara2 
-PASS 21,10: resulting range position for range [paras[0], 0, paras[0].firstChild, 7], node foreignPara2 
-PASS 21,11: resulting DOM for range [paras[0], 0, paras[0].firstChild, 7], node xmlDoc 
-PASS 21,11: resulting range position for range [paras[0], 0, paras[0].firstChild, 7], node xmlDoc 
-PASS 21,12: resulting DOM for range [paras[0], 0, paras[0].firstChild, 7], node xmlElement 
-PASS 21,12: resulting range position for range [paras[0], 0, paras[0].firstChild, 7], node xmlElement 
-PASS 21,13: resulting DOM for range [paras[0], 0, paras[0].firstChild, 7], node detachedTextNode 
-PASS 21,13: resulting range position for range [paras[0], 0, paras[0].firstChild, 7], node detachedTextNode 
-PASS 21,14: resulting DOM for range [paras[0], 0, paras[0].firstChild, 7], node foreignTextNode 
-PASS 21,14: resulting range position for range [paras[0], 0, paras[0].firstChild, 7], node foreignTextNode 
-PASS 21,15: resulting DOM for range [paras[0], 0, paras[0].firstChild, 7], node processingInstruction 
-PASS 21,15: resulting range position for range [paras[0], 0, paras[0].firstChild, 7], node processingInstruction 
-PASS 21,16: resulting DOM for range [paras[0], 0, paras[0].firstChild, 7], node detachedProcessingInstruction 
-PASS 21,16: resulting range position for range [paras[0], 0, paras[0].firstChild, 7], node detachedProcessingInstruction 
-PASS 21,17: resulting DOM for range [paras[0], 0, paras[0].firstChild, 7], node comment 
-PASS 21,17: resulting range position for range [paras[0], 0, paras[0].firstChild, 7], node comment 
-PASS 21,18: resulting DOM for range [paras[0], 0, paras[0].firstChild, 7], node detachedComment 
-PASS 21,18: resulting range position for range [paras[0], 0, paras[0].firstChild, 7], node detachedComment 
-PASS 21,19: resulting DOM for range [paras[0], 0, paras[0].firstChild, 7], node docfrag 
-PASS 21,19: resulting range position for range [paras[0], 0, paras[0].firstChild, 7], node docfrag 
-PASS 21,20: resulting DOM for range [paras[0], 0, paras[0].firstChild, 7], node doctype 
-PASS 21,20: resulting range position for range [paras[0], 0, paras[0].firstChild, 7], node doctype 
-PASS 21,21: resulting DOM for range [paras[0], 0, paras[0].firstChild, 7], node foreignDoctype 
-PASS 21,21: resulting range position for range [paras[0], 0, paras[0].firstChild, 7], node foreignDoctype 
-PASS 22,0: resulting DOM for range [testDiv, 2, paras[4], 1], node paras[0] 
-PASS 22,0: resulting range position for range [testDiv, 2, paras[4], 1], node paras[0] 
-PASS 22,1: resulting DOM for range [testDiv, 2, paras[4], 1], node paras[0].firstChild 
-PASS 22,1: resulting range position for range [testDiv, 2, paras[4], 1], node paras[0].firstChild 
-PASS 22,2: resulting DOM for range [testDiv, 2, paras[4], 1], node paras[1].firstChild 
-PASS 22,2: resulting range position for range [testDiv, 2, paras[4], 1], node paras[1].firstChild 
-PASS 22,3: resulting DOM for range [testDiv, 2, paras[4], 1], node foreignPara1 
-PASS 22,3: resulting range position for range [testDiv, 2, paras[4], 1], node foreignPara1 
-PASS 22,4: resulting DOM for range [testDiv, 2, paras[4], 1], node foreignPara1.firstChild 
-PASS 22,4: resulting range position for range [testDiv, 2, paras[4], 1], node foreignPara1.firstChild 
-PASS 22,5: resulting DOM for range [testDiv, 2, paras[4], 1], node detachedPara1 
-PASS 22,5: resulting range position for range [testDiv, 2, paras[4], 1], node detachedPara1 
-PASS 22,6: resulting DOM for range [testDiv, 2, paras[4], 1], node detachedPara1.firstChild 
-PASS 22,6: resulting range position for range [testDiv, 2, paras[4], 1], node detachedPara1.firstChild 
-PASS 22,7: resulting DOM for range [testDiv, 2, paras[4], 1], node document 
-PASS 22,7: resulting range position for range [testDiv, 2, paras[4], 1], node document 
-PASS 22,8: resulting DOM for range [testDiv, 2, paras[4], 1], node detachedDiv 
-PASS 22,8: resulting range position for range [testDiv, 2, paras[4], 1], node detachedDiv 
-PASS 22,9: resulting DOM for range [testDiv, 2, paras[4], 1], node foreignDoc 
-PASS 22,9: resulting range position for range [testDiv, 2, paras[4], 1], node foreignDoc 
-PASS 22,10: resulting DOM for range [testDiv, 2, paras[4], 1], node foreignPara2 
-PASS 22,10: resulting range position for range [testDiv, 2, paras[4], 1], node foreignPara2 
-PASS 22,11: resulting DOM for range [testDiv, 2, paras[4], 1], node xmlDoc 
-PASS 22,11: resulting range position for range [testDiv, 2, paras[4], 1], node xmlDoc 
-PASS 22,12: resulting DOM for range [testDiv, 2, paras[4], 1], node xmlElement 
-PASS 22,12: resulting range position for range [testDiv, 2, paras[4], 1], node xmlElement 
-PASS 22,13: resulting DOM for range [testDiv, 2, paras[4], 1], node detachedTextNode 
-PASS 22,13: resulting range position for range [testDiv, 2, paras[4], 1], node detachedTextNode 
-PASS 22,14: resulting DOM for range [testDiv, 2, paras[4], 1], node foreignTextNode 
-PASS 22,14: resulting range position for range [testDiv, 2, paras[4], 1], node foreignTextNode 
-PASS 22,15: resulting DOM for range [testDiv, 2, paras[4], 1], node processingInstruction 
-PASS 22,15: resulting range position for range [testDiv, 2, paras[4], 1], node processingInstruction 
-PASS 22,16: resulting DOM for range [testDiv, 2, paras[4], 1], node detachedProcessingInstruction 
-PASS 22,16: resulting range position for range [testDiv, 2, paras[4], 1], node detachedProcessingInstruction 
-PASS 22,17: resulting DOM for range [testDiv, 2, paras[4], 1], node comment 
-PASS 22,17: resulting range position for range [testDiv, 2, paras[4], 1], node comment 
-PASS 22,18: resulting DOM for range [testDiv, 2, paras[4], 1], node detachedComment 
-PASS 22,18: resulting range position for range [testDiv, 2, paras[4], 1], node detachedComment 
-PASS 22,19: resulting DOM for range [testDiv, 2, paras[4], 1], node docfrag 
-PASS 22,19: resulting range position for range [testDiv, 2, paras[4], 1], node docfrag 
-PASS 22,20: resulting DOM for range [testDiv, 2, paras[4], 1], node doctype 
-PASS 22,20: resulting range position for range [testDiv, 2, paras[4], 1], node doctype 
-PASS 22,21: resulting DOM for range [testDiv, 2, paras[4], 1], node foreignDoctype 
-PASS 22,21: resulting range position for range [testDiv, 2, paras[4], 1], node foreignDoctype 
-PASS 23,0: resulting DOM for range [document, 0, document, 1], node paras[0] 
-PASS 23,0: resulting range position for range [document, 0, document, 1], node paras[0] 
-PASS 23,1: resulting DOM for range [document, 0, document, 1], node paras[0].firstChild 
-PASS 23,1: resulting range position for range [document, 0, document, 1], node paras[0].firstChild 
-PASS 23,2: resulting DOM for range [document, 0, document, 1], node paras[1].firstChild 
-PASS 23,2: resulting range position for range [document, 0, document, 1], node paras[1].firstChild 
-PASS 23,3: resulting DOM for range [document, 0, document, 1], node foreignPara1 
-PASS 23,3: resulting range position for range [document, 0, document, 1], node foreignPara1 
-PASS 23,4: resulting DOM for range [document, 0, document, 1], node foreignPara1.firstChild 
-PASS 23,4: resulting range position for range [document, 0, document, 1], node foreignPara1.firstChild 
-PASS 23,5: resulting DOM for range [document, 0, document, 1], node detachedPara1 
-PASS 23,5: resulting range position for range [document, 0, document, 1], node detachedPara1 
-PASS 23,6: resulting DOM for range [document, 0, document, 1], node detachedPara1.firstChild 
-PASS 23,6: resulting range position for range [document, 0, document, 1], node detachedPara1.firstChild 
-PASS 23,7: resulting DOM for range [document, 0, document, 1], node document 
-PASS 23,7: resulting range position for range [document, 0, document, 1], node document 
-PASS 23,8: resulting DOM for range [document, 0, document, 1], node detachedDiv 
-PASS 23,8: resulting range position for range [document, 0, document, 1], node detachedDiv 
-PASS 23,9: resulting DOM for range [document, 0, document, 1], node foreignDoc 
-PASS 23,9: resulting range position for range [document, 0, document, 1], node foreignDoc 
-PASS 23,10: resulting DOM for range [document, 0, document, 1], node foreignPara2 
-PASS 23,10: resulting range position for range [document, 0, document, 1], node foreignPara2 
-PASS 23,11: resulting DOM for range [document, 0, document, 1], node xmlDoc 
-PASS 23,11: resulting range position for range [document, 0, document, 1], node xmlDoc 
-PASS 23,12: resulting DOM for range [document, 0, document, 1], node xmlElement 
-PASS 23,12: resulting range position for range [document, 0, document, 1], node xmlElement 
-PASS 23,13: resulting DOM for range [document, 0, document, 1], node detachedTextNode 
-PASS 23,13: resulting range position for range [document, 0, document, 1], node detachedTextNode 
-PASS 23,14: resulting DOM for range [document, 0, document, 1], node foreignTextNode 
-PASS 23,14: resulting range position for range [document, 0, document, 1], node foreignTextNode 
-PASS 23,15: resulting DOM for range [document, 0, document, 1], node processingInstruction 
-PASS 23,15: resulting range position for range [document, 0, document, 1], node processingInstruction 
-PASS 23,16: resulting DOM for range [document, 0, document, 1], node detachedProcessingInstruction 
-PASS 23,16: resulting range position for range [document, 0, document, 1], node detachedProcessingInstruction 
-PASS 23,17: resulting DOM for range [document, 0, document, 1], node comment 
-PASS 23,17: resulting range position for range [document, 0, document, 1], node comment 
-PASS 23,18: resulting DOM for range [document, 0, document, 1], node detachedComment 
-PASS 23,18: resulting range position for range [document, 0, document, 1], node detachedComment 
-PASS 23,19: resulting DOM for range [document, 0, document, 1], node docfrag 
-PASS 23,19: resulting range position for range [document, 0, document, 1], node docfrag 
-PASS 23,20: resulting DOM for range [document, 0, document, 1], node doctype 
-PASS 23,20: resulting range position for range [document, 0, document, 1], node doctype 
-PASS 23,21: resulting DOM for range [document, 0, document, 1], node foreignDoctype 
-PASS 23,21: resulting range position for range [document, 0, document, 1], node foreignDoctype 
-PASS 24,0: resulting DOM for range [document, 0, document, 2], node paras[0] 
-PASS 24,0: resulting range position for range [document, 0, document, 2], node paras[0] 
-PASS 24,1: resulting DOM for range [document, 0, document, 2], node paras[0].firstChild 
-PASS 24,1: resulting range position for range [document, 0, document, 2], node paras[0].firstChild 
-PASS 24,2: resulting DOM for range [document, 0, document, 2], node paras[1].firstChild 
-PASS 24,2: resulting range position for range [document, 0, document, 2], node paras[1].firstChild 
-PASS 24,3: resulting DOM for range [document, 0, document, 2], node foreignPara1 
-PASS 24,3: resulting range position for range [document, 0, document, 2], node foreignPara1 
-PASS 24,4: resulting DOM for range [document, 0, document, 2], node foreignPara1.firstChild 
-PASS 24,4: resulting range position for range [document, 0, document, 2], node foreignPara1.firstChild 
-PASS 24,5: resulting DOM for range [document, 0, document, 2], node detachedPara1 
-PASS 24,5: resulting range position for range [document, 0, document, 2], node detachedPara1 
-PASS 24,6: resulting DOM for range [document, 0, document, 2], node detachedPara1.firstChild 
-PASS 24,6: resulting range position for range [document, 0, document, 2], node detachedPara1.firstChild 
-PASS 24,7: resulting DOM for range [document, 0, document, 2], node document 
-PASS 24,7: resulting range position for range [document, 0, document, 2], node document 
-PASS 24,8: resulting DOM for range [document, 0, document, 2], node detachedDiv 
-PASS 24,8: resulting range position for range [document, 0, document, 2], node detachedDiv 
-PASS 24,9: resulting DOM for range [document, 0, document, 2], node foreignDoc 
-PASS 24,9: resulting range position for range [document, 0, document, 2], node foreignDoc 
-PASS 24,10: resulting DOM for range [document, 0, document, 2], node foreignPara2 
-PASS 24,10: resulting range position for range [document, 0, document, 2], node foreignPara2 
-PASS 24,11: resulting DOM for range [document, 0, document, 2], node xmlDoc 
-PASS 24,11: resulting range position for range [document, 0, document, 2], node xmlDoc 
-PASS 24,12: resulting DOM for range [document, 0, document, 2], node xmlElement 
-PASS 24,12: resulting range position for range [document, 0, document, 2], node xmlElement 
-PASS 24,13: resulting DOM for range [document, 0, document, 2], node detachedTextNode 
-PASS 24,13: resulting range position for range [document, 0, document, 2], node detachedTextNode 
-PASS 24,14: resulting DOM for range [document, 0, document, 2], node foreignTextNode 
-PASS 24,14: resulting range position for range [document, 0, document, 2], node foreignTextNode 
-PASS 24,15: resulting DOM for range [document, 0, document, 2], node processingInstruction 
-PASS 24,15: resulting range position for range [document, 0, document, 2], node processingInstruction 
-PASS 24,16: resulting DOM for range [document, 0, document, 2], node detachedProcessingInstruction 
-PASS 24,16: resulting range position for range [document, 0, document, 2], node detachedProcessingInstruction 
-PASS 24,17: resulting DOM for range [document, 0, document, 2], node comment 
-PASS 24,17: resulting range position for range [document, 0, document, 2], node comment 
-PASS 24,18: resulting DOM for range [document, 0, document, 2], node detachedComment 
-PASS 24,18: resulting range position for range [document, 0, document, 2], node detachedComment 
-PASS 24,19: resulting DOM for range [document, 0, document, 2], node docfrag 
-PASS 24,19: resulting range position for range [document, 0, document, 2], node docfrag 
-PASS 24,20: resulting DOM for range [document, 0, document, 2], node doctype 
-PASS 24,20: resulting range position for range [document, 0, document, 2], node doctype 
-PASS 24,21: resulting DOM for range [document, 0, document, 2], node foreignDoctype 
-PASS 24,21: resulting range position for range [document, 0, document, 2], node foreignDoctype 
-PASS 25,0: resulting DOM for range [comment, 2, comment, 3], node paras[0] 
-PASS 25,0: resulting range position for range [comment, 2, comment, 3], node paras[0] 
-PASS 25,1: resulting DOM for range [comment, 2, comment, 3], node paras[0].firstChild 
-PASS 25,1: resulting range position for range [comment, 2, comment, 3], node paras[0].firstChild 
-PASS 25,2: resulting DOM for range [comment, 2, comment, 3], node paras[1].firstChild 
-PASS 25,2: resulting range position for range [comment, 2, comment, 3], node paras[1].firstChild 
-PASS 25,3: resulting DOM for range [comment, 2, comment, 3], node foreignPara1 
-PASS 25,3: resulting range position for range [comment, 2, comment, 3], node foreignPara1 
-PASS 25,4: resulting DOM for range [comment, 2, comment, 3], node foreignPara1.firstChild 
-PASS 25,4: resulting range position for range [comment, 2, comment, 3], node foreignPara1.firstChild 
-PASS 25,5: resulting DOM for range [comment, 2, comment, 3], node detachedPara1 
-PASS 25,5: resulting range position for range [comment, 2, comment, 3], node detachedPara1 
-PASS 25,6: resulting DOM for range [comment, 2, comment, 3], node detachedPara1.firstChild 
-PASS 25,6: resulting range position for range [comment, 2, comment, 3], node detachedPara1.firstChild 
-PASS 25,7: resulting DOM for range [comment, 2, comment, 3], node document 
-PASS 25,7: resulting range position for range [comment, 2, comment, 3], node document 
-PASS 25,8: resulting DOM for range [comment, 2, comment, 3], node detachedDiv 
-PASS 25,8: resulting range position for range [comment, 2, comment, 3], node detachedDiv 
-PASS 25,9: resulting DOM for range [comment, 2, comment, 3], node foreignDoc 
-PASS 25,9: resulting range position for range [comment, 2, comment, 3], node foreignDoc 
-PASS 25,10: resulting DOM for range [comment, 2, comment, 3], node foreignPara2 
-PASS 25,10: resulting range position for range [comment, 2, comment, 3], node foreignPara2 
-PASS 25,11: resulting DOM for range [comment, 2, comment, 3], node xmlDoc 
-PASS 25,11: resulting range position for range [comment, 2, comment, 3], node xmlDoc 
-PASS 25,12: resulting DOM for range [comment, 2, comment, 3], node xmlElement 
-PASS 25,12: resulting range position for range [comment, 2, comment, 3], node xmlElement 
-PASS 25,13: resulting DOM for range [comment, 2, comment, 3], node detachedTextNode 
-PASS 25,13: resulting range position for range [comment, 2, comment, 3], node detachedTextNode 
-PASS 25,14: resulting DOM for range [comment, 2, comment, 3], node foreignTextNode 
-PASS 25,14: resulting range position for range [comment, 2, comment, 3], node foreignTextNode 
-PASS 25,15: resulting DOM for range [comment, 2, comment, 3], node processingInstruction 
-PASS 25,15: resulting range position for range [comment, 2, comment, 3], node processingInstruction 
-PASS 25,16: resulting DOM for range [comment, 2, comment, 3], node detachedProcessingInstruction 
-PASS 25,16: resulting range position for range [comment, 2, comment, 3], node detachedProcessingInstruction 
-PASS 25,17: resulting DOM for range [comment, 2, comment, 3], node comment 
-PASS 25,17: resulting range position for range [comment, 2, comment, 3], node comment 
-PASS 25,18: resulting DOM for range [comment, 2, comment, 3], node detachedComment 
-PASS 25,18: resulting range position for range [comment, 2, comment, 3], node detachedComment 
-PASS 25,19: resulting DOM for range [comment, 2, comment, 3], node docfrag 
-PASS 25,19: resulting range position for range [comment, 2, comment, 3], node docfrag 
-PASS 25,20: resulting DOM for range [comment, 2, comment, 3], node doctype 
-PASS 25,20: resulting range position for range [comment, 2, comment, 3], node doctype 
-PASS 25,21: resulting DOM for range [comment, 2, comment, 3], node foreignDoctype 
-PASS 25,21: resulting range position for range [comment, 2, comment, 3], node foreignDoctype 
-PASS 26,0: resulting DOM for range [testDiv, 0, comment, 5], node paras[0] 
-PASS 26,0: resulting range position for range [testDiv, 0, comment, 5], node paras[0] 
-PASS 26,1: resulting DOM for range [testDiv, 0, comment, 5], node paras[0].firstChild 
-PASS 26,1: resulting range position for range [testDiv, 0, comment, 5], node paras[0].firstChild 
-PASS 26,2: resulting DOM for range [testDiv, 0, comment, 5], node paras[1].firstChild 
-PASS 26,2: resulting range position for range [testDiv, 0, comment, 5], node paras[1].firstChild 
-PASS 26,3: resulting DOM for range [testDiv, 0, comment, 5], node foreignPara1 
-PASS 26,3: resulting range position for range [testDiv, 0, comment, 5], node foreignPara1 
-PASS 26,4: resulting DOM for range [testDiv, 0, comment, 5], node foreignPara1.firstChild 
-PASS 26,4: resulting range position for range [testDiv, 0, comment, 5], node foreignPara1.firstChild 
-PASS 26,5: resulting DOM for range [testDiv, 0, comment, 5], node detachedPara1 
-PASS 26,5: resulting range position for range [testDiv, 0, comment, 5], node detachedPara1 
-PASS 26,6: resulting DOM for range [testDiv, 0, comment, 5], node detachedPara1.firstChild 
-PASS 26,6: resulting range position for range [testDiv, 0, comment, 5], node detachedPara1.firstChild 
-PASS 26,7: resulting DOM for range [testDiv, 0, comment, 5], node document 
-PASS 26,7: resulting range position for range [testDiv, 0, comment, 5], node document 
-PASS 26,8: resulting DOM for range [testDiv, 0, comment, 5], node detachedDiv 
-PASS 26,8: resulting range position for range [testDiv, 0, comment, 5], node detachedDiv 
-PASS 26,9: resulting DOM for range [testDiv, 0, comment, 5], node foreignDoc 
-PASS 26,9: resulting range position for range [testDiv, 0, comment, 5], node foreignDoc 
-PASS 26,10: resulting DOM for range [testDiv, 0, comment, 5], node foreignPara2 
-PASS 26,10: resulting range position for range [testDiv, 0, comment, 5], node foreignPara2 
-PASS 26,11: resulting DOM for range [testDiv, 0, comment, 5], node xmlDoc 
-PASS 26,11: resulting range position for range [testDiv, 0, comment, 5], node xmlDoc 
-PASS 26,12: resulting DOM for range [testDiv, 0, comment, 5], node xmlElement 
-PASS 26,12: resulting range position for range [testDiv, 0, comment, 5], node xmlElement 
-PASS 26,13: resulting DOM for range [testDiv, 0, comment, 5], node detachedTextNode 
-PASS 26,13: resulting range position for range [testDiv, 0, comment, 5], node detachedTextNode 
-PASS 26,14: resulting DOM for range [testDiv, 0, comment, 5], node foreignTextNode 
-PASS 26,14: resulting range position for range [testDiv, 0, comment, 5], node foreignTextNode 
-PASS 26,15: resulting DOM for range [testDiv, 0, comment, 5], node processingInstruction 
-PASS 26,15: resulting range position for range [testDiv, 0, comment, 5], node processingInstruction 
-PASS 26,16: resulting DOM for range [testDiv, 0, comment, 5], node detachedProcessingInstruction 
-PASS 26,16: resulting range position for range [testDiv, 0, comment, 5], node detachedProcessingInstruction 
-PASS 26,17: resulting DOM for range [testDiv, 0, comment, 5], node comment 
-PASS 26,17: resulting range position for range [testDiv, 0, comment, 5], node comment 
-PASS 26,18: resulting DOM for range [testDiv, 0, comment, 5], node detachedComment 
-PASS 26,18: resulting range position for range [testDiv, 0, comment, 5], node detachedComment 
-PASS 26,19: resulting DOM for range [testDiv, 0, comment, 5], node docfrag 
-PASS 26,19: resulting range position for range [testDiv, 0, comment, 5], node docfrag 
-PASS 26,20: resulting DOM for range [testDiv, 0, comment, 5], node doctype 
-PASS 26,20: resulting range position for range [testDiv, 0, comment, 5], node doctype 
-PASS 26,21: resulting DOM for range [testDiv, 0, comment, 5], node foreignDoctype 
-PASS 26,21: resulting range position for range [testDiv, 0, comment, 5], node foreignDoctype 
-PASS 27,0: resulting DOM for range [foreignDoc, 1, foreignComment, 2], node paras[0] 
-PASS 27,0: resulting range position for range [foreignDoc, 1, foreignComment, 2], node paras[0] 
-PASS 27,1: resulting DOM for range [foreignDoc, 1, foreignComment, 2], node paras[0].firstChild 
-PASS 27,1: resulting range position for range [foreignDoc, 1, foreignComment, 2], node paras[0].firstChild 
-PASS 27,2: resulting DOM for range [foreignDoc, 1, foreignComment, 2], node paras[1].firstChild 
-PASS 27,2: resulting range position for range [foreignDoc, 1, foreignComment, 2], node paras[1].firstChild 
-PASS 27,3: resulting DOM for range [foreignDoc, 1, foreignComment, 2], node foreignPara1 
-PASS 27,3: resulting range position for range [foreignDoc, 1, foreignComment, 2], node foreignPara1 
-PASS 27,4: resulting DOM for range [foreignDoc, 1, foreignComment, 2], node foreignPara1.firstChild 
-PASS 27,4: resulting range position for range [foreignDoc, 1, foreignComment, 2], node foreignPara1.firstChild 
-PASS 27,5: resulting DOM for range [foreignDoc, 1, foreignComment, 2], node detachedPara1 
-PASS 27,5: resulting range position for range [foreignDoc, 1, foreignComment, 2], node detachedPara1 
-PASS 27,6: resulting DOM for range [foreignDoc, 1, foreignComment, 2], node detachedPara1.firstChild 
-PASS 27,6: resulting range position for range [foreignDoc, 1, foreignComment, 2], node detachedPara1.firstChild 
-PASS 27,7: resulting DOM for range [foreignDoc, 1, foreignComment, 2], node document 
-PASS 27,7: resulting range position for range [foreignDoc, 1, foreignComment, 2], node document 
-PASS 27,8: resulting DOM for range [foreignDoc, 1, foreignComment, 2], node detachedDiv 
-PASS 27,8: resulting range position for range [foreignDoc, 1, foreignComment, 2], node detachedDiv 
-PASS 27,9: resulting DOM for range [foreignDoc, 1, foreignComment, 2], node foreignDoc 
-PASS 27,9: resulting range position for range [foreignDoc, 1, foreignComment, 2], node foreignDoc 
-PASS 27,10: resulting DOM for range [foreignDoc, 1, foreignComment, 2], node foreignPara2 
-PASS 27,10: resulting range position for range [foreignDoc, 1, foreignComment, 2], node foreignPara2 
-PASS 27,11: resulting DOM for range [foreignDoc, 1, foreignComment, 2], node xmlDoc 
-PASS 27,11: resulting range position for range [foreignDoc, 1, foreignComment, 2], node xmlDoc 
-PASS 27,12: resulting DOM for range [foreignDoc, 1, foreignComment, 2], node xmlElement 
-PASS 27,12: resulting range position for range [foreignDoc, 1, foreignComment, 2], node xmlElement 
-PASS 27,13: resulting DOM for range [foreignDoc, 1, foreignComment, 2], node detachedTextNode 
-PASS 27,13: resulting range position for range [foreignDoc, 1, foreignComment, 2], node detachedTextNode 
-PASS 27,14: resulting DOM for range [foreignDoc, 1, foreignComment, 2], node foreignTextNode 
-PASS 27,14: resulting range position for range [foreignDoc, 1, foreignComment, 2], node foreignTextNode 
-PASS 27,15: resulting DOM for range [foreignDoc, 1, foreignComment, 2], node processingInstruction 
-PASS 27,15: resulting range position for range [foreignDoc, 1, foreignComment, 2], node processingInstruction 
-PASS 27,16: resulting DOM for range [foreignDoc, 1, foreignComment, 2], node detachedProcessingInstruction 
-PASS 27,16: resulting range position for range [foreignDoc, 1, foreignComment, 2], node detachedProcessingInstruction 
-PASS 27,17: resulting DOM for range [foreignDoc, 1, foreignComment, 2], node comment 
-PASS 27,17: resulting range position for range [foreignDoc, 1, foreignComment, 2], node comment 
-PASS 27,18: resulting DOM for range [foreignDoc, 1, foreignComment, 2], node detachedComment 
-PASS 27,18: resulting range position for range [foreignDoc, 1, foreignComment, 2], node detachedComment 
-PASS 27,19: resulting DOM for range [foreignDoc, 1, foreignComment, 2], node docfrag 
-PASS 27,19: resulting range position for range [foreignDoc, 1, foreignComment, 2], node docfrag 
-PASS 27,20: resulting DOM for range [foreignDoc, 1, foreignComment, 2], node doctype 
-PASS 27,20: resulting range position for range [foreignDoc, 1, foreignComment, 2], node doctype 
-PASS 27,21: resulting DOM for range [foreignDoc, 1, foreignComment, 2], node foreignDoctype 
-PASS 27,21: resulting range position for range [foreignDoc, 1, foreignComment, 2], node foreignDoctype 
-PASS 28,0: resulting DOM for range [foreignDoc.body, 0, foreignTextNode, 36], node paras[0] 
-PASS 28,0: resulting range position for range [foreignDoc.body, 0, foreignTextNode, 36], node paras[0] 
-PASS 28,1: resulting DOM for range [foreignDoc.body, 0, foreignTextNode, 36], node paras[0].firstChild 
-PASS 28,1: resulting range position for range [foreignDoc.body, 0, foreignTextNode, 36], node paras[0].firstChild 
-PASS 28,2: resulting DOM for range [foreignDoc.body, 0, foreignTextNode, 36], node paras[1].firstChild 
-PASS 28,2: resulting range position for range [foreignDoc.body, 0, foreignTextNode, 36], node paras[1].firstChild 
-PASS 28,3: resulting DOM for range [foreignDoc.body, 0, foreignTextNode, 36], node foreignPara1 
-PASS 28,3: resulting range position for range [foreignDoc.body, 0, foreignTextNode, 36], node foreignPara1 
-PASS 28,4: resulting DOM for range [foreignDoc.body, 0, foreignTextNode, 36], node foreignPara1.firstChild 
-PASS 28,4: resulting range position for range [foreignDoc.body, 0, foreignTextNode, 36], node foreignPara1.firstChild 
-PASS 28,5: resulting DOM for range [foreignDoc.body, 0, foreignTextNode, 36], node detachedPara1 
-PASS 28,5: resulting range position for range [foreignDoc.body, 0, foreignTextNode, 36], node detachedPara1 
-PASS 28,6: resulting DOM for range [foreignDoc.body, 0, foreignTextNode, 36], node detachedPara1.firstChild 
-PASS 28,6: resulting range position for range [foreignDoc.body, 0, foreignTextNode, 36], node detachedPara1.firstChild 
-PASS 28,7: resulting DOM for range [foreignDoc.body, 0, foreignTextNode, 36], node document 
-PASS 28,7: resulting range position for range [foreignDoc.body, 0, foreignTextNode, 36], node document 
-PASS 28,8: resulting DOM for range [foreignDoc.body, 0, foreignTextNode, 36], node detachedDiv 
-PASS 28,8: resulting range position for range [foreignDoc.body, 0, foreignTextNode, 36], node detachedDiv 
-PASS 28,9: resulting DOM for range [foreignDoc.body, 0, foreignTextNode, 36], node foreignDoc 
-PASS 28,9: resulting range position for range [foreignDoc.body, 0, foreignTextNode, 36], node foreignDoc 
-PASS 28,10: resulting DOM for range [foreignDoc.body, 0, foreignTextNode, 36], node foreignPara2 
-PASS 28,10: resulting range position for range [foreignDoc.body, 0, foreignTextNode, 36], node foreignPara2 
-PASS 28,11: resulting DOM for range [foreignDoc.body, 0, foreignTextNode, 36], node xmlDoc 
-PASS 28,11: resulting range position for range [foreignDoc.body, 0, foreignTextNode, 36], node xmlDoc 
-PASS 28,12: resulting DOM for range [foreignDoc.body, 0, foreignTextNode, 36], node xmlElement 
-PASS 28,12: resulting range position for range [foreignDoc.body, 0, foreignTextNode, 36], node xmlElement 
-PASS 28,13: resulting DOM for range [foreignDoc.body, 0, foreignTextNode, 36], node detachedTextNode 
-PASS 28,13: resulting range position for range [foreignDoc.body, 0, foreignTextNode, 36], node detachedTextNode 
-PASS 28,14: resulting DOM for range [foreignDoc.body, 0, foreignTextNode, 36], node foreignTextNode 
-PASS 28,14: resulting range position for range [foreignDoc.body, 0, foreignTextNode, 36], node foreignTextNode 
-PASS 28,15: resulting DOM for range [foreignDoc.body, 0, foreignTextNode, 36], node processingInstruction 
-PASS 28,15: resulting range position for range [foreignDoc.body, 0, foreignTextNode, 36], node processingInstruction 
-PASS 28,16: resulting DOM for range [foreignDoc.body, 0, foreignTextNode, 36], node detachedProcessingInstruction 
-PASS 28,16: resulting range position for range [foreignDoc.body, 0, foreignTextNode, 36], node detachedProcessingInstruction 
-PASS 28,17: resulting DOM for range [foreignDoc.body, 0, foreignTextNode, 36], node comment 
-PASS 28,17: resulting range position for range [foreignDoc.body, 0, foreignTextNode, 36], node comment 
-PASS 28,18: resulting DOM for range [foreignDoc.body, 0, foreignTextNode, 36], node detachedComment 
-PASS 28,18: resulting range position for range [foreignDoc.body, 0, foreignTextNode, 36], node detachedComment 
-PASS 28,19: resulting DOM for range [foreignDoc.body, 0, foreignTextNode, 36], node docfrag 
-PASS 28,19: resulting range position for range [foreignDoc.body, 0, foreignTextNode, 36], node docfrag 
-PASS 28,20: resulting DOM for range [foreignDoc.body, 0, foreignTextNode, 36], node doctype 
-PASS 28,20: resulting range position for range [foreignDoc.body, 0, foreignTextNode, 36], node doctype 
-PASS 28,21: resulting DOM for range [foreignDoc.body, 0, foreignTextNode, 36], node foreignDoctype 
-PASS 28,21: resulting range position for range [foreignDoc.body, 0, foreignTextNode, 36], node foreignDoctype 
-PASS 29,0: resulting DOM for range [xmlDoc, 1, xmlComment, 0], node paras[0] 
-PASS 29,0: resulting range position for range [xmlDoc, 1, xmlComment, 0], node paras[0] 
-PASS 29,1: resulting DOM for range [xmlDoc, 1, xmlComment, 0], node paras[0].firstChild 
-PASS 29,1: resulting range position for range [xmlDoc, 1, xmlComment, 0], node paras[0].firstChild 
-PASS 29,2: resulting DOM for range [xmlDoc, 1, xmlComment, 0], node paras[1].firstChild 
-PASS 29,2: resulting range position for range [xmlDoc, 1, xmlComment, 0], node paras[1].firstChild 
-PASS 29,3: resulting DOM for range [xmlDoc, 1, xmlComment, 0], node foreignPara1 
-PASS 29,3: resulting range position for range [xmlDoc, 1, xmlComment, 0], node foreignPara1 
-PASS 29,4: resulting DOM for range [xmlDoc, 1, xmlComment, 0], node foreignPara1.firstChild 
-PASS 29,4: resulting range position for range [xmlDoc, 1, xmlComment, 0], node foreignPara1.firstChild 
-PASS 29,5: resulting DOM for range [xmlDoc, 1, xmlComment, 0], node detachedPara1 
-PASS 29,5: resulting range position for range [xmlDoc, 1, xmlComment, 0], node detachedPara1 
-PASS 29,6: resulting DOM for range [xmlDoc, 1, xmlComment, 0], node detachedPara1.firstChild 
-PASS 29,6: resulting range position for range [xmlDoc, 1, xmlComment, 0], node detachedPara1.firstChild 
-PASS 29,7: resulting DOM for range [xmlDoc, 1, xmlComment, 0], node document 
-PASS 29,7: resulting range position for range [xmlDoc, 1, xmlComment, 0], node document 
-PASS 29,8: resulting DOM for range [xmlDoc, 1, xmlComment, 0], node detachedDiv 
-PASS 29,8: resulting range position for range [xmlDoc, 1, xmlComment, 0], node detachedDiv 
-PASS 29,9: resulting DOM for range [xmlDoc, 1, xmlComment, 0], node foreignDoc 
-PASS 29,9: resulting range position for range [xmlDoc, 1, xmlComment, 0], node foreignDoc 
-PASS 29,10: resulting DOM for range [xmlDoc, 1, xmlComment, 0], node foreignPara2 
-PASS 29,10: resulting range position for range [xmlDoc, 1, xmlComment, 0], node foreignPara2 
-PASS 29,11: resulting DOM for range [xmlDoc, 1, xmlComment, 0], node xmlDoc 
-PASS 29,11: resulting range position for range [xmlDoc, 1, xmlComment, 0], node xmlDoc 
-PASS 29,12: resulting DOM for range [xmlDoc, 1, xmlComment, 0], node xmlElement 
-PASS 29,12: resulting range position for range [xmlDoc, 1, xmlComment, 0], node xmlElement 
-PASS 29,13: resulting DOM for range [xmlDoc, 1, xmlComment, 0], node detachedTextNode 
-PASS 29,13: resulting range position for range [xmlDoc, 1, xmlComment, 0], node detachedTextNode 
-PASS 29,14: resulting DOM for range [xmlDoc, 1, xmlComment, 0], node foreignTextNode 
-PASS 29,14: resulting range position for range [xmlDoc, 1, xmlComment, 0], node foreignTextNode 
-PASS 29,15: resulting DOM for range [xmlDoc, 1, xmlComment, 0], node processingInstruction 
-PASS 29,15: resulting range position for range [xmlDoc, 1, xmlComment, 0], node processingInstruction 
-PASS 29,16: resulting DOM for range [xmlDoc, 1, xmlComment, 0], node detachedProcessingInstruction 
-PASS 29,16: resulting range position for range [xmlDoc, 1, xmlComment, 0], node detachedProcessingInstruction 
-PASS 29,17: resulting DOM for range [xmlDoc, 1, xmlComment, 0], node comment 
-PASS 29,17: resulting range position for range [xmlDoc, 1, xmlComment, 0], node comment 
-PASS 29,18: resulting DOM for range [xmlDoc, 1, xmlComment, 0], node detachedComment 
-PASS 29,18: resulting range position for range [xmlDoc, 1, xmlComment, 0], node detachedComment 
-PASS 29,19: resulting DOM for range [xmlDoc, 1, xmlComment, 0], node docfrag 
-PASS 29,19: resulting range position for range [xmlDoc, 1, xmlComment, 0], node docfrag 
-PASS 29,20: resulting DOM for range [xmlDoc, 1, xmlComment, 0], node doctype 
-PASS 29,20: resulting range position for range [xmlDoc, 1, xmlComment, 0], node doctype 
-PASS 29,21: resulting DOM for range [xmlDoc, 1, xmlComment, 0], node foreignDoctype 
-PASS 29,21: resulting range position for range [xmlDoc, 1, xmlComment, 0], node foreignDoctype 
-PASS 30,0: resulting DOM for range [detachedTextNode, 0, detachedTextNode, 8], node paras[0] 
-PASS 30,0: resulting range position for range [detachedTextNode, 0, detachedTextNode, 8], node paras[0] 
-PASS 30,1: resulting DOM for range [detachedTextNode, 0, detachedTextNode, 8], node paras[0].firstChild 
-PASS 30,1: resulting range position for range [detachedTextNode, 0, detachedTextNode, 8], node paras[0].firstChild 
-PASS 30,2: resulting DOM for range [detachedTextNode, 0, detachedTextNode, 8], node paras[1].firstChild 
-PASS 30,2: resulting range position for range [detachedTextNode, 0, detachedTextNode, 8], node paras[1].firstChild 
-PASS 30,3: resulting DOM for range [detachedTextNode, 0, detachedTextNode, 8], node foreignPara1 
-PASS 30,3: resulting range position for range [detachedTextNode, 0, detachedTextNode, 8], node foreignPara1 
-PASS 30,4: resulting DOM for range [detachedTextNode, 0, detachedTextNode, 8], node foreignPara1.firstChild 
-PASS 30,4: resulting range position for range [detachedTextNode, 0, detachedTextNode, 8], node foreignPara1.firstChild 
-PASS 30,5: resulting DOM for range [detachedTextNode, 0, detachedTextNode, 8], node detachedPara1 
-PASS 30,5: resulting range position for range [detachedTextNode, 0, detachedTextNode, 8], node detachedPara1 
-PASS 30,6: resulting DOM for range [detachedTextNode, 0, detachedTextNode, 8], node detachedPara1.firstChild 
-PASS 30,6: resulting range position for range [detachedTextNode, 0, detachedTextNode, 8], node detachedPara1.firstChild 
-PASS 30,7: resulting DOM for range [detachedTextNode, 0, detachedTextNode, 8], node document 
-PASS 30,7: resulting range position for range [detachedTextNode, 0, detachedTextNode, 8], node document 
-PASS 30,8: resulting DOM for range [detachedTextNode, 0, detachedTextNode, 8], node detachedDiv 
-PASS 30,8: resulting range position for range [detachedTextNode, 0, detachedTextNode, 8], node detachedDiv 
-PASS 30,9: resulting DOM for range [detachedTextNode, 0, detachedTextNode, 8], node foreignDoc 
-PASS 30,9: resulting range position for range [detachedTextNode, 0, detachedTextNode, 8], node foreignDoc 
-PASS 30,10: resulting DOM for range [detachedTextNode, 0, detachedTextNode, 8], node foreignPara2 
-PASS 30,10: resulting range position for range [detachedTextNode, 0, detachedTextNode, 8], node foreignPara2 
-PASS 30,11: resulting DOM for range [detachedTextNode, 0, detachedTextNode, 8], node xmlDoc 
-PASS 30,11: resulting range position for range [detachedTextNode, 0, detachedTextNode, 8], node xmlDoc 
-PASS 30,12: resulting DOM for range [detachedTextNode, 0, detachedTextNode, 8], node xmlElement 
-PASS 30,12: resulting range position for range [detachedTextNode, 0, detachedTextNode, 8], node xmlElement 
-PASS 30,13: resulting DOM for range [detachedTextNode, 0, detachedTextNode, 8], node detachedTextNode 
-PASS 30,13: resulting range position for range [detachedTextNode, 0, detachedTextNode, 8], node detachedTextNode 
-PASS 30,14: resulting DOM for range [detachedTextNode, 0, detachedTextNode, 8], node foreignTextNode 
-PASS 30,14: resulting range position for range [detachedTextNode, 0, detachedTextNode, 8], node foreignTextNode 
-PASS 30,15: resulting DOM for range [detachedTextNode, 0, detachedTextNode, 8], node processingInstruction 
-PASS 30,15: resulting range position for range [detachedTextNode, 0, detachedTextNode, 8], node processingInstruction 
-PASS 30,16: resulting DOM for range [detachedTextNode, 0, detachedTextNode, 8], node detachedProcessingInstruction 
-PASS 30,16: resulting range position for range [detachedTextNode, 0, detachedTextNode, 8], node detachedProcessingInstruction 
-PASS 30,17: resulting DOM for range [detachedTextNode, 0, detachedTextNode, 8], node comment 
-PASS 30,17: resulting range position for range [detachedTextNode, 0, detachedTextNode, 8], node comment 
-PASS 30,18: resulting DOM for range [detachedTextNode, 0, detachedTextNode, 8], node detachedComment 
-PASS 30,18: resulting range position for range [detachedTextNode, 0, detachedTextNode, 8], node detachedComment 
-PASS 30,19: resulting DOM for range [detachedTextNode, 0, detachedTextNode, 8], node docfrag 
-PASS 30,19: resulting range position for range [detachedTextNode, 0, detachedTextNode, 8], node docfrag 
-PASS 30,20: resulting DOM for range [detachedTextNode, 0, detachedTextNode, 8], node doctype 
-PASS 30,20: resulting range position for range [detachedTextNode, 0, detachedTextNode, 8], node doctype 
-PASS 30,21: resulting DOM for range [detachedTextNode, 0, detachedTextNode, 8], node foreignDoctype 
-PASS 30,21: resulting range position for range [detachedTextNode, 0, detachedTextNode, 8], node foreignDoctype 
-PASS 31,0: resulting DOM for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node paras[0] 
-PASS 31,0: resulting range position for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node paras[0] 
-PASS 31,1: resulting DOM for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node paras[0].firstChild 
-PASS 31,1: resulting range position for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node paras[0].firstChild 
-PASS 31,2: resulting DOM for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node paras[1].firstChild 
-PASS 31,2: resulting range position for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node paras[1].firstChild 
-PASS 31,3: resulting DOM for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node foreignPara1 
-PASS 31,3: resulting range position for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node foreignPara1 
-PASS 31,4: resulting DOM for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node foreignPara1.firstChild 
-PASS 31,4: resulting range position for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node foreignPara1.firstChild 
-PASS 31,5: resulting DOM for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node detachedPara1 
-PASS 31,5: resulting range position for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node detachedPara1 
-PASS 31,6: resulting DOM for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node detachedPara1.firstChild 
-PASS 31,6: resulting range position for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node detachedPara1.firstChild 
-PASS 31,7: resulting DOM for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node document 
-PASS 31,7: resulting range position for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node document 
-PASS 31,8: resulting DOM for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node detachedDiv 
-PASS 31,8: resulting range position for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node detachedDiv 
-PASS 31,9: resulting DOM for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node foreignDoc 
-PASS 31,9: resulting range position for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node foreignDoc 
-PASS 31,10: resulting DOM for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node foreignPara2 
-PASS 31,10: resulting range position for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node foreignPara2 
-PASS 31,11: resulting DOM for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node xmlDoc 
-PASS 31,11: resulting range position for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node xmlDoc 
-PASS 31,12: resulting DOM for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node xmlElement 
-PASS 31,12: resulting range position for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node xmlElement 
-PASS 31,13: resulting DOM for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node detachedTextNode 
-PASS 31,13: resulting range position for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node detachedTextNode 
-PASS 31,14: resulting DOM for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node foreignTextNode 
-PASS 31,14: resulting range position for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node foreignTextNode 
-PASS 31,15: resulting DOM for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node processingInstruction 
-PASS 31,15: resulting range position for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node processingInstruction 
-PASS 31,16: resulting DOM for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node detachedProcessingInstruction 
-PASS 31,16: resulting range position for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node detachedProcessingInstruction 
-PASS 31,17: resulting DOM for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node comment 
-PASS 31,17: resulting range position for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node comment 
-PASS 31,18: resulting DOM for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node detachedComment 
-PASS 31,18: resulting range position for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node detachedComment 
-PASS 31,19: resulting DOM for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node docfrag 
-PASS 31,19: resulting range position for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node docfrag 
-PASS 31,20: resulting DOM for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node doctype 
-PASS 31,20: resulting range position for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node doctype 
-PASS 31,21: resulting DOM for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node foreignDoctype 
-PASS 31,21: resulting range position for range [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node foreignDoctype 
-PASS 32,0: resulting DOM for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node paras[0] 
-PASS 32,0: resulting range position for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node paras[0] 
-PASS 32,1: resulting DOM for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node paras[0].firstChild 
-PASS 32,1: resulting range position for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node paras[0].firstChild 
-PASS 32,2: resulting DOM for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node paras[1].firstChild 
-PASS 32,2: resulting range position for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node paras[1].firstChild 
-PASS 32,3: resulting DOM for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node foreignPara1 
-PASS 32,3: resulting range position for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node foreignPara1 
-PASS 32,4: resulting DOM for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node foreignPara1.firstChild 
-PASS 32,4: resulting range position for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node foreignPara1.firstChild 
-PASS 32,5: resulting DOM for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node detachedPara1 
-PASS 32,5: resulting range position for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node detachedPara1 
-PASS 32,6: resulting DOM for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node detachedPara1.firstChild 
-PASS 32,6: resulting range position for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node detachedPara1.firstChild 
-PASS 32,7: resulting DOM for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node document 
-PASS 32,7: resulting range position for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node document 
-PASS 32,8: resulting DOM for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node detachedDiv 
-PASS 32,8: resulting range position for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node detachedDiv 
-PASS 32,9: resulting DOM for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node foreignDoc 
-PASS 32,9: resulting range position for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node foreignDoc 
-PASS 32,10: resulting DOM for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node foreignPara2 
-PASS 32,10: resulting range position for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node foreignPara2 
-PASS 32,11: resulting DOM for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node xmlDoc 
-PASS 32,11: resulting range position for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node xmlDoc 
-PASS 32,12: resulting DOM for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node xmlElement 
-PASS 32,12: resulting range position for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node xmlElement 
-PASS 32,13: resulting DOM for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node detachedTextNode 
-PASS 32,13: resulting range position for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node detachedTextNode 
-PASS 32,14: resulting DOM for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node foreignTextNode 
-PASS 32,14: resulting range position for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node foreignTextNode 
-PASS 32,15: resulting DOM for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node processingInstruction 
-PASS 32,15: resulting range position for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node processingInstruction 
-PASS 32,16: resulting DOM for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node detachedProcessingInstruction 
-PASS 32,16: resulting range position for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node detachedProcessingInstruction 
-PASS 32,17: resulting DOM for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node comment 
-PASS 32,17: resulting range position for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node comment 
-PASS 32,18: resulting DOM for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node detachedComment 
-PASS 32,18: resulting range position for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node detachedComment 
-PASS 32,19: resulting DOM for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node docfrag 
-PASS 32,19: resulting range position for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node docfrag 
-PASS 32,20: resulting DOM for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node doctype 
-PASS 32,20: resulting range position for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node doctype 
-PASS 32,21: resulting DOM for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node foreignDoctype 
-PASS 32,21: resulting range position for range [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node foreignDoctype 
-PASS 33,0: resulting DOM for range [detachedComment, 3, detachedComment, 4], node paras[0] 
-PASS 33,0: resulting range position for range [detachedComment, 3, detachedComment, 4], node paras[0] 
-PASS 33,1: resulting DOM for range [detachedComment, 3, detachedComment, 4], node paras[0].firstChild 
-PASS 33,1: resulting range position for range [detachedComment, 3, detachedComment, 4], node paras[0].firstChild 
-PASS 33,2: resulting DOM for range [detachedComment, 3, detachedComment, 4], node paras[1].firstChild 
-PASS 33,2: resulting range position for range [detachedComment, 3, detachedComment, 4], node paras[1].firstChild 
-PASS 33,3: resulting DOM for range [detachedComment, 3, detachedComment, 4], node foreignPara1 
-PASS 33,3: resulting range position for range [detachedComment, 3, detachedComment, 4], node foreignPara1 
-PASS 33,4: resulting DOM for range [detachedComment, 3, detachedComment, 4], node foreignPara1.firstChild 
-PASS 33,4: resulting range position for range [detachedComment, 3, detachedComment, 4], node foreignPara1.firstChild 
-PASS 33,5: resulting DOM for range [detachedComment, 3, detachedComment, 4], node detachedPara1 
-PASS 33,5: resulting range position for range [detachedComment, 3, detachedComment, 4], node detachedPara1 
-PASS 33,6: resulting DOM for range [detachedComment, 3, detachedComment, 4], node detachedPara1.firstChild 
-PASS 33,6: resulting range position for range [detachedComment, 3, detachedComment, 4], node detachedPara1.firstChild 
-PASS 33,7: resulting DOM for range [detachedComment, 3, detachedComment, 4], node document 
-PASS 33,7: resulting range position for range [detachedComment, 3, detachedComment, 4], node document 
-PASS 33,8: resulting DOM for range [detachedComment, 3, detachedComment, 4], node detachedDiv 
-PASS 33,8: resulting range position for range [detachedComment, 3, detachedComment, 4], node detachedDiv 
-PASS 33,9: resulting DOM for range [detachedComment, 3, detachedComment, 4], node foreignDoc 
-PASS 33,9: resulting range position for range [detachedComment, 3, detachedComment, 4], node foreignDoc 
-PASS 33,10: resulting DOM for range [detachedComment, 3, detachedComment, 4], node foreignPara2 
-PASS 33,10: resulting range position for range [detachedComment, 3, detachedComment, 4], node foreignPara2 
-PASS 33,11: resulting DOM for range [detachedComment, 3, detachedComment, 4], node xmlDoc 
-PASS 33,11: resulting range position for range [detachedComment, 3, detachedComment, 4], node xmlDoc 
-PASS 33,12: resulting DOM for range [detachedComment, 3, detachedComment, 4], node xmlElement 
-PASS 33,12: resulting range position for range [detachedComment, 3, detachedComment, 4], node xmlElement 
-PASS 33,13: resulting DOM for range [detachedComment, 3, detachedComment, 4], node detachedTextNode 
-PASS 33,13: resulting range position for range [detachedComment, 3, detachedComment, 4], node detachedTextNode 
-PASS 33,14: resulting DOM for range [detachedComment, 3, detachedComment, 4], node foreignTextNode 
-PASS 33,14: resulting range position for range [detachedComment, 3, detachedComment, 4], node foreignTextNode 
-PASS 33,15: resulting DOM for range [detachedComment, 3, detachedComment, 4], node processingInstruction 
-PASS 33,15: resulting range position for range [detachedComment, 3, detachedComment, 4], node processingInstruction 
-PASS 33,16: resulting DOM for range [detachedComment, 3, detachedComment, 4], node detachedProcessingInstruction 
-PASS 33,16: resulting range position for range [detachedComment, 3, detachedComment, 4], node detachedProcessingInstruction 
-PASS 33,17: resulting DOM for range [detachedComment, 3, detachedComment, 4], node comment 
-PASS 33,17: resulting range position for range [detachedComment, 3, detachedComment, 4], node comment 
-PASS 33,18: resulting DOM for range [detachedComment, 3, detachedComment, 4], node detachedComment 
-PASS 33,18: resulting range position for range [detachedComment, 3, detachedComment, 4], node detachedComment 
-PASS 33,19: resulting DOM for range [detachedComment, 3, detachedComment, 4], node docfrag 
-PASS 33,19: resulting range position for range [detachedComment, 3, detachedComment, 4], node docfrag 
-PASS 33,20: resulting DOM for range [detachedComment, 3, detachedComment, 4], node doctype 
-PASS 33,20: resulting range position for range [detachedComment, 3, detachedComment, 4], node doctype 
-PASS 33,21: resulting DOM for range [detachedComment, 3, detachedComment, 4], node foreignDoctype 
-PASS 33,21: resulting range position for range [detachedComment, 3, detachedComment, 4], node foreignDoctype 
-PASS 34,0: resulting DOM for range [detachedForeignComment, 0, detachedForeignComment, 1], node paras[0] 
-PASS 34,0: resulting range position for range [detachedForeignComment, 0, detachedForeignComment, 1], node paras[0] 
-PASS 34,1: resulting DOM for range [detachedForeignComment, 0, detachedForeignComment, 1], node paras[0].firstChild 
-PASS 34,1: resulting range position for range [detachedForeignComment, 0, detachedForeignComment, 1], node paras[0].firstChild 
-PASS 34,2: resulting DOM for range [detachedForeignComment, 0, detachedForeignComment, 1], node paras[1].firstChild 
-PASS 34,2: resulting range position for range [detachedForeignComment, 0, detachedForeignComment, 1], node paras[1].firstChild 
-PASS 34,3: resulting DOM for range [detachedForeignComment, 0, detachedForeignComment, 1], node foreignPara1 
-PASS 34,3: resulting range position for range [detachedForeignComment, 0, detachedForeignComment, 1], node foreignPara1 
-PASS 34,4: resulting DOM for range [detachedForeignComment, 0, detachedForeignComment, 1], node foreignPara1.firstChild 
-PASS 34,4: resulting range position for range [detachedForeignComment, 0, detachedForeignComment, 1], node foreignPara1.firstChild 
-PASS 34,5: resulting DOM for range [detachedForeignComment, 0, detachedForeignComment, 1], node detachedPara1 
-PASS 34,5: resulting range position for range [detachedForeignComment, 0, detachedForeignComment, 1], node detachedPara1 
-PASS 34,6: resulting DOM for range [detachedForeignComment, 0, detachedForeignComment, 1], node detachedPara1.firstChild 
-PASS 34,6: resulting range position for range [detachedForeignComment, 0, detachedForeignComment, 1], node detachedPara1.firstChild 
-PASS 34,7: resulting DOM for range [detachedForeignComment, 0, detachedForeignComment, 1], node document 
-PASS 34,7: resulting range position for range [detachedForeignComment, 0, detachedForeignComment, 1], node document 
-PASS 34,8: resulting DOM for range [detachedForeignComment, 0, detachedForeignComment, 1], node detachedDiv 
-PASS 34,8: resulting range position for range [detachedForeignComment, 0, detachedForeignComment, 1], node detachedDiv 
-PASS 34,9: resulting DOM for range [detachedForeignComment, 0, detachedForeignComment, 1], node foreignDoc 
-PASS 34,9: resulting range position for range [detachedForeignComment, 0, detachedForeignComment, 1], node foreignDoc 
-PASS 34,10: resulting DOM for range [detachedForeignComment, 0, detachedForeignComment, 1], node foreignPara2 
-PASS 34,10: resulting range position for range [detachedForeignComment, 0, detachedForeignComment, 1], node foreignPara2 
-PASS 34,11: resulting DOM for range [detachedForeignComment, 0, detachedForeignComment, 1], node xmlDoc 
-PASS 34,11: resulting range position for range [detachedForeignComment, 0, detachedForeignComment, 1], node xmlDoc 
-PASS 34,12: resulting DOM for range [detachedForeignComment, 0, detachedForeignComment, 1], node xmlElement 
-PASS 34,12: resulting range position for range [detachedForeignComment, 0, detachedForeignComment, 1], node xmlElement 
-PASS 34,13: resulting DOM for range [detachedForeignComment, 0, detachedForeignComment, 1], node detachedTextNode 
-PASS 34,13: resulting range position for range [detachedForeignComment, 0, detachedForeignComment, 1], node detachedTextNode 
-PASS 34,14: resulting DOM for range [detachedForeignComment, 0, detachedForeignComment, 1], node foreignTextNode 
-PASS 34,14: resulting range position for range [detachedForeignComment, 0, detachedForeignComment, 1], node foreignTextNode 
-PASS 34,15: resulting DOM for range [detachedForeignComment, 0, detachedForeignComment, 1], node processingInstruction 
-PASS 34,15: resulting range position for range [detachedForeignComment, 0, detachedForeignComment, 1], node processingInstruction 
-PASS 34,16: resulting DOM for range [detachedForeignComment, 0, detachedForeignComment, 1], node detachedProcessingInstruction 
-PASS 34,16: resulting range position for range [detachedForeignComment, 0, detachedForeignComment, 1], node detachedProcessingInstruction 
-PASS 34,17: resulting DOM for range [detachedForeignComment, 0, detachedForeignComment, 1], node comment 
-PASS 34,17: resulting range position for range [detachedForeignComment, 0, detachedForeignComment, 1], node comment 
-PASS 34,18: resulting DOM for range [detachedForeignComment, 0, detachedForeignComment, 1], node detachedComment 
-PASS 34,18: resulting range position for range [detachedForeignComment, 0, detachedForeignComment, 1], node detachedComment 
-PASS 34,19: resulting DOM for range [detachedForeignComment, 0, detachedForeignComment, 1], node docfrag 
-PASS 34,19: resulting range position for range [detachedForeignComment, 0, detachedForeignComment, 1], node docfrag 
-PASS 34,20: resulting DOM for range [detachedForeignComment, 0, detachedForeignComment, 1], node doctype 
-PASS 34,20: resulting range position for range [detachedForeignComment, 0, detachedForeignComment, 1], node doctype 
-PASS 34,21: resulting DOM for range [detachedForeignComment, 0, detachedForeignComment, 1], node foreignDoctype 
-PASS 34,21: resulting range position for range [detachedForeignComment, 0, detachedForeignComment, 1], node foreignDoctype 
-PASS 35,0: resulting DOM for range [detachedXmlComment, 2, detachedXmlComment, 6], node paras[0] 
-PASS 35,0: resulting range position for range [detachedXmlComment, 2, detachedXmlComment, 6], node paras[0] 
-PASS 35,1: resulting DOM for range [detachedXmlComment, 2, detachedXmlComment, 6], node paras[0].firstChild 
-PASS 35,1: resulting range position for range [detachedXmlComment, 2, detachedXmlComment, 6], node paras[0].firstChild 
-PASS 35,2: resulting DOM for range [detachedXmlComment, 2, detachedXmlComment, 6], node paras[1].firstChild 
-PASS 35,2: resulting range position for range [detachedXmlComment, 2, detachedXmlComment, 6], node paras[1].firstChild 
-PASS 35,3: resulting DOM for range [detachedXmlComment, 2, detachedXmlComment, 6], node foreignPara1 
-PASS 35,3: resulting range position for range [detachedXmlComment, 2, detachedXmlComment, 6], node foreignPara1 
-PASS 35,4: resulting DOM for range [detachedXmlComment, 2, detachedXmlComment, 6], node foreignPara1.firstChild 
-PASS 35,4: resulting range position for range [detachedXmlComment, 2, detachedXmlComment, 6], node foreignPara1.firstChild 
-PASS 35,5: resulting DOM for range [detachedXmlComment, 2, detachedXmlComment, 6], node detachedPara1 
-PASS 35,5: resulting range position for range [detachedXmlComment, 2, detachedXmlComment, 6], node detachedPara1 
-PASS 35,6: resulting DOM for range [detachedXmlComment, 2, detachedXmlComment, 6], node detachedPara1.firstChild 
-PASS 35,6: resulting range position for range [detachedXmlComment, 2, detachedXmlComment, 6], node detachedPara1.firstChild 
-PASS 35,7: resulting DOM for range [detachedXmlComment, 2, detachedXmlComment, 6], node document 
-PASS 35,7: resulting range position for range [detachedXmlComment, 2, detachedXmlComment, 6], node document 
-PASS 35,8: resulting DOM for range [detachedXmlComment, 2, detachedXmlComment, 6], node detachedDiv 
-PASS 35,8: resulting range position for range [detachedXmlComment, 2, detachedXmlComment, 6], node detachedDiv 
-PASS 35,9: resulting DOM for range [detachedXmlComment, 2, detachedXmlComment, 6], node foreignDoc 
-PASS 35,9: resulting range position for range [detachedXmlComment, 2, detachedXmlComment, 6], node foreignDoc 
-PASS 35,10: resulting DOM for range [detachedXmlComment, 2, detachedXmlComment, 6], node foreignPara2 
-PASS 35,10: resulting range position for range [detachedXmlComment, 2, detachedXmlComment, 6], node foreignPara2 
-PASS 35,11: resulting DOM for range [detachedXmlComment, 2, detachedXmlComment, 6], node xmlDoc 
-PASS 35,11: resulting range position for range [detachedXmlComment, 2, detachedXmlComment, 6], node xmlDoc 
-PASS 35,12: resulting DOM for range [detachedXmlComment, 2, detachedXmlComment, 6], node xmlElement 
-PASS 35,12: resulting range position for range [detachedXmlComment, 2, detachedXmlComment, 6], node xmlElement 
-PASS 35,13: resulting DOM for range [detachedXmlComment, 2, detachedXmlComment, 6], node detachedTextNode 
-PASS 35,13: resulting range position for range [detachedXmlComment, 2, detachedXmlComment, 6], node detachedTextNode 
-PASS 35,14: resulting DOM for range [detachedXmlComment, 2, detachedXmlComment, 6], node foreignTextNode 
-PASS 35,14: resulting range position for range [detachedXmlComment, 2, detachedXmlComment, 6], node foreignTextNode 
-PASS 35,15: resulting DOM for range [detachedXmlComment, 2, detachedXmlComment, 6], node processingInstruction 
-PASS 35,15: resulting range position for range [detachedXmlComment, 2, detachedXmlComment, 6], node processingInstruction 
-PASS 35,16: resulting DOM for range [detachedXmlComment, 2, detachedXmlComment, 6], node detachedProcessingInstruction 
-PASS 35,16: resulting range position for range [detachedXmlComment, 2, detachedXmlComment, 6], node detachedProcessingInstruction 
-PASS 35,17: resulting DOM for range [detachedXmlComment, 2, detachedXmlComment, 6], node comment 
-PASS 35,17: resulting range position for range [detachedXmlComment, 2, detachedXmlComment, 6], node comment 
-PASS 35,18: resulting DOM for range [detachedXmlComment, 2, detachedXmlComment, 6], node detachedComment 
-PASS 35,18: resulting range position for range [detachedXmlComment, 2, detachedXmlComment, 6], node detachedComment 
-PASS 35,19: resulting DOM for range [detachedXmlComment, 2, detachedXmlComment, 6], node docfrag 
-PASS 35,19: resulting range position for range [detachedXmlComment, 2, detachedXmlComment, 6], node docfrag 
-PASS 35,20: resulting DOM for range [detachedXmlComment, 2, detachedXmlComment, 6], node doctype 
-PASS 35,20: resulting range position for range [detachedXmlComment, 2, detachedXmlComment, 6], node doctype 
-PASS 35,21: resulting DOM for range [detachedXmlComment, 2, detachedXmlComment, 6], node foreignDoctype 
-PASS 35,21: resulting range position for range [detachedXmlComment, 2, detachedXmlComment, 6], node foreignDoctype 
-PASS 36,0: resulting DOM for range [docfrag, 0, docfrag, 0], node paras[0] 
-PASS 36,0: resulting range position for range [docfrag, 0, docfrag, 0], node paras[0] 
-PASS 36,1: resulting DOM for range [docfrag, 0, docfrag, 0], node paras[0].firstChild 
-PASS 36,1: resulting range position for range [docfrag, 0, docfrag, 0], node paras[0].firstChild 
-PASS 36,2: resulting DOM for range [docfrag, 0, docfrag, 0], node paras[1].firstChild 
-PASS 36,2: resulting range position for range [docfrag, 0, docfrag, 0], node paras[1].firstChild 
-PASS 36,3: resulting DOM for range [docfrag, 0, docfrag, 0], node foreignPara1 
-PASS 36,3: resulting range position for range [docfrag, 0, docfrag, 0], node foreignPara1 
-PASS 36,4: resulting DOM for range [docfrag, 0, docfrag, 0], node foreignPara1.firstChild 
-PASS 36,4: resulting range position for range [docfrag, 0, docfrag, 0], node foreignPara1.firstChild 
-PASS 36,5: resulting DOM for range [docfrag, 0, docfrag, 0], node detachedPara1 
-PASS 36,5: resulting range position for range [docfrag, 0, docfrag, 0], node detachedPara1 
-PASS 36,6: resulting DOM for range [docfrag, 0, docfrag, 0], node detachedPara1.firstChild 
-PASS 36,6: resulting range position for range [docfrag, 0, docfrag, 0], node detachedPara1.firstChild 
-PASS 36,7: resulting DOM for range [docfrag, 0, docfrag, 0], node document 
-PASS 36,7: resulting range position for range [docfrag, 0, docfrag, 0], node document 
-PASS 36,8: resulting DOM for range [docfrag, 0, docfrag, 0], node detachedDiv 
-PASS 36,8: resulting range position for range [docfrag, 0, docfrag, 0], node detachedDiv 
-PASS 36,9: resulting DOM for range [docfrag, 0, docfrag, 0], node foreignDoc 
-PASS 36,9: resulting range position for range [docfrag, 0, docfrag, 0], node foreignDoc 
-PASS 36,10: resulting DOM for range [docfrag, 0, docfrag, 0], node foreignPara2 
-PASS 36,10: resulting range position for range [docfrag, 0, docfrag, 0], node foreignPara2 
-PASS 36,11: resulting DOM for range [docfrag, 0, docfrag, 0], node xmlDoc 
-PASS 36,11: resulting range position for range [docfrag, 0, docfrag, 0], node xmlDoc 
-PASS 36,12: resulting DOM for range [docfrag, 0, docfrag, 0], node xmlElement 
-PASS 36,12: resulting range position for range [docfrag, 0, docfrag, 0], node xmlElement 
-PASS 36,13: resulting DOM for range [docfrag, 0, docfrag, 0], node detachedTextNode 
-PASS 36,13: resulting range position for range [docfrag, 0, docfrag, 0], node detachedTextNode 
-PASS 36,14: resulting DOM for range [docfrag, 0, docfrag, 0], node foreignTextNode 
-PASS 36,14: resulting range position for range [docfrag, 0, docfrag, 0], node foreignTextNode 
-PASS 36,15: resulting DOM for range [docfrag, 0, docfrag, 0], node processingInstruction 
-PASS 36,15: resulting range position for range [docfrag, 0, docfrag, 0], node processingInstruction 
-PASS 36,16: resulting DOM for range [docfrag, 0, docfrag, 0], node detachedProcessingInstruction 
-PASS 36,16: resulting range position for range [docfrag, 0, docfrag, 0], node detachedProcessingInstruction 
-PASS 36,17: resulting DOM for range [docfrag, 0, docfrag, 0], node comment 
-PASS 36,17: resulting range position for range [docfrag, 0, docfrag, 0], node comment 
-PASS 36,18: resulting DOM for range [docfrag, 0, docfrag, 0], node detachedComment 
-PASS 36,18: resulting range position for range [docfrag, 0, docfrag, 0], node detachedComment 
-PASS 36,19: resulting DOM for range [docfrag, 0, docfrag, 0], node docfrag 
-PASS 36,19: resulting range position for range [docfrag, 0, docfrag, 0], node docfrag 
-PASS 36,20: resulting DOM for range [docfrag, 0, docfrag, 0], node doctype 
-PASS 36,20: resulting range position for range [docfrag, 0, docfrag, 0], node doctype 
-PASS 36,21: resulting DOM for range [docfrag, 0, docfrag, 0], node foreignDoctype 
-PASS 36,21: resulting range position for range [docfrag, 0, docfrag, 0], node foreignDoctype 
-PASS 37,0: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node paras[0] 
-PASS 37,0: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node paras[0] 
-PASS 37,1: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node paras[0].firstChild 
-PASS 37,1: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node paras[0].firstChild 
-PASS 37,2: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node paras[1].firstChild 
-PASS 37,2: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node paras[1].firstChild 
-PASS 37,3: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node foreignPara1 
-PASS 37,3: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node foreignPara1 
-PASS 37,4: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node foreignPara1.firstChild 
-PASS 37,4: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node foreignPara1.firstChild 
-PASS 37,5: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node detachedPara1 
-PASS 37,5: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node detachedPara1 
-PASS 37,6: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node detachedPara1.firstChild 
-PASS 37,6: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node detachedPara1.firstChild 
-PASS 37,7: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node document 
-PASS 37,7: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node document 
-PASS 37,8: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node detachedDiv 
-PASS 37,8: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node detachedDiv 
-PASS 37,9: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node foreignDoc 
-PASS 37,9: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node foreignDoc 
-PASS 37,10: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node foreignPara2 
-PASS 37,10: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node foreignPara2 
-PASS 37,11: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node xmlDoc 
-PASS 37,11: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node xmlDoc 
-PASS 37,12: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node xmlElement 
-PASS 37,12: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node xmlElement 
-PASS 37,13: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node detachedTextNode 
-PASS 37,13: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node detachedTextNode 
-PASS 37,14: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node foreignTextNode 
-PASS 37,14: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node foreignTextNode 
-PASS 37,15: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node processingInstruction 
-PASS 37,15: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node processingInstruction 
-PASS 37,16: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node detachedProcessingInstruction 
-PASS 37,16: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node detachedProcessingInstruction 
-PASS 37,17: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node comment 
-PASS 37,17: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node comment 
-PASS 37,18: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node detachedComment 
-PASS 37,18: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node detachedComment 
-PASS 37,19: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node docfrag 
-PASS 37,19: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node docfrag 
-PASS 37,20: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node doctype 
-PASS 37,20: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node doctype 
-PASS 37,21: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node foreignDoctype 
-PASS 37,21: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node foreignDoctype 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Range/range-exceptions-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/Range/range-exceptions-expected.txt
index a81976f..670454b 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/Range/range-exceptions-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/dom/Range/range-exceptions-expected.txt
@@ -5,7 +5,7 @@
 
 PASS node.innerHTML is '<bar>AB<moo>C</moo>DE</bar>'
 PASS r.surroundContents(document.createElement('a')) threw exception InvalidStateError: Failed to execute 'surroundContents' on 'Range': The Range has partially selected a non-Text node..
-PASS r.surroundContents(document.createElement('a')) threw exception HierarchyRequestError: Failed to execute 'surroundContents' on 'Range': The node to be inserted is a 'A' node, which may not be inserted here..
+PASS r.surroundContents(document.createElement('a')) threw exception HierarchyRequestError: Failed to execute 'surroundContents' on 'Range': Nodes of type 'A' may not be inserted inside nodes of type '#comment'..
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Range/range-exceptions.html b/third_party/WebKit/LayoutTests/fast/dom/Range/range-exceptions.html
index deee2328..da2a819 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/Range/range-exceptions.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/Range/range-exceptions.html
@@ -28,7 +28,7 @@
 // But not when we don't try to split the comment.
 r.setStart(c1, 0);
 r.setEnd(c1, 5);
-shouldThrow("r.surroundContents(document.createElement('a'))", '"HierarchyRequestError: Failed to execute \'surroundContents\' on \'Range\': The node to be inserted is a \'A\' node, which may not be inserted here."');
+shouldThrow("r.surroundContents(document.createElement('a'))", '"HierarchyRequestError: Failed to execute \'surroundContents\' on \'Range\': Nodes of type \'A\' may not be inserted inside nodes of type \'#comment\'."');
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/slots-fallback.html b/third_party/WebKit/LayoutTests/shadow-dom/slots-fallback.html
deleted file mode 100644
index 3f085ec..0000000
--- a/third_party/WebKit/LayoutTests/shadow-dom/slots-fallback.html
+++ /dev/null
@@ -1,219 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="resources/shadow-dom.js"></script>
-
-<div id="test1">
-  <div id="host">
-    <template data-mode="open">
-      <slot id="s1" name="slot1">
-        <div id="f1"></div>
-      </slot>
-    </template>
-  </div>
-</div>
-
-<script>
-test(() => {
-  let n = createTestTree(test1);
-  removeWhiteSpaceOnlyTextNodes(n.test1);
-
-  assert_equals(n.f1.assignedSlot, null);
-
-  assert_array_equals(n.s1.assignedNodes(), []);
-  assert_array_equals(n.s1.assignedNodes({ flatten: true }), [n.f1]);
-}, 'Slots fallback: Basic.');
-</script>
-
-<div id="test2">
-  <div id="host">
-    <template data-mode="open">
-      <slot id="s1" name="slot1">
-        <slot id="s2" name="slot2">
-          <div id="f1"></div>
-        </slot>
-      </slot>
-    </template>
-  </div>
-</div>
-
-<script>
-test(() => {
-  let n = createTestTree(test2);
-  removeWhiteSpaceOnlyTextNodes(n.test2);
-
-  assert_equals(n.f1.assignedSlot, null);
-
-  assert_array_equals(n.s1.assignedNodes(), []);
-  assert_array_equals(n.s2.assignedNodes(), []);
-
-  assert_array_equals(n.s1.assignedNodes({ flatten: true }), [n.f1]);
-  assert_array_equals(n.s2.assignedNodes({ flatten: true }), [n.f1]);
-}, 'Slots fallback: Slots in Slots.');
-</script>
-
-<div id="test3">
-  <div id="host">
-    <template data-mode="open">
-      <slot id="s1" name="slot1">
-        <slot id="s2" name="slot2">
-          <div id="f1"></div>
-        </slot>
-      </slot>
-    </template>
-    <div id="c1" slot="slot1"></div>
-  </div>
-</div>
-
-<script>
-test(() => {
-  let n = createTestTree(test3);
-  removeWhiteSpaceOnlyTextNodes(n.test3);
-
-  assert_equals(n.c1.assignedSlot, n.s1);
-  assert_equals(n.f1.assignedSlot, null);
-
-  assert_array_equals(n.s1.assignedNodes(), [n.c1]);
-  assert_array_equals(n.s2.assignedNodes(), []);
-
-  assert_array_equals(n.s1.assignedNodes({ flatten: true }), [n.c1]);
-  assert_array_equals(n.s2.assignedNodes({ flatten: true }), [n.f1]);
-}, 'Slots fallback: Fallback contents should not be used if a node is assigned.');
-</script>
-
-<div id="test4">
-  <div id="host">
-    <template data-mode="open">
-      <slot id="s1" name="slot1">
-        <slot id="s2" name="slot2">
-          <div id="f1"></div>
-        </slot>
-      </slot>
-    </template>
-    <div id="c1" slot="slot2"></div>
-  </div>
-</div>
-
-<script>
-test(() => {
-  let n = createTestTree(test4);
-  removeWhiteSpaceOnlyTextNodes(n.test4);
-
-  assert_equals(n.c1.assignedSlot, n.s2);
-  assert_equals(n.f1.assignedSlot, null);
-
-  assert_array_equals(n.s1.assignedNodes(), []);
-  assert_array_equals(n.s2.assignedNodes(), [n.c1]);
-
-  assert_array_equals(n.s1.assignedNodes({ flatten: true }), [n.c1]);
-  assert_array_equals(n.s2.assignedNodes({ flatten: true }), [n.c1]);
-}, 'Slots fallback: Slots in Slots: Assinged nodes should be used as fallback contents of another slot');
-</script>
-
-<div id="test5">
-  <div id="host1">
-    <template data-mode="open">
-      <div id="host2">
-        <template data-mode="open">
-          <slot id="s4" name="slot4">
-            <slot id="s3" name="slot3">
-              <div id="f3"></div>
-            </slot>
-            <div id="f4"></div>
-          </slot>
-        </template>
-        <slot id="s2" name="slot2" slot="slot3">
-          <slot id="s1" name="slot1">
-            <div id="f1"></div>
-          </slot>
-          <div id="f2"></div>
-        </slot>
-      </div>
-    </template>
-    <div id="c1" slot="slot1"></div>
-  </div>
-</div>
-
-<script>
-test(() => {
-  let n = createTestTree(test5);
-  removeWhiteSpaceOnlyTextNodes(n.test5);
-
-  assert_array_equals(n.s1.assignedNodes(), [n.c1]);
-  assert_array_equals(n.s2.assignedNodes(), []);
-  assert_array_equals(n.s3.assignedNodes(), [n.s2]);
-  assert_array_equals(n.s4.assignedNodes(), []);
-
-  assert_array_equals(n.s1.assignedNodes({ flatten: true }), [n.c1]);
-  assert_array_equals(n.s2.assignedNodes({ flatten: true }), [n.c1, n.f2]);
-  assert_array_equals(n.s3.assignedNodes({ flatten: true }), [n.c1, n.f2]);
-  assert_array_equals(n.s4.assignedNodes({ flatten: true }), [n.c1, n.f2, n.f4]);
-}, 'Slots fallback: Complex case.');
-
-test(() => {
-  let n = createTestTree(test5);
-  removeWhiteSpaceOnlyTextNodes(n.test5);
-
-  let d1 = document.createElement('div');
-  n.s2.appendChild(d1);
-
-  assert_array_equals(n.s1.assignedNodes({ flatten: true }), [n.c1]);
-  assert_array_equals(n.s2.assignedNodes({ flatten: true }), [n.c1, n.f2, d1]);
-  assert_array_equals(n.s3.assignedNodes({ flatten: true }), [n.c1, n.f2, d1]);
-  assert_array_equals(n.s4.assignedNodes({ flatten: true }), [n.c1, n.f2, d1, n.f4]);
-}, 'Slots fallback: Mutation. Append fallback contents.');
-
-test(() => {
-  let n = createTestTree(test5);
-  removeWhiteSpaceOnlyTextNodes(n.test5);
-
-  n.f2.remove();
-
-  assert_array_equals(n.s1.assignedNodes({ flatten: true }), [n.c1]);
-  assert_array_equals(n.s2.assignedNodes({ flatten: true }), [n.c1]);
-  assert_array_equals(n.s3.assignedNodes({ flatten: true }), [n.c1]);
-  assert_array_equals(n.s4.assignedNodes({ flatten: true }), [n.c1, n.f4]);
-}, 'Slots fallback: Mutation. Remove fallback contents.');
-
-test(() => {
-  let n = createTestTree(test5);
-  removeWhiteSpaceOnlyTextNodes(n.test5);
-
-  let d2 = document.createElement('div');
-  d2.setAttribute('slot', 'slot2');
-  n.host1.appendChild(d2);
-
-  assert_array_equals(n.s2.assignedNodes(), [d2]);
-  assert_array_equals(n.s2.assignedNodes({ flatten: true }), [d2]);
-  assert_array_equals(n.s3.assignedNodes({ flatten: true }), [d2]);
-  assert_array_equals(n.s4.assignedNodes({ flatten: true }), [d2, n.f4]);
-}, 'Slots fallback: Mutation. Assign a node to a slot so that fallback contens are no longer used.');
-
-test(() => {
-  let n = createTestTree(test5);
-  removeWhiteSpaceOnlyTextNodes(n.test5);
-
-  n.c1.remove();
-
-  assert_array_equals(n.s1.assignedNodes(), []);
-
-  assert_array_equals(n.s1.assignedNodes({ flatten: true }), [n.f1]);
-  assert_array_equals(n.s2.assignedNodes({ flatten: true }), [n.f1, n.f2]);
-  assert_array_equals(n.s3.assignedNodes({ flatten: true }), [n.f1, n.f2]);
-  assert_array_equals(n.s4.assignedNodes({ flatten: true }), [n.f1, n.f2, n.f4]);
-}, 'Slots fallback: Mutation. Remove an assigned node from a slot so that fallback contens will be used.');
-
-test(() => {
-  let n = createTestTree(test5);
-  removeWhiteSpaceOnlyTextNodes(n.test5);
-
-  n.s1.remove();
-
-  assert_array_equals(n.s1.assignedNodes(), []);
-
-  assert_array_equals(n.s1.assignedNodes({ flatten: true }), [n.f1]);
-  assert_array_equals(n.s2.assignedNodes({ flatten: true }), [n.f2]);
-  assert_array_equals(n.s3.assignedNodes({ flatten: true }), [n.f2]);
-  assert_array_equals(n.s4.assignedNodes({ flatten: true }), [n.f2, n.f4]);
-}, 'Slots fallback: Mutation.  Remove a slot which is a fallback content of another slot.');
-</script>
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/slots.html b/third_party/WebKit/LayoutTests/shadow-dom/slots.html
index 50bcfa9..28897b52 100644
--- a/third_party/WebKit/LayoutTests/shadow-dom/slots.html
+++ b/third_party/WebKit/LayoutTests/shadow-dom/slots.html
@@ -1,511 +1,12 @@
 <!DOCTYPE html>
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
-<script src="resources/shadow-dom.js"></script>
 
 <slot id='slot_in_document'></slot>
 
-<div id="test_basic">
-  <div id="host">
-    <template data-mode="open">
-      <slot id="s1" name="slot1"></slot>
-    </template>
-    <div id="c1" slot="slot1"></div>
-  </div>
-</div>
-
 <script>
 test(() => {
   assert_equals(window.getComputedStyle(slot_in_document).getPropertyValue('display'),
                 'contents');
-
-  let n = createTestTree(test_basic);
-  removeWhiteSpaceOnlyTextNodes(n.test_basic);
-
-  assert_equals(n.c1.assignedSlot, n.s1);
-  assert_array_equals(n.s1.assignedNodes(), [n.c1]);
-}, 'Slots: Basic.');
-</script>
-
-<div id="test_basic_closed">
-  <div id="host">
-    <template data-mode="closed">
-      <slot id="s1" name="slot1"></slot>
-    </template>
-    <div id="c1" slot="slot1"></div>
-  </div>
-</div>
-
-<script>
-test(() => {
-  let n = createTestTree(test_basic_closed);
-  removeWhiteSpaceOnlyTextNodes(n.test_basic_closed);
-
-  assert_equals(n.c1.assignedSlot, null);
-  assert_array_equals(n.s1.assignedNodes(), [n.c1]);
-}, 'Slots: Slots in closed.');
-</script>
-
-<div id="test_slot_not_in_shadow">
-  <slot id="s1"></slot>
-</div>
-
-<script>
-test(() => {
-  let n = createTestTree(test_slot_not_in_shadow);
-  removeWhiteSpaceOnlyTextNodes(n.test_slot_not_in_shadow);
-
-  assert_array_equals(n.s1.assignedNodes(), []);
-}, 'Slots: Slots not in a shadow tree.');
-</script>
-
-<div id="test_slot_not_in_shadow_2">
-  <slot id="s1">
-    <div id="c1"></div>
-  </slot>
-  <slot id="s2">
-    <div id="c2"></div>
-    <slot id="s3">
-      <div id="c3_1"></div>
-      <div id="c3_2"></div>
-    </slot>
-  </slot>
-</div>
-
-<script>
-test(() => {
-  let n = createTestTree(test_slot_not_in_shadow_2);
-  removeWhiteSpaceOnlyTextNodes(n.test_slot_not_in_shadow_2);
-
-  assert_equals(n.c1.assignedSlot, null);
-  assert_equals(n.c2.assignedSlot, null);
-  assert_equals(n.c3_1.assignedSlot, null);
-  assert_equals(n.c3_2.assignedSlot, null);
-
-  assert_array_equals(n.s1.assignedNodes(), []);
-  assert_array_equals(n.s2.assignedNodes(), []);
-  assert_array_equals(n.s3.assignedNodes(), []);
-
-  assert_array_equals(n.s1.assignedNodes({ flatten: true }), [n.c1]);
-  assert_array_equals(n.s2.assignedNodes({ flatten: true }), [n.c2, n.c3_1, n.c3_2]);
-  assert_array_equals(n.s3.assignedNodes({ flatten: true }), [n.c3_1, n.c3_2]);
-}, 'Slots: Distributed nooes for Slots not in a shadow tree.');
-</script>
-
-<div id="test_slot_name_matching">
-  <div id="host">
-    <template data-mode="open">
-      <slot id="s1" name="slot1"></slot>
-      <slot id="s2" name="slot2"></slot>
-      <slot id="s3" name="xxx"></slot>
-    </template>
-    <div id="c1" slot="slot1"></div>
-    <div id="c2" slot="slot2"></div>
-    <div id="c3" slot="yyy"></div>
-  </div>
-</div>
-
-<script>
-test(() => {
-  let n = createTestTree(test_slot_name_matching);
-  removeWhiteSpaceOnlyTextNodes(n.test_slot_name_matching);
-
-  assert_equals(n.c1.assignedSlot, n.s1);
-  assert_equals(n.c2.assignedSlot, n.s2);
-  assert_equals(n.c3.assignedSlot, null);
-}, 'Slots: Name matching');
-</script>
-
-<div id="test_no_direct_host_child">
-  <div id="host">
-    <template data-mode="open">
-      <slot id="s1" name="slot1"></slot>
-      <slot id="s2" name="slot1"></slot>
-    </template>
-    <div id="c1" slot="slot1"></div>
-    <div id="c2" slot="slot1"></div>
-    <div>
-      <div id="c3" slot="slot1"></div>
-    </div>
-  </div>
-</div>
-
-<script>
-test(() => {
-  let n = createTestTree(test_no_direct_host_child);
-  removeWhiteSpaceOnlyTextNodes(n.test_no_direct_host_child);
-
-  assert_equals(n.c1.assignedSlot, n.s1);
-  assert_equals(n.c2.assignedSlot, n.s1);
-  assert_equals(n.c3.assignedSlot, null);
-
-  assert_array_equals(n.s1.assignedNodes(), [n.c1, n.c2]);
-}, 'Slots: No direct host child.');
-</script>
-
-<div id="test_default_slot">
-  <div id="host">
-    <template data-mode="open">
-      <slot id="s1" name="slot1"></slot>
-      <slot id="s2"></slot>
-      <slot id="s3"></slot>
-    </template>
-    <div id="c1"></div>
-    <div id="c2" slot=""></div>
-    <div id="c3" slot="foo"></div>
-  </div>
-</div>
-
-<script>
-test(() => {
-  let n = createTestTree(test_default_slot);
-  removeWhiteSpaceOnlyTextNodes(n.test_default_slot);
-
-  assert_equals(n.c1.assignedSlot, n.s2);
-  assert_equals(n.c2.assignedSlot, n.s2);
-  assert_equals(n.c3.assignedSlot, null);
-}, 'Slots: Default Slot.');
-</script>
-
-<div id="test_slot_in_slot">
-  <div id="host">
-    <template data-mode="open">
-      <slot id="s1" name="slot1">
-        <slot id="s2" name="slot2"></slot>
-      </slot>
-    </template>
-    <div id="c1" slot="slot2"></div>
-    <div id="c2" slot="slot1"></div>
-  </div>
-</div>
-
-<script>
-test(() => {
-  let n = createTestTree(test_slot_in_slot);
-  removeWhiteSpaceOnlyTextNodes(n.test_slot_in_slot);
-
-  assert_equals(n.c1.assignedSlot, n.s2);
-  assert_equals(n.c2.assignedSlot, n.s1);
-}, 'Slots: Slot in Slot does not matter in assignment.');
-</script>
-
-<div id="test_slot_is_assigned_to_slot">
-  <div id="host1">
-    <template data-mode="open">
-      <div id="host2">
-        <template data-mode="open">
-          <slot id="s2" name="slot2"></slot>
-        </template>
-        <slot id="s1" name="slot1" slot="slot2"></slot>
-      </div>
-    </template>
-    <div id="c1" slot="slot1"></div>
-  </div>
-</div>
-
-<script>
-test(() => {
-  let n = createTestTree(test_slot_is_assigned_to_slot);
-  removeWhiteSpaceOnlyTextNodes(n.test_slot_is_assigned_to_slot);
-
-  assert_equals(n.c1.assignedSlot, n.s1);
-  assert_equals(n.s1.assignedSlot, n.s2);
-
-  assert_array_equals(n.s1.assignedNodes(), [n.c1]);
-  assert_array_equals(n.s2.assignedNodes(), [n.s1]);
-
-  assert_array_equals(n.s1.assignedNodes({ flatten: true }), [n.c1]);
-  assert_array_equals(n.s2.assignedNodes({ flatten: true }), [n.c1]);
-}, 'Slots: Slot is assigned to another slot');
-</script>
-
-<div id="test_open_closed">
-  <div id="host1">
-    <template data-mode="open">
-      <div id="host2">
-        <template data-mode="closed">
-          <slot id="s2" name="slot2"></slot>
-        </template>
-        <slot id="s1" name="slot1" slot="slot2"></slot>
-      </div>
-    </template>
-    <div id="c1" slot="slot1"></div>
-  </div>
-</div>
-
-<script>
-test(() => {
-  let n = createTestTree(test_open_closed);
-  removeWhiteSpaceOnlyTextNodes(n.test_open_closed);
-
-  assert_equals(n.c1.assignedSlot, n.s1);
-  assert_equals(n.s1.assignedSlot, null,
-                'A slot in a closed shadow tree should not be accessed via assignedSlot');
-
-  assert_array_equals(n.s1.assignedNodes(), [n.c1]);
-  assert_array_equals(n.s2.assignedNodes(), [n.s1]);
-
-  assert_array_equals(n.s1.assignedNodes({ flatten: true }), [n.c1]);
-  assert_array_equals(n.s2.assignedNodes({ flatten: true }), [n.c1]);
-}, 'Slots: Open > Closed.');
-</script>
-
-<div id="test_closed_closed">
-  <div id="host1">
-    <template data-mode="closed">
-      <div id="host2">
-        <template data-mode="closed">
-          <slot id="s2" name="slot2"></slot>
-        </template>
-        <slot id="s1" name="slot1" slot="slot2"></slot>
-      </div>
-    </template>
-    <div id="c1" slot="slot1"></div>
-  </div>
-</div>
-
-<script>
-test(() => {
-  let n = createTestTree(test_closed_closed);
-  removeWhiteSpaceOnlyTextNodes(n.test_closed_closed);
-
-  assert_equals(n.c1.assignedSlot, null,
-                'A slot in a closed shadow tree should not be accessed via assignedSlot');
-  assert_equals(n.s1.assignedSlot, null,
-                'A slot in a closed shadow tree should not be accessed via assignedSlot');
-
-  assert_array_equals(n.s1.assignedNodes(), [n.c1]);
-  assert_array_equals(n.s2.assignedNodes(), [n.s1]);
-
-  assert_array_equals(n.s1.assignedNodes({ flatten: true }), [n.c1]);
-  assert_array_equals(n.s2.assignedNodes({ flatten: true }), [n.c1]);
-}, 'Slots: Closed > Closed.');
-</script>
-
-<div id="test_closed_open">
-  <div id="host1">
-    <template data-mode="closed">
-      <div id="host2">
-        <template data-mode="open">
-          <slot id="s2" name="slot2"></slot>
-        </template>
-        <slot id="s1" name="slot1" slot="slot2"></slot>
-      </div>
-    </template>
-    <div id="c1" slot="slot1"></div>
-  </div>
-</div>
-
-<script>
-test(() => {
-  let n = createTestTree(test_closed_open);
-  removeWhiteSpaceOnlyTextNodes(n.test_closed_open);
-
-  assert_equals(n.c1.assignedSlot, null,
-                'A slot in a closed shadow tree should not be accessed via assignedSlot');
-  assert_equals(n.s1.assignedSlot, n.s2);
-
-  assert_array_equals(n.s1.assignedNodes(), [n.c1]);
-  assert_array_equals(n.s2.assignedNodes(), [n.s1]);
-
-  assert_array_equals(n.s1.assignedNodes({ flatten: true }), [n.c1]);
-  assert_array_equals(n.s2.assignedNodes({ flatten: true }), [n.c1]);
-}, 'Slots: Closed > Open.');
-</script>
-
-<div id="test_complex">
-  <div id="host1">
-    <template data-mode="open">
-      <div id="host2">
-        <template data-mode="open">
-          <slot id="s5" name="slot5"></slot>
-          <slot id="s6" name="slot6"></slot>
-          <slot id="s7"></slot>
-          <slot id="s8" name="slot8"></slot>
-        </template>
-        <slot id="s1" name="slot1" slot="slot5"></slot>
-        <slot id="s2" name="slot2" slot="slot6"></slot>
-        <slot id="s3"></slot>
-        <slot id="s4" name="slot4" slot="slot-none"></slot>
-        <div id="c5" slot="slot5"></div>
-        <div id="c6" slot="slot6"></div>
-        <div id="c7"></div>
-        <div id="c8" slot="slot-none"></div>
-      </div>
-    </template>
-    <div id="c1" slot="slot1"></div>
-    <div id="c2" slot="slot2"></div>
-    <div id="c3"></div>
-    <div id="c4" slot="slot-none"></div>
-  </div>
-</div>
-
-<script>
-test(() => {
-  let n = createTestTree(test_complex);
-  removeWhiteSpaceOnlyTextNodes(n.test_complex);
-
-  assert_equals(n.c1.assignedSlot, n.s1);
-  assert_equals(n.c2.assignedSlot, n.s2);
-  assert_equals(n.c3.assignedSlot, n.s3);
-  assert_equals(n.c4.assignedSlot, null);
-
-  assert_equals(n.s1.assignedSlot, n.s5);
-  assert_equals(n.s2.assignedSlot, n.s6);
-  assert_equals(n.s3.assignedSlot, n.s7);
-  assert_equals(n.s4.assignedSlot, null);
-
-  assert_equals(n.c5.assignedSlot, n.s5);
-  assert_equals(n.c6.assignedSlot, n.s6);
-  assert_equals(n.c7.assignedSlot, n.s7);
-  assert_equals(n.c8.assignedSlot, null);
-
-  assert_array_equals(n.s1.assignedNodes(), [n.c1]);
-  assert_array_equals(n.s2.assignedNodes(), [n.c2]);
-  assert_array_equals(n.s3.assignedNodes(), [n.c3]);
-  assert_array_equals(n.s4.assignedNodes(), []);
-  assert_array_equals(n.s5.assignedNodes(), [n.s1, n.c5]);
-  assert_array_equals(n.s6.assignedNodes(), [n.s2, n.c6]);
-  assert_array_equals(n.s7.assignedNodes(), [n.s3, n.c7]);
-  assert_array_equals(n.s8.assignedNodes(), []);
-
-  assert_array_equals(n.s1.assignedNodes({ flatten: true }), [n.c1]);
-  assert_array_equals(n.s2.assignedNodes({ flatten: true }), [n.c2]);
-  assert_array_equals(n.s3.assignedNodes({ flatten: true }), [n.c3]);
-  assert_array_equals(n.s4.assignedNodes({ flatten: true }), []);
-  assert_array_equals(n.s5.assignedNodes({ flatten: true }), [n.c1, n.c5]);
-  assert_array_equals(n.s6.assignedNodes({ flatten: true }), [n.c2, n.c6]);
-  assert_array_equals(n.s7.assignedNodes({ flatten: true }), [n.c3, n.c7]);
-  assert_array_equals(n.s8.assignedNodes({ flatten: true }), []);
-}, 'Slots: Complex case: Basi line.');
-
-test(() => {
-  let n = createTestTree(test_complex);
-  removeWhiteSpaceOnlyTextNodes(n.test_complex);
-
-  let d1 = document.createElement('div');
-  d1.setAttribute('slot', 'slot1');
-  n.host1.appendChild(d1);
-
-  assert_array_equals(n.s1.assignedNodes(), [n.c1, d1]);
-  assert_equals(d1.assignedSlot, n.s1);
-
-  assert_array_equals(n.s5.assignedNodes({ flatten: true }), [n.c1, d1, n.c5]);
-}, 'Slots: Mutation: appendChild.');
-
-test(() => {
-  let n = createTestTree(test_complex);
-  removeWhiteSpaceOnlyTextNodes(n.test_complex);
-
-  n.c1.setAttribute('slot', 'slot-none');
-
-  assert_array_equals(n.s1.assignedNodes(), []);
-  assert_equals(n.c1.assignedSlot, null);
-
-  assert_array_equals(n.s5.assignedNodes({ flatten: true }), [n.c5]);
-}, 'Slots: Mutation: Change slot= attribute 1.');
-
-test(() => {
-  let n = createTestTree(test_complex);
-  removeWhiteSpaceOnlyTextNodes(n.test_complex);
-
-  n.c1.setAttribute('slot', 'slot2');
-
-  assert_array_equals(n.s1.assignedNodes(), []);
-  assert_array_equals(n.s2.assignedNodes(), [n.c1, n.c2]);
-  assert_equals(n.c1.assignedSlot, n.s2);
-
-  assert_array_equals(n.s5.assignedNodes({ flatten: true }), [n.c5]);
-  assert_array_equals(n.s6.assignedNodes({ flatten: true }), [n.c1, n.c2, n.c6]);
-}, 'Slots: Mutation: Change slot= attribute 2.');
-
-test(() => {
-  let n = createTestTree(test_complex);
-  removeWhiteSpaceOnlyTextNodes(n.test_complex);
-
-  n.c4.setAttribute('slot', 'slot1');
-
-  assert_array_equals(n.s1.assignedNodes(), [n.c1, n.c4]);
-  assert_equals(n.c4.assignedSlot, n.s1);
-
-  assert_array_equals(n.s5.assignedNodes({ flatten: true }), [n.c1, n.c4, n.c5]);
-}, 'Slots: Mutation: Change slot= attribute 3.');
-
-test(() => {
-  let n = createTestTree(test_complex);
-  removeWhiteSpaceOnlyTextNodes(n.test_complex);
-
-  n.c1.remove();
-
-  assert_array_equals(n.s1.assignedNodes(), []);
-  assert_equals(n.c1.assignedSlot, null);
-
-  assert_array_equals(n.s5.assignedNodes({ flatten: true }), [n.c5]);
-}, 'Slots: Mutation: Remove a child.');
-
-test(() => {
-  let n = createTestTree(test_complex);
-  removeWhiteSpaceOnlyTextNodes(n.test_complex);
-
-  let slot = document.createElement('slot');
-  slot.setAttribute('name', 'slot1');
-  n.host2.appendChild(slot);
-
-  assert_array_equals(slot.assignedNodes(), []);
-}, 'Slots: Mutation: Add a slot: after.');
-
-test(() => {
-  let n = createTestTree(test_complex);
-  removeWhiteSpaceOnlyTextNodes(n.test_complex);
-
-  let slot = document.createElement('slot');
-  slot.setAttribute('name', 'slot1');
-  n.host2.insertBefore(slot, n.s1);
-
-  assert_array_equals(slot.assignedNodes(), [n.c1]);
-  assert_equals(n.c1.assignedSlot, slot);
-
-  assert_array_equals(n.s7.assignedNodes(), [slot, n.s3, n.c7]);
-  assert_array_equals(n.s7.assignedNodes({ flatten: true }), [n.c1, n.c3, n.c7]);
-}, 'Slots: Mutation: Add a slot: before.');
-
-test(() => {
-  let n = createTestTree(test_complex);
-  removeWhiteSpaceOnlyTextNodes(n.test_complex);
-
-  n.s1.remove();
-
-  assert_array_equals(n.s1.assignedNodes(), []);
-  assert_equals(n.c1.assignedSlot, null);
-
-  assert_array_equals(n.s5.assignedNodes(), [n.c5]);
-  assert_array_equals(n.s5.assignedNodes({ flatten: true }), [n.c5]);
-}, 'Slots: Mutation: Remove a slot.');
-
-test(() => {
-  let n = createTestTree(test_complex);
-  removeWhiteSpaceOnlyTextNodes(n.test_complex);
-
-  n.s1.setAttribute('name', 'slot2');
-
-  assert_array_equals(n.s1.assignedNodes(), [n.c2]);
-  assert_equals(n.c1.assignedSlot, null);
-  assert_equals(n.c2.assignedSlot, n.s1);
-
-  assert_array_equals(n.s5.assignedNodes(), [n.s1, n.c5]);
-  assert_array_equals(n.s5.assignedNodes({ flatten: true }), [n.c2, n.c5]);
-}, 'Slots: Mutation: Change slot name= attribute.');
-
-test(() => {
-  let n = createTestTree(test_complex);
-  removeWhiteSpaceOnlyTextNodes(n.test_complex);
-
-  n.s1.setAttribute('slot', 'slot6');
-
-  assert_array_equals(n.s1.assignedNodes(), [n.c1]);
-
-  assert_array_equals(n.s5.assignedNodes(), [n.c5]);
-  assert_array_equals(n.s6.assignedNodes(), [n.s1, n.s2, n.c6]);
-  assert_array_equals(n.s6.assignedNodes({ flatten: true }), [n.c1, n.c2, n.c6]);
-}, 'Slots: Mutation: Change slot slot= attribute.');
+}, 'Slots: Blink specific tests for slots.');
 </script>
diff --git a/third_party/WebKit/Source/core/dom/AXObjectCacheBase.h b/third_party/WebKit/Source/core/dom/AXObjectCacheBase.h
index 6d6c0c06..4192e4102 100644
--- a/third_party/WebKit/Source/core/dom/AXObjectCacheBase.h
+++ b/third_party/WebKit/Source/core/dom/AXObjectCacheBase.h
@@ -10,7 +10,9 @@
 
 namespace blink {
 
+class LayoutObject;
 class Node;
+class AXObject;
 class AXObjectImpl;
 
 // AXObjectCacheBase is a temporary class that sits between AXObjectCache and
@@ -25,7 +27,8 @@
  public:
   virtual ~AXObjectCacheBase();
 
-  virtual AXObjectImpl* Get(const Node*) = 0;
+  virtual AXObject* Get(const Node*) = 0;
+  virtual AXObject* GetOrCreate(LayoutObject*) = 0;
 
  protected:
   AXObjectCacheBase();
diff --git a/third_party/WebKit/Source/core/dom/DocumentWriteIntervention.cpp b/third_party/WebKit/Source/core/dom/DocumentWriteIntervention.cpp
index 3ddd87f..cd50894 100644
--- a/third_party/WebKit/Source/core/dom/DocumentWriteIntervention.cpp
+++ b/third_party/WebKit/Source/core/dom/DocumentWriteIntervention.cpp
@@ -128,7 +128,7 @@
   }
 
   EmitWarningForDocWriteScripts(request.Url().GetString(), document);
-  request.SetHTTPHeaderField("Intervention",
+  request.AddHTTPHeaderField("Intervention",
                              "<https://www.chromestatus.com/feature/"
                              "5718547946799104>; level=\"warning\"");
 
diff --git a/third_party/WebKit/Source/core/dom/Range.cpp b/third_party/WebKit/Source/core/dom/Range.cpp
index 302303e4..fbbf2649 100644
--- a/third_party/WebKit/Source/core/dom/Range.cpp
+++ b/third_party/WebKit/Source/core/dom/Range.cpp
@@ -852,6 +852,7 @@
   return ProcessContents(CLONE_CONTENTS, exception_state);
 }
 
+// https://dom.spec.whatwg.org/#concept-range-insert
 void Range::insertNode(Node* new_node, ExceptionState& exception_state) {
   if (!new_node) {
     // FIXME: Generated bindings code never calls with null, and neither should
@@ -860,140 +861,105 @@
     return;
   }
 
-  // HierarchyRequestError: Raised if the container of the start of the Range is
-  // of a type that does not allow children of the type of newNode or if newNode
-  // is an ancestor of the container.
-
-  // an extra one here - if a text node is going to split, it must have a parent
-  // to insert into
-  bool start_is_text = start_.Container().IsTextNode();
-  if (start_is_text && !start_.Container().parentNode()) {
+  // 1. If range’s start node is a ProcessingInstruction or Comment node, is a
+  // Text node whose parent is null, or is node, then throw a
+  // HierarchyRequestError.
+  Node& start_node = start_.Container();
+  if (start_node.getNodeType() == Node::kProcessingInstructionNode ||
+      start_node.getNodeType() == Node::kCommentNode) {
+    exception_state.ThrowDOMException(
+        kHierarchyRequestError,
+        "Nodes of type '" + new_node->nodeName() +
+            "' may not be inserted inside nodes of type '" +
+            start_node.nodeName() + "'.");
+    return;
+  }
+  const bool start_is_text = start_node.IsTextNode();
+  if (start_is_text && !start_node.parentNode()) {
     exception_state.ThrowDOMException(kHierarchyRequestError,
                                       "This operation would split a text node, "
                                       "but there's no parent into which to "
                                       "insert.");
     return;
   }
+  if (start_node == new_node) {
+    exception_state.ThrowDOMException(
+        kHierarchyRequestError,
+        "Unable to insert a node into a Range starting from the node itself.");
+    return;
+  }
 
-  // In the case where the container is a text node, we check against the
-  // container's parent, because text nodes get split up upon insertion.
-  Node* check_against;
+  // According to the specification, the following condition is checked in the
+  // step 6. However our EnsurePreInsertionValidity() supports only
+  // ContainerNode parent.
+  if (start_node.IsAttributeNode()) {
+    exception_state.ThrowDOMException(
+        kHierarchyRequestError,
+        "Nodes of type '" + new_node->nodeName() +
+            "' may not be inserted inside nodes of type 'Attr'.");
+    return;
+  }
+
+  // 2. Let referenceNode be null.
+  Node* reference_node = nullptr;
+  // 3. If range’s start node is a Text node, set referenceNode to that Text
+  // node.
+  // 4. Otherwise, set referenceNode to the child of start node whose index is
+  // start offset, and null if there is no such child.
   if (start_is_text)
-    check_against = start_.Container().parentNode();
+    reference_node = &start_node;
   else
-    check_against = &start_.Container();
+    reference_node = NodeTraversal::ChildAt(start_node, start_.Offset());
 
-  Node::NodeType new_node_type = new_node->getNodeType();
-  int num_new_children;
-  if (new_node_type == Node::kDocumentFragmentNode) {
-    // check each child node, not the DocumentFragment itself
-    num_new_children = 0;
-    for (Node* c = ToDocumentFragment(new_node)->firstChild(); c;
-         c = c->nextSibling()) {
-      if (!check_against->ChildTypeAllowed(c->getNodeType())) {
-        exception_state.ThrowDOMException(
-            kHierarchyRequestError,
-            "The node to be inserted contains a '" + c->nodeName() +
-                "' node, which may not be inserted here.");
-        return;
-      }
-      ++num_new_children;
-    }
-  } else {
-    num_new_children = 1;
-    if (!check_against->ChildTypeAllowed(new_node_type)) {
-      exception_state.ThrowDOMException(
-          kHierarchyRequestError,
-          "The node to be inserted is a '" + new_node->nodeName() +
-              "' node, which may not be inserted here.");
-      return;
-    }
-  }
+  // 5. Let parent be range’s start node if referenceNode is null, and
+  // referenceNode’s parent otherwise.
+  ContainerNode& parent = reference_node ? *reference_node->parentNode()
+                                         : ToContainerNode(start_node);
 
-  for (Node& node : NodeTraversal::InclusiveAncestorsOf(start_.Container())) {
-    if (node == new_node) {
-      exception_state.ThrowDOMException(kHierarchyRequestError,
-                                        "The node to be inserted contains the "
-                                        "insertion point; it may not be "
-                                        "inserted into itself.");
-      return;
-    }
-  }
-
-  // InvalidNodeTypeError: Raised if new_node is an Attr or Document node.
-  switch (new_node_type) {
-    case Node::kAttributeNode:
-    case Node::kDocumentNode:
-      exception_state.ThrowDOMException(
-          kInvalidNodeTypeError, "The node to be inserted is a '" +
-                                     new_node->nodeName() +
-                                     "' node, which may not be inserted here.");
-      return;
-    default:
-      break;
-  }
+  // 6. Ensure pre-insertion validity of node into parent before referenceNode.
+  if (!parent.EnsurePreInsertionValidity(*new_node, reference_node, nullptr,
+                                         exception_state))
+    return;
 
   EventQueueScope scope;
-  bool collapsed = start_ == end_;
-  Node* container = nullptr;
+  // 7. If range's start node is a Text node, set referenceNode to the result of
+  // splitting it with offset range’s start offset.
   if (start_is_text) {
-    container = &start_.Container();
-    Text* new_text =
-        ToText(container)->splitText(start_.Offset(), exception_state);
+    reference_node =
+        ToText(start_node).splitText(start_.Offset(), exception_state);
     if (exception_state.HadException())
       return;
-
-    container = &start_.Container();
-    container->parentNode()->InsertBefore(new_node, new_text, exception_state);
-    if (exception_state.HadException())
-      return;
-
-    if (collapsed) {
-      // Some types of events don't support EventQueueScope.  Given
-      // circumstance may mutate the tree so newText->parentNode() may
-      // become null.
-      if (!new_text->parentNode()) {
-        exception_state.ThrowDOMException(
-            kHierarchyRequestError,
-            "This operation would set range's end to parent with new offset, "
-            "but there's no parent into which to continue.");
-        return;
-      }
-      end_.SetToBeforeChild(*new_text);
-    }
-  } else {
-    Node* last_child = (new_node_type == Node::kDocumentFragmentNode)
-                           ? ToDocumentFragment(new_node)->lastChild()
-                           : new_node;
-    if (last_child && last_child == start_.ChildBefore()) {
-      // The insertion will do nothing, but we need to extend the range to
-      // include the inserted nodes.
-      Node* first_child = (new_node_type == Node::kDocumentFragmentNode)
-                              ? ToDocumentFragment(new_node)->firstChild()
-                              : new_node;
-      DCHECK(first_child);
-      start_.SetToBeforeChild(*first_child);
-      return;
-    }
-
-    container = &start_.Container();
-    Node* reference_node = NodeTraversal::ChildAt(*container, start_.Offset());
-    // TODO(tkent): The following check must be unnecessary if we follow the
-    // algorithm defined in the specification.
-    // https://dom.spec.whatwg.org/#concept-range-insert
-    if (new_node != reference_node) {
-      container->insertBefore(new_node, reference_node, exception_state);
-      if (exception_state.HadException())
-        return;
-    }
-
-    // Note that m_start.offset() may have changed as a result of
-    // container->insertBefore, when the node we are inserting comes before the
-    // range in the same container.
-    if (collapsed && num_new_children)
-      end_.Set(start_.Container(), start_.Offset() + num_new_children,
-               last_child);
   }
+
+  // 8. If node is referenceNode, set referenceNode to its next sibling.
+  if (new_node == reference_node)
+    reference_node = reference_node->nextSibling();
+
+  // 9. If node's parent is not null, remove node from its parent.
+  if (new_node->parentNode()) {
+    new_node->remove(exception_state);
+    if (exception_state.HadException())
+      return;
+  }
+
+  // 10. Let newOffset be parent's length if referenceNode is null, and
+  // referenceNode's index otherwise.
+  unsigned new_offset =
+      reference_node ? reference_node->NodeIndex() : LengthOfContents(&parent);
+
+  // 11. Increase newOffset by node's length if node is a DocumentFragment node,
+  // and one otherwise.
+  new_offset += new_node->IsDocumentFragment() ? LengthOfContents(new_node) : 1;
+
+  // 12. Pre-insert node into parent before referenceNode.
+  parent.insertBefore(new_node, reference_node, exception_state);
+  if (exception_state.HadException())
+    return;
+
+  // 13. If range's start and end are the same, set range's end to (parent,
+  // newOffset).
+  if (start_ == end_)
+    setEnd(&parent, new_offset, exception_state);
 }
 
 String Range::toString() const {
diff --git a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
index 4a1c471..9d19f83 100644
--- a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
+++ b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
@@ -705,7 +705,7 @@
   // [Intervention]
   if (document_write_intervention_ ==
       DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) {
-    resource_request.SetHTTPHeaderField(
+    resource_request.AddHTTPHeaderField(
         "Intervention",
         "<https://www.chromestatus.com/feature/5718547946799104>");
     defer = FetchParameters::kIdleLoad;
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
index 10d7bb2..5def9600 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
@@ -755,6 +755,20 @@
                                                                  UnicodeBidi,
                                                                  TextDirection);
 
+// Returns true if |caret_offset| is at edge of |box| based on |affinity|.
+// |caret_offset| must be either |box.CaretMinOffset()| or
+// |box.CaretMaxOffset()|.
+static bool IsCaretAtEdgeOfInlineTextBox(int caret_offset,
+                                         const InlineTextBox& box,
+                                         TextAffinity affinity) {
+  if (caret_offset == box.CaretMinOffset())
+    return affinity == TextAffinity::kDownstream;
+  DCHECK_EQ(caret_offset, box.CaretMaxOffset());
+  if (affinity == TextAffinity::kUpstream)
+    return true;
+  return box.NextLeafChild() && box.NextLeafChild()->IsLineBreak();
+}
+
 template <typename Strategy>
 static InlineBoxPosition ComputeInlineBoxPositionTemplate(
     const PositionTemplate<Strategy>& position,
@@ -790,15 +804,17 @@
           UpstreamIgnoringEditingBoundaries(position);
       if (upstream_equivalent == position ||
           DownstreamIgnoringEditingBoundaries(upstream_equivalent) == position)
-        return InlineBoxPosition(inline_box, caret_offset);
+        return InlineBoxPosition();
 
       return ComputeInlineBoxPosition(
           upstream_equivalent, TextAffinity::kUpstream, primary_direction);
     }
     if (layout_object->IsBox()) {
       inline_box = ToLayoutBox(layout_object)->InlineBoxWrapper();
-      if (!inline_box || (caret_offset > inline_box->CaretMinOffset() &&
-                          caret_offset < inline_box->CaretMaxOffset()))
+      if (!inline_box)
+        return InlineBoxPosition();
+      if ((caret_offset > inline_box->CaretMinOffset() &&
+           caret_offset < inline_box->CaretMaxOffset()))
         return InlineBoxPosition(inline_box, caret_offset);
     }
   } else {
@@ -817,12 +833,7 @@
       if (caret_offset > caret_min_offset && caret_offset < caret_max_offset)
         return InlineBoxPosition(box, caret_offset);
 
-      if (((caret_offset == caret_max_offset) ^
-           (affinity == TextAffinity::kDownstream)) ||
-          ((caret_offset == caret_min_offset) ^
-           (affinity == TextAffinity::kUpstream)) ||
-          (caret_offset == caret_max_offset && box->NextLeafChild() &&
-           box->NextLeafChild()->IsLineBreak())) {
+      if (IsCaretAtEdgeOfInlineTextBox(caret_offset, *box, affinity)) {
         inline_box = box;
         break;
       }
@@ -840,7 +851,7 @@
   }
 
   if (!inline_box)
-    return InlineBoxPosition(inline_box, caret_offset);
+    return InlineBoxPosition();
   return AdjustInlineBoxPositionForTextDirection(
       inline_box, caret_offset, layout_object->Style()->GetUnicodeBidi(),
       primary_direction);
@@ -1024,7 +1035,11 @@
             box_position.inline_box->GetLineLayoutItem()),
         box_position);
   }
-  return ComputeLocalCaretRect(layout_object, box_position);
+  // DeleteSelectionCommandTest.deleteListFromTable goes here.
+  return LocalCaretRect(
+      layout_object,
+      layout_object->LocalCaretRect(
+          nullptr, position.GetPosition().ComputeEditingOffset()));
 }
 
 // This function was added because the caret rect that is calculated by
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnits.h b/third_party/WebKit/Source/core/editing/VisibleUnits.h
index 16e3a9e49..77618f7 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnits.h
+++ b/third_party/WebKit/Source/core/editing/VisibleUnits.h
@@ -52,7 +52,10 @@
   InlineBoxPosition() : inline_box(nullptr), offset_in_box(0) {}
 
   InlineBoxPosition(InlineBox* inline_box, int offset_in_box)
-      : inline_box(inline_box), offset_in_box(offset_in_box) {}
+      : inline_box(inline_box), offset_in_box(offset_in_box) {
+    DCHECK(inline_box);
+    DCHECK_GE(offset_in_box, 0);
+  }
 
   bool operator==(const InlineBoxPosition& other) const {
     return inline_box == other.inline_box &&
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnitsTest.cpp b/third_party/WebKit/Source/core/editing/VisibleUnitsTest.cpp
index f463135..6b2f9149 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnitsTest.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleUnitsTest.cpp
@@ -303,9 +303,7 @@
       Position::LastPositionInNode(sample), TextAffinity::kDownstream);
   // Should not be in infinite-loop
   EXPECT_EQ(nullptr, actual.inline_box);
-  // TODO(editing-dev): We should return 0 for |InlineBoxPosition| when
-  // |inline_box| is null.
-  EXPECT_EQ(2, actual.offset_in_box);
+  EXPECT_EQ(0, actual.offset_in_box);
 }
 
 TEST_F(VisibleUnitsTest, endOfDocument) {
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameClient.h b/third_party/WebKit/Source/core/frame/LocalFrameClient.h
index 46fe331..2f8236e 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameClient.h
+++ b/third_party/WebKit/Source/core/frame/LocalFrameClient.h
@@ -322,6 +322,10 @@
     return WebEffectiveConnectionType::kTypeUnknown;
   }
 
+  // Returns whether or not Client Lo-Fi is enabled for the frame
+  // (and so image requests may be replaced with a placeholder).
+  virtual bool IsClientLoFiActiveForFrame() { return false; }
+
   // Returns whether or not the requested image should be replaced with a
   // placeholder as part of the Client Lo-Fi previews feature.
   virtual bool ShouldUseClientLoFiForRequest(const ResourceRequest&) {
diff --git a/third_party/WebKit/Source/core/html/BUILD.gn b/third_party/WebKit/Source/core/html/BUILD.gn
index 72434e53..9bc0f97 100644
--- a/third_party/WebKit/Source/core/html/BUILD.gn
+++ b/third_party/WebKit/Source/core/html/BUILD.gn
@@ -317,6 +317,8 @@
     "forms/DateTimeSymbolicFieldElement.h",
     "forms/EmailInputType.cpp",
     "forms/EmailInputType.h",
+    "forms/ExternalDateTimeChooser.cpp",
+    "forms/ExternalDateTimeChooser.h",
     "forms/FileInputType.cpp",
     "forms/FileInputType.h",
     "forms/FormController.cpp",
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
index d14730b3..c4f80b5 100644
--- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
@@ -510,6 +510,12 @@
   return true;
 }
 
+CanvasColorParams HTMLCanvasElement::GetCanvasColorParams() const {
+  if (context_)
+    return context_->color_params();
+  return CanvasColorParams();
+}
+
 void HTMLCanvasElement::NotifyListenersCanvasChanged() {
   if (listeners_.size() == 0)
     return;
@@ -872,7 +878,7 @@
   // Rasterization of web contents will blend in the output space. Only embed
   // the canvas as a display list if it intended to do output space blending as
   // well.
-  if (!context_->color_params().UsesOutputSpaceBlending())
+  if (!GetCanvasColorParams().UsesOutputSpaceBlending())
     return false;
 
   if (RuntimeEnabledFeatures::ForceDisplayList2dCanvasEnabled())
@@ -894,7 +900,7 @@
   // then make a non-accelerated ImageBuffer. This means copying the internal
   // Image will require a pixel readback, but that is unavoidable in this case.
   auto surface = WTF::MakeUnique<AcceleratedImageBufferSurface>(
-      Size(), opacity_mode, context_->color_params());
+      Size(), opacity_mode, GetCanvasColorParams());
   if (surface->IsValid())
     return std::move(surface);
   return nullptr;
@@ -923,7 +929,7 @@
 
   auto surface = WTF::MakeUnique<Canvas2DImageBufferSurface>(
       std::move(context_provider), Size(), *msaa_sample_count, opacity_mode,
-      Canvas2DLayerBridge::kEnableAcceleration, context_->color_params());
+      Canvas2DLayerBridge::kEnableAcceleration, GetCanvasColorParams());
   if (!surface->IsValid()) {
     CanvasMetrics::CountCanvasContextUsage(
         CanvasMetrics::kGPUAccelerated2DCanvasImageBufferCreationFailed);
@@ -944,7 +950,7 @@
   if (ShouldUseDisplayList()) {
     auto surface = WTF::MakeUnique<RecordingImageBufferSurface>(
         Size(), RecordingImageBufferSurface::kAllowFallback, opacity_mode,
-        context_->color_params());
+        GetCanvasColorParams());
     if (surface->IsValid()) {
       CanvasMetrics::CountCanvasContextUsage(
           CanvasMetrics::kDisplayList2DCanvasImageBufferCreated);
@@ -955,7 +961,7 @@
   }
 
   auto surface = WTF::MakeUnique<UnacceleratedImageBufferSurface>(
-      Size(), opacity_mode, kInitializeImagePixels, context_->color_params());
+      Size(), opacity_mode, kInitializeImagePixels, GetCanvasColorParams());
   if (surface->IsValid()) {
     CanvasMetrics::CountCanvasContextUsage(
         CanvasMetrics::kUnaccelerated2DCanvasImageBufferCreated);
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.h b/third_party/WebKit/Source/core/html/HTMLCanvasElement.h
index 23675df..0221e32 100644
--- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.h
@@ -56,6 +56,7 @@
 namespace blink {
 
 class AffineTransform;
+class CanvasColorParams;
 class CanvasContextCreationAttributes;
 class CanvasRenderingContext;
 class CanvasRenderingContextFactory;
@@ -304,6 +305,7 @@
   void SetSurfaceSize(const IntSize&);
 
   bool PaintsIntoCanvasBuffer() const;
+  CanvasColorParams GetCanvasColorParams() const;
 
   ImageData* ToImageData(SourceDrawingBuffer, SnapshotReason) const;
 
diff --git a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
index 2e459e0..8cc37030 100644
--- a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
@@ -220,7 +220,7 @@
   if (!insertion_point->isConnected())
     return;
 
-  link_loader_->Released();
+  link_loader_->Abort();
 
   if (!was_connected) {
     DCHECK(!GetLinkStyle() || !GetLinkStyle()->HasSheet());
diff --git a/third_party/WebKit/Source/web/ExternalDateTimeChooser.cpp b/third_party/WebKit/Source/core/html/forms/ExternalDateTimeChooser.cpp
similarity index 98%
rename from third_party/WebKit/Source/web/ExternalDateTimeChooser.cpp
rename to third_party/WebKit/Source/core/html/forms/ExternalDateTimeChooser.cpp
index 41602c9..cd06e5d 100644
--- a/third_party/WebKit/Source/web/ExternalDateTimeChooser.cpp
+++ b/third_party/WebKit/Source/core/html/forms/ExternalDateTimeChooser.cpp
@@ -23,7 +23,7 @@
  * SUCH DAMAGE.
  */
 
-#include "web/ExternalDateTimeChooser.h"
+#include "core/html/forms/ExternalDateTimeChooser.h"
 
 #include "core/InputTypeNames.h"
 #include "core/html/forms/DateTimeChooserClient.h"
diff --git a/third_party/WebKit/Source/web/ExternalDateTimeChooser.h b/third_party/WebKit/Source/core/html/forms/ExternalDateTimeChooser.h
similarity index 95%
rename from third_party/WebKit/Source/web/ExternalDateTimeChooser.h
rename to third_party/WebKit/Source/core/html/forms/ExternalDateTimeChooser.h
index 207abb4..e1c96e4 100644
--- a/third_party/WebKit/Source/web/ExternalDateTimeChooser.h
+++ b/third_party/WebKit/Source/core/html/forms/ExternalDateTimeChooser.h
@@ -26,6 +26,7 @@
 #ifndef ExternalDateTimeChooser_h
 #define ExternalDateTimeChooser_h
 
+#include "core/CoreExport.h"
 #include "core/html/forms/DateTimeChooser.h"
 
 namespace blink {
@@ -35,7 +36,7 @@
 class WebString;
 class WebViewClient;
 
-class ExternalDateTimeChooser final : public DateTimeChooser {
+class CORE_EXPORT ExternalDateTimeChooser final : public DateTimeChooser {
  public:
   static ExternalDateTimeChooser* Create(ChromeClient*,
                                          WebViewClient*,
diff --git a/third_party/WebKit/Source/core/loader/BUILD.gn b/third_party/WebKit/Source/core/loader/BUILD.gn
index 01821207..45e3cf7 100644
--- a/third_party/WebKit/Source/core/loader/BUILD.gn
+++ b/third_party/WebKit/Source/core/loader/BUILD.gn
@@ -105,8 +105,6 @@
     "resource/ImageResourceObserver.h",
     "resource/LinkFetchResource.cpp",
     "resource/LinkFetchResource.h",
-    "resource/LinkPreloadResourceClients.cpp",
-    "resource/LinkPreloadResourceClients.h",
     "resource/MultipartImageResourceParser.cpp",
     "resource/MultipartImageResourceParser.h",
     "resource/ScriptResource.cpp",
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
index 8b4ff1cf..de9a99e 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
@@ -284,6 +284,13 @@
   if (GetFrame()->GetSettings() &&
       GetFrame()->GetSettings()->GetDataSaverEnabled())
     request.SetHTTPHeaderField("Save-Data", "on");
+
+  if (GetLocalFrameClient()->IsClientLoFiActiveForFrame()) {
+    request.AddHTTPHeaderField(
+        "Intervention",
+        "<https://www.chromestatus.com/features/6072546726248448>; "
+        "level=\"warning\"");
+  }
 }
 
 // TODO(toyoshim, arthursonzogni): PlzNavigate doesn't use this function to set
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp
index 4c6b217..6c976d2 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp
@@ -88,6 +88,8 @@
   MOCK_METHOD2(DispatchDidLoadResourceFromMemoryCache,
                void(const ResourceRequest&, const ResourceResponse&));
   MOCK_METHOD0(UserAgent, String());
+  MOCK_METHOD0(MayUseClientLoFiForImageRequests, bool());
+  MOCK_METHOD0(IsClientLoFiActiveForFrame, bool());
 };
 
 class FixedPolicySubresourceFilter : public WebDocumentSubresourceFilter {
@@ -1278,4 +1280,38 @@
   EXPECT_EQ(nullptr, child_fetch_context->Archive());
 }
 
+// Tests if "Intervention" header is added for frame with Client Lo-Fi enabled.
+TEST_F(FrameFetchContextMockedLocalFrameClientTest,
+       ClientLoFiInterventionHeader) {
+  // Verify header not added if Lo-Fi not active.
+  EXPECT_CALL(*client, IsClientLoFiActiveForFrame())
+      .WillRepeatedly(testing::Return(false));
+  ResourceRequest resource_request("http://www.example.com/style.css");
+  fetch_context->AddAdditionalRequestHeaders(resource_request,
+                                             kFetchMainResource);
+  EXPECT_EQ(g_null_atom, resource_request.HttpHeaderField("Intervention"));
+
+  // Verify header is added if Lo-Fi is active.
+  EXPECT_CALL(*client, IsClientLoFiActiveForFrame())
+      .WillRepeatedly(testing::Return(true));
+  fetch_context->AddAdditionalRequestHeaders(resource_request,
+                                             kFetchSubresource);
+  EXPECT_EQ(
+      "<https://www.chromestatus.com/features/6072546726248448>; "
+      "level=\"warning\"",
+      resource_request.HttpHeaderField("Intervention"));
+
+  // Verify appended to an existing "Intervention" header value.
+  ResourceRequest resource_request2("http://www.example.com/getad.js");
+  resource_request2.SetHTTPHeaderField("Intervention",
+                                       "<https://otherintervention.org>");
+  fetch_context->AddAdditionalRequestHeaders(resource_request2,
+                                             kFetchSubresource);
+  EXPECT_EQ(
+      "<https://otherintervention.org>, "
+      "<https://www.chromestatus.com/features/6072546726248448>; "
+      "level=\"warning\"",
+      resource_request2.HttpHeaderField("Intervention"));
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/LinkLoader.cpp b/third_party/WebKit/Source/core/loader/LinkLoader.cpp
index 8843652d..0a4f022 100644
--- a/third_party/WebKit/Source/core/loader/LinkLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/LinkLoader.cpp
@@ -47,11 +47,12 @@
 #include "core/loader/private/PrerenderHandle.h"
 #include "core/loader/resource/LinkFetchResource.h"
 #include "platform/Prerender.h"
-#include "platform/Timer.h"
 #include "platform/loader/LinkHeader.h"
 #include "platform/loader/fetch/FetchInitiatorTypeNames.h"
 #include "platform/loader/fetch/FetchParameters.h"
+#include "platform/loader/fetch/ResourceClient.h"
 #include "platform/loader/fetch/ResourceFetcher.h"
+#include "platform/loader/fetch/ResourceFinishObserver.h"
 #include "platform/loader/fetch/ResourceLoaderOptions.h"
 #include "platform/network/mime/MIMETypeRegistry.h"
 #include "public/platform/WebPrerender.h"
@@ -74,40 +75,65 @@
   return result;
 }
 
+class LinkLoader::FinishObserver final
+    : public GarbageCollectedFinalized<ResourceFinishObserver>,
+      public ResourceFinishObserver {
+  USING_GARBAGE_COLLECTED_MIXIN(FinishObserver);
+  USING_PRE_FINALIZER(FinishObserver, ClearResource);
+
+ public:
+  FinishObserver(LinkLoader* loader,
+                 Resource* resource,
+                 Resource::PreloadReferencePolicy reference_policy)
+      : loader_(loader), resource_(resource) {
+    resource_->AddFinishObserver(this, reference_policy);
+  }
+
+  // ResourceFinishObserver implementation
+  void NotifyFinished() override {
+    if (!resource_)
+      return;
+    loader_->NotifyFinished();
+    ClearResource();
+  }
+  String DebugName() const override {
+    return "LinkLoader::ResourceFinishObserver";
+  }
+
+  Resource* GetResource() { return resource_; }
+  void ClearResource() {
+    if (!resource_)
+      return;
+    resource_->RemoveFinishObserver(this);
+    resource_ = nullptr;
+  }
+
+  DEFINE_INLINE_VIRTUAL_TRACE() {
+    visitor->Trace(loader_);
+    visitor->Trace(resource_);
+    blink::ResourceFinishObserver::Trace(visitor);
+  }
+
+ private:
+  Member<LinkLoader> loader_;
+  Member<Resource> resource_;
+};
+
 LinkLoader::LinkLoader(LinkLoaderClient* client,
                        RefPtr<WebTaskRunner> task_runner)
-    : client_(client),
-      link_load_timer_(task_runner, this, &LinkLoader::LinkLoadTimerFired),
-      link_loading_error_timer_(task_runner,
-                                this,
-                                &LinkLoader::LinkLoadingErrorTimerFired) {
+    : client_(client) {
   DCHECK(client_);
 }
 
 LinkLoader::~LinkLoader() {}
 
-void LinkLoader::LinkLoadTimerFired(TimerBase* timer) {
-  DCHECK_EQ(timer, &link_load_timer_);
-  client_->LinkLoaded();
-}
-
-void LinkLoader::LinkLoadingErrorTimerFired(TimerBase* timer) {
-  DCHECK_EQ(timer, &link_loading_error_timer_);
-  client_->LinkLoadingErrored();
-}
-
-void LinkLoader::TriggerEvents(const Resource* resource) {
+void LinkLoader::NotifyFinished() {
+  DCHECK(finish_observer_);
+  Resource* resource = finish_observer_->GetResource();
   if (resource->ErrorOccurred())
-    link_loading_error_timer_.StartOneShot(0, BLINK_FROM_HERE);
+    client_->LinkLoadingErrored();
   else
-    link_load_timer_.StartOneShot(0, BLINK_FROM_HERE);
-}
-
-void LinkLoader::NotifyFinished(Resource* resource) {
-  DCHECK_EQ(this->GetResource(), resource);
-
-  TriggerEvents(resource);
-  ClearResource();
+    client_->LinkLoaded();
 }
 
 void LinkLoader::DidStartPrerender() {
@@ -233,41 +259,8 @@
   return WTF::nullopt;
 }
 
-Resource* LinkLoader::LinkPreloadedResourceForTesting() {
-  return link_preload_resource_client_
-             ? link_preload_resource_client_->GetResource()
-             : nullptr;
-}
-
-void LinkLoader::CreateLinkPreloadResourceClient(Resource* resource) {
-  if (!resource)
-    return;
-  switch (resource->GetType()) {
-    case Resource::kImage:
-      link_preload_resource_client_ = LinkPreloadImageResourceClient::Create(
-          this, ToImageResource(resource));
-      break;
-    case Resource::kScript:
-      link_preload_resource_client_ = LinkPreloadScriptResourceClient::Create(
-          this, ToScriptResource(resource));
-      break;
-    case Resource::kCSSStyleSheet:
-      link_preload_resource_client_ = LinkPreloadStyleResourceClient::Create(
-          this, ToCSSStyleSheetResource(resource));
-      break;
-    case Resource::kFont:
-      link_preload_resource_client_ =
-          LinkPreloadFontResourceClient::Create(this, ToFontResource(resource));
-      break;
-    case Resource::kMedia:
-    case Resource::kTextTrack:
-    case Resource::kRaw:
-      link_preload_resource_client_ =
-          LinkPreloadRawResourceClient::Create(this, ToRawResource(resource));
-      break;
-    default:
-      NOTREACHED();
-  }
+Resource* LinkLoader::GetResourceForTesting() {
+  return finish_observer_ ? finish_observer_->GetResource() : nullptr;
 }
 
 static bool IsSupportedType(Resource::Type resource_type,
@@ -473,6 +466,9 @@
     const KURL& href,
     Document& document,
     const NetworkHintsInterface& network_hints_interface) {
+  // If any loading process is in progress, abort it.
+  Abort();
+
   if (!client_->ShouldLoadLink())
     return false;
 
@@ -483,17 +479,22 @@
                      cross_origin, network_hints_interface,
                      kLinkCalledFromMarkup);
 
-  CreateLinkPreloadResourceClient(PreloadIfNeeded(
+  Resource* preloaded_resource = PreloadIfNeeded(
       rel_attribute, href, document, as, type, media, cross_origin,
-      kLinkCalledFromMarkup, nullptr, referrer_policy));
+      kLinkCalledFromMarkup, nullptr, referrer_policy);
+  Resource* prefetched_resource = PrefetchIfNeeded(
+      document, href, rel_attribute, cross_origin, referrer_policy);
 
-  if (href.IsEmpty() || !href.IsValid())
-    Released();
+  DCHECK(!preloaded_resource || !prefetched_resource);
 
-  Resource* resource = PrefetchIfNeeded(document, href, rel_attribute,
-                                        cross_origin, referrer_policy);
-  if (resource)
-    SetResource(resource);
+  if (preloaded_resource) {
+    finish_observer_ = new FinishObserver(this, preloaded_resource,
+                                          Resource::kDontMarkAsReferenced);
+  }
+  if (prefetched_resource) {
+    finish_observer_ = new FinishObserver(this, prefetched_resource,
+                                          Resource::kMarkAsReferenced);
+  }
 
   if (const unsigned prerender_rel_types =
           PrerenderRelTypesFromRelAttribute(rel_attribute, document)) {
@@ -513,22 +514,21 @@
   return true;
 }
 
-void LinkLoader::Released() {
-  // Only prerenders need treatment here; other links either use the Resource
-  // interface, or are notionally atomic (dns prefetch).
+void LinkLoader::Abort() {
   if (prerender_) {
     prerender_->Cancel();
     prerender_.Clear();
   }
-  if (link_preload_resource_client_)
-    link_preload_resource_client_->Clear();
+  if (finish_observer_) {
+    finish_observer_->ClearResource();
+    finish_observer_ = nullptr;
+  }
 }
 
 DEFINE_TRACE(LinkLoader) {
+  visitor->Trace(finish_observer_);
   visitor->Trace(client_);
   visitor->Trace(prerender_);
-  visitor->Trace(link_preload_resource_client_);
-  ResourceOwner<Resource, ResourceClient>::Trace(visitor);
   PrerenderClient::Trace(visitor);
 }
 
diff --git a/third_party/WebKit/Source/core/loader/LinkLoader.h b/third_party/WebKit/Source/core/loader/LinkLoader.h
index 35a4ad81..48233cc 100644
--- a/third_party/WebKit/Source/core/loader/LinkLoader.h
+++ b/third_party/WebKit/Source/core/loader/LinkLoader.h
@@ -34,10 +34,8 @@
 
 #include "core/CoreExport.h"
 #include "core/loader/LinkLoaderClient.h"
-#include "core/loader/resource/LinkPreloadResourceClients.h"
 #include "platform/CrossOriginAttributeValue.h"
 #include "platform/PrerenderClient.h"
-#include "platform/loader/fetch/ResourceClient.h"
 #include "platform/loader/fetch/ResourceOwner.h"
 #include "platform/wtf/Optional.h"
 
@@ -54,7 +52,6 @@
 // prerender.
 class CORE_EXPORT LinkLoader final
     : public GarbageCollectedFinalized<LinkLoader>,
-      public ResourceOwner<Resource, ResourceClient>,
       public PrerenderClient {
   USING_GARBAGE_COLLECTED_MIXIN(LinkLoader);
 
@@ -64,19 +61,13 @@
   }
   ~LinkLoader() override;
 
-  // from ResourceClient
-  void NotifyFinished(Resource*) override;
-  String DebugName() const override { return "LinkLoader"; }
-
   // from PrerenderClient
   void DidStartPrerender() override;
   void DidStopPrerender() override;
   void DidSendLoadForPrerender() override;
   void DidSendDOMContentLoadedForPrerender() override;
 
-  void TriggerEvents(const Resource*);
-
-  void Released();
+  void Abort();
   bool LoadLink(const LinkRelAttribute&,
                 CrossOriginAttributeValue,
                 const String& type,
@@ -105,24 +96,20 @@
   static WTF::Optional<Resource::Type> GetResourceTypeFromAsAttribute(
       const String& as);
 
-  Resource* LinkPreloadedResourceForTesting();
+  Resource* GetResourceForTesting();
 
   DECLARE_TRACE();
 
  private:
+  class FinishObserver;
   LinkLoader(LinkLoaderClient*, RefPtr<WebTaskRunner>);
 
-  void LinkLoadTimerFired(TimerBase*);
-  void LinkLoadingErrorTimerFired(TimerBase*);
-  void CreateLinkPreloadResourceClient(Resource*);
+  void NotifyFinished();
 
+  Member<FinishObserver> finish_observer_;
   Member<LinkLoaderClient> client_;
 
-  TaskRunnerTimer<LinkLoader> link_load_timer_;
-  TaskRunnerTimer<LinkLoader> link_loading_error_timer_;
-
   Member<PrerenderHandle> prerender_;
-  Member<LinkPreloadResourceClient> link_preload_resource_client_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/LinkLoaderTest.cpp b/third_party/WebKit/Source/core/loader/LinkLoaderTest.cpp
index b6c2d5343..fe995f5f 100644
--- a/third_party/WebKit/Source/core/loader/LinkLoaderTest.cpp
+++ b/third_party/WebKit/Source/core/loader/LinkLoaderTest.cpp
@@ -125,7 +125,7 @@
   if (test_case.expecting_load &&
       test_case.priority != kResourceLoadPriorityUnresolved) {
     ASSERT_EQ(1, fetcher->CountPreloads());
-    Resource* resource = loader->LinkPreloadedResourceForTesting();
+    Resource* resource = loader->GetResourceForTesting();
     ASSERT_NE(resource, nullptr);
     EXPECT_TRUE(fetcher->ContainsAsPreload(resource));
     EXPECT_EQ(test_case.priority, resource->GetResourceRequest().Priority());
@@ -310,7 +310,7 @@
                      test_case.referrer_policy, href_url,
                      dummy_page_holder->GetDocument(), NetworkHintsMock());
     ASSERT_TRUE(dummy_page_holder->GetDocument().Fetcher());
-    Resource* resource = loader->GetResource();
+    Resource* resource = loader->GetResourceForTesting();
     if (test_case.expecting_load) {
       EXPECT_TRUE(resource);
     } else {
diff --git a/third_party/WebKit/Source/core/loader/resource/CSSStyleSheetResource.cpp b/third_party/WebKit/Source/core/loader/resource/CSSStyleSheetResource.cpp
index 1cb7788..66ff744 100644
--- a/third_party/WebKit/Source/core/loader/resource/CSSStyleSheetResource.cpp
+++ b/third_party/WebKit/Source/core/loader/resource/CSSStyleSheetResource.cpp
@@ -149,6 +149,8 @@
 }
 
 void CSSStyleSheetResource::CheckNotify() {
+  TriggerNotificationForFinishObservers();
+
   // Decode the data to find out the encoding and cache the decoded sheet text.
   if (Data())
     SetDecodedSheetText(DecodedText());
diff --git a/third_party/WebKit/Source/core/loader/resource/LinkPreloadResourceClients.cpp b/third_party/WebKit/Source/core/loader/resource/LinkPreloadResourceClients.cpp
deleted file mode 100644
index ea9e65cc..0000000
--- a/third_party/WebKit/Source/core/loader/resource/LinkPreloadResourceClients.cpp
+++ /dev/null
@@ -1,15 +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.
-
-#include "core/loader/resource/LinkPreloadResourceClients.h"
-
-#include "core/loader/LinkLoader.h"
-
-namespace blink {
-
-void LinkPreloadResourceClient::TriggerEvents(const Resource* resource) {
-  if (loader_)
-    loader_->TriggerEvents(resource);
-}
-}
diff --git a/third_party/WebKit/Source/core/loader/resource/LinkPreloadResourceClients.h b/third_party/WebKit/Source/core/loader/resource/LinkPreloadResourceClients.h
deleted file mode 100644
index a3e73d3..0000000
--- a/third_party/WebKit/Source/core/loader/resource/LinkPreloadResourceClients.h
+++ /dev/null
@@ -1,228 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef LinkPreloadResourceClients_h
-#define LinkPreloadResourceClients_h
-
-#include "core/loader/resource/CSSStyleSheetResource.h"
-#include "core/loader/resource/FontResource.h"
-#include "core/loader/resource/ImageResource.h"
-#include "core/loader/resource/ScriptResource.h"
-#include "core/loader/resource/StyleSheetResourceClient.h"
-#include "platform/loader/fetch/RawResource.h"
-#include "platform/loader/fetch/ResourceOwner.h"
-
-namespace blink {
-
-class LinkLoader;
-
-class LinkPreloadResourceClient
-    : public GarbageCollectedFinalized<LinkPreloadResourceClient> {
- public:
-  virtual ~LinkPreloadResourceClient() {}
-
-  void TriggerEvents(const Resource*);
-  virtual Resource* GetResource() = 0;
-  virtual void Clear() = 0;
-
-  DEFINE_INLINE_VIRTUAL_TRACE() { visitor->Trace(loader_); }
-
- protected:
-  explicit LinkPreloadResourceClient(LinkLoader* loader) : loader_(loader) {
-    DCHECK(loader);
-  }
-
- private:
-  Member<LinkLoader> loader_;
-};
-
-class LinkPreloadScriptResourceClient
-    : public LinkPreloadResourceClient,
-      public ResourceOwner<ScriptResource, ScriptResourceClient> {
-  USING_GARBAGE_COLLECTED_MIXIN(LinkPreloadScriptResourceClient);
-
- public:
-  static LinkPreloadScriptResourceClient* Create(LinkLoader* loader,
-                                                 ScriptResource* resource) {
-    return new LinkPreloadScriptResourceClient(loader, resource);
-  }
-
-  virtual String DebugName() const { return "LinkPreloadScript"; }
-  virtual ~LinkPreloadScriptResourceClient() {}
-
-  Resource* GetResource() override {
-    return ResourceOwner<ScriptResource>::GetResource();
-  }
-  void Clear() override { ClearResource(); }
-
-  void NotifyFinished(Resource* resource) override {
-    DCHECK_EQ(this->GetResource(), resource);
-    TriggerEvents(resource);
-  }
-
-  DEFINE_INLINE_VIRTUAL_TRACE() {
-    LinkPreloadResourceClient::Trace(visitor);
-    ResourceOwner<ScriptResource, ScriptResourceClient>::Trace(visitor);
-  }
-
- private:
-  LinkPreloadScriptResourceClient(LinkLoader* loader, ScriptResource* resource)
-      : LinkPreloadResourceClient(loader) {
-    SetResource(resource, Resource::kDontMarkAsReferenced);
-  }
-};
-
-class LinkPreloadStyleResourceClient
-    : public LinkPreloadResourceClient,
-      public ResourceOwner<CSSStyleSheetResource, StyleSheetResourceClient> {
-  USING_GARBAGE_COLLECTED_MIXIN(LinkPreloadStyleResourceClient);
-
- public:
-  static LinkPreloadStyleResourceClient* Create(
-      LinkLoader* loader,
-      CSSStyleSheetResource* resource) {
-    return new LinkPreloadStyleResourceClient(loader, resource);
-  }
-
-  virtual String DebugName() const { return "LinkPreloadStyle"; }
-  virtual ~LinkPreloadStyleResourceClient() {}
-
-  Resource* GetResource() override {
-    return ResourceOwner<CSSStyleSheetResource>::GetResource();
-  }
-  void Clear() override { ClearResource(); }
-
-  void SetCSSStyleSheet(const String&,
-                        const KURL&,
-                        ReferrerPolicy,
-                        const String&,
-                        const CSSStyleSheetResource* resource) override {
-    DCHECK_EQ(this->GetResource(), resource);
-    TriggerEvents(static_cast<const Resource*>(resource));
-  }
-
-  DEFINE_INLINE_VIRTUAL_TRACE() {
-    LinkPreloadResourceClient::Trace(visitor);
-    ResourceOwner<CSSStyleSheetResource, StyleSheetResourceClient>::Trace(
-        visitor);
-  }
-
- private:
-  LinkPreloadStyleResourceClient(LinkLoader* loader,
-                                 CSSStyleSheetResource* resource)
-      : LinkPreloadResourceClient(loader) {
-    SetResource(resource, Resource::kDontMarkAsReferenced);
-  }
-};
-
-class LinkPreloadImageResourceClient : public LinkPreloadResourceClient,
-                                       public ResourceOwner<ImageResource> {
-  USING_GARBAGE_COLLECTED_MIXIN(LinkPreloadImageResourceClient);
-
- public:
-  static LinkPreloadImageResourceClient* Create(LinkLoader* loader,
-                                                ImageResource* resource) {
-    return new LinkPreloadImageResourceClient(loader, resource);
-  }
-
-  virtual String DebugName() const { return "LinkPreloadImage"; }
-  virtual ~LinkPreloadImageResourceClient() {}
-
-  Resource* GetResource() override {
-    return ResourceOwner<ImageResource>::GetResource();
-  }
-  void Clear() override { ClearResource(); }
-
-  void NotifyFinished(Resource* resource) override {
-    DCHECK_EQ(this->GetResource(), ToImageResource(resource));
-    TriggerEvents(resource);
-  }
-
-  DEFINE_INLINE_VIRTUAL_TRACE() {
-    LinkPreloadResourceClient::Trace(visitor);
-    ResourceOwner<ImageResource>::Trace(visitor);
-  }
-
- private:
-  LinkPreloadImageResourceClient(LinkLoader* loader, ImageResource* resource)
-      : LinkPreloadResourceClient(loader) {
-    SetResource(resource, Resource::kDontMarkAsReferenced);
-  }
-};
-
-class LinkPreloadFontResourceClient
-    : public LinkPreloadResourceClient,
-      public ResourceOwner<FontResource, FontResourceClient> {
-  USING_GARBAGE_COLLECTED_MIXIN(LinkPreloadFontResourceClient);
-
- public:
-  static LinkPreloadFontResourceClient* Create(LinkLoader* loader,
-                                               FontResource* resource) {
-    return new LinkPreloadFontResourceClient(loader, resource);
-  }
-
-  virtual String DebugName() const { return "LinkPreloadFont"; }
-  virtual ~LinkPreloadFontResourceClient() {}
-
-  Resource* GetResource() override {
-    return ResourceOwner<FontResource>::GetResource();
-  }
-  void Clear() override { ClearResource(); }
-
-  void NotifyFinished(Resource* resource) override {
-    DCHECK_EQ(this->GetResource(), ToFontResource(resource));
-    TriggerEvents(resource);
-  }
-
-  DEFINE_INLINE_VIRTUAL_TRACE() {
-    LinkPreloadResourceClient::Trace(visitor);
-    ResourceOwner<FontResource, FontResourceClient>::Trace(visitor);
-  }
-
- private:
-  LinkPreloadFontResourceClient(LinkLoader* loader, FontResource* resource)
-      : LinkPreloadResourceClient(loader) {
-    SetResource(resource, Resource::kDontMarkAsReferenced);
-  }
-};
-
-class LinkPreloadRawResourceClient
-    : public LinkPreloadResourceClient,
-      public ResourceOwner<RawResource, RawResourceClient> {
-  USING_GARBAGE_COLLECTED_MIXIN(LinkPreloadRawResourceClient);
-
- public:
-  static LinkPreloadRawResourceClient* Create(LinkLoader* loader,
-                                              RawResource* resource) {
-    return new LinkPreloadRawResourceClient(loader, resource);
-  }
-
-  virtual String DebugName() const { return "LinkPreloadRaw"; }
-  virtual ~LinkPreloadRawResourceClient() {}
-
-  Resource* GetResource() override {
-    return ResourceOwner<RawResource>::GetResource();
-  }
-  void Clear() override { ClearResource(); }
-
-  void NotifyFinished(Resource* resource) override {
-    DCHECK_EQ(this->GetResource(), ToRawResource(resource));
-    TriggerEvents(resource);
-  }
-
-  DEFINE_INLINE_VIRTUAL_TRACE() {
-    LinkPreloadResourceClient::Trace(visitor);
-    ResourceOwner<RawResource, RawResourceClient>::Trace(visitor);
-  }
-
- private:
-  LinkPreloadRawResourceClient(LinkLoader* loader, RawResource* resource)
-      : LinkPreloadResourceClient(loader) {
-    SetResource(resource, Resource::kDontMarkAsReferenced);
-  }
-};
-
-}  // namespace blink
-
-#endif  // LinkPreloadResourceClients_h
diff --git a/third_party/WebKit/Source/core/loader/resource/XSLStyleSheetResource.cpp b/third_party/WebKit/Source/core/loader/resource/XSLStyleSheetResource.cpp
index 4ee7c443..f222f060 100644
--- a/third_party/WebKit/Source/core/loader/resource/XSLStyleSheetResource.cpp
+++ b/third_party/WebKit/Source/core/loader/resource/XSLStyleSheetResource.cpp
@@ -88,6 +88,8 @@
 }
 
 void XSLStyleSheetResource::CheckNotify() {
+  TriggerNotificationForFinishObservers();
+
   if (Data())
     sheet_ = DecodedText();
 
diff --git a/third_party/WebKit/Source/core/page/BUILD.gn b/third_party/WebKit/Source/core/page/BUILD.gn
index b210479..2e1a05dd 100644
--- a/third_party/WebKit/Source/core/page/BUILD.gn
+++ b/third_party/WebKit/Source/core/page/BUILD.gn
@@ -26,6 +26,8 @@
     "DragState.h",
     "EditorClient.h",
     "EventWithHitTestResults.h",
+    "ExternalPopupMenu.cpp",
+    "ExternalPopupMenu.h",
     "FocusChangedObserver.cpp",
     "FocusChangedObserver.h",
     "FocusController.cpp",
@@ -52,6 +54,8 @@
     "PageWidgetDelegate.h",
     "PointerLockController.cpp",
     "PointerLockController.h",
+    "PopupMenuImpl.cpp",
+    "PopupMenuImpl.h",
     "PopupOpeningObserver.h",
     "PrintContext.cpp",
     "PrintContext.h",
diff --git a/third_party/WebKit/Source/web/ExternalPopupMenu.cpp b/third_party/WebKit/Source/core/page/ExternalPopupMenu.cpp
similarity index 95%
rename from third_party/WebKit/Source/web/ExternalPopupMenu.cpp
rename to third_party/WebKit/Source/core/page/ExternalPopupMenu.cpp
index e1cb3c49..9b78c24 100644
--- a/third_party/WebKit/Source/web/ExternalPopupMenu.cpp
+++ b/third_party/WebKit/Source/core/page/ExternalPopupMenu.cpp
@@ -28,7 +28,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "web/ExternalPopupMenu.h"
+#include "core/page/ExternalPopupMenu.h"
 
 #include "core/dom/NodeComputedStyle.h"
 #include "core/dom/TaskRunnerHelper.h"
@@ -53,6 +53,9 @@
 #include "public/web/WebMenuItemInfo.h"
 #include "public/web/WebPopupMenuInfo.h"
 #include "public/web/WebView.h"
+#if OS(MACOSX)
+#include "core/page/ChromeClient.h"
+#endif
 
 namespace blink {
 
@@ -103,19 +106,22 @@
     IntRect rect_in_viewport = local_frame_->View()->ContentsToViewport(rect);
     web_external_popup_menu_->Show(rect_in_viewport);
     return true;
-  } else {
-    // The client might refuse to create a popup (when there is already one
-    // pending to be shown for example).
-    DidCancel();
-    return false;
   }
+
+  // The client might refuse to create a popup (when there is already one
+  // pending to be shown for example).
+  DidCancel();
+  return false;
 }
 
 void ExternalPopupMenu::Show() {
   if (!ShowInternal())
     return;
 #if OS(MACOSX)
-  const WebInputEvent* current_event = WebViewBase::CurrentInputEvent();
+  // TODO(sashab): Change this back to WebViewBase::CurrentInputEvent() once
+  // WebViewImpl is in core/.
+  const WebInputEvent* current_event =
+      local_frame_->GetPage()->GetChromeClient().GetCurrentInputEvent();
   if (current_event && current_event->GetType() == WebInputEvent::kMouseDown) {
     synthetic_event_ = WTF::WrapUnique(new WebMouseEvent);
     *synthetic_event_ = *static_cast<const WebMouseEvent*>(current_event);
diff --git a/third_party/WebKit/Source/web/ExternalPopupMenu.h b/third_party/WebKit/Source/core/page/ExternalPopupMenu.h
similarity index 94%
rename from third_party/WebKit/Source/web/ExternalPopupMenu.h
rename to third_party/WebKit/Source/core/page/ExternalPopupMenu.h
index aa6d8019..67469e27 100644
--- a/third_party/WebKit/Source/web/ExternalPopupMenu.h
+++ b/third_party/WebKit/Source/core/page/ExternalPopupMenu.h
@@ -32,13 +32,13 @@
 #define ExternalPopupMenu_h
 
 #include <memory>
+#include "core/CoreExport.h"
 #include "platform/PopupMenu.h"
 #include "platform/Timer.h"
 #include "platform/wtf/Compiler.h"
 #include "public/platform/WebCanvas.h"
 #include "public/platform/WebScrollbar.h"
 #include "public/web/WebExternalPopupMenuClient.h"
-#include "web/WebExport.h"
 
 namespace blink {
 
@@ -51,8 +51,8 @@
 
 // The ExternalPopupMenu connects the actual implementation of the popup menu
 // to the WebCore popup menu.
-class WEB_EXPORT ExternalPopupMenu final : NON_EXPORTED_BASE(public PopupMenu),
-                                           public WebExternalPopupMenuClient {
+class CORE_EXPORT ExternalPopupMenu final : NON_EXPORTED_BASE(public PopupMenu),
+                                            public WebExternalPopupMenuClient {
  public:
   ExternalPopupMenu(LocalFrame&, HTMLSelectElement&, WebView&);
   ~ExternalPopupMenu() override;
diff --git a/third_party/WebKit/Source/web/PopupMenuImpl.cpp b/third_party/WebKit/Source/core/page/PopupMenuImpl.cpp
similarity index 98%
rename from third_party/WebKit/Source/web/PopupMenuImpl.cpp
rename to third_party/WebKit/Source/core/page/PopupMenuImpl.cpp
index 0cdfa6d9..fe25f2ef 100644
--- a/third_party/WebKit/Source/web/PopupMenuImpl.cpp
+++ b/third_party/WebKit/Source/core/page/PopupMenuImpl.cpp
@@ -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 "web/PopupMenuImpl.h"
+#include "core/page/PopupMenuImpl.h"
 
 #include "core/HTMLNames.h"
 #include "core/css/CSSFontSelector.h"
@@ -366,9 +366,10 @@
     AddProperty("fontSize", font_description.ComputedPixelSize(), data);
   }
   // Our UA stylesheet has font-weight:normal for OPTION.
-  if (kFontWeightNormal != font_description.Weight())
+  if (kFontWeightNormal != font_description.Weight()) {
     AddProperty("fontWeight",
                 String(FontWeightToString(font_description.Weight())), data);
+  }
   if (base_font.Family() != font_description.Family()) {
     PagePopupClient::AddString("fontFamily: [\n", data);
     for (const FontFamily* f = &font_description.Family(); f; f = f->Next()) {
@@ -378,17 +379,19 @@
     }
     PagePopupClient::AddString("],\n", data);
   }
-  if (base_font.Style() != font_description.Style())
+  if (base_font.Style() != font_description.Style()) {
     AddProperty("fontStyle",
                 String(FontStyleToString(font_description.Style())), data);
+  }
 
   if (base_font.VariantCaps() != font_description.VariantCaps() &&
       font_description.VariantCaps() == FontDescription::kSmallCaps)
     AddProperty("fontVariant", String("small-caps"), data);
 
-  if (base_style.TextTransform() != style->TextTransform())
+  if (base_style.TextTransform() != style->TextTransform()) {
     AddProperty("textTransform",
                 String(TextTransformToString(style->TextTransform())), data);
+  }
 
   PagePopupClient::AddString("},\n", data);
 }
diff --git a/third_party/WebKit/Source/web/PopupMenuImpl.h b/third_party/WebKit/Source/core/page/PopupMenuImpl.h
similarity index 87%
rename from third_party/WebKit/Source/web/PopupMenuImpl.h
rename to third_party/WebKit/Source/core/page/PopupMenuImpl.h
index 4ddebf4..3f1c13fa 100644
--- a/third_party/WebKit/Source/web/PopupMenuImpl.h
+++ b/third_party/WebKit/Source/core/page/PopupMenuImpl.h
@@ -5,6 +5,7 @@
 #ifndef PopupMenuImpl_h
 #define PopupMenuImpl_h
 
+#include "core/CoreExport.h"
 #include "core/page/PagePopupClient.h"
 #include "platform/PopupMenu.h"
 
@@ -18,7 +19,9 @@
 class HTMLOptionElement;
 class HTMLSelectElement;
 
-class PopupMenuImpl final : public PopupMenu, public PagePopupClient {
+// TODO(sashab): Merge this class with its parent (PopupMenu).
+class CORE_EXPORT PopupMenuImpl final : NON_EXPORTED_BASE(public PopupMenu),
+                                        public PagePopupClient {
  public:
   static PopupMenuImpl* Create(ChromeClient*, HTMLSelectElement&);
   ~PopupMenuImpl() override;
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
index 09f65a3..b2c8e893 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
@@ -99,6 +99,8 @@
    */
   backgroundColor() {
     var bgColors = Network.NetworkNode._themedBackgroundColors();
+    if (this.selected)
+      return /** @type {string} */ (bgColors.Selected.asString(Common.Color.Format.HEX));
     var color = this.isStriped() ? bgColors.Stripe : bgColors.Default;
     if (this.isNavigationRequest())
       color = color.blendWith(bgColors.Navigation);
@@ -108,8 +110,6 @@
       color = color.blendWith(bgColors.InitiatorPath);
     if (this.isOnInitiatedPath())
       color = color.blendWith(bgColors.InitiatedPath);
-    if (this.selected)
-      color = color.blendWith(bgColors.Selected);
 
     return /** @type {string} */ (color.asString(Common.Color.Format.HEX));
   }
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 8270c73..12ad336 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
@@ -1274,6 +1274,7 @@
   showPane(parent) {
     this.show(parent);
     parent.classList.add('tinted');
+    this._stopButton.focus();
   }
 
   /**
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 3899a4b..097c516a 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
@@ -84,7 +84,7 @@
     this._splitWidget.setSidebarWidget(this._detailsView);
     this._splitWidget.hideSidebar();
     this._splitWidget.show(this.element);
-    this._splitWidget.addEventListener(UI.SplitWidget.Events.ShowModeChanged, this._updateDetailsForSelection, this);
+    this._splitWidget.addEventListener(UI.SplitWidget.Events.ShowModeChanged, this._onShowModeChanged, this);
 
     /** @type {?TimelineModel.TimelineProfileTree.Node|undefined} */
     this._lastSelectedNode;
@@ -352,6 +352,13 @@
     }
   }
 
+  _onShowModeChanged() {
+    if (this._splitWidget.showMode() === UI.SplitWidget.ShowMode.OnlyMain)
+      return;
+    this._lastSelectedNode = undefined;
+    this._updateDetailsForSelection();
+  }
+
   _updateDetailsForSelection() {
     var selectedNode = this._dataGrid.selectedNode ?
         /** @type {!Timeline.TimelineTreeView.TreeGridNode} */ (this._dataGrid.selectedNode)._profileNode :
@@ -363,10 +370,10 @@
       return;
     this._detailsView.detachChildWidgets();
     this._detailsView.element.removeChildren();
-    if (!selectedNode || !this._showDetailsForNode(selectedNode)) {
-      var banner = this._detailsView.element.createChild('div', 'full-widget-dimmed-banner');
-      banner.createTextChild(Common.UIString('Select item for details.'));
-    }
+    if (selectedNode && this._showDetailsForNode(selectedNode))
+      return;
+    var banner = this._detailsView.element.createChild('div', 'full-widget-dimmed-banner');
+    banner.createTextChild(Common.UIString('Select item for details.'));
   }
 
   /**
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 2c66eae..729a8fc 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/timelinePanel.css
@@ -623,11 +623,12 @@
 }
 
 .timeline-stack-view-header {
-    height: 26px;
+    height: 27px;
     background-color: white;
     padding: 6px 10px;
     color: #5a5a5a;
     white-space: nowrap;
+    border-bottom: 1px solid #dadada;
 }
 
 .timeline-landing-page {
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.h b/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.h
index d6e2aef..9097193fb 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.h
+++ b/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.h
@@ -125,7 +125,7 @@
 
   // used for objects without backing elements
   AXObjectImpl* GetOrCreate(AccessibilityRole);
-  AXObjectImpl* GetOrCreate(LayoutObject*);
+  AXObjectImpl* GetOrCreate(LayoutObject*) override;
   AXObjectImpl* GetOrCreate(Node*);
   AXObjectImpl* GetOrCreate(AbstractInlineTextBox*);
 
diff --git a/third_party/WebKit/Source/modules/exported/WebAXObject.cpp b/third_party/WebKit/Source/modules/exported/WebAXObject.cpp
index 52efb1f..088e3a3a 100644
--- a/third_party/WebKit/Source/modules/exported/WebAXObject.cpp
+++ b/third_party/WebKit/Source/modules/exported/WebAXObject.cpp
@@ -1554,7 +1554,7 @@
 WebAXObject WebAXObject::FromWebNode(const WebNode& web_node) {
   WebDocument web_document = web_node.GetDocument();
   const Document* doc = web_document.ConstUnwrap<Document>();
-  AXObjectCacheBase* cache = ToAXObjectCacheBase(doc->ExistingAXObjectCache());
+  AXObjectCacheImpl* cache = ToAXObjectCacheImpl(doc->ExistingAXObjectCache());
   const Node* node = web_node.ConstUnwrap<Node>();
   return cache ? WebAXObject(cache->Get(node)) : WebAXObject();
 }
diff --git a/third_party/WebKit/Source/modules/modules_idl_files.gni b/third_party/WebKit/Source/modules/modules_idl_files.gni
index 25f7705..f4c23b11 100644
--- a/third_party/WebKit/Source/modules/modules_idl_files.gni
+++ b/third_party/WebKit/Source/modules/modules_idl_files.gni
@@ -477,6 +477,7 @@
                     "payments/AndroidPayMethodData.idl",
                     "payments/AndroidPayTokenization.idl",
                     "payments/BasicCardRequest.idl",
+                    "payments/ImageObject.idl",
                     "payments/PaymentAppResponse.idl",
                     "payments/PaymentRequestEventInit.idl",
                     "payments/PaymentCurrencyAmount.idl",
diff --git a/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtilsClientImpl.h b/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtilsClientImpl.h
index f6409f1..ae823f1 100644
--- a/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtilsClientImpl.h
+++ b/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtilsClientImpl.h
@@ -14,8 +14,9 @@
 
 class WebLocalFrameBase;
 
+// TODO(sashab): Merge this class with its parent (NavigatorContentUtilsClient).
 class MODULES_EXPORT NavigatorContentUtilsClientImpl final
-    : public NON_EXPORTED_BASE(NavigatorContentUtilsClient) {
+    : NON_EXPORTED_BASE(public NavigatorContentUtilsClient) {
  public:
   static NavigatorContentUtilsClientImpl* Create(WebLocalFrameBase*);
   ~NavigatorContentUtilsClientImpl() override {}
diff --git a/third_party/WebKit/Source/modules/payments/ImageObject.idl b/third_party/WebKit/Source/modules/payments/ImageObject.idl
new file mode 100644
index 0000000..ac8f460
--- /dev/null
+++ b/third_party/WebKit/Source/modules/payments/ImageObject.idl
@@ -0,0 +1,16 @@
+// 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.
+
+// https://github.com/w3c/payment-handler/pull/174/files/6e6768c423e24719cb0e592cd98614f052e52a78
+
+dictionary ImageObject {
+    // Note that the src could be relative path to the service worker
+    // scope.
+    required USVString src;
+
+    // TODO(gogerald): Below two attributes have not been used for now.
+    // Enable them when necessary.
+    // DOMString sizes;
+    // DOMString type;
+};
\ No newline at end of file
diff --git a/third_party/WebKit/Source/modules/payments/PaymentInstrument.idl b/third_party/WebKit/Source/modules/payments/PaymentInstrument.idl
index 9f57261..ad09a3376 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentInstrument.idl
+++ b/third_party/WebKit/Source/modules/payments/PaymentInstrument.idl
@@ -2,15 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// https://w3c.github.io/webpayments-payment-apps-api/#payment-instrument
+// https://w3c.github.io/payment-handler/#paymentinstrument-dictionary
 
 dictionary PaymentInstrument {
     required DOMString name;
-    // TODO(zino): PaymentInstrument should have icons attribute.
-    // The spec[1] defines it as a sequence of ImageObject but its definition
-    // is not clear yet.
-    // Please see: https://github.com/w3c/webpayments-payment-apps-api/issues/69
-    // sequence<ImageObject> icons;
+    sequence<ImageObject> icons;
     sequence<DOMString> enabledMethods;
     object capabilities;
 };
diff --git a/third_party/WebKit/Source/modules/payments/PaymentInstruments.cpp b/third_party/WebKit/Source/modules/payments/PaymentInstruments.cpp
index 8905048b..2da969b6 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentInstruments.cpp
+++ b/third_party/WebKit/Source/modules/payments/PaymentInstruments.cpp
@@ -41,6 +41,11 @@
       resolver->Reject(DOMException::Create(kInvalidStateError,
                                             "Storage operation is failed"));
       return true;
+    case payments::mojom::blink::PaymentHandlerStatus::
+        FETCH_INSTRUMENT_ICON_FAILED:
+      resolver->Reject(DOMException::Create(
+          kNotFoundError, "Fetch or decode instrument icon failed"));
+      return true;
   }
   NOTREACHED();
   return false;
@@ -139,6 +144,22 @@
   payments::mojom::blink::PaymentInstrumentPtr instrument =
       payments::mojom::blink::PaymentInstrument::New();
   instrument->name = details.hasName() ? details.name() : WTF::g_empty_string;
+  if (details.hasIcons()) {
+    ExecutionContext* context = ExecutionContext::From(script_state);
+    for (const ImageObject image_object : details.icons()) {
+      KURL parsed_url = context->CompleteURL(image_object.src());
+      if (!parsed_url.IsValid() || !parsed_url.ProtocolIsInHTTPFamily()) {
+        resolver->Reject(V8ThrowException::CreateTypeError(
+            script_state->GetIsolate(),
+            "'" + image_object.src() + "' is not a valid URL."));
+        return promise;
+      }
+
+      instrument->icons.push_back(payments::mojom::blink::ImageObject::New());
+      instrument->icons.back()->src = parsed_url;
+    }
+  }
+
   if (details.hasEnabledMethods()) {
     instrument->enabled_methods = details.enabledMethods();
   }
@@ -200,6 +221,15 @@
     return;
   PaymentInstrument instrument;
   instrument.setName(stored_instrument->name);
+
+  HeapVector<ImageObject> icons;
+  for (const auto& icon : stored_instrument->icons) {
+    ImageObject image_object;
+    image_object.setSrc(icon->src.GetString());
+    icons.emplace_back(image_object);
+  }
+  instrument.setIcons(icons);
+
   Vector<String> enabled_methods;
   for (const auto& method : stored_instrument->enabled_methods) {
     enabled_methods.push_back(method);
diff --git a/third_party/WebKit/Source/platform/PopupMenu.h b/third_party/WebKit/Source/platform/PopupMenu.h
index 58f2159..25b6aca 100644
--- a/third_party/WebKit/Source/platform/PopupMenu.h
+++ b/third_party/WebKit/Source/platform/PopupMenu.h
@@ -26,6 +26,7 @@
 
 namespace blink {
 
+// TODO(sashab): Move PopupMenu to core/page.
 class PopupMenu : public GarbageCollectedFinalized<PopupMenu> {
  public:
   virtual ~PopupMenu() {}
diff --git a/third_party/WebKit/Source/platform/loader/BUILD.gn b/third_party/WebKit/Source/platform/loader/BUILD.gn
index 62e39ebc..60842f9c 100644
--- a/third_party/WebKit/Source/platform/loader/BUILD.gn
+++ b/third_party/WebKit/Source/platform/loader/BUILD.gn
@@ -51,6 +51,7 @@
     "fetch/ResourceError.h",
     "fetch/ResourceFetcher.cpp",
     "fetch/ResourceFetcher.h",
+    "fetch/ResourceFinishObserver.h",
     "fetch/ResourceLoadInfo.h",
     "fetch/ResourceLoadPriority.h",
     "fetch/ResourceLoadTiming.cpp",
diff --git a/third_party/WebKit/Source/platform/loader/fetch/FetchUtils.cpp b/third_party/WebKit/Source/platform/loader/fetch/FetchUtils.cpp
index 5580e6d..b1c5137 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/FetchUtils.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/FetchUtils.cpp
@@ -93,13 +93,16 @@
   // Data Saver feature is enabled.
   // Treat inspector headers as a simple headers, since they are added by blink
   // when the inspector is open.
+  // Treat 'Intervention' as a simple header, since it is added by Chrome when
+  // an intervention is (or may be) applied.
 
   if (EqualIgnoringASCIICase(name, "accept") ||
       EqualIgnoringASCIICase(name, "accept-language") ||
       EqualIgnoringASCIICase(name, "content-language") ||
       EqualIgnoringASCIICase(
           name, HTTPNames::X_DevTools_Emulate_Network_Conditions_Client_Id) ||
-      EqualIgnoringASCIICase(name, "save-data"))
+      EqualIgnoringASCIICase(name, "save-data") ||
+      EqualIgnoringASCIICase(name, "intervention"))
     return true;
 
   if (EqualIgnoringASCIICase(name, "content-type"))
diff --git a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
index d67a8fa..0e554ea5 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
@@ -42,6 +42,7 @@
 #include "platform/loader/fetch/MemoryCache.h"
 #include "platform/loader/fetch/ResourceClient.h"
 #include "platform/loader/fetch/ResourceClientWalker.h"
+#include "platform/loader/fetch/ResourceFinishObserver.h"
 #include "platform/loader/fetch/ResourceLoader.h"
 #include "platform/network/HTTPParsers.h"
 #include "platform/scheduler/child/web_scheduler.h"
@@ -58,6 +59,16 @@
 
 namespace blink {
 
+namespace {
+
+void NotifyFinishObservers(
+    HeapHashSet<WeakMember<ResourceFinishObserver>> observers) {
+  for (const auto& observer : observers)
+    observer->NotifyFinished();
+}
+
+}  // namespace
+
 // These response headers are not copied from a revalidated response to the
 // cached response headers. For compatibility, this list is based on Chromium's
 // net/http/http_response_headers.cc.
@@ -302,6 +313,7 @@
   visitor->Trace(clients_);
   visitor->Trace(clients_awaiting_callback_);
   visitor->Trace(finished_clients_);
+  visitor->Trace(finish_observers_);
   MemoryCoordinatorClient::Trace(visitor);
 }
 
@@ -316,6 +328,8 @@
   if (IsLoading())
     return;
 
+  TriggerNotificationForFinishObservers();
+
   ResourceClientWalker<ResourceClient> w(clients_);
   while (ResourceClient* c = w.Next()) {
     MarkClientFinished(c);
@@ -356,6 +370,18 @@
   encoded_size_memory_usage_ = 0;
 }
 
+void Resource::TriggerNotificationForFinishObservers() {
+  Platform::Current()
+      ->CurrentThread()
+      ->Scheduler()
+      ->LoadingTaskRunner()
+      ->PostTask(BLINK_FROM_HERE, WTF::Bind(&NotifyFinishObservers,
+                                            std::move(finish_observers_)));
+
+  finish_observers_.clear();
+  DidRemoveClientOrObserver();
+}
+
 void Resource::SetDataBufferingPolicy(
     DataBufferingPolicy data_buffering_policy) {
   options_.data_buffering_policy = data_buffering_policy;
@@ -711,6 +737,24 @@
   DidRemoveClientOrObserver();
 }
 
+void Resource::AddFinishObserver(ResourceFinishObserver* client,
+                                 PreloadReferencePolicy policy) {
+  CHECK(!is_add_remove_client_prohibited_);
+  DCHECK(!finish_observers_.Contains(client));
+
+  WillAddClientOrObserver(policy);
+  finish_observers_.insert(client);
+  if (IsLoaded())
+    TriggerNotificationForFinishObservers();
+}
+
+void Resource::RemoveFinishObserver(ResourceFinishObserver* client) {
+  CHECK(!is_add_remove_client_prohibited_);
+
+  finish_observers_.erase(client);
+  DidRemoveClientOrObserver();
+}
+
 void Resource::DidRemoveClientOrObserver() {
   if (!HasClientsOrObservers() && is_alive_) {
     is_alive_ = false;
diff --git a/third_party/WebKit/Source/platform/loader/fetch/Resource.h b/third_party/WebKit/Source/platform/loader/fetch/Resource.h
index 537d2954..7c07f6e 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/Resource.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/Resource.h
@@ -52,6 +52,7 @@
 class FetchParameters;
 class ResourceClient;
 class ResourceFetcher;
+class ResourceFinishObserver;
 class ResourceTimingInfo;
 class ResourceLoader;
 class SecurityOrigin;
@@ -157,6 +158,10 @@
   void AddClient(ResourceClient*, PreloadReferencePolicy = kMarkAsReferenced);
   void RemoveClient(ResourceClient*);
 
+  void AddFinishObserver(ResourceFinishObserver*,
+                         PreloadReferencePolicy = kMarkAsReferenced);
+  void RemoveFinishObserver(ResourceFinishObserver*);
+
   enum PreloadResult {
     kPreloadNotReferenced,
     kPreloadReferenced,
@@ -363,7 +368,7 @@
 
   virtual bool HasClientsOrObservers() const {
     return !clients_.IsEmpty() || !clients_awaiting_callback_.IsEmpty() ||
-           !finished_clients_.IsEmpty();
+           !finished_clients_.IsEmpty() || !finish_observers_.IsEmpty();
   }
   virtual void DestroyDecodedDataForFailedRevalidation() {}
 
@@ -413,6 +418,8 @@
   SharedBuffer* Data() const { return data_.Get(); }
   void ClearData();
 
+  void TriggerNotificationForFinishObservers();
+
  private:
   class CachedMetadataHandlerImpl;
   class ServiceWorkerResponseCachedMetadataHandler;
@@ -474,6 +481,7 @@
   HeapHashCountedSet<WeakMember<ResourceClient>> clients_;
   HeapHashCountedSet<WeakMember<ResourceClient>> clients_awaiting_callback_;
   HeapHashCountedSet<WeakMember<ResourceClient>> finished_clients_;
+  HeapHashSet<WeakMember<ResourceFinishObserver>> finish_observers_;
 
   ResourceLoaderOptions options_;
 
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceClient.h b/third_party/WebKit/Source/platform/loader/fetch/ResourceClient.h
index f2b238c0..d1eadea 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceClient.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceClient.h
@@ -61,6 +61,7 @@
  protected:
   ResourceClient() {}
 };
+
 }  // namespace blink
 
 #endif
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceFinishObserver.h b/third_party/WebKit/Source/platform/loader/fetch/ResourceFinishObserver.h
new file mode 100644
index 0000000..404343e
--- /dev/null
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceFinishObserver.h
@@ -0,0 +1,38 @@
+// 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 ResourceFinishObserver_h
+#define ResourceFinishObserver_h
+
+#include "platform/PlatformExport.h"
+#include "platform/heap/Handle.h"
+#include "platform/wtf/text/WTFString.h"
+
+namespace blink {
+
+// ResourceFinishObserver is different from ResourceClient in several ways.
+//  - NotifyFinished is dispatched asynchronously.
+//  - ResourceFinishObservers will be removed from Resource when the load
+//  finishes. - This class is not intended to be "subclassed" per each Resource
+//  subclass.
+//    There is no ImageResourceFinishObserver, for example.
+// ResourceFinishObserver should be quite simple. All notifications must be
+// notified AFTER the loading finishes.
+class PLATFORM_EXPORT ResourceFinishObserver : public GarbageCollectedMixin {
+ public:
+  virtual ~ResourceFinishObserver() = default;
+
+  // Called asynchronously when loading finishes.
+  // Note that this can be dispatched after removing |this| client from a
+  // Resource, because of the asynchronicity.
+  virtual void NotifyFinished() = 0;
+  // Name for debugging
+  virtual String DebugName() const = 0;
+
+  DEFINE_INLINE_VIRTUAL_TRACE() {}
+};
+
+}  // namespace blink
+
+#endif  // ResourceFinishObserver_h
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceOwner.h b/third_party/WebKit/Source/platform/loader/fetch/ResourceOwner.h
index cd607ee..339acf8 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceOwner.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceOwner.h
@@ -56,9 +56,7 @@
  protected:
   ResourceOwner() {}
 
-  void SetResource(
-      ResourceType*,
-      Resource::PreloadReferencePolicy = Resource::kMarkAsReferenced);
+  void SetResource(ResourceType*);
   void ClearResource() { SetResource(nullptr); }
 
  private:
@@ -66,9 +64,7 @@
 };
 
 template <class R, class C>
-inline void ResourceOwner<R, C>::SetResource(
-    R* new_resource,
-    Resource::PreloadReferencePolicy preload_reference_policy) {
+inline void ResourceOwner<R, C>::SetResource(R* new_resource) {
   if (new_resource == resource_)
     return;
 
@@ -79,7 +75,7 @@
 
   if (new_resource) {
     resource_ = new_resource;
-    resource_->AddClient(this, preload_reference_policy);
+    resource_->AddClient(this);
   }
 }
 
diff --git a/third_party/WebKit/Source/web/BUILD.gn b/third_party/WebKit/Source/web/BUILD.gn
index 3c11a1b2..3994284 100644
--- a/third_party/WebKit/Source/web/BUILD.gn
+++ b/third_party/WebKit/Source/web/BUILD.gn
@@ -43,10 +43,6 @@
     "DedicatedWorkerMessagingProxyProviderImpl.h",
     "EditorClientImpl.cpp",
     "EditorClientImpl.h",
-    "ExternalDateTimeChooser.cpp",
-    "ExternalDateTimeChooser.h",
-    "ExternalPopupMenu.cpp",
-    "ExternalPopupMenu.h",
     "InspectorOverlayAgent.cpp",
     "InspectorOverlayAgent.h",
     "LocalFrameClientImpl.cpp",
@@ -55,8 +51,6 @@
     "MediaKeysClientImpl.h",
     "PageOverlay.cpp",
     "PageOverlay.h",
-    "PopupMenuImpl.cpp",
-    "PopupMenuImpl.h",
     "PrerendererClientImpl.cpp",
     "PrerendererClientImpl.h",
     "ServiceWorkerGlobalScopeClientImpl.cpp",
diff --git a/third_party/WebKit/Source/web/ChromeClientImpl.cpp b/third_party/WebKit/Source/web/ChromeClientImpl.cpp
index b3f87fa..9a4be596 100644
--- a/third_party/WebKit/Source/web/ChromeClientImpl.cpp
+++ b/third_party/WebKit/Source/web/ChromeClientImpl.cpp
@@ -55,6 +55,7 @@
 #include "core/html/forms/DateTimeChooser.h"
 #include "core/html/forms/DateTimeChooserClient.h"
 #include "core/html/forms/DateTimeChooserImpl.h"
+#include "core/html/forms/ExternalDateTimeChooser.h"
 #include "core/inspector/DevToolsEmulator.h"
 #include "core/layout/HitTestResult.h"
 #include "core/layout/LayoutEmbeddedContent.h"
@@ -62,7 +63,9 @@
 #include "core/loader/DocumentLoader.h"
 #include "core/loader/FrameLoadRequest.h"
 #include "core/page/ChromeClient.h"
+#include "core/page/ExternalPopupMenu.h"
 #include "core/page/Page.h"
+#include "core/page/PopupMenuImpl.h"
 #include "core/page/PopupOpeningObserver.h"
 #include "platform/Cursor.h"
 #include "platform/FileChooser.h"
@@ -104,9 +107,6 @@
 #include "public/web/WebUserGestureToken.h"
 #include "public/web/WebViewClient.h"
 #include "public/web/WebWindowFeatures.h"
-#include "web/ExternalDateTimeChooser.h"
-#include "web/ExternalPopupMenu.h"
-#include "web/PopupMenuImpl.h"
 #include "web/WebFrameWidgetImpl.h"
 #include "web/WebLocalFrameImpl.h"
 
diff --git a/third_party/WebKit/Source/web/ExternalPopupMenuTest.cpp b/third_party/WebKit/Source/web/ExternalPopupMenuTest.cpp
index 1ab2b97..a9b58da5 100644
--- a/third_party/WebKit/Source/web/ExternalPopupMenuTest.cpp
+++ b/third_party/WebKit/Source/web/ExternalPopupMenuTest.cpp
@@ -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 "web/ExternalPopupMenu.h"
+#include "core/page/ExternalPopupMenu.h"
 
 #include <memory>
 #include "core/HTMLNames.h"
diff --git a/third_party/WebKit/Source/web/LocalFrameClientImpl.cpp b/third_party/WebKit/Source/web/LocalFrameClientImpl.cpp
index b6d1616..7bc97f1 100644
--- a/third_party/WebKit/Source/web/LocalFrameClientImpl.cpp
+++ b/third_party/WebKit/Source/web/LocalFrameClientImpl.cpp
@@ -1006,6 +1006,12 @@
   return WebEffectiveConnectionType::kTypeUnknown;
 }
 
+bool LocalFrameClientImpl::IsClientLoFiActiveForFrame() {
+  if (web_frame_->Client())
+    return web_frame_->Client()->IsClientLoFiActiveForFrame();
+  return false;
+}
+
 bool LocalFrameClientImpl::ShouldUseClientLoFiForRequest(
     const ResourceRequest& request) {
   if (web_frame_->Client()) {
diff --git a/third_party/WebKit/Source/web/LocalFrameClientImpl.h b/third_party/WebKit/Source/web/LocalFrameClientImpl.h
index da335fb..9b8d95b 100644
--- a/third_party/WebKit/Source/web/LocalFrameClientImpl.h
+++ b/third_party/WebKit/Source/web/LocalFrameClientImpl.h
@@ -220,6 +220,8 @@
 
   WebEffectiveConnectionType GetEffectiveConnectionType() override;
 
+  bool IsClientLoFiActiveForFrame() override;
+
   bool ShouldUseClientLoFiForRequest(const ResourceRequest&) override;
 
   KURL OverrideFlashEmbedWithHTML(const KURL&) override;
diff --git a/third_party/WebKit/Source/web/WebPagePopupImpl.cpp b/third_party/WebKit/Source/web/WebPagePopupImpl.cpp
index 80293a5e..08bc2c9 100644
--- a/third_party/WebKit/Source/web/WebPagePopupImpl.cpp
+++ b/third_party/WebKit/Source/web/WebPagePopupImpl.cpp
@@ -29,6 +29,7 @@
 
 #include "web/WebPagePopupImpl.h"
 
+#include "core/dom/AXObjectCacheBase.h"
 #include "core/dom/ContextFeatures.h"
 #include "core/events/MessageEvent.h"
 #include "core/events/WebInputEventConversion.h"
@@ -48,8 +49,6 @@
 #include "core/page/Page.h"
 #include "core/page/PagePopupClient.h"
 #include "core/page/PagePopupSupplement.h"
-#include "modules/accessibility/AXObjectCacheImpl.h"
-#include "modules/accessibility/AXObjectImpl.h"
 #include "platform/EventDispatchForbiddenScope.h"
 #include "platform/LayoutTestSupport.h"
 #include "platform/ScriptForbiddenScope.h"
@@ -350,7 +349,7 @@
     return 0;
   AXObjectCache* cache = document->AxObjectCache();
   DCHECK(cache);
-  return ToAXObjectCacheImpl(cache)->GetOrCreate(ToLayoutView(
+  return ToAXObjectCacheBase(cache)->GetOrCreate(ToLayoutView(
       LayoutAPIShim::LayoutObjectFrom(document->GetLayoutViewItem())));
 }
 
diff --git a/third_party/WebKit/Source/web/WebViewImpl.cpp b/third_party/WebKit/Source/web/WebViewImpl.cpp
index 551f670..6fc9ba0 100644
--- a/third_party/WebKit/Source/web/WebViewImpl.cpp
+++ b/third_party/WebKit/Source/web/WebViewImpl.cpp
@@ -81,6 +81,7 @@
 #include "core/layout/TextAutosizer.h"
 #include "core/layout/api/LayoutViewItem.h"
 #include "core/layout/compositing/PaintLayerCompositor.h"
+#include "core/loader/DocumentLoader.h"
 #include "core/loader/FrameLoadRequest.h"
 #include "core/loader/FrameLoader.h"
 #include "core/loader/FrameLoaderStateMachine.h"
@@ -3285,6 +3286,14 @@
       scrollable_area->SetScrollOffset(ScrollOffset(), kProgrammaticScroll);
   }
 
+  if (Document* document =
+          ToLocalFrame(GetPage()->MainFrame())->GetDocument()) {
+    if (DocumentLoader* loader = document->Loader()) {
+      if (HistoryItem* item = loader->GetHistoryItem())
+        item->SetDidSaveScrollOrScaleState(false);
+    }
+  }
+
   GetPageScaleConstraintsSet().SetNeedsReset(true);
 }
 
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
index 6567f197..0ec5d4048 100644
--- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -4273,20 +4273,15 @@
       WebSize(kPageWidth / 4, kPageHeight / 4));
   web_view_helper.WebView()->SetPageScaleFactor(kPageScaleFactor);
 
-  WebSize previous_offset =
-      web_view_helper.WebView()->MainFrame()->GetScrollOffset();
-  float previous_scale = web_view_helper.WebView()->PageScaleFactor();
-
-  // Reload the page and end up at the same url. State should be propagated.
+  // Reload the page and end up at the same url. State should not be propagated.
   web_view_helper.WebView()->MainFrame()->ReloadWithOverrideURL(
       ToKURL(base_url_ + first_url), WebFrameLoadType::kReload);
   FrameTestHelpers::PumpPendingRequestsForFrameToLoad(
       web_view_helper.WebView()->MainFrame());
-  EXPECT_EQ(previous_offset.width,
-            web_view_helper.WebView()->MainFrame()->GetScrollOffset().width);
-  EXPECT_EQ(previous_offset.height,
+  EXPECT_EQ(0, web_view_helper.WebView()->MainFrame()->GetScrollOffset().width);
+  EXPECT_EQ(0,
             web_view_helper.WebView()->MainFrame()->GetScrollOffset().height);
-  EXPECT_EQ(previous_scale, web_view_helper.WebView()->PageScaleFactor());
+  EXPECT_EQ(1.0f, web_view_helper.WebView()->PageScaleFactor());
 
   // Reload the page using the cache. State should not be propagated.
   web_view_helper.WebView()->MainFrame()->ReloadWithOverrideURL(
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/chromium_commit.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/chromium_commit.py
index 09f461e1..d20e0ea 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/chromium_commit.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/chromium_commit.py
@@ -5,19 +5,21 @@
 from webkitpy.w3c.chromium_finder import absolute_chromium_dir, absolute_chromium_wpt_dir
 from webkitpy.common.system.executive import ScriptError
 
+# TODO(qyearsley): Use PathFinder to get this path.
 CHROMIUM_WPT_DIR = 'third_party/WebKit/LayoutTests/external/wpt/'
 
 
 class ChromiumCommit(object):
 
     def __init__(self, host, sha=None, position=None):
-        """
+        """Initializes a ChomiumCommit object, given a sha or commit position.
+
         Args:
-            host: A Host object
-            sha: A Chromium commit SHA
-            position: A string of the form:
+            host: A Host object.
+            sha: A Chromium commit SHA hash.
+            position: A commit position footer string of the form:
                     'Cr-Commit-Position: refs/heads/master@{#431915}'
-                or just:
+                or just the commit position string:
                     'refs/heads/master@{#431915}'
         """
         self.host = host
@@ -46,6 +48,7 @@
 
     def num_behind_master(self):
         """Returns the number of commits this commit is behind origin/master.
+
         It is inclusive of this commit and of the latest commit.
         """
         return len(self.host.executive.run_command([
@@ -63,7 +66,8 @@
                 'git', 'footers', '--position', sha
             ], cwd=self.absolute_chromium_dir).strip()
         except ScriptError as e:
-            # Some commits don't have a position, e.g. when creating PRs for Gerrit CLs.
+            # Commits from Gerrit CLs that have not yet been committed in
+            # Chromium do not have a commit position.
             if 'Unable to infer commit position from footers' in e.message:
                 return 'no-commit-position-yet'
             else:
@@ -91,6 +95,7 @@
         ], cwd=self.absolute_chromium_dir)
 
     def change_id(self):
+        """Returns the Change-Id footer if it is present."""
         return self.host.executive.run_command([
             'git', 'footers', '--key', 'Change-Id', self.sha
         ], cwd=self.absolute_chromium_dir).strip()
@@ -117,6 +122,7 @@
 
     @staticmethod
     def is_baseline(basename):
+        """Checks whether a given file name in wpt appears to be a baseline."""
         # TODO(qyearsley): Find a better, centralized place for this.
         return basename.endswith('-expected.txt')
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor.py
index bd2db91..1c8ed5e 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/directory_owners_extractor.py
@@ -17,12 +17,17 @@
         self.owner_map = None
 
     def read_owner_map(self):
-        """Reads the W3CImportExpectations file and returns a map of directories to owners."""
+        """Reads W3CImportExpectations and stores the owner information."""
         input_path = self.finder.path_from_layout_tests('W3CImportExpectations')
         input_contents = self.filesystem.read_text_file(input_path)
         self.owner_map = self.lines_to_owner_map(input_contents.splitlines())
 
     def lines_to_owner_map(self, lines):
+        """Returns a dict mapping directories to owners.
+
+        Args:
+            lines: Lines in W3CImportExpectations.
+        """
         current_owners = []
         owner_map = {}
         for line in lines:
@@ -49,6 +54,7 @@
 
     @staticmethod
     def extract_directory(line):
+        """Extracts the directory substring for an enabled directory."""
         match = re.match(r'# ?(?P<directory>\S+) \[ (Pass|Skip) \]', line)
         if match and match.group('directory'):
             return match.group('directory')
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/gerrit.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/gerrit.py
index 70c4140..ddc16e1 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/gerrit.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/gerrit.py
@@ -133,6 +133,7 @@
         return True
 
     def exportable_filename(self, filename):
+        """Returns True if the file could be exportable, or False otherwise."""
         filename = os.path.basename(filename.lower())
         return (
             not filename.endswith('-expected.txt')
@@ -175,7 +176,7 @@
             else:
                 in_exportable_diff = False
 
-        # Join into string, newline at end is required.
+        # Join into string; the newline at the end is required.
         if not filtered_patch[-1].strip():
             filtered_patch = filtered_patch[:-1]
         patch = '\n'.join(filtered_patch) + '\n'
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt.py
index 9517116..c934c5b 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/local_wpt.py
@@ -10,14 +10,14 @@
 from webkitpy.w3c.chromium_commit import ChromiumCommit
 from webkitpy.w3c.common import WPT_GH_SSH_URL_TEMPLATE, CHROMIUM_WPT_DIR
 
-
 _log = logging.getLogger(__name__)
 
 
 class LocalWPT(object):
 
     def __init__(self, host, gh_token=None, path='/tmp/wpt'):
-        """
+        """Initializes a LocalWPT instance.
+
         Args:
             host: A Host object.
             path: Optional, the path to the web-platform-tests repo.
@@ -29,6 +29,7 @@
         self.gh_token = gh_token
 
     def fetch(self):
+        """Fetches a copy of the web-platform-tests repo into `self.path`."""
         assert self.gh_token, 'LocalWPT.gh_token required for fetch'
         if self.host.filesystem.exists(self.path):
             _log.info('WPT checkout exists at %s, fetching latest', self.path)
@@ -44,7 +45,11 @@
         return self.host.executive.run_command(command, cwd=self.path, **kwargs)
 
     def most_recent_chromium_commit(self):
-        """Finds the most recent commit in WPT with a Chromium commit position."""
+        """Finds the most recent commit in WPT with a Chromium commit position.
+
+        Returns:
+            A pair (commit hash, ChromiumCommit instance).
+        """
         wpt_commit_hash = self.run(['git', 'rev-list', 'HEAD', '-n', '1', '--grep=Cr-Commit-Position'])
         if not wpt_commit_hash:
             return None, None
@@ -58,6 +63,7 @@
         return wpt_commit_hash, chromium_commit
 
     def clean(self):
+        """Resets git to a clean state, on origin/master with no changed files."""
         self.run(['git', 'reset', '--hard', 'HEAD'])
         self.run(['git', 'clean', '-fdx'])
         self.run(['git', 'checkout', 'origin/master'])
@@ -81,7 +87,7 @@
             _log.info('Deleting old branch %s', branch_name)
             self.run(['git', 'branch', '-D', branch_name])
         except ScriptError:
-            # Ignore errors if branch not found.
+            # This might mean the branch wasn't found. Ignore this error.
             pass
 
         _log.info('Creating local branch %s', branch_name)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py
index 6898af1..07ac7033 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py
@@ -8,11 +8,7 @@
  1. Upload a CL.
  2. Trigger try jobs and wait for them to complete.
  3. Make any changes that are required for new failing tests.
- 4. Commit the CL.
-
-If this script is given the argument --auto-update, it will also attempt to
-upload a CL, trigger try jobs, and make any changes that are required for
-new failing tests before committing.
+ 4. Attempt to land the CL.
 """
 
 import argparse
@@ -166,6 +162,7 @@
         return exportable_commits_since(chromium_commit.sha, self.host, local_wpt)
 
     def clean_up_temp_repo(self, temp_repo_path):
+        """Removes the temporary copy of the wpt repo that was downloaded."""
         _log.info('Deleting temp repo directory %s.', temp_repo_path)
         self.fs.rmtree(temp_repo_path)
 
@@ -240,6 +237,13 @@
 
         self._generate_manifest(dest_path)
 
+        # TODO(qyearsley): Consider running the imported tests with
+        # `run-webkit-tests --reset-results external/wpt` to get most of
+        # the cross-platform baselines without having to wait for try jobs.
+        # TODO(qyearsley): Consider updating manifest after adding baselines.
+        # TODO(qyearsley): Consider starting CQ at the same time as the
+        # initial try jobs.
+
         _log.info('Updating TestExpectations for any removed or renamed tests.')
         self.update_all_test_expectations_files(self._list_deleted_tests(), self._list_renamed_tests())
 
@@ -438,13 +442,24 @@
         return '\n'.join(message_lines)
 
     def fetch_new_expectations_and_baselines(self):
-        """Adds new expectations and downloads baselines based on try job results, then commits and uploads the change."""
+        """Modifies expectation lines and baselines based on try job results.
+
+        Assuming that there are some try job results available, this
+        adds new expectation lines to TestExpectations and downloads new
+        baselines based on the try job results.
+
+        This is the same as invoking the `wpt-update-expectations` script.
+        """
         _log.info('Adding test expectations lines to LayoutTests/TestExpectations.')
         expectation_updater = WPTExpectationsUpdater(self.host)
         expectation_updater.run(args=[])
 
     def update_all_test_expectations_files(self, deleted_tests, renamed_tests):
-        """Updates all test expectations files for tests that have been deleted or renamed."""
+        """Updates all test expectations files for tests that have been deleted or renamed.
+
+        This is only for deleted or renamed tests in the initial import,
+        not for tests that have failures in try jobs.
+        """
         port = self.host.port_factory.get()
         for path, file_contents in port.all_expectations_dict().iteritems():
             parser = TestExpectationParser(port, all_tests=None, is_lint_mode=False)
@@ -452,7 +467,7 @@
             self._update_single_test_expectations_file(path, expectation_lines, deleted_tests, renamed_tests)
 
     def _update_single_test_expectations_file(self, path, expectation_lines, deleted_tests, renamed_tests):
-        """Updates single test expectations file."""
+        """Updates a single test expectations file."""
         # FIXME: This won't work for removed or renamed directories with test expectations
         # that are directories rather than individual tests.
         new_lines = []
@@ -473,7 +488,7 @@
         self.host.filesystem.write_text_file(path, new_file_contents)
 
     def _list_deleted_tests(self):
-        """Returns a list of layout tests that have been deleted."""
+        """List of layout tests that have been deleted."""
         out = self.check_run(['git', 'diff', 'origin/master', '-M100%', '--diff-filter=D', '--name-only'])
         deleted_tests = []
         for line in out.splitlines():
@@ -483,7 +498,10 @@
         return deleted_tests
 
     def _list_renamed_tests(self):
-        """Returns a dict mapping source to dest name for layout tests that have been renamed."""
+        """Lists tests that have been renamed.
+
+        Returns a dict mapping source name to destination name.
+        """
         out = self.check_run(['git', 'diff', 'origin/master', '-M100%', '--diff-filter=R', '--name-status'])
         renamed_tests = {}
         for line in out.splitlines():
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github.py
index c6bc6aa6..15387d00 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github.py
@@ -11,13 +11,16 @@
 from webkitpy.w3c.common import WPT_GH_ORG, WPT_GH_REPO_NAME
 from webkitpy.common.memoized import memoized
 
-
 _log = logging.getLogger(__name__)
 API_BASE = 'https://api.github.com'
 EXPORT_LABEL = 'chromium-export'
 
 
 class WPTGitHub(object):
+    """An interface to GitHub for interacting with the web-platform-tests repo.
+
+    This class contains methods for sending requests to the GitHub API.
+    """
 
     def __init__(self, host, user, token, pr_history_window=30):
         self.host = host
@@ -224,7 +227,6 @@
         return None
 
 
-
 class MergeError(Exception):
     """An error specifically for when a PR cannot be merged.
 
@@ -233,4 +235,5 @@
     """
     pass
 
+
 PullRequest = namedtuple('PullRequest', ['title', 'number', 'body', 'state'])
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github_mock.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github_mock.py
index 8f40df1..951233c 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github_mock.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_github_mock.py
@@ -7,6 +7,9 @@
 
 class MockWPTGitHub(object):
 
+    # Some unused arguments may be included to match the real class's API.
+    # pylint: disable=unused-argument
+
     def __init__(self, pull_requests, unsuccessful_merge_index=-1, create_pr_fail_index=-1):
         self.pull_requests = pull_requests
         self.calls = []
@@ -16,7 +19,7 @@
         self.create_pr_index = 0
         self.create_pr_fail_index = create_pr_fail_index
 
-    def all_pull_requests(self, limit=30):  # pylint: disable=unused-argument
+    def all_pull_requests(self, limit=30):
         self.calls.append('all_pull_requests')
         return self.pull_requests
 
@@ -39,7 +42,7 @@
 
         return {'number': 5678}
 
-    def update_pr(self, pr_number, desc_title, body):  # pylint: disable=unused-argument
+    def update_pr(self, pr_number, desc_title, body):
         self.calls.append('update_pr')
 
         return {'number': 5678}
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_manifest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_manifest.py
index 05cee668..25be40d 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_manifest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/wpt_manifest.py
@@ -27,13 +27,12 @@
     def _items_for_path(self, path_in_wpt):
         """Returns manifest items for the given WPT path, or None if not found.
 
-        The format of a manifest item depends on
-        https://github.com/w3c/wpt-tools/blob/master/manifest/item.py
-        and is assumed to be a list of the format [url, extras],
-        or [url, references, extras] for reftests, or None if not found.
+        The format of a manifest item depends on:
+          https://github.com/w3c/web-platform-tests/blob/master/tools/manifest/item.py
 
         For most testharness tests, the returned items is expected
-        to look like this:: [["/some/test/path.html", {}]]
+        to look like this: [["/some/test/path.html", {}]]. For reference tests,
+        it will be a list with three items ([url, references, extras]).
         """
         items = self.raw_dict['items']
         if path_in_wpt in items['manual']:
@@ -74,7 +73,7 @@
         """Extracts reference information of the specified reference test.
 
         The return value is a list of (match/not-match, reference path in wpt)
-        like:
+        pairs, like:
            [("==", "foo/bar/baz-match.html"),
             ("!=", "foo/bar/baz-mismatch.html")]
         """
@@ -89,7 +88,7 @@
 
     @staticmethod
     def ensure_manifest(host):
-        """Checks whether the manifest exists, and then generates it if necessary."""
+        """Generates the MANIFEST.json file if it does not exist."""
         finder = PathFinder(host.filesystem)
         manifest_path = finder.path_from_layout_tests('external', 'wpt', 'MANIFEST.json')
         base_manifest_path = finder.path_from_layout_tests('external', 'WPT_BASE_MANIFEST.json')
diff --git a/third_party/WebKit/public/web/WebFrameClient.h b/third_party/WebKit/public/web/WebFrameClient.h
index fe89d1b..10a10b0e 100644
--- a/third_party/WebKit/public/web/WebFrameClient.h
+++ b/third_party/WebKit/public/web/WebFrameClient.h
@@ -484,6 +484,10 @@
     return WebEffectiveConnectionType::kTypeUnknown;
   }
 
+  // Returns whether or not Client LoFi is enabled for the frame (and
+  // so any image requests may be replaced with a placeholder).
+  virtual bool IsClientLoFiActiveForFrame() { return false; }
+
   // Returns whether or not the requested image should be replaced with a
   // placeholder as part of the Client Lo-Fi previews feature.
   virtual bool ShouldUseClientLoFiForRequest(const WebURLRequest&) {
diff --git a/tools/android/eclipse/.classpath b/tools/android/eclipse/.classpath
index e933cd8..3fb0f5e 100644
--- a/tools/android/eclipse/.classpath
+++ b/tools/android/eclipse/.classpath
@@ -45,6 +45,9 @@
     <classpathentry kind="src" path="chrome/test/chromedriver/test/webview_shell/java/src"/>
     <classpathentry kind="src" path="chromecast/browser/android/apk/src"/>
     <classpathentry kind="src" path="components/autofill/android/java/src"/>
+    <classpathentry kind="src" path="components/background_task_scheduler/android/java/src"/>
+    <classpathentry kind="src" path="components/background_task_scheduler/android/javatests/src"/>
+    <classpathentry kind="src" path="components/background_task_scheduler/android/junit/src"/>
     <classpathentry kind="src" path="components/bookmarks/common/android/java/src"/>
     <classpathentry kind="src" path="components/cronet/android/api/src"/>
     <classpathentry kind="src" path="components/cronet/android/java/src"/>
diff --git a/tools/chrome_proxy/webdriver/lofi.py b/tools/chrome_proxy/webdriver/lofi.py
index 5960ad0bc..ac1198ad 100644
--- a/tools/chrome_proxy/webdriver/lofi.py
+++ b/tools/chrome_proxy/webdriver/lofi.py
@@ -211,5 +211,26 @@
       # Verify that Lo-Fi responses were seen.
       self.assertNotEqual(0, lofi_responses)
 
+  # Checks that Client LoFi resource requests have the Intervention header
+  # (in case page has https images that may not be fully loaded).
+  def testClientLoFiInterventionHeader(self):
+    with TestDriver() as test_driver:
+      test_driver.AddChromeArg('--enable-spdy-proxy-auth')
+      test_driver.AddChromeArg('--force-fieldtrials='
+                               'PreviewsClientLoFi/Enabled')
+      test_driver.AddChromeArg('--force-fieldtrial-params='
+                               'PreviewsClientLoFi.Enabled:'
+                               'max_allowed_effective_connection_type/4G')
+
+      test_driver.LoadURL('http://check.googlezip.net/static/index.html')
+
+      intervention_headers = 0
+      for response in test_driver.GetHTTPResponses():
+        if not response.url.endswith('html'):
+          self.assertIn('intervention', response.request_headers)
+          intervention_headers = intervention_headers + 1
+
+      self.assertNotEqual(0, intervention_headers)
+
 if __name__ == '__main__':
   IntegrationTest.RunAllTests()
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 6f8ac11..5c17759 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -5646,7 +5646,6 @@
   <int value="31" label="Permission autoblocker data setting"/>
   <int value="32" label="Ads setting"/>
   <int value="33" label="Ads metadata"/>
-  <int value="34" label="Password protection setting"/>
 </enum>
 
 <enum name="ContentTypeParseableResult" type="int">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index b155d0f40..ede5304 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -51672,8 +51672,8 @@
   </summary>
 </histogram>
 
-<histogram base="true"
-    name="PasswordProtection.NumberOfCachedVerdictBeforeShutdown" units="count">
+<histogram name="PasswordProtection.NumberOfCachedVerdictBeforeShutdown"
+    units="count">
   <owner>jialiul@chromium.org</owner>
   <owner>nparker@chromium.org</owner>
   <summary>
@@ -93039,8 +93039,6 @@
 </histogram_suffixes>
 
 <histogram_suffixes name="PasswordProtectionTrigger" separator=".">
-  <affected-histogram
-      name="PasswordProtection.NumberOfCachedVerdictBeforeShutdown"/>
   <suffix name="PasswordFieldOnFocus"
       label="Password protection triggered by password field on focus event."/>
   <suffix name="ProtectedPasswordEntry"
diff --git a/tools/perf/benchmarks/blink_perf.py b/tools/perf/benchmarks/blink_perf.py
index 6b1581a..c97e754 100644
--- a/tools/perf/benchmarks/blink_perf.py
+++ b/tools/perf/benchmarks/blink_perf.py
@@ -67,8 +67,7 @@
   else:
     _AddPage(path)
   ps = story.StorySet(base_dir=os.getcwd() + os.sep,
-                      serving_dirs=serving_dirs,
-                      verify_names=True)
+                      serving_dirs=serving_dirs)
 
   all_urls = [p.rstrip('/') for p in page_urls]
   common_prefix = os.path.dirname(os.path.commonprefix(all_urls))
diff --git a/tools/perf/benchmarks/dromaeo.py b/tools/perf/benchmarks/dromaeo.py
index c34714a..b2cbdb1c 100644
--- a/tools/perf/benchmarks/dromaeo.py
+++ b/tools/perf/benchmarks/dromaeo.py
@@ -118,8 +118,7 @@
     ps = story.StorySet(
         archive_data_file=archive_data_file,
         base_dir=os.path.dirname(os.path.abspath(__file__)),
-        cloud_storage_bucket=story.PUBLIC_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PUBLIC_BUCKET)
     url = 'http://dromaeo.com?%s' % self.query_param
     ps.AddStory(page_module.Page(
         url, ps, ps.base_dir, make_javascript_deterministic=False, name=url))
diff --git a/tools/perf/benchmarks/jetstream.py b/tools/perf/benchmarks/jetstream.py
index d00db53..b594f50b 100644
--- a/tools/perf/benchmarks/jetstream.py
+++ b/tools/perf/benchmarks/jetstream.py
@@ -87,8 +87,7 @@
     ps = story.StorySet(
         archive_data_file='../page_sets/data/jetstream.json',
         base_dir=os.path.dirname(os.path.abspath(__file__)),
-        cloud_storage_bucket=story.INTERNAL_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.INTERNAL_BUCKET)
     ps.AddStory(page_module.Page(
         'http://browserbench.org/JetStream/', ps, ps.base_dir,
         make_javascript_deterministic=False,
diff --git a/tools/perf/benchmarks/kraken.py b/tools/perf/benchmarks/kraken.py
index df0fcda3..521c27e 100644
--- a/tools/perf/benchmarks/kraken.py
+++ b/tools/perf/benchmarks/kraken.py
@@ -132,8 +132,7 @@
     ps = story.StorySet(
         archive_data_file='../page_sets/data/kraken.json',
         base_dir=os.path.dirname(os.path.abspath(__file__)),
-        cloud_storage_bucket=story.PARTNER_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PARTNER_BUCKET)
     ps.AddStory(page_module.Page(
         'http://krakenbenchmark.mozilla.org/kraken-1.1/driver.html',
         ps, ps.base_dir,
diff --git a/tools/perf/benchmarks/octane.py b/tools/perf/benchmarks/octane.py
index 117c0fe..d6de296 100644
--- a/tools/perf/benchmarks/octane.py
+++ b/tools/perf/benchmarks/octane.py
@@ -148,8 +148,7 @@
     ps = story.StorySet(
         archive_data_file='../page_sets/data/octane.json',
         base_dir=os.path.dirname(os.path.abspath(__file__)),
-        cloud_storage_bucket=story.PUBLIC_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PUBLIC_BUCKET)
     ps.AddStory(page_module.Page(
         'http://chromium.github.io/octane/index.html?auto=1',
         ps, ps.base_dir, make_javascript_deterministic=False,
diff --git a/tools/perf/benchmarks/speedometer.py b/tools/perf/benchmarks/speedometer.py
index cf325400..fbe431da 100644
--- a/tools/perf/benchmarks/speedometer.py
+++ b/tools/perf/benchmarks/speedometer.py
@@ -101,8 +101,7 @@
     ps = story.StorySet(
         base_dir=os.path.dirname(os.path.abspath(__file__)),
         archive_data_file='../page_sets/data/speedometer.json',
-        cloud_storage_bucket=story.PUBLIC_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PUBLIC_BUCKET)
     ps.AddStory(page_module.Page(
         'http://browserbench.org/Speedometer/', ps, ps.base_dir,
         make_javascript_deterministic=False,
diff --git a/tools/perf/benchmarks/tab_switching.py b/tools/perf/benchmarks/tab_switching.py
index 975a24f..b1cf856 100644
--- a/tools/perf/benchmarks/tab_switching.py
+++ b/tools/perf/benchmarks/tab_switching.py
@@ -36,8 +36,7 @@
     story_set = story.StorySet(
         archive_data_file='../page_sets/data/system_health_desktop.json',
         base_dir=os.path.dirname(os.path.abspath(__file__)),
-        cloud_storage_bucket=story.PARTNER_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PARTNER_BUCKET)
     story_set.AddStory(multi_tab_stories.MultiTabTypical24Story(
         story_set, False, options.tabset_repeat))
     return story_set
diff --git a/tools/perf/page_sets/blank_page.py b/tools/perf/page_sets/blank_page.py
index a7ce08e..b44d4c1 100644
--- a/tools/perf/page_sets/blank_page.py
+++ b/tools/perf/page_sets/blank_page.py
@@ -26,6 +26,6 @@
   """A single blank page."""
 
   def __init__(self):
-    super(BlankPageSet, self).__init__(verify_names=True)
+    super(BlankPageSet, self).__init__()
     self.AddStory(BlankPage('file://blank_page/blank_page.html',
                             self, 'blank_page.html'))
diff --git a/tools/perf/page_sets/blank_page_with_extension_profile.py b/tools/perf/page_sets/blank_page_with_extension_profile.py
index a20afee..bae248e 100644
--- a/tools/perf/page_sets/blank_page_with_extension_profile.py
+++ b/tools/perf/page_sets/blank_page_with_extension_profile.py
@@ -22,7 +22,7 @@
   """PageSet tied to BlankPageWithExtensionProfile."""
 
   def __init__(self):
-    super(BlankPageSetWithExtensionProfile, self).__init__(verify_names=True)
+    super(BlankPageSetWithExtensionProfile, self).__init__()
     self.AddStory(BlankPageWithExtensionProfile(
         'file://blank_page/blank_page.html', self,
         'blank_page.html'))
diff --git a/tools/perf/page_sets/blank_page_with_large_profile.py b/tools/perf/page_sets/blank_page_with_large_profile.py
index 9d268d5..c86bf22a 100644
--- a/tools/perf/page_sets/blank_page_with_large_profile.py
+++ b/tools/perf/page_sets/blank_page_with_large_profile.py
@@ -19,7 +19,7 @@
   """A single blank page loaded with a large profile."""
 
   def __init__(self):
-    super(BlankPageSetWithLargeProfile, self).__init__(verify_names=True)
+    super(BlankPageSetWithLargeProfile, self).__init__()
     self.AddStory(BlankPageWithLargeProfile(
         'file://blank_page/blank_page.html', self,
         'blank_page.html'))
diff --git a/tools/perf/page_sets/blink_memory_mobile.py b/tools/perf/page_sets/blink_memory_mobile.py
index 68d9766..e6c53c94 100644
--- a/tools/perf/page_sets/blink_memory_mobile.py
+++ b/tools/perf/page_sets/blink_memory_mobile.py
@@ -92,8 +92,7 @@
   def __init__(self):
     super(BlinkMemoryMobilePageSet, self).__init__(
         archive_data_file='data/blink_memory_mobile.json',
-        cloud_storage_bucket=story.PARTNER_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PARTNER_BUCKET)
 
     # Why: High rate of Blink's memory consumption rate.
     self.AddStory(BlinkMemoryMobilePage(
diff --git a/tools/perf/page_sets/blob_workshop.py b/tools/perf/page_sets/blob_workshop.py
index 0643173a..049983f 100644
--- a/tools/perf/page_sets/blob_workshop.py
+++ b/tools/perf/page_sets/blob_workshop.py
@@ -73,7 +73,7 @@
   """The BlobWorkshop page set."""
 
   def __init__(self):
-    super(BlobWorkshopPageSet, self).__init__(verify_names=True)
+    super(BlobWorkshopPageSet, self).__init__()
     self.AddStory(
         BlobMassCreate('2Bx200', [2] * 200, self))
     self.AddStory(
diff --git a/tools/perf/page_sets/chrome_signin.py b/tools/perf/page_sets/chrome_signin.py
index db695ff..68ff691 100644
--- a/tools/perf/page_sets/chrome_signin.py
+++ b/tools/perf/page_sets/chrome_signin.py
@@ -33,6 +33,5 @@
   def __init__(self):
     super(ChromeSigninPageSet, self).__init__(
         archive_data_file='data/chrome_signin_archive.json',
-        cloud_storage_bucket=story.INTERNAL_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.INTERNAL_BUCKET)
     self.AddStory(ChromeSigninPage(self))
diff --git a/tools/perf/page_sets/desktop_memory.py b/tools/perf/page_sets/desktop_memory.py
index b3a95fd..59f9005 100644
--- a/tools/perf/page_sets/desktop_memory.py
+++ b/tools/perf/page_sets/desktop_memory.py
@@ -50,7 +50,7 @@
   """ Desktop sites with interesting memory characteristics """
 
   def __init__(self):
-    super(DesktopMemoryPageSet, self).__init__(verify_names=True)
+    super(DesktopMemoryPageSet, self).__init__()
 
     urls_list = [
       'http://www.google.com',
diff --git a/tools/perf/page_sets/dual_browser_story.py b/tools/perf/page_sets/dual_browser_story.py
index 08240623..e50fbe7 100644
--- a/tools/perf/page_sets/dual_browser_story.py
+++ b/tools/perf/page_sets/dual_browser_story.py
@@ -241,8 +241,7 @@
   def __init__(self):
     super(DualBrowserStorySet, self).__init__(
         archive_data_file='data/dual_browser_story.json',
-        cloud_storage_bucket=story_module.PARTNER_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story_module.PARTNER_BUCKET)
 
     for query, url in zip(SEARCH_QUERIES, URL_LIST):
       # Stories that run on the android-webview browser.
diff --git a/tools/perf/page_sets/dummy_story_set.py b/tools/perf/page_sets/dummy_story_set.py
index d3609db..884b00dd 100644
--- a/tools/perf/page_sets/dummy_story_set.py
+++ b/tools/perf/page_sets/dummy_story_set.py
@@ -20,5 +20,5 @@
 class DummyStorySet(story.StorySet):
 
   def __init__(self):
-    super(DummyStorySet, self).__init__(verify_names=True)
+    super(DummyStorySet, self).__init__()
     self.AddStory(DummyPage(self))
diff --git a/tools/perf/page_sets/idle_after_loading_stories.py b/tools/perf/page_sets/idle_after_loading_stories.py
index 47c62906..fc2248c 100644
--- a/tools/perf/page_sets/idle_after_loading_stories.py
+++ b/tools/perf/page_sets/idle_after_loading_stories.py
@@ -47,8 +47,7 @@
   def __init__(self, wait_in_seconds=0):
     super(IdleAfterLoadingStories, self).__init__(
         archive_data_file='data/idle_after_loading_stories.json',
-        cloud_storage_bucket=story.PARTNER_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PARTNER_BUCKET)
 
     # Chrome has high idle CPU usage on this site, even after its quiesced.
     # https://crbug.com/638365.
diff --git a/tools/perf/page_sets/idle_platform.py b/tools/perf/page_sets/idle_platform.py
index 4f478f4..b25af54 100644
--- a/tools/perf/page_sets/idle_platform.py
+++ b/tools/perf/page_sets/idle_platform.py
@@ -44,7 +44,7 @@
 
 class IdleStorySet(story.StorySet):
   def __init__(self):
-    super(IdleStorySet, self).__init__(verify_names=True)
+    super(IdleStorySet, self).__init__()
     self.AddStory(_IdleStory('IdleStory_10s', 10))
     self.AddStory(_IdleStory('IdleStory_60s', 60))
     self.AddStory(_IdleStory('IdleStory_120s', 120))
diff --git a/tools/perf/page_sets/image_decoding_cases.py b/tools/perf/page_sets/image_decoding_cases.py
index 826858cc..735c90f 100644
--- a/tools/perf/page_sets/image_decoding_cases.py
+++ b/tools/perf/page_sets/image_decoding_cases.py
@@ -19,7 +19,7 @@
   """ A directed benchmark of accelerated jpeg image decoding performance """
 
   def __init__(self):
-    super(ImageDecodingCasesPageSet, self).__init__(verify_names=True)
+    super(ImageDecodingCasesPageSet, self).__init__()
 
     urls_list = [
       ('file://image_decoding_cases/yuv_decoding.html', 'yuv_decoding.html')
diff --git a/tools/perf/page_sets/image_decoding_measurement.py b/tools/perf/page_sets/image_decoding_measurement.py
index 24325b59..c192afe7 100644
--- a/tools/perf/page_sets/image_decoding_measurement.py
+++ b/tools/perf/page_sets/image_decoding_measurement.py
@@ -24,7 +24,7 @@
   """ A directed benchmark of image decoding performance """
 
   def __init__(self):
-    super(ImageDecodingMeasurementPageSet, self).__init__(verify_names=True)
+    super(ImageDecodingMeasurementPageSet, self).__init__()
     self.image_decoding_measurement_limit_results_to_min_iterations = True
 
     urls_list = [
diff --git a/tools/perf/page_sets/indexeddb_endure_page.py b/tools/perf/page_sets/indexeddb_endure_page.py
index 7f100ba..80feb6e 100644
--- a/tools/perf/page_sets/indexeddb_endure_page.py
+++ b/tools/perf/page_sets/indexeddb_endure_page.py
@@ -29,7 +29,7 @@
   """
 
   def __init__(self):
-    super(IndexedDBEndurePageSet, self).__init__(verify_names=True)
+    super(IndexedDBEndurePageSet, self).__init__()
     tests = [
       'testCreateAndDeleteDatabases',
       'testCreateAndDeleteDatabase',
diff --git a/tools/perf/page_sets/infinite_scroll_cases.py b/tools/perf/page_sets/infinite_scroll_cases.py
index 1268f408..25221f0 100644
--- a/tools/perf/page_sets/infinite_scroll_cases.py
+++ b/tools/perf/page_sets/infinite_scroll_cases.py
@@ -134,8 +134,7 @@
   def __init__(self):
     super(InfiniteScrollStorySet, self).__init__(
         archive_data_file='data/infinite_scroll.json',
-        cloud_storage_bucket=story.PARTNER_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PARTNER_BUCKET)
     for story_class in _FindInfiniteScrollStoryClasses(platforms.DESKTOP):
       self.AddStory(story_class(self))
 
@@ -144,8 +143,7 @@
   def __init__(self):
     super(MobileInfiniteScrollStorySet, self).__init__(
         archive_data_file='data/mobile_infinite_scroll.json',
-        cloud_storage_bucket=story.PARTNER_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PARTNER_BUCKET)
     for story_class in _FindInfiniteScrollStoryClasses(platforms.MOBILE):
       self.AddStory(story_class(self))
 
diff --git a/tools/perf/page_sets/intl_ar_fa_he.py b/tools/perf/page_sets/intl_ar_fa_he.py
index 46c6b28..0f2f727 100644
--- a/tools/perf/page_sets/intl_ar_fa_he.py
+++ b/tools/perf/page_sets/intl_ar_fa_he.py
@@ -26,8 +26,7 @@
   def __init__(self, cache_temperatures=None):
     super(IntlArFaHePageSet, self).__init__(
       archive_data_file='data/intl_ar_fa_he.json',
-      cloud_storage_bucket=story.PARTNER_BUCKET,
-      verify_names=True)
+      cloud_storage_bucket=story.PARTNER_BUCKET)
     if cache_temperatures is None:
       cache_temperatures = [cache_temperature_module.ANY]
 
diff --git a/tools/perf/page_sets/intl_es_fr_pt-BR.py b/tools/perf/page_sets/intl_es_fr_pt-BR.py
index f2053eb5..416108e 100644
--- a/tools/perf/page_sets/intl_es_fr_pt-BR.py
+++ b/tools/perf/page_sets/intl_es_fr_pt-BR.py
@@ -28,8 +28,7 @@
   def __init__(self, cache_temperatures=None):
     super(IntlEsFrPtBrPageSet, self).__init__(
       archive_data_file='data/intl_es_fr_pt-BR.json',
-      cloud_storage_bucket=story.PARTNER_BUCKET,
-      verify_names=True)
+      cloud_storage_bucket=story.PARTNER_BUCKET)
     if cache_temperatures is None:
       cache_temperatures = [cache_temperature_module.ANY]
 
diff --git a/tools/perf/page_sets/intl_hi_ru.py b/tools/perf/page_sets/intl_hi_ru.py
index 7a1c052d..4bf42c09 100644
--- a/tools/perf/page_sets/intl_hi_ru.py
+++ b/tools/perf/page_sets/intl_hi_ru.py
@@ -26,8 +26,7 @@
   def __init__(self, cache_temperatures=None):
     super(IntlHiRuPageSet, self).__init__(
       archive_data_file='data/intl_hi_ru.json',
-      cloud_storage_bucket=story.PARTNER_BUCKET,
-      verify_names=True)
+      cloud_storage_bucket=story.PARTNER_BUCKET)
     if cache_temperatures is None:
       cache_temperatures = [cache_temperature_module.ANY]
 
diff --git a/tools/perf/page_sets/intl_ja_zh.py b/tools/perf/page_sets/intl_ja_zh.py
index dd804f6..b5439795 100644
--- a/tools/perf/page_sets/intl_ja_zh.py
+++ b/tools/perf/page_sets/intl_ja_zh.py
@@ -25,8 +25,7 @@
   def __init__(self, cache_temperatures=None):
     super(IntlJaZhPageSet, self).__init__(
       archive_data_file='data/intl_ja_zh.json',
-      cloud_storage_bucket=story.PARTNER_BUCKET,
-      verify_names=True)
+      cloud_storage_bucket=story.PARTNER_BUCKET)
     if cache_temperatures is None:
       cache_temperatures = [cache_temperature_module.ANY]
 
diff --git a/tools/perf/page_sets/intl_ko_th_vi.py b/tools/perf/page_sets/intl_ko_th_vi.py
index 0a1e7eb..928b7245c 100644
--- a/tools/perf/page_sets/intl_ko_th_vi.py
+++ b/tools/perf/page_sets/intl_ko_th_vi.py
@@ -25,8 +25,7 @@
   def __init__(self, cache_temperatures=None):
     super(IntlKoThViPageSet, self).__init__(
       archive_data_file='data/intl_ko_th_vi.json',
-      cloud_storage_bucket=story.PARTNER_BUCKET,
-      verify_names=True)
+      cloud_storage_bucket=story.PARTNER_BUCKET)
     if cache_temperatures is None:
       cache_temperatures = [cache_temperature_module.ANY]
 
diff --git a/tools/perf/page_sets/key_desktop_move_cases.py b/tools/perf/page_sets/key_desktop_move_cases.py
index 1cd6811..180cdc9 100644
--- a/tools/perf/page_sets/key_desktop_move_cases.py
+++ b/tools/perf/page_sets/key_desktop_move_cases.py
@@ -118,8 +118,7 @@
   def __init__(self):
     super(KeyDesktopMoveCasesPageSet, self).__init__(
       archive_data_file='data/key_desktop_move_cases.json',
-      cloud_storage_bucket=story.PARTNER_BUCKET,
-      verify_names=True)
+      cloud_storage_bucket=story.PARTNER_BUCKET)
 
     self.AddStory(GmailMouseScrollPage(self))
     self.AddStory(GoogleMapsPage(self))
diff --git a/tools/perf/page_sets/key_hit_test_cases.py b/tools/perf/page_sets/key_hit_test_cases.py
index eedf710..d9dd86c 100644
--- a/tools/perf/page_sets/key_hit_test_cases.py
+++ b/tools/perf/page_sets/key_hit_test_cases.py
@@ -40,6 +40,6 @@
 class KeyHitTestCasesPageSet(story.StorySet):
 
   def __init__(self):
-    super(KeyHitTestCasesPageSet, self).__init__(verify_names=True)
+    super(KeyHitTestCasesPageSet, self).__init__()
 
     self.AddStory(PaperCalculatorHitTest(self))
diff --git a/tools/perf/page_sets/key_idle_power_cases.py b/tools/perf/page_sets/key_idle_power_cases.py
index 43ca9fc..73c90a7 100644
--- a/tools/perf/page_sets/key_idle_power_cases.py
+++ b/tools/perf/page_sets/key_idle_power_cases.py
@@ -58,7 +58,7 @@
   """ Key idle power cases """
 
   def __init__(self):
-    super(KeyIdlePowerCasesPageSet, self).__init__(verify_names=True)
+    super(KeyIdlePowerCasesPageSet, self).__init__()
 
     foreground_urls_list = [
       # Why: Ensure minimal activity for static, empty pages in the foreground.
diff --git a/tools/perf/page_sets/key_mobile_sites.py b/tools/perf/page_sets/key_mobile_sites.py
index b73a474..b3c0e812 100644
--- a/tools/perf/page_sets/key_mobile_sites.py
+++ b/tools/perf/page_sets/key_mobile_sites.py
@@ -29,8 +29,7 @@
   def __init__(self):
     super(KeyMobileSitesPageSet, self).__init__(
       archive_data_file='data/key_mobile_sites.json',
-      cloud_storage_bucket=story.PARTNER_BUCKET,
-      verify_names=True)
+      cloud_storage_bucket=story.PARTNER_BUCKET)
 
 
     # Add pages with predefined classes that contain custom navigation logic.
diff --git a/tools/perf/page_sets/key_mobile_sites_smooth.py b/tools/perf/page_sets/key_mobile_sites_smooth.py
index 19d96a8..fd2b15d 100644
--- a/tools/perf/page_sets/key_mobile_sites_smooth.py
+++ b/tools/perf/page_sets/key_mobile_sites_smooth.py
@@ -132,8 +132,7 @@
   def __init__(self):
     super(KeyMobileSitesSmoothPageSet, self).__init__(
       archive_data_file='data/key_mobile_sites_smooth.json',
-      cloud_storage_bucket=story.PARTNER_BUCKET,
-      verify_names=True)
+      cloud_storage_bucket=story.PARTNER_BUCKET)
 
 
     # Add pages with predefined classes that contain custom navigation logic.
diff --git a/tools/perf/page_sets/key_noop_cases.py b/tools/perf/page_sets/key_noop_cases.py
index a4639e4..0d05765 100644
--- a/tools/perf/page_sets/key_noop_cases.py
+++ b/tools/perf/page_sets/key_noop_cases.py
@@ -42,7 +42,7 @@
   """ Key no-op cases """
 
   def __init__(self):
-    super(KeyNoOpCasesPageSet, self).__init__(verify_names=True)
+    super(KeyNoOpCasesPageSet, self).__init__()
 
     # Why: An infinite rAF loop which does not modify the page should incur
     # minimal activity.
diff --git a/tools/perf/page_sets/key_silk_cases.py b/tools/perf/page_sets/key_silk_cases.py
index 078915c0..ec2b4b4 100644
--- a/tools/perf/page_sets/key_silk_cases.py
+++ b/tools/perf/page_sets/key_silk_cases.py
@@ -727,8 +727,7 @@
   def __init__(self, run_no_page_interactions=False):
     super(KeySilkCasesPageSet, self).__init__(
       archive_data_file='data/key_silk_cases.json',
-      cloud_storage_bucket=story.PARTNER_BUCKET,
-      verify_names=True)
+      cloud_storage_bucket=story.PARTNER_BUCKET)
 
     self.AddStory(Page1(self, run_no_page_interactions))
     self.AddStory(Page2(self, run_no_page_interactions))
diff --git a/tools/perf/page_sets/loading_desktop.py b/tools/perf/page_sets/loading_desktop.py
index 9d266f5c..1ee6f1c 100644
--- a/tools/perf/page_sets/loading_desktop.py
+++ b/tools/perf/page_sets/loading_desktop.py
@@ -18,8 +18,7 @@
   def __init__(self, cache_temperatures=None):
     super(LoadingDesktopStorySet, self).__init__(
         archive_data_file='data/loading_desktop.json',
-        cloud_storage_bucket=story.PARTNER_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PARTNER_BUCKET)
 
     if cache_temperatures is None:
       cache_temperatures = [
diff --git a/tools/perf/page_sets/loading_mobile.py b/tools/perf/page_sets/loading_mobile.py
index 54f9ffe2..23d39d3 100644
--- a/tools/perf/page_sets/loading_mobile.py
+++ b/tools/perf/page_sets/loading_mobile.py
@@ -19,8 +19,7 @@
   def __init__(self, cache_temperatures=None, traffic_settings=None):
     super(LoadingMobileStorySet, self).__init__(
         archive_data_file='data/loading_mobile.json',
-        cloud_storage_bucket=story.PARTNER_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PARTNER_BUCKET)
 
     if cache_temperatures is None:
       cache_temperatures = [cache_temperature_module.ANY]
diff --git a/tools/perf/page_sets/long_running_idle_google_cases.py b/tools/perf/page_sets/long_running_idle_google_cases.py
index 559e5421..302cddf 100644
--- a/tools/perf/page_sets/long_running_idle_google_cases.py
+++ b/tools/perf/page_sets/long_running_idle_google_cases.py
@@ -35,8 +35,7 @@
   def __init__(self):
     super(LongRunningIdleGmailPageSet, self).__init__(
         archive_data_file='data/long_running_idle_gmail_page.json',
-        cloud_storage_bucket=story.PARTNER_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PARTNER_BUCKET)
     self.AddStory(
         _CreateIdlePageClass(google_pages.GmailPage)(self))
 
@@ -46,7 +45,6 @@
     # Reuse the wpr of foreground gmail.
     super(LongRunningIdleGmailBackgroundPageSet, self).__init__(
         archive_data_file='data/long_running_idle_gmail_page.json',
-        cloud_storage_bucket=story.PARTNER_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PARTNER_BUCKET)
     self.AddStory(
         _CreateIdleBackgroundPageClass(google_pages.GmailPage)(self))
diff --git a/tools/perf/page_sets/maps.py b/tools/perf/page_sets/maps.py
index cb112fb..bfdab2e 100644
--- a/tools/perf/page_sets/maps.py
+++ b/tools/perf/page_sets/maps.py
@@ -42,7 +42,6 @@
   def __init__(self):
     super(MapsPageSet, self).__init__(
         archive_data_file='data/maps.json',
-        cloud_storage_bucket=story.PUBLIC_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PUBLIC_BUCKET)
 
     self.AddStory(MapsPage(self))
diff --git a/tools/perf/page_sets/media_cns_cases.py b/tools/perf/page_sets/media_cns_cases.py
index c0ddc19..b09c1e4 100644
--- a/tools/perf/page_sets/media_cns_cases.py
+++ b/tools/perf/page_sets/media_cns_cases.py
@@ -46,7 +46,7 @@
   """ Media benchmark on network constrained conditions. """
 
   def __init__(self):
-    super(MediaCnsCasesPageSet, self).__init__(verify_names=True)
+    super(MediaCnsCasesPageSet, self).__init__()
 
     urls_list = [
       # pylint: disable=line-too-long
diff --git a/tools/perf/page_sets/memory_top_10_mobile.py b/tools/perf/page_sets/memory_top_10_mobile.py
index 95a622e..260af357 100644
--- a/tools/perf/page_sets/memory_top_10_mobile.py
+++ b/tools/perf/page_sets/memory_top_10_mobile.py
@@ -68,8 +68,7 @@
   def __init__(self):
     super(MemoryTop10Mobile, self).__init__(
         archive_data_file='data/memory_top_10_mobile.json',
-        cloud_storage_bucket=story.PARTNER_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PARTNER_BUCKET)
 
     for url in top_10_mobile.URL_LIST:
       # We name pages so their foreground/background counterparts are easy
diff --git a/tools/perf/page_sets/mse_cases.py b/tools/perf/page_sets/mse_cases.py
index b39ca19..75477b1 100644
--- a/tools/perf/page_sets/mse_cases.py
+++ b/tools/perf/page_sets/mse_cases.py
@@ -21,8 +21,7 @@
 
   def __init__(self):
     super(MseCasesPageSet, self).__init__(
-        cloud_storage_bucket=story.PUBLIC_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PUBLIC_BUCKET)
 
     urls_list = [
       'file://mse_cases/startup_test.html?testType=AV',
diff --git a/tools/perf/page_sets/oopif_basic_page_set.py b/tools/perf/page_sets/oopif_basic_page_set.py
index 9276096..6aa886e 100644
--- a/tools/perf/page_sets/oopif_basic_page_set.py
+++ b/tools/perf/page_sets/oopif_basic_page_set.py
@@ -13,8 +13,7 @@
   def __init__(self, cache_temperatures=None):
     super(OopifBasicPageSet, self).__init__(
         archive_data_file='data/oopif_basic.json',
-        cloud_storage_bucket=story.PARTNER_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PARTNER_BUCKET)
     if cache_temperatures is None:
       cache_temperatures = [cache_temperature_module.ANY]
 
diff --git a/tools/perf/page_sets/oortonline.py b/tools/perf/page_sets/oortonline.py
index 312f580..570630d6 100644
--- a/tools/perf/page_sets/oortonline.py
+++ b/tools/perf/page_sets/oortonline.py
@@ -43,8 +43,7 @@
   def __init__(self):
     super(OortOnlinePageSet, self).__init__(
       archive_data_file='data/oortonline.json',
-      cloud_storage_bucket=story.PARTNER_BUCKET,
-      verify_names=True)
+      cloud_storage_bucket=story.PARTNER_BUCKET)
     self.AddStory(OortOnlinePage(self))
 
 class OortOnlineTBMPage(OortOnlinePage):
@@ -78,6 +77,5 @@
   def __init__(self):
     super(OortOnlineTBMPageSet, self).__init__(
       archive_data_file='data/oortonline.json',
-      cloud_storage_bucket=story.PARTNER_BUCKET,
-      verify_names=True)
+      cloud_storage_bucket=story.PARTNER_BUCKET)
     self.AddStory(OortOnlineTBMPage(self))
diff --git a/tools/perf/page_sets/page_reload_cases.py b/tools/perf/page_sets/page_reload_cases.py
index 9887809..9851401 100644
--- a/tools/perf/page_sets/page_reload_cases.py
+++ b/tools/perf/page_sets/page_reload_cases.py
@@ -33,8 +33,7 @@
   def __init__(self):
     super(PageReloadCasesPageSet, self).__init__(
         archive_data_file='data/top_25.json',
-        cloud_storage_bucket=story.PARTNER_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PARTNER_BUCKET)
 
     shared_desktop_state = shared_page_state.SharedDesktopPageState
 
diff --git a/tools/perf/page_sets/partial_invalidation_cases.py b/tools/perf/page_sets/partial_invalidation_cases.py
index a8a9473b..939df7be0 100644
--- a/tools/perf/page_sets/partial_invalidation_cases.py
+++ b/tools/perf/page_sets/partial_invalidation_cases.py
@@ -24,7 +24,7 @@
 
   def __init__(self):
     super(PartialInvalidationCasesPageSet, self).__init__(
-        cloud_storage_bucket=story.PARTNER_BUCKET, verify_names=True)
+        cloud_storage_bucket=story.PARTNER_BUCKET)
 
     other_urls = [
         # Why: Reduced test case similar to the single page html5 spec wherein
diff --git a/tools/perf/page_sets/pathological_mobile_sites.py b/tools/perf/page_sets/pathological_mobile_sites.py
index bbef7db..514f3cc4 100644
--- a/tools/perf/page_sets/pathological_mobile_sites.py
+++ b/tools/perf/page_sets/pathological_mobile_sites.py
@@ -26,8 +26,7 @@
   def __init__(self):
     super(PathologicalMobileSitesPageSet, self).__init__(
         archive_data_file='data/pathological_mobile_sites.json',
-        cloud_storage_bucket=story.PARTNER_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PARTNER_BUCKET)
 
     sites = ['http://edition.cnn.com',
              'http://m.espn.go.com/nhl/rankings',
diff --git a/tools/perf/page_sets/polymer.py b/tools/perf/page_sets/polymer.py
index bb8b998..fb465044 100644
--- a/tools/perf/page_sets/polymer.py
+++ b/tools/perf/page_sets/polymer.py
@@ -224,8 +224,7 @@
   def __init__(self, run_no_page_interactions=False):
     super(PolymerPageSet, self).__init__(
       archive_data_file='data/polymer.json',
-      cloud_storage_bucket=story.PUBLIC_BUCKET,
-      verify_names=True)
+      cloud_storage_bucket=story.PUBLIC_BUCKET)
 
     self.AddStory(PolymerCalculatorPage(self, run_no_page_interactions))
     self.AddStory(PolymerShadowPage(self, run_no_page_interactions))
diff --git a/tools/perf/page_sets/service_worker.py b/tools/perf/page_sets/service_worker.py
index 58e2eea..798bfc5 100644
--- a/tools/perf/page_sets/service_worker.py
+++ b/tools/perf/page_sets/service_worker.py
@@ -15,8 +15,7 @@
   def __init__(self):
     super(ServiceWorkerPageSet, self).__init__(
         archive_data_file=archive_data_file_path,
-        cloud_storage_bucket=story.PARTNER_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PARTNER_BUCKET)
 
     # Why: the first application using ServiceWorker
     # 1st time: registration
diff --git a/tools/perf/page_sets/service_worker_micro_benchmark.py b/tools/perf/page_sets/service_worker_micro_benchmark.py
index 57f9848..788defc 100644
--- a/tools/perf/page_sets/service_worker_micro_benchmark.py
+++ b/tools/perf/page_sets/service_worker_micro_benchmark.py
@@ -20,8 +20,7 @@
   def __init__(self):
     super(ServiceWorkerMicroBenchmarkPageSet, self).__init__(
         archive_data_file='data/service_worker_micro_benchmark.json',
-        cloud_storage_bucket=story.PUBLIC_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PUBLIC_BUCKET)
 
     # pylint: disable=line-too-long
     # The latest code of localhost:8091 is from:
diff --git a/tools/perf/page_sets/simple_mobile_sites.py b/tools/perf/page_sets/simple_mobile_sites.py
index f3cb9a6..0e2b1ea 100644
--- a/tools/perf/page_sets/simple_mobile_sites.py
+++ b/tools/perf/page_sets/simple_mobile_sites.py
@@ -38,8 +38,7 @@
   def __init__(self):
     super(SimpleMobileSitesPageSet, self).__init__(
       archive_data_file='data/simple_mobile_sites.json',
-      cloud_storage_bucket=story.PUBLIC_BUCKET,
-      verify_names=True)
+      cloud_storage_bucket=story.PUBLIC_BUCKET)
 
     scroll_page_list = [
       # Why: Scrolls moderately complex pages (up to 60 layers)
diff --git a/tools/perf/page_sets/startup_pages.py b/tools/perf/page_sets/startup_pages.py
index 0b6327d..f40edc7 100644
--- a/tools/perf/page_sets/startup_pages.py
+++ b/tools/perf/page_sets/startup_pages.py
@@ -48,8 +48,7 @@
   def __init__(self):
     super(StartupPagesPageSet, self).__init__(
         archive_data_file='data/startup_pages.json',
-        cloud_storage_bucket=story.PARTNER_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PARTNER_BUCKET)
 
     # Typical page.
     self.AddStory(StartedPage('about:blank', self))
diff --git a/tools/perf/page_sets/system_health/system_health_stories.py b/tools/perf/page_sets/system_health/system_health_stories.py
index 63e90e4..578d7fb 100644
--- a/tools/perf/page_sets/system_health/system_health_stories.py
+++ b/tools/perf/page_sets/system_health/system_health_stories.py
@@ -20,8 +20,7 @@
   def __init__(self, platform, case=None, take_memory_measurement=False):
     super(SystemHealthStorySet, self).__init__(
         archive_data_file=('../data/system_health_%s.json' % platform),
-        cloud_storage_bucket=story.PARTNER_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PARTNER_BUCKET)
 
     assert platform in platforms.ALL_PLATFORMS
 
@@ -35,7 +34,7 @@
 
 class SystemHealthBlankStorySet(story.StorySet):
   """A story set containing the chrome:blank story only."""
-  def __init__(self, take_memory_measurement=False, verify_names=True):
+  def __init__(self, take_memory_measurement=False):
     super(SystemHealthBlankStorySet, self).__init__()
     self.AddStory(
         chrome_stories.BlankAboutBlankStory(self, take_memory_measurement))
diff --git a/tools/perf/page_sets/top_10.py b/tools/perf/page_sets/top_10.py
index 9692ee6..2d7b0a4 100644
--- a/tools/perf/page_sets/top_10.py
+++ b/tools/perf/page_sets/top_10.py
@@ -94,8 +94,7 @@
   def __init__(self):
     super(Top10PageSet, self).__init__(
       archive_data_file='data/top_10.json',
-      cloud_storage_bucket=story.PARTNER_BUCKET,
-      verify_names=True)
+      cloud_storage_bucket=story.PARTNER_BUCKET)
 
     # top google property; a google tab is often open
     self.AddStory(Google(self))
diff --git a/tools/perf/page_sets/top_10_mobile.py b/tools/perf/page_sets/top_10_mobile.py
index fca2dfe..40691dca 100644
--- a/tools/perf/page_sets/top_10_mobile.py
+++ b/tools/perf/page_sets/top_10_mobile.py
@@ -67,8 +67,7 @@
   """ Base class for Top 10 mobile sites """
 
   def __init__(self, run_no_page_interactions=False,
-               collect_memory_dumps=False, cache_temperatures=None,
-               verify_names=True):
+               collect_memory_dumps=False, cache_temperatures=None):
     super(_Top10MobilePageSet, self).__init__(
       archive_data_file='data/top_10_mobile.json',
       cloud_storage_bucket=story.PARTNER_BUCKET)
diff --git a/tools/perf/page_sets/top_25_pages.py b/tools/perf/page_sets/top_25_pages.py
index 670aaa39..2032d63 100644
--- a/tools/perf/page_sets/top_25_pages.py
+++ b/tools/perf/page_sets/top_25_pages.py
@@ -15,8 +15,7 @@
   def __init__(self):
     super(Top25PageSet, self).__init__(
         archive_data_file='data/top_25.json',
-        cloud_storage_bucket=story.PARTNER_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PARTNER_BUCKET)
 
     shared_desktop_state = shared_page_state.SharedDesktopPageState
     self.AddStory(top_pages.GoogleWebSearchPage(self, shared_desktop_state))
diff --git a/tools/perf/page_sets/top_25_smooth.py b/tools/perf/page_sets/top_25_smooth.py
index cb90c55..f23261a 100644
--- a/tools/perf/page_sets/top_25_smooth.py
+++ b/tools/perf/page_sets/top_25_smooth.py
@@ -114,8 +114,7 @@
   def __init__(self, techcrunch=True):
     super(Top25SmoothPageSet, self).__init__(
         archive_data_file='data/top_25_smooth.json',
-        cloud_storage_bucket=story.PARTNER_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PARTNER_BUCKET)
 
     desktop_state_class = shared_page_state.SharedDesktopPageState
 
diff --git a/tools/perf/page_sets/tough_ad_cases.py b/tools/perf/page_sets/tough_ad_cases.py
index f1748d01..6ad608b 100644
--- a/tools/perf/page_sets/tough_ad_cases.py
+++ b/tools/perf/page_sets/tough_ad_cases.py
@@ -119,8 +119,7 @@
   def __init__(self):
     super(SyntheticToughAdCasesPageSet, self).__init__(
         archive_data_file='data/tough_ad_cases.json',
-        cloud_storage_bucket=story.INTERNAL_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.INTERNAL_BUCKET)
 
     base_url = 'http://localhost:8000'
 
@@ -150,8 +149,7 @@
   def __init__(self):
     super(SyntheticToughWebglAdCasesPageSet, self).__init__(
         archive_data_file='data/tough_ad_cases.json',
-        cloud_storage_bucket=story.INTERNAL_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.INTERNAL_BUCKET)
 
     base_url = 'http://localhost:8000'
 
@@ -181,8 +179,7 @@
   def __init__(self, scroll=False):
     super(ToughAdCasesPageSet, self).__init__(
         archive_data_file='data/tough_ad_cases.json',
-        cloud_storage_bucket=story.INTERNAL_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.INTERNAL_BUCKET)
 
     self.AddStory(AdPage('file://tough_ad_cases/'
         'swiffy_collection.html', self, make_javascript_deterministic=False,
diff --git a/tools/perf/page_sets/tough_animation_cases.py b/tools/perf/page_sets/tough_animation_cases.py
index 2adafbaf..da5cbf9 100644
--- a/tools/perf/page_sets/tough_animation_cases.py
+++ b/tools/perf/page_sets/tough_animation_cases.py
@@ -31,8 +31,7 @@
   def __init__(self):
     super(ToughAnimationCasesPageSet, self).__init__(
       archive_data_file='data/tough_animation_cases.json',
-      cloud_storage_bucket=story.PARTNER_BUCKET,
-      verify_names=True)
+      cloud_storage_bucket=story.PARTNER_BUCKET)
 
     urls_list_one = [
       # Why: Tests the balls animation implemented with SVG animations.
diff --git a/tools/perf/page_sets/tough_canvas_cases.py b/tools/perf/page_sets/tough_canvas_cases.py
index d9b50b0..aa0ab93 100644
--- a/tools/perf/page_sets/tough_canvas_cases.py
+++ b/tools/perf/page_sets/tough_canvas_cases.py
@@ -43,8 +43,7 @@
   def __init__(self):
     super(ToughCanvasCasesPageSet, self).__init__(
       archive_data_file='data/tough_canvas_cases.json',
-      cloud_storage_bucket=story.PARTNER_BUCKET,
-      verify_names=True)
+      cloud_storage_bucket=story.PARTNER_BUCKET)
 
     # Crashes on Galaxy Nexus. crbug.com/314131
     # self.AddStory(MicrosofFirefliesPage(self))
diff --git a/tools/perf/page_sets/tough_compositor_cases.py b/tools/perf/page_sets/tough_compositor_cases.py
index 82ee6f2f..d49e09e 100644
--- a/tools/perf/page_sets/tough_compositor_cases.py
+++ b/tools/perf/page_sets/tough_compositor_cases.py
@@ -48,8 +48,7 @@
   def __init__(self):
     super(ToughCompositorCasesPageSet, self).__init__(
       archive_data_file='data/tough_compositor_cases.json',
-      cloud_storage_bucket=story.PUBLIC_BUCKET,
-      verify_names=True)
+      cloud_storage_bucket=story.PUBLIC_BUCKET)
 
     scroll_urls_list = [
       # Why: Baseline CC scrolling page. A long page with only text. """
diff --git a/tools/perf/page_sets/tough_filters_cases.py b/tools/perf/page_sets/tough_filters_cases.py
index 7aa88c8..1056d1a 100644
--- a/tools/perf/page_sets/tough_filters_cases.py
+++ b/tools/perf/page_sets/tough_filters_cases.py
@@ -34,8 +34,7 @@
   def __init__(self):
     super(ToughFiltersCasesPageSet, self).__init__(
       archive_data_file='data/tough_filters_cases.json',
-      cloud_storage_bucket=story.PARTNER_BUCKET,
-      verify_names=True)
+      cloud_storage_bucket=story.PARTNER_BUCKET)
 
     urls_list = [
       ('http://rawgit.com/WebKit/webkit/master/PerformanceTests/Animometer/developer.html?test-interval=20&display=minimal&controller=fixed&frame-rate=50&kalman-process-error=1&kalman-measurement-error=4&time-measurement=performance&suite-name=Animometer&test-name=Focus&complexity=100', # pylint: disable=line-too-long
diff --git a/tools/perf/page_sets/tough_image_decode_cases.py b/tools/perf/page_sets/tough_image_decode_cases.py
index a140fdf..fd20064 100644
--- a/tools/perf/page_sets/tough_image_decode_cases.py
+++ b/tools/perf/page_sets/tough_image_decode_cases.py
@@ -31,8 +31,7 @@
   def __init__(self):
     super(ToughImageDecodeCasesPageSet, self).__init__(
       archive_data_file='data/tough_image_decode_cases.json',
-      cloud_storage_bucket=story.PUBLIC_BUCKET,
-      verify_names=True)
+      cloud_storage_bucket=story.PUBLIC_BUCKET)
 
     page_name_list = [
       'http://localhost:9000/cats-unscaled.html',
diff --git a/tools/perf/page_sets/tough_path_rendering_cases.py b/tools/perf/page_sets/tough_path_rendering_cases.py
index c99bb215..debbabf 100644
--- a/tools/perf/page_sets/tough_path_rendering_cases.py
+++ b/tools/perf/page_sets/tough_path_rendering_cases.py
@@ -28,8 +28,7 @@
   def __init__(self):
     super(ToughPathRenderingCasesPageSet, self).__init__(
       archive_data_file='data/tough_path_rendering_cases.json',
-      cloud_storage_bucket=story.PARTNER_BUCKET,
-      verify_names=True)
+      cloud_storage_bucket=story.PARTNER_BUCKET)
 
     page_list = [
       ('GUIMark Vector Chart Test',
diff --git a/tools/perf/page_sets/tough_pinch_zoom_cases.py b/tools/perf/page_sets/tough_pinch_zoom_cases.py
index 371870e2..cecbc7e 100644
--- a/tools/perf/page_sets/tough_pinch_zoom_cases.py
+++ b/tools/perf/page_sets/tough_pinch_zoom_cases.py
@@ -218,8 +218,7 @@
   def __init__(self, target_scale_factor):
     super(ToughPinchZoomCasesPageSet, self).__init__(
       archive_data_file='data/tough_pinch_zoom_cases.json',
-      cloud_storage_bucket=story.PARTNER_BUCKET,
-      verify_names=True)
+      cloud_storage_bucket=story.PARTNER_BUCKET)
 
     self.target_scale_factor = target_scale_factor
 
diff --git a/tools/perf/page_sets/tough_scheduling_cases.py b/tools/perf/page_sets/tough_scheduling_cases.py
index b7b6edba..68e8f48 100644
--- a/tools/perf/page_sets/tough_scheduling_cases.py
+++ b/tools/perf/page_sets/tough_scheduling_cases.py
@@ -397,8 +397,7 @@
   def __init__(self):
     super(ToughSchedulingCasesPageSet, self).__init__(
         archive_data_file='data/tough_scheduling_cases.json',
-        cloud_storage_bucket=story.INTERNAL_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.INTERNAL_BUCKET)
 
     # Why: Simple scrolling baseline
     self.AddStory(ToughSchedulingCasesPage(
diff --git a/tools/perf/page_sets/tough_scrolling_cases.py b/tools/perf/page_sets/tough_scrolling_cases.py
index dce65ce9..0f5e91d 100644
--- a/tools/perf/page_sets/tough_scrolling_cases.py
+++ b/tools/perf/page_sets/tough_scrolling_cases.py
@@ -31,7 +31,7 @@
   """
 
   def __init__(self):
-    super(ToughScrollingCasesPageSet, self).__init__(verify_names=True)
+    super(ToughScrollingCasesPageSet, self).__init__()
 
     fast_scrolling_page_name_list = [
       'text',
diff --git a/tools/perf/page_sets/tough_texture_upload_cases.py b/tools/perf/page_sets/tough_texture_upload_cases.py
index 9f6fe47..cfd686e 100644
--- a/tools/perf/page_sets/tough_texture_upload_cases.py
+++ b/tools/perf/page_sets/tough_texture_upload_cases.py
@@ -27,7 +27,7 @@
   """
 
   def __init__(self):
-    super(ToughTextureUploadCasesPageSet, self).__init__(verify_names=True)
+    super(ToughTextureUploadCasesPageSet, self).__init__()
 
     urls_list = [
       'file://tough_texture_upload_cases/background_color_animation.html',
diff --git a/tools/perf/page_sets/tough_video_cases.py b/tools/perf/page_sets/tough_video_cases.py
index e32cf3ef..80be1cf1 100644
--- a/tools/perf/page_sets/tough_video_cases.py
+++ b/tools/perf/page_sets/tough_video_cases.py
@@ -395,8 +395,7 @@
   """
   def __init__(self, measure_memory=False):
     super(ToughVideoCasesPageSet, self).__init__(
-            cloud_storage_bucket=story.PARTNER_BUCKET,
-            verify_names=True)
+            cloud_storage_bucket=story.PARTNER_BUCKET)
 
     self.measure_memory = measure_memory
 
diff --git a/tools/perf/page_sets/tough_webgl_cases.py b/tools/perf/page_sets/tough_webgl_cases.py
index cdbeacd..34f8d1d7 100644
--- a/tools/perf/page_sets/tough_webgl_cases.py
+++ b/tools/perf/page_sets/tough_webgl_cases.py
@@ -46,8 +46,7 @@
   def __init__(self):
     super(ToughWebglCasesPageSet, self).__init__(
       archive_data_file='data/tough_webgl_cases.json',
-      cloud_storage_bucket=story.PUBLIC_BUCKET,
-      verify_names=True)
+      cloud_storage_bucket=story.PUBLIC_BUCKET)
 
     urls_list = [
       # pylint: disable=line-too-long
diff --git a/tools/perf/page_sets/trivial_sites.py b/tools/perf/page_sets/trivial_sites.py
index 192ce5b..ae951d7 100644
--- a/tools/perf/page_sets/trivial_sites.py
+++ b/tools/perf/page_sets/trivial_sites.py
@@ -133,12 +133,10 @@
 
 class TrivialSitesStorySet(story.StorySet):
   def __init__(self, shared_state = shared_page_state.SharedPageState,
-               wait_in_seconds=0, measure_memory=False,
-               verify_names=True):
+               wait_in_seconds=0, measure_memory=False):
     # Wait is time to wait_in_seconds on page in seconds.
     super(TrivialSitesStorySet, self).__init__(
-        cloud_storage_bucket=story.PUBLIC_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PUBLIC_BUCKET)
     self.AddStory(TrivialScrollingPage(
         self, shared_state, wait_in_seconds, measure_memory))
     self.AddStory(TrivialBlinkingCursorPage(
diff --git a/tools/perf/page_sets/typical_10_mobile.py b/tools/perf/page_sets/typical_10_mobile.py
index 53ffbcc6..7ef61b2 100644
--- a/tools/perf/page_sets/typical_10_mobile.py
+++ b/tools/perf/page_sets/typical_10_mobile.py
@@ -51,8 +51,7 @@
   def __init__(self):
     super(Typical10MobilePageSet, self).__init__(
         archive_data_file='data/typical_10_mobile.json',
-        cloud_storage_bucket=story.PARTNER_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PARTNER_BUCKET)
 
     for url in urls_list:
       self.AddStory(Typical10MobilePage(url, self, name=url))
diff --git a/tools/perf/page_sets/typical_25.py b/tools/perf/page_sets/typical_25.py
index 87fc8e3..fbee296 100644
--- a/tools/perf/page_sets/typical_25.py
+++ b/tools/perf/page_sets/typical_25.py
@@ -37,8 +37,7 @@
                cache_temperatures=None):
     super(Typical25PageSet, self).__init__(
       archive_data_file='data/typical_25.json',
-      cloud_storage_bucket=story.PARTNER_BUCKET,
-      verify_names=True)
+      cloud_storage_bucket=story.PARTNER_BUCKET)
     if cache_temperatures is None:
       cache_temperatures = [cache_temperature_module.ANY]
 
diff --git a/tools/perf/page_sets/v8_top_25.py b/tools/perf/page_sets/v8_top_25.py
index f7f98c93..c34ed2e5 100644
--- a/tools/perf/page_sets/v8_top_25.py
+++ b/tools/perf/page_sets/v8_top_25.py
@@ -67,8 +67,7 @@
   def __init__(self):
     super(V8Top25StorySet, self).__init__(
         archive_data_file='data/v8_top_25.json',
-        cloud_storage_bucket=story.INTERNAL_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.INTERNAL_BUCKET)
 
     for url in urls_list:
       self.AddStory(V8Top25(url, self, url))
diff --git a/tools/perf/page_sets/webrtc_cases.py b/tools/perf/page_sets/webrtc_cases.py
index 9a554a1..582dc53 100644
--- a/tools/perf/page_sets/webrtc_cases.py
+++ b/tools/perf/page_sets/webrtc_cases.py
@@ -122,8 +122,7 @@
 class WebrtcPageSet(story.StorySet):
   def __init__(self):
     super(WebrtcPageSet, self).__init__(
-        cloud_storage_bucket=story.PUBLIC_BUCKET,
-        verify_names=True)
+        cloud_storage_bucket=story.PUBLIC_BUCKET)
 
     self.AddStory(MultiplePeerConnections(self, tags=['stress']))
     self.AddStory(DataChannel(self, tags=['datachannel']))
diff --git a/tools/sublime/OWNERS b/tools/sublime/OWNERS
new file mode 100644
index 0000000..21010ce
--- /dev/null
+++ b/tools/sublime/OWNERS
@@ -0,0 +1,2 @@
+jkarlin@chromium.org
+sashab@chromium.org
diff --git a/ui/events/gesture_detection/gesture_provider.cc b/ui/events/gesture_detection/gesture_provider.cc
index 1572b70..2c0c9bf 100644
--- a/ui/events/gesture_detection/gesture_provider.cc
+++ b/ui/events/gesture_detection/gesture_provider.cc
@@ -327,6 +327,9 @@
           ET_GESTURE_SCROLL_BEGIN, -raw_distance_x, -raw_distance_y);
       scroll_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
 
+      // Scroll focus point always starts with the first touch down point.
+      scroll_focus_point_.SetPoint(e1.GetX(), e1.GetY());
+
       // Use the co-ordinates from the touch down, as these co-ordinates are
       // used to determine which layer the scroll should affect.
       Send(CreateGesture(scroll_details, e2.GetPointerId(), e2.GetToolType(),
@@ -336,18 +339,20 @@
                          e2.GetFlags()));
       DCHECK(scroll_event_sent_);
     }
+    scroll_focus_point_.SetPoint(scroll_focus_point_.x() - raw_distance_x,
+                                 scroll_focus_point_.y() - raw_distance_y);
 
     GestureEventDetails scroll_details(ET_GESTURE_SCROLL_UPDATE, -distance_x,
                                        -distance_y);
     scroll_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
     const gfx::RectF bounding_box = GetBoundingBox(e2, scroll_details.type());
-    const gfx::PointF center = bounding_box.CenterPoint();
     const gfx::PointF raw_center =
-        center + gfx::Vector2dF(e2.GetRawOffsetX(), e2.GetRawOffsetY());
+        scroll_focus_point_ +
+        gfx::Vector2dF(e2.GetRawOffsetX(), e2.GetRawOffsetY());
     Send(CreateGesture(scroll_details, e2.GetPointerId(), e2.GetToolType(),
-                       e2.GetEventTime(), center.x(), center.y(),
-                       raw_center.x(), raw_center.y(), e2.GetPointerCount(),
-                       bounding_box, e2.GetFlags()));
+                       e2.GetEventTime(), scroll_focus_point_.x(),
+                       scroll_focus_point_.y(), raw_center.x(), raw_center.y(),
+                       e2.GetPointerCount(), bounding_box, e2.GetFlags()));
 
     return true;
   }
@@ -747,6 +752,9 @@
   // sequence.
   bool show_press_event_sent_;
 
+  // The scroll focus point is set to the first touch down point when scroll
+  // begins and is later updated based on the delta of touch points.
+  gfx::PointF scroll_focus_point_;
   DISALLOW_COPY_AND_ASSIGN(GestureListenerImpl);
 };
 
diff --git a/ui/events/test/event_generator.cc b/ui/events/test/event_generator.cc
index 190d70e..071198be3 100644
--- a/ui/events/test/event_generator.cc
+++ b/ui/events/test/event_generator.cc
@@ -398,16 +398,90 @@
   callback.Run(ui::ET_GESTURE_SCROLL_END, gfx::Vector2dF());
 }
 
-void EventGenerator::GestureMultiFingerScroll(int count,
-                                              const gfx::Point start[],
-                                              int event_separation_time_ms,
-                                              int steps,
-                                              int move_x,
-                                              int move_y) {
+void EventGenerator::GestureMultiFingerScrollWithDelays(
+    int count,
+    const gfx::Point start[],
+    const gfx::Vector2d delta[],
+    const int delay_adding_finger_ms[],
+    const int delay_releasing_finger_ms[],
+    int event_separation_time_ms,
+    int steps) {
   const int kMaxTouchPoints = 10;
-  int delays[kMaxTouchPoints] = { 0 };
-  GestureMultiFingerScrollWithDelays(
-      count, start, delays, event_separation_time_ms, steps, move_x, move_y);
+  CHECK_LE(count, kMaxTouchPoints);
+  CHECK_GT(steps, 0);
+
+  gfx::Point points[kMaxTouchPoints];
+  gfx::Vector2d delta_per_step[kMaxTouchPoints];
+  for (int i = 0; i < count; ++i) {
+    points[i] = start[i];
+    delta_per_step[i].set_x(delta[i].x() / steps);
+    delta_per_step[i].set_y(delta[i].y() / steps);
+  }
+
+  base::TimeTicks press_time_first = ui::EventTimeForNow();
+  base::TimeTicks press_time[kMaxTouchPoints];
+  base::TimeTicks release_time[kMaxTouchPoints];
+  bool pressed[kMaxTouchPoints];
+  for (int i = 0; i < count; ++i) {
+    pressed[i] = false;
+    press_time[i] = press_time_first +
+        base::TimeDelta::FromMilliseconds(delay_adding_finger_ms[i]);
+    release_time[i] = press_time_first + base::TimeDelta::FromMilliseconds(
+                                             delay_releasing_finger_ms[i]);
+    DCHECK_LE(press_time[i], release_time[i]);
+  }
+
+  for (int step = 0; step < steps; ++step) {
+    base::TimeTicks move_time =
+        press_time_first +
+        base::TimeDelta::FromMilliseconds(event_separation_time_ms * step);
+
+    for (int i = 0; i < count; ++i) {
+      if (!pressed[i] && move_time >= press_time[i]) {
+        ui::TouchEvent press(
+            ui::ET_TOUCH_PRESSED, points[i], press_time[i],
+            ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, i));
+        Dispatch(&press);
+        pressed[i] = true;
+      }
+    }
+
+    // All touch release events should occur at the end if
+    // |event_separation_time_ms| is 0.
+    for (int i = 0; i < count && event_separation_time_ms > 0; ++i) {
+      if (pressed[i] && move_time >= release_time[i]) {
+        ui::TouchEvent release(
+            ui::ET_TOUCH_RELEASED, points[i], release_time[i],
+            ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, i));
+        Dispatch(&release);
+        pressed[i] = false;
+      }
+    }
+
+    for (int i = 0; i < count; ++i) {
+      points[i] += delta_per_step[i];
+      if (pressed[i]) {
+        ui::TouchEvent move(
+            ui::ET_TOUCH_MOVED, points[i], move_time,
+            ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, i));
+        Dispatch(&move);
+      }
+    }
+  }
+
+  base::TimeTicks default_release_time =
+      press_time_first +
+      base::TimeDelta::FromMilliseconds(event_separation_time_ms * steps);
+  // Ensures that all pressed fingers are released in the end.
+  for (int i = 0; i < count; ++i) {
+    if (pressed[i]) {
+      ui::TouchEvent release(
+          ui::ET_TOUCH_RELEASED, points[i], default_release_time,
+          ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, i));
+      Dispatch(&release);
+      pressed[i] = false;
+    }
+  }
 }
 
 void EventGenerator::GestureMultiFingerScrollWithDelays(
@@ -419,64 +493,28 @@
     int move_x,
     int move_y) {
   const int kMaxTouchPoints = 10;
-  gfx::Point points[kMaxTouchPoints];
-  CHECK_LE(count, kMaxTouchPoints);
-  CHECK_GT(steps, 0);
-
-  int delta_x = move_x / steps;
-  int delta_y = move_y / steps;
-
-  for (int i = 0; i < count; ++i) {
-    points[i] = start[i];
+  int delay_releasing_finger_ms[kMaxTouchPoints];
+  gfx::Vector2d delta[kMaxTouchPoints];
+  for (int i = 0; i < kMaxTouchPoints; ++i) {
+    delay_releasing_finger_ms[i] = event_separation_time_ms * steps;
+    delta[i].set_x(move_x);
+    delta[i].set_y(move_y);
   }
+  GestureMultiFingerScrollWithDelays(
+      count, start, delta, delay_adding_finger_ms, delay_releasing_finger_ms,
+      event_separation_time_ms, steps);
+}
 
-  base::TimeTicks press_time_first = ui::EventTimeForNow();
-  base::TimeTicks press_time[kMaxTouchPoints];
-  bool pressed[kMaxTouchPoints];
-  for (int i = 0; i < count; ++i) {
-    pressed[i] = false;
-    press_time[i] = press_time_first +
-        base::TimeDelta::FromMilliseconds(delay_adding_finger_ms[i]);
-  }
-
-  int last_id = 0;
-  for (int step = 0; step < steps; ++step) {
-    base::TimeTicks move_time =
-        press_time_first +
-        base::TimeDelta::FromMilliseconds(event_separation_time_ms * step);
-
-    while (last_id < count &&
-           !pressed[last_id] &&
-           move_time >= press_time[last_id]) {
-      ui::TouchEvent press(
-          ui::ET_TOUCH_PRESSED, points[last_id], press_time[last_id],
-          ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH,
-                             last_id));
-      Dispatch(&press);
-      pressed[last_id] = true;
-      last_id++;
-    }
-
-    for (int i = 0; i < count; ++i) {
-      points[i].Offset(delta_x, delta_y);
-      if (i >= last_id)
-        continue;
-      ui::TouchEvent move(
-          ui::ET_TOUCH_MOVED, points[i], move_time,
-          ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, i));
-      Dispatch(&move);
-    }
-  }
-
-  base::TimeTicks release_time =
-      press_time_first +
-      base::TimeDelta::FromMilliseconds(event_separation_time_ms * steps);
-  for (int i = 0; i < last_id; ++i) {
-    ui::TouchEvent release(
-        ui::ET_TOUCH_RELEASED, points[i], release_time,
-        ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, i));
-    Dispatch(&release);
-  }
+void EventGenerator::GestureMultiFingerScroll(int count,
+                                              const gfx::Point start[],
+                                              int event_separation_time_ms,
+                                              int steps,
+                                              int move_x,
+                                              int move_y) {
+  const int kMaxTouchPoints = 10;
+  int delays[kMaxTouchPoints] = {0};
+  GestureMultiFingerScrollWithDelays(
+      count, start, delays, event_separation_time_ms, steps, move_x, move_y);
 }
 
 void EventGenerator::ScrollSequence(const gfx::Point& start,
diff --git a/ui/events/test/event_generator.h b/ui/events/test/event_generator.h
index c262dcf3..1ce4542 100644
--- a/ui/events/test/event_generator.h
+++ b/ui/events/test/event_generator.h
@@ -356,29 +356,26 @@
   // Generates press, move, release touch-events to generate a sequence of
   // multi-finger scroll events. |count| specifies the number of touch-points
   // that should generate the scroll events. |start| are the starting positions
-  // of all the touch points. |steps| and |event_separation_time_ms| are
-  // relevant when testing velocity/fling/swipe, otherwise these can be any
-  // non-zero value. |delta_x| and |delta_y| are the amount that each finger
-  // should be moved. Internally calls GestureMultiFingerScrollWithDelays
-  // with zeros as |delay_adding_finger_ms| forcing all touch down events to be
-  // immediate.
-  void GestureMultiFingerScroll(int count,
-                                const gfx::Point start[],
-                                int event_separation_time_ms,
-                                int steps,
-                                int move_x,
-                                int move_y);
+  // of all the touch points. |delta| specifies the moving vectors for all
+  // fingers. |delay_adding_finger_ms| are delays in ms from the starting time
+  // till touching down of each finger. |delay_releasing_finger_ms| are delays
+  // in ms from starting time till touching release of each finger. These two
+  // parameters are useful when testing complex gestures that start with 1 or 2
+  // fingers and add fingers with a delay. |steps| and
+  // |event_separation_time_ms| are relevant when testing velocity/fling/swipe,
+  // otherwise these can be any non-zero value.
+  void GestureMultiFingerScrollWithDelays(int count,
+                                          const gfx::Point start[],
+                                          const gfx::Vector2d delta[],
+                                          const int delay_adding_finger_ms[],
+                                          const int delay_releasing_finger_ms[],
+                                          int event_separation_time_ms,
+                                          int steps);
 
-  // Generates press, move, release touch-events to generate a sequence of
-  // multi-finger scroll events. |count| specifies the number of touch-points
-  // that should generate the scroll events. |start| are the starting positions
-  // of all the touch points. |delay_adding_finger_ms| are delays in ms from the
-  // starting time till touching down of each finger. |delay_adding_finger_ms|
-  // is useful when testing complex gestures that start with 1 or 2 fingers and
-  // add fingers with a delay. |steps| and |event_separation_time_ms| are
-  // relevant when testing velocity/fling/swipe, otherwise these can be any
-  // non-zero value. |delta_x| and |delta_y| are the amount that each finger
-  // should be moved.
+  // Similar to GestureMultiFingerScrollWithDelays() above. Generates press,
+  // move, release touch-events to generate a sequence of multi-finger scroll
+  // events. All fingers are released at the end of scrolling together. All
+  // fingers move the same amount specified by |move_x| and |move_y|.
   void GestureMultiFingerScrollWithDelays(int count,
                                           const gfx::Point start[],
                                           const int delay_adding_finger_ms[],
@@ -387,6 +384,18 @@
                                           int move_x,
                                           int move_y);
 
+  // Similar to GestureMultiFingerScrollWithDelays(). Generates press, move,
+  // release touch-events to generate a sequence of multi-finger scroll events.
+  // All fingers are pressed at the beginning together and are released at the
+  // end of scrolling together. All fingers move move the same amount specified
+  // by |move_x| and |move_y|.
+  void GestureMultiFingerScroll(int count,
+                                const gfx::Point start[],
+                                int event_separation_time_ms,
+                                int steps,
+                                int move_x,
+                                int move_y);
+
   // Generates scroll sequences of a FlingCancel, Scrolls, FlingStart, with
   // constant deltas to |x_offset| and |y_offset| in |steps|.
   void ScrollSequence(const gfx::Point& start,
diff --git a/ui/message_center/views/notification_view_md.cc b/ui/message_center/views/notification_view_md.cc
index d8b64def..068a2a55 100644
--- a/ui/message_center/views/notification_view_md.cc
+++ b/ui/message_center/views/notification_view_md.cc
@@ -90,6 +90,41 @@
   return gfx::CreateVectorIcon(kProductIcon, kSmallImageColor);
 }
 
+// ItemView ////////////////////////////////////////////////////////////////////
+
+// ItemViews are responsible for drawing each list notification item's title and
+// message next to each other within a single column.
+class ItemView : public views::View {
+ public:
+  explicit ItemView(const message_center::NotificationItem& item);
+  ~ItemView() override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ItemView);
+};
+
+ItemView::ItemView(const message_center::NotificationItem& item) {
+  SetLayoutManager(
+      new views::BoxLayout(views::BoxLayout::kHorizontal, gfx::Insets(),
+                           message_center::kItemTitleToMessagePadding));
+
+  views::Label* title = new views::Label(item.title);
+  title->set_collapse_when_hidden(true);
+  title->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  title->SetEnabledColor(message_center::kRegularTextColor);
+  title->SetBackgroundColor(message_center::kDimTextBackgroundColor);
+  AddChildView(title);
+
+  views::Label* message = new views::Label(item.message);
+  message->set_collapse_when_hidden(true);
+  message->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  message->SetEnabledColor(message_center::kDimTextColor);
+  message->SetBackgroundColor(message_center::kDimTextBackgroundColor);
+  AddChildView(message);
+}
+
+ItemView::~ItemView() {}
+
 }  // anonymous namespace
 
 // ////////////////////////////////////////////////////////////
@@ -347,6 +382,8 @@
   } else {
     message_view_->SetText(text);
   }
+
+  message_view_->SetVisible(notification.items().empty());
 }
 
 void NotificationViewMD::CreateOrUpdateProgressBarView(
@@ -356,7 +393,21 @@
 
 void NotificationViewMD::CreateOrUpdateListItemViews(
     const Notification& notification) {
-  // TODO(yoshiki): Implement this.
+  for (auto* item_view : item_views_)
+    delete item_view;
+  item_views_.clear();
+
+  const std::vector<NotificationItem>& items = notification.items();
+
+  for (size_t i = 0; i < items.size() && i < kNotificationMaximumItems; ++i) {
+    ItemView* item_view = new ItemView(items[i]);
+    item_views_.push_back(item_view);
+    left_content_->AddChildView(item_view);
+  }
+
+  // Needed when CreateOrUpdateViews is called for update.
+  if (!item_views_.empty())
+    left_content_->InvalidateLayout();
 }
 
 void NotificationViewMD::CreateOrUpdateIconView(
@@ -485,6 +536,10 @@
   if (image_view_)
     return true;
 
+  // Expandable if there are multiple list items.
+  if (item_views_.size() > 1)
+    return true;
+
   // TODO(fukino): Expandable if both progress bar and message exist.
 
   return false;
@@ -507,6 +562,9 @@
   if (image_container_)
     image_container_->SetVisible(expanded);
   actions_row_->SetVisible(expanded && actions_row_->has_children());
+  for (size_t i = 1; i < item_views_.size(); ++i) {
+    item_views_[i]->SetVisible(expanded);
+  }
 }
 
 void NotificationViewMD::UpdateControlButtonsVisibility() {
diff --git a/ui/message_center/views/notification_view_md.h b/ui/message_center/views/notification_view_md.h
index 4d8054e2..38ff06d 100644
--- a/ui/message_center/views/notification_view_md.h
+++ b/ui/message_center/views/notification_view_md.h
@@ -98,6 +98,7 @@
   views::View* image_container_ = nullptr;
   ProportionalImageView* image_view_ = nullptr;
   std::vector<views::LabelButton*> action_buttons_;
+  std::vector<views::View*> item_views_;
 
   DISALLOW_COPY_AND_ASSIGN(NotificationViewMD);
 };
diff --git a/ui/views/bubble/bubble_dialog_delegate.cc b/ui/views/bubble/bubble_dialog_delegate.cc
index b8be537..502bc0b8 100644
--- a/ui/views/bubble/bubble_dialog_delegate.cc
+++ b/ui/views/bubble/bubble_dialog_delegate.cc
@@ -98,7 +98,11 @@
 
 ClientView* BubbleDialogDelegateView::CreateClientView(Widget* widget) {
   DialogClientView* client = new DialogClientView(widget, GetContentsView());
-  client->SetButtonRowInsets(gfx::Insets());
+  LayoutProvider* provider = LayoutProvider::Get();
+  // The other three sides are taken care of by the |margins_| given to
+  // BubbleFrameView in CreateNonClientFrameView().
+  client->SetButtonRowInsets(gfx::Insets(
+      provider->GetDistanceMetric(DISTANCE_BUBBLE_BUTTON_TOP_MARGIN), 0, 0, 0));
   widget->non_client_view()->set_mirror_client_in_rtl(mirror_arrow_in_rtl_);
   return client;
 }
diff --git a/ui/views/layout/layout_provider.cc b/ui/views/layout/layout_provider.cc
index a4fd678..10b40e3 100644
--- a/ui/views/layout/layout_provider.cc
+++ b/ui/views/layout/layout_provider.cc
@@ -86,6 +86,7 @@
       return kRelatedButtonHSpacing;
     case DistanceMetric::DISTANCE_RELATED_CONTROL_HORIZONTAL:
       return kRelatedControlHorizontalSpacing;
+    case DistanceMetric::DISTANCE_BUBBLE_BUTTON_TOP_MARGIN:
     case DistanceMetric::DISTANCE_RELATED_CONTROL_VERTICAL:
       return kRelatedControlVerticalSpacing;
     case DISTANCE_DIALOG_BUTTON_BOTTOM_MARGIN:
diff --git a/ui/views/layout/layout_provider.h b/ui/views/layout/layout_provider.h
index 5d67084..92b5fdf 100644
--- a/ui/views/layout/layout_provider.h
+++ b/ui/views/layout/layout_provider.h
@@ -49,8 +49,11 @@
   // two types have not been interchanged.
   VIEWS_DISTANCE_START = VIEWS_INSETS_MAX,
 
+  // If a bubble has buttons, this is the margin between them and the rest of
+  // the content.
+  DISTANCE_BUBBLE_BUTTON_TOP_MARGIN = VIEWS_DISTANCE_START,
   // Margin on the left and right of the contents of a bubble.
-  DISTANCE_BUBBLE_CONTENTS_HORIZONTAL_MARGIN = VIEWS_DISTANCE_START,
+  DISTANCE_BUBBLE_CONTENTS_HORIZONTAL_MARGIN,
   // Margin on the top and bottom of the contents of a bubble.
   DISTANCE_BUBBLE_CONTENTS_VERTICAL_MARGIN,
   // The default padding to add on each side of a button's label.
diff --git a/ui/views/window/dialog_client_view.cc b/ui/views/window/dialog_client_view.cc
index 0e4a4c34..7d62cadf 100644
--- a/ui/views/window/dialog_client_view.cc
+++ b/ui/views/window/dialog_client_view.cc
@@ -342,17 +342,6 @@
   if (std::count(views.begin(), views.end(), nullptr) == kNumButtons)
     return;
 
-  gfx::Insets insets = button_row_insets_;
-  LayoutProvider* const layout_provider = LayoutProvider::Get();
-  // Support dialogs that clear |button_row_insets_| to do their own layout.
-  // They expect GetDialogRelatedControlVerticalSpacing() in this case.
-  if (insets.top() == 0 &&
-      !ui::MaterialDesignController::IsSecondaryUiMaterial()) {
-    const int top =
-        layout_provider->GetDistanceMetric(DISTANCE_RELATED_CONTROL_VERTICAL);
-    insets.Set(top, insets.left(), insets.bottom(), insets.right());
-  }
-
   // The |resize_percent| constants. There's only one stretchy column (padding
   // to the left of ok/cancel buttons).
   constexpr float kFixed = 0.f;
@@ -361,6 +350,7 @@
   // Button row is [ extra <pad+stretchy> second <pad> third ]. Ensure the <pad>
   // column is zero width if there isn't a button on either side.
   // GetExtraViewSpacing() handles <pad+stretchy>.
+  LayoutProvider* const layout_provider = LayoutProvider::Get();
   const int button_spacing = (ok_button_ && cancel_button_)
                                  ? layout_provider->GetDistanceMetric(
                                        DISTANCE_RELATED_BUTTON_HORIZONTAL)
@@ -371,7 +361,7 @@
 
   // Rather than giving |button_row_container_| a Border, incorporate the insets
   // into the layout. This simplifies min/max size calculations.
-  column_set->AddPaddingColumn(kFixed, insets.left());
+  column_set->AddPaddingColumn(kFixed, button_row_insets_.left());
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, kFixed,
                         GridLayout::USE_PREF, 0, 0);
   column_set->AddPaddingColumn(kStretchy, GetExtraViewSpacing());
@@ -380,14 +370,15 @@
   column_set->AddPaddingColumn(kFixed, button_spacing);
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, kFixed,
                         GridLayout::USE_PREF, 0, 0);
-  column_set->AddPaddingColumn(kFixed, insets.right());
+  column_set->AddPaddingColumn(kFixed, button_row_insets_.right());
 
   // Track which columns to link sizes under MD.
   constexpr int kViewToColumnIndex[] = {1, 3, 5};
   int link[] = {-1, -1, -1};
   size_t link_index = 0;
 
-  layout->StartRowWithPadding(kFixed, kButtonRowId, kFixed, insets.top());
+  layout->StartRowWithPadding(kFixed, kButtonRowId, kFixed,
+                              button_row_insets_.top());
   for (size_t view_index = 0; view_index < kNumButtons; ++view_index) {
     if (views[view_index]) {
       layout->AddView(views[view_index]);
@@ -411,7 +402,7 @@
   else
     column_set->LinkColumnSizes(link[0], link[1], link[2], -1);
 
-  layout->AddPaddingRow(kFixed, insets.bottom());
+  layout->AddPaddingRow(kFixed, button_row_insets_.bottom());
 
   // The default focus is lost when child views are added back into the dialog.
   // This restores focus if the button is still available.