diff --git a/DEPS b/DEPS
index 3bbe73b..e8a3175e 100644
--- a/DEPS
+++ b/DEPS
@@ -64,7 +64,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '54a4214c86bc790cc2a3ae454b1aa709e868fa1a',
+  'pdfium_revision': '952477dbee761a6e38ce675f2095bbfc9cfd7450',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
diff --git a/WATCHLISTS b/WATCHLISTS
index fe14ef5..9fa14fa 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -1698,8 +1698,7 @@
                         'kalyan.kondapally@intel.com',
                         'piman+watch@chromium.org'],
     'auto_bisect': ['auto-bisect-reviews@chromium.org'],
-    'autofill': ['estade+watch@chromium.org',
-                 'rouslan+autofill@chromium.org',
+    'autofill': ['rouslan+autofill@chromium.org',
                  'vabr+watchlistautofill@chromium.org',
                  'mathp+autofillwatch@chromium.org',
                  'sebsg+autofillwatch@chromium.org',
diff --git a/ash/display/extended_mouse_warp_controller.h b/ash/display/extended_mouse_warp_controller.h
index 5c812aa..2e34fa2 100644
--- a/ash/display/extended_mouse_warp_controller.h
+++ b/ash/display/extended_mouse_warp_controller.h
@@ -90,8 +90,6 @@
     DISALLOW_COPY_AND_ASSIGN(WarpRegion);
   };
 
-  std::vector<std::unique_ptr<WarpRegion>> warp_regions_;
-
   // Registers the WarpRegion; also displays a drag indicator on the screen if
   // |has_drag_source| is true.
   void AddWarpRegion(std::unique_ptr<WarpRegion> region, bool has_drag_source);
@@ -123,6 +121,8 @@
 
   bool allow_non_native_event_;
 
+  std::vector<std::unique_ptr<WarpRegion>> warp_regions_;
+
   DISALLOW_COPY_AND_ASSIGN(ExtendedMouseWarpController);
 };
 
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 59acf5c..334d6be 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -580,17 +580,6 @@
     "nix/mime_util_xdg.h",
     "nix/xdg_util.cc",
     "nix/xdg_util.h",
-    "numerics/checked_math.h",
-    "numerics/checked_math_impl.h",
-    "numerics/clamped_math.h",
-    "numerics/clamped_math_impl.h",
-    "numerics/safe_conversions.h",
-    "numerics/safe_conversions_arm_impl.h",
-    "numerics/safe_conversions_impl.h",
-    "numerics/safe_math.h",
-    "numerics/safe_math_arm_impl.h",
-    "numerics/safe_math_clang_gcc_impl.h",
-    "numerics/safe_math_shared_impl.h",
     "observer_list.h",
     "observer_list_threadsafe.h",
     "optional.h",
@@ -1130,6 +1119,7 @@
     ":base_static",
     ":build_date",
     ":debugging_flags",
+    "//base/numerics:base_numerics",
   ]
 
   # Needed for <atomic> if using newer C++ library than sysroot, except if
@@ -2097,7 +2087,6 @@
     "metrics/sparse_histogram_unittest.cc",
     "metrics/statistics_recorder_unittest.cc",
     "native_library_unittest.cc",
-    "numerics/safe_numerics_unittest.cc",
     "observer_list_unittest.cc",
     "optional_unittest.cc",
     "os_compat_android_unittest.cc",
@@ -2119,6 +2108,7 @@
     "profiler/stack_sampling_profiler_unittest.cc",
     "rand_util_unittest.cc",
     "run_loop_unittest.cc",
+    "safe_numerics_unittest.cc",
     "scoped_clear_errno_unittest.cc",
     "scoped_generic_unittest.cc",
     "scoped_native_library_unittest.cc",
diff --git a/base/debug/activity_tracker.cc b/base/debug/activity_tracker.cc
index cff1e47..fb7beb5 100644
--- a/base/debug/activity_tracker.cc
+++ b/base/debug/activity_tracker.cc
@@ -1459,7 +1459,7 @@
 
   // The persistent allocator is thread-safe so run the iteration and
   // adjustments on a worker thread if one was provided.
-  if (task_runner && !task_runner->RunsTasksOnCurrentThread()) {
+  if (task_runner && !task_runner->RunsTasksInCurrentSequence()) {
     task_runner->PostTask(
         FROM_HERE,
         BindOnce(&GlobalActivityTracker::CleanupAfterProcess, Unretained(this),
diff --git a/base/files/file_path_watcher_fsevents.cc b/base/files/file_path_watcher_fsevents.cc
index e9a87b0..49ed36b 100644
--- a/base/files/file_path_watcher_fsevents.cc
+++ b/base/files/file_path_watcher_fsevents.cc
@@ -75,7 +75,7 @@
       weak_factory_(this) {}
 
 FilePathWatcherFSEvents::~FilePathWatcherFSEvents() {
-  DCHECK(!task_runner() || task_runner()->RunsTasksOnCurrentThread());
+  DCHECK(!task_runner() || task_runner()->RunsTasksInCurrentSequence());
   DCHECK(callback_.is_null())
       << "Cancel() must be called before FilePathWatcher is destroyed.";
 }
@@ -188,7 +188,7 @@
 void FilePathWatcherFSEvents::DispatchEvents(const std::vector<FilePath>& paths,
                                              const FilePath& target,
                                              const FilePath& resolved_target) {
-  DCHECK(task_runner()->RunsTasksOnCurrentThread());
+  DCHECK(task_runner()->RunsTasksInCurrentSequence());
 
   // Don't issue callbacks after Cancel() has been called.
   if (is_cancelled() || callback_.is_null()) {
@@ -257,7 +257,7 @@
 }
 
 void FilePathWatcherFSEvents::ReportError(const FilePath& target) {
-  DCHECK(task_runner()->RunsTasksOnCurrentThread());
+  DCHECK(task_runner()->RunsTasksInCurrentSequence());
   if (!callback_.is_null()) {
     callback_.Run(target, true);
   }
diff --git a/base/files/file_path_watcher_kqueue.cc b/base/files/file_path_watcher_kqueue.cc
index a28726a..036809d 100644
--- a/base/files/file_path_watcher_kqueue.cc
+++ b/base/files/file_path_watcher_kqueue.cc
@@ -27,7 +27,7 @@
 FilePathWatcherKQueue::FilePathWatcherKQueue() : kqueue_(-1) {}
 
 FilePathWatcherKQueue::~FilePathWatcherKQueue() {
-  DCHECK(!task_runner() || task_runner()->RunsTasksOnCurrentThread());
+  DCHECK(!task_runner() || task_runner()->RunsTasksInCurrentSequence());
 }
 
 void FilePathWatcherKQueue::ReleaseEvent(struct kevent& event) {
@@ -283,7 +283,7 @@
     return;
   }
 
-  DCHECK(task_runner()->RunsTasksOnCurrentThread());
+  DCHECK(task_runner()->RunsTasksInCurrentSequence());
   if (!is_cancelled()) {
     set_cancelled();
     kqueue_watch_controller_.reset();
@@ -298,7 +298,7 @@
 }
 
 void FilePathWatcherKQueue::OnKQueueReadable() {
-  DCHECK(task_runner()->RunsTasksOnCurrentThread());
+  DCHECK(task_runner()->RunsTasksInCurrentSequence());
   DCHECK(events_.size());
 
   // Request the file system update notifications that have occurred and return
diff --git a/base/files/file_path_watcher_linux.cc b/base/files/file_path_watcher_linux.cc
index 745d3a8..310add2 100644
--- a/base/files/file_path_watcher_linux.cc
+++ b/base/files/file_path_watcher_linux.cc
@@ -316,7 +316,7 @@
     : recursive_(false), weak_factory_(this) {}
 
 FilePathWatcherImpl::~FilePathWatcherImpl() {
-  DCHECK(!task_runner() || task_runner()->RunsTasksOnCurrentThread());
+  DCHECK(!task_runner() || task_runner()->RunsTasksInCurrentSequence());
 }
 
 void FilePathWatcherImpl::OnFilePathChanged(InotifyReader::Watch fired_watch,
@@ -324,7 +324,7 @@
                                             bool created,
                                             bool deleted,
                                             bool is_dir) {
-  DCHECK(!task_runner()->RunsTasksOnCurrentThread());
+  DCHECK(!task_runner()->RunsTasksInCurrentSequence());
 
   // This method is invoked on the Inotify thread. Switch to task_runner() to
   // access |watches_| safely. Use a WeakPtr to prevent the callback from
@@ -342,7 +342,7 @@
     bool created,
     bool deleted,
     bool is_dir) {
-  DCHECK(task_runner()->RunsTasksOnCurrentThread());
+  DCHECK(task_runner()->RunsTasksInCurrentSequence());
   DCHECK(!watches_.empty());
   DCHECK(HasValidWatchVector());
 
@@ -451,7 +451,7 @@
     return;
   }
 
-  DCHECK(task_runner()->RunsTasksOnCurrentThread());
+  DCHECK(task_runner()->RunsTasksInCurrentSequence());
   DCHECK(!is_cancelled());
 
   set_cancelled();
@@ -467,7 +467,7 @@
 void FilePathWatcherImpl::UpdateWatches() {
   // Ensure this runs on the task_runner() exclusively in order to avoid
   // concurrency issues.
-  DCHECK(task_runner()->RunsTasksOnCurrentThread());
+  DCHECK(task_runner()->RunsTasksInCurrentSequence());
   DCHECK(HasValidWatchVector());
 
   // Walk the list of watches and update them as we go.
diff --git a/base/files/file_path_watcher_win.cc b/base/files/file_path_watcher_win.cc
index fba6625..3fc0482 100644
--- a/base/files/file_path_watcher_win.cc
+++ b/base/files/file_path_watcher_win.cc
@@ -81,7 +81,7 @@
 };
 
 FilePathWatcherImpl::~FilePathWatcherImpl() {
-  DCHECK(!task_runner() || task_runner()->RunsTasksOnCurrentThread());
+  DCHECK(!task_runner() || task_runner()->RunsTasksInCurrentSequence());
   if (was_deleted_ptr_)
     *was_deleted_ptr_ = true;
 }
@@ -117,7 +117,7 @@
     return;
   }
 
-  DCHECK(task_runner()->RunsTasksOnCurrentThread());
+  DCHECK(task_runner()->RunsTasksInCurrentSequence());
   set_cancelled();
 
   if (handle_ != INVALID_HANDLE_VALUE)
@@ -127,7 +127,7 @@
 }
 
 void FilePathWatcherImpl::OnObjectSignaled(HANDLE object) {
-  DCHECK(task_runner()->RunsTasksOnCurrentThread());
+  DCHECK(task_runner()->RunsTasksInCurrentSequence());
   DCHECK_EQ(object, handle_);
   DCHECK(!was_deleted_ptr_);
 
diff --git a/base/memory/ref_counted_delete_on_sequence.h b/base/memory/ref_counted_delete_on_sequence.h
index 2be035c..633d3a1 100644
--- a/base/memory/ref_counted_delete_on_sequence.h
+++ b/base/memory/ref_counted_delete_on_sequence.h
@@ -58,7 +58,7 @@
  private:
   void DestructOnSequence() const {
     const T* t = static_cast<const T*>(this);
-    if (task_runner_->RunsTasksOnCurrentThread())
+    if (task_runner_->RunsTasksInCurrentSequence())
       delete t;
     else
       task_runner_->DeleteSoon(FROM_HERE, t);
diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc
index e2668b12..1a020fe 100644
--- a/base/metrics/field_trial.cc
+++ b/base/metrics/field_trial.cc
@@ -1112,7 +1112,7 @@
 }
 
 // static
-bool FieldTrialList::IsFieldTrialListRegisteredForTesting() {
+bool FieldTrialList::IsGlobalSetForTesting() {
   return global_ != nullptr;
 }
 
diff --git a/base/metrics/field_trial.h b/base/metrics/field_trial.h
index d5411329..a7685cd 100644
--- a/base/metrics/field_trial.h
+++ b/base/metrics/field_trial.h
@@ -637,7 +637,7 @@
       PersistentMemoryAllocator const& allocator);
 
   // Returns true if a global field trial list is set. Only used for testing.
-  static bool IsFieldTrialListRegisteredForTesting();
+  static bool IsGlobalSetForTesting();
 
  private:
   // Allow tests to access our innards for testing purposes.
diff --git a/base/numerics/BUILD.gn b/base/numerics/BUILD.gn
new file mode 100644
index 0000000..cbd3ba31
--- /dev/null
+++ b/base/numerics/BUILD.gn
@@ -0,0 +1,25 @@
+# Copyright (c) 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.

+
+# This is a dependency-free, header-only, library, and it needs to stay that
+# way to facilitate pulling it into various third-party projects. So, this
+# file is here to protect against accidentally introducing external
+# dependencies or depending on internal implementation details.
+source_set("base_numerics") {
+  visibility = [ "//base/*" ]
+  sources = [
+    "checked_math_impl.h",
+    "clamped_math_impl.h",
+    "safe_conversions_arm_impl.h",
+    "safe_conversions_impl.h",
+    "safe_math_arm_impl.h",
+    "safe_math_clang_gcc_impl.h",
+  ]
+  public = [
+    "checked_math.h",
+    "clamped_math.h",
+    "safe_conversions.h",
+    "safe_math.h",
+  ]
+}
diff --git a/base/numerics/DEPS b/base/numerics/DEPS
new file mode 100644
index 0000000..d95bf13
--- /dev/null
+++ b/base/numerics/DEPS
@@ -0,0 +1,7 @@
+# This is a dependency-free, header-only, library, and it needs to stay that
+# way to facilitate pulling it into various third-party projects. So, this
+# file is here to protect against accidentally introducing dependencies.
+include_rules = [
+  "-base",
+  "+base/numerics",
+]
diff --git a/base/observer_list_threadsafe.h b/base/observer_list_threadsafe.h
index cc2be59..c107a93 100644
--- a/base/observer_list_threadsafe.h
+++ b/base/observer_list_threadsafe.h
@@ -170,7 +170,7 @@
       auto it = observers_.find(observer);
       if (it == observers_.end())
         return;
-      DCHECK(it->second->RunsTasksOnCurrentThread());
+      DCHECK(it->second->RunsTasksInCurrentSequence());
     }
 
     // Keep track of the notification being dispatched on the current thread.
diff --git a/base/observer_list_unittest.cc b/base/observer_list_unittest.cc
index 132667c..cf1c8037 100644
--- a/base/observer_list_unittest.cc
+++ b/base/observer_list_unittest.cc
@@ -512,7 +512,7 @@
   ~SequenceVerificationObserver() override = default;
 
   void Observe(int x) override {
-    called_on_valid_sequence_ = task_runner_->RunsTasksOnCurrentThread();
+    called_on_valid_sequence_ = task_runner_->RunsTasksInCurrentSequence();
   }
 
   bool called_on_valid_sequence() const { return called_on_valid_sequence_; }
diff --git a/base/numerics/safe_numerics_unittest.cc b/base/safe_numerics_unittest.cc
similarity index 98%
rename from base/numerics/safe_numerics_unittest.cc
rename to base/safe_numerics_unittest.cc
index 5005e52..65f6597 100644
--- a/base/numerics/safe_numerics_unittest.cc
+++ b/base/safe_numerics_unittest.cc
@@ -583,14 +583,15 @@
   using DstLimits = SaturationDefaultLimits<Dst>;
 
   EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid());
-  EXPECT_EQ(false,
-            CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
-                                DstLimits::max()).IsValid());
+  EXPECT_EQ(false, CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
+                                       DstLimits::max())
+                       .IsValid());
   EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDie());
   EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDefault(1));
   EXPECT_EQ(static_cast<Dst>(1),
             CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
-                                DstLimits::max()).ValueOrDefault(1));
+                                DstLimits::max())
+                .ValueOrDefault(1));
 
   // Test the operator combinations.
   TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + CheckedNumeric<Dst>(1));
@@ -915,7 +916,7 @@
 
 template <typename Dst, typename Src>
 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> {
-  static void Test(const char *dst, const char *src, int line) {
+  static void Test(const char* dst, const char* src, int line) {
     using SrcLimits = SaturationDefaultLimits<Src>;
     using DstLimits = SaturationDefaultLimits<Dst>;
     // Integral to floating.
@@ -971,7 +972,7 @@
 
 template <typename Dst, typename Src>
 struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> {
-  static void Test(const char *dst, const char *src, int line) {
+  static void Test(const char* dst, const char* src, int line) {
     using SrcLimits = SaturationDefaultLimits<Src>;
     using DstLimits = SaturationDefaultLimits<Dst>;
     static_assert(SrcLimits::is_signed == DstLimits::is_signed,
@@ -1026,7 +1027,7 @@
 
 template <typename Dst, typename Src>
 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> {
-  static void Test(const char *dst, const char *src, int line) {
+  static void Test(const char* dst, const char* src, int line) {
     using SrcLimits = SaturationDefaultLimits<Src>;
     using DstLimits = SaturationDefaultLimits<Dst>;
     static_assert(MaxExponent<Dst>::value >= MaxExponent<Src>::value,
@@ -1059,7 +1060,7 @@
 
 template <typename Dst, typename Src>
 struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> {
-  static void Test(const char *dst, const char *src, int line) {
+  static void Test(const char* dst, const char* src, int line) {
     using SrcLimits = SaturationDefaultLimits<Src>;
     using DstLimits = SaturationDefaultLimits<Dst>;
     static_assert(MaxExponent<Dst>::value < MaxExponent<Src>::value,
@@ -1118,7 +1119,7 @@
 
 template <typename Dst, typename Src>
 struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> {
-  static void Test(const char *dst, const char *src, int line) {
+  static void Test(const char* dst, const char* src, int line) {
     using SrcLimits = SaturationDefaultLimits<Src>;
     using DstLimits = SaturationDefaultLimits<Dst>;
     static_assert(MaxExponent<Dst>::value <= MaxExponent<Src>::value,
@@ -1243,8 +1244,7 @@
 
 TEST(SafeNumerics, FloatOperations) {
   TEST_NUMERIC_CONVERSION(float, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
-  TEST_NUMERIC_CONVERSION(float, uintmax_t,
-                          SIGN_PRESERVING_VALUE_PRESERVING);
+  TEST_NUMERIC_CONVERSION(float, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
   TEST_NUMERIC_CONVERSION(float, int, SIGN_PRESERVING_VALUE_PRESERVING);
   TEST_NUMERIC_CONVERSION(float, unsigned int,
                           SIGN_PRESERVING_VALUE_PRESERVING);
@@ -1254,8 +1254,7 @@
 
 TEST(SafeNumerics, DoubleOperations) {
   TEST_NUMERIC_CONVERSION(double, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
-  TEST_NUMERIC_CONVERSION(double, uintmax_t,
-                          SIGN_PRESERVING_VALUE_PRESERVING);
+  TEST_NUMERIC_CONVERSION(double, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
   TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING);
   TEST_NUMERIC_CONVERSION(double, unsigned int,
                           SIGN_PRESERVING_VALUE_PRESERVING);
@@ -1354,10 +1353,8 @@
             static_cast<int>(small_negative));
   EXPECT_EQ(saturated_cast<int>(small_positive),
             static_cast<int>(small_positive));
-  EXPECT_EQ(saturated_cast<unsigned>(small_negative),
-            static_cast<unsigned>(0));
-  EXPECT_EQ(saturated_cast<int>(double_small),
-            static_cast<int>(double_small));
+  EXPECT_EQ(saturated_cast<unsigned>(small_negative), static_cast<unsigned>(0));
+  EXPECT_EQ(saturated_cast<int>(double_small), static_cast<int>(double_small));
   EXPECT_EQ(saturated_cast<int>(double_large), numeric_limits<int>::max());
   EXPECT_EQ(saturated_cast<float>(double_large), double_infinity);
   EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity);
diff --git a/base/single_thread_task_runner.h b/base/single_thread_task_runner.h
index 6e931931..12b0575 100644
--- a/base/single_thread_task_runner.h
+++ b/base/single_thread_task_runner.h
@@ -24,10 +24,8 @@
 //     running other kinds of message loop, e.g. Jingle threads.
 class BASE_EXPORT SingleThreadTaskRunner : public SequencedTaskRunner {
  public:
-  // A more explicit alias to RunsTasksOnCurrentThread().
-  bool BelongsToCurrentThread() const {
-    return RunsTasksOnCurrentThread();
-  }
+  // A more explicit alias to RunsTasksInCurrentSequence().
+  bool BelongsToCurrentThread() const { return RunsTasksInCurrentSequence(); }
 
  protected:
   ~SingleThreadTaskRunner() override {}
diff --git a/base/task/cancelable_task_tracker.cc b/base/task/cancelable_task_tracker.cc
index bb3cc019..1b45bcf 100644
--- a/base/task/cancelable_task_tracker.cc
+++ b/base/task/cancelable_task_tracker.cc
@@ -42,7 +42,7 @@
 }
 
 void RunOrPostToTaskRunner(TaskRunner* task_runner, OnceClosure closure) {
-  if (task_runner->RunsTasksOnCurrentThread())
+  if (task_runner->RunsTasksInCurrentSequence())
     std::move(closure).Run();
   else
     task_runner->PostTask(FROM_HERE, std::move(closure));
diff --git a/base/task_runner.h b/base/task_runner.h
index e198f96..468e7e6 100644
--- a/base/task_runner.h
+++ b/base/task_runner.h
@@ -70,12 +70,6 @@
                                OnceClosure task,
                                base::TimeDelta delay) = 0;
 
-  // Drepecated: favor RunsTasksInCurrentSequence().
-  // TODO(http://crbug.com/665062): mass redirect callers and remove this.
-  bool RunsTasksOnCurrentThread() const {
-    return RunsTasksInCurrentSequence();
-  }
-
   // Returns true iff tasks posted to this TaskRunner are sequenced
   // with this call.
   //
diff --git a/base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc b/base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc
index 00ac74c0..2fbcb42 100644
--- a/base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc
+++ b/base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc
@@ -146,7 +146,7 @@
 }
 
 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest,
-       RunsTasksOnCurrentThread) {
+       RunsTasksInCurrentSequence) {
   scoped_refptr<SingleThreadTaskRunner> task_runner_1 =
       single_thread_task_runner_manager_
           ->CreateSingleThreadTaskRunnerWithTraits(
@@ -158,26 +158,28 @@
               "B", {TaskShutdownBehavior::BLOCK_SHUTDOWN},
               SingleThreadTaskRunnerThreadMode::DEDICATED);
 
-  EXPECT_FALSE(task_runner_1->RunsTasksOnCurrentThread());
-  EXPECT_FALSE(task_runner_2->RunsTasksOnCurrentThread());
+  EXPECT_FALSE(task_runner_1->RunsTasksInCurrentSequence());
+  EXPECT_FALSE(task_runner_2->RunsTasksInCurrentSequence());
 
   task_runner_1->PostTask(
-      FROM_HERE, BindOnce(
-                     [](scoped_refptr<SingleThreadTaskRunner> task_runner_1,
-                        scoped_refptr<SingleThreadTaskRunner> task_runner_2) {
-                       EXPECT_TRUE(task_runner_1->RunsTasksOnCurrentThread());
-                       EXPECT_FALSE(task_runner_2->RunsTasksOnCurrentThread());
-                     },
-                     task_runner_1, task_runner_2));
+      FROM_HERE,
+      BindOnce(
+          [](scoped_refptr<SingleThreadTaskRunner> task_runner_1,
+             scoped_refptr<SingleThreadTaskRunner> task_runner_2) {
+            EXPECT_TRUE(task_runner_1->RunsTasksInCurrentSequence());
+            EXPECT_FALSE(task_runner_2->RunsTasksInCurrentSequence());
+          },
+          task_runner_1, task_runner_2));
 
   task_runner_2->PostTask(
-      FROM_HERE, BindOnce(
-                     [](scoped_refptr<SingleThreadTaskRunner> task_runner_1,
-                        scoped_refptr<SingleThreadTaskRunner> task_runner_2) {
-                       EXPECT_FALSE(task_runner_1->RunsTasksOnCurrentThread());
-                       EXPECT_TRUE(task_runner_2->RunsTasksOnCurrentThread());
-                     },
-                     task_runner_1, task_runner_2));
+      FROM_HERE,
+      BindOnce(
+          [](scoped_refptr<SingleThreadTaskRunner> task_runner_1,
+             scoped_refptr<SingleThreadTaskRunner> task_runner_2) {
+            EXPECT_FALSE(task_runner_1->RunsTasksInCurrentSequence());
+            EXPECT_TRUE(task_runner_2->RunsTasksInCurrentSequence());
+          },
+          task_runner_1, task_runner_2));
 
   task_tracker_.Shutdown();
 }
diff --git a/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc b/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc
index 673b69b96..b3ed90c4 100644
--- a/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc
+++ b/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc
@@ -158,7 +158,7 @@
 
  private:
   void Run() override {
-    EXPECT_FALSE(factory_.task_runner()->RunsTasksOnCurrentThread());
+    EXPECT_FALSE(factory_.task_runner()->RunsTasksInCurrentSequence());
 
     for (size_t i = 0; i < kNumTasksPostedPerThread; ++i) {
       if (wait_before_post_task_ ==
@@ -342,12 +342,12 @@
             TimeDelta::FromMilliseconds(250) + TestTimeouts::tiny_timeout());
 }
 
-// Verify that the RunsTasksOnCurrentThread() method of a SEQUENCED TaskRunner
+// Verify that the RunsTasksInCurrentSequence() method of a SEQUENCED TaskRunner
 // returns false when called from a task that isn't part of the sequence. Note:
-// Tests that use TestTaskFactory already verify that RunsTasksOnCurrentThread()
-// returns true when appropriate so this method complements it to get full
-// coverage of that method.
-TEST_P(TaskSchedulerWorkerPoolImplTest, SequencedRunsTasksOnCurrentThread) {
+// Tests that use TestTaskFactory already verify that
+// RunsTasksInCurrentSequence() returns true when appropriate so this method
+// complements it to get full coverage of that method.
+TEST_P(TaskSchedulerWorkerPoolImplTest, SequencedRunsTasksInCurrentSequence) {
   auto task_runner =
       CreateTaskRunnerWithExecutionMode(worker_pool_.get(), GetParam());
   auto sequenced_task_runner =
@@ -360,7 +360,7 @@
       BindOnce(
           [](scoped_refptr<TaskRunner> sequenced_task_runner,
              WaitableEvent* task_ran) {
-            EXPECT_FALSE(sequenced_task_runner->RunsTasksOnCurrentThread());
+            EXPECT_FALSE(sequenced_task_runner->RunsTasksInCurrentSequence());
             task_ran->Signal();
           },
           sequenced_task_runner, Unretained(&task_ran)));
diff --git a/base/task_scheduler/task_scheduler_impl_unittest.cc b/base/task_scheduler/task_scheduler_impl_unittest.cc
index b9b8d13..4cf2f0e 100644
--- a/base/task_scheduler/task_scheduler_impl_unittest.cc
+++ b/base/task_scheduler/task_scheduler_impl_unittest.cc
@@ -149,7 +149,7 @@
 
  private:
   void Run() override {
-    EXPECT_FALSE(factory_.task_runner()->RunsTasksOnCurrentThread());
+    EXPECT_FALSE(factory_.task_runner()->RunsTasksInCurrentSequence());
 
     const size_t kNumTasksPerThread = 150;
     for (size_t i = 0; i < kNumTasksPerThread; ++i) {
@@ -262,7 +262,7 @@
       CreateTaskRunnerWithTraitsAndExecutionMode(&scheduler_, GetParam().traits,
                                                  GetParam().execution_mode),
       GetParam().execution_mode);
-  EXPECT_FALSE(factory.task_runner()->RunsTasksOnCurrentThread());
+  EXPECT_FALSE(factory.task_runner()->RunsTasksInCurrentSequence());
 
   const size_t kNumTasksPerTest = 150;
   for (size_t i = 0; i < kNumTasksPerTest; ++i) {
@@ -382,9 +382,9 @@
                     {MayBlock(), TaskPriority::USER_BLOCKING}));
 }
 
-// Verify that the RunsTasksOnCurrentThread() method of a SequencedTaskRunner
+// Verify that the RunsTasksInCurrentSequence() method of a SequencedTaskRunner
 // returns false when called from a task that isn't part of the sequence.
-TEST_F(TaskSchedulerImplTest, SequencedRunsTasksOnCurrentThread) {
+TEST_F(TaskSchedulerImplTest, SequencedRunsTasksInCurrentSequence) {
   StartTaskScheduler();
   auto single_thread_task_runner =
       scheduler_.CreateSingleThreadTaskRunnerWithTraits(
@@ -399,16 +399,17 @@
       BindOnce(
           [](scoped_refptr<TaskRunner> sequenced_task_runner,
              WaitableEvent* task_ran) {
-            EXPECT_FALSE(sequenced_task_runner->RunsTasksOnCurrentThread());
+            EXPECT_FALSE(sequenced_task_runner->RunsTasksInCurrentSequence());
             task_ran->Signal();
           },
           sequenced_task_runner, Unretained(&task_ran)));
   task_ran.Wait();
 }
 
-// Verify that the RunsTasksOnCurrentThread() method of a SingleThreadTaskRunner
-// returns false when called from a task that isn't part of the sequence.
-TEST_F(TaskSchedulerImplTest, SingleThreadRunsTasksOnCurrentThread) {
+// Verify that the RunsTasksInCurrentSequence() method of a
+// SingleThreadTaskRunner returns false when called from a task that isn't part
+// of the sequence.
+TEST_F(TaskSchedulerImplTest, SingleThreadRunsTasksInCurrentSequence) {
   StartTaskScheduler();
   auto sequenced_task_runner =
       scheduler_.CreateSequencedTaskRunnerWithTraits(TaskTraits());
@@ -423,7 +424,8 @@
       BindOnce(
           [](scoped_refptr<TaskRunner> single_thread_task_runner,
              WaitableEvent* task_ran) {
-            EXPECT_FALSE(single_thread_task_runner->RunsTasksOnCurrentThread());
+            EXPECT_FALSE(
+                single_thread_task_runner->RunsTasksInCurrentSequence());
             task_ran->Signal();
           },
           single_thread_task_runner, Unretained(&task_ran)));
diff --git a/base/task_scheduler/test_task_factory.cc b/base/task_scheduler/test_task_factory.cc
index 8db2042..215e8d12 100644
--- a/base/task_scheduler/test_task_factory.cc
+++ b/base/task_scheduler/test_task_factory.cc
@@ -53,7 +53,7 @@
   if (post_nested_task == PostNestedTask::YES)
     PostTask(PostNestedTask::NO, Closure());
 
-  EXPECT_TRUE(task_runner_->RunsTasksOnCurrentThread());
+  EXPECT_TRUE(task_runner_->RunsTasksInCurrentSequence());
 
   // Verify TaskRunnerHandles are set as expected in the task's scope.
   switch (execution_mode_) {
diff --git a/base/task_scheduler/test_task_factory.h b/base/task_scheduler/test_task_factory.h
index 5bdd561e..5abf0f54 100644
--- a/base/task_scheduler/test_task_factory.h
+++ b/base/task_scheduler/test_task_factory.h
@@ -25,8 +25,8 @@
 
 // A TestTaskFactory posts tasks to a TaskRunner and verifies that they run as
 // expected. Generates a test failure when:
-// - The RunsTasksOnCurrentThread() method of the TaskRunner returns false on a
-//   thread on which a Task is run.
+// - The RunsTasksInCurrentSequence() method of the TaskRunner returns false on
+//   a thread on which a Task is run.
 // - The TaskRunnerHandles set in the context of the task don't match what's
 //   expected for the tested ExecutionMode.
 // - The ExecutionMode of the TaskRunner is SEQUENCED or SINGLE_THREADED and
diff --git a/base/test/scoped_feature_list.cc b/base/test/scoped_feature_list.cc
index d259ba0b..074d8a8 100644
--- a/base/test/scoped_feature_list.cc
+++ b/base/test/scoped_feature_list.cc
@@ -84,11 +84,10 @@
 ScopedFeatureList::ScopedFeatureList() {}
 
 ScopedFeatureList::~ScopedFeatureList() {
-  if (field_trial_override_) {
+  if (field_trial_override_)
     base::FieldTrialParamAssociator::GetInstance()->ClearParamsForTesting(
         field_trial_override_->trial_name(),
         field_trial_override_->group_name());
-  }
 
   if (original_feature_list_) {
     FeatureList::ClearInstanceForTesting();
@@ -127,22 +126,10 @@
   InitWithFeaturesAndFieldTrials({feature}, {}, {});
 }
 
-void ScopedFeatureList::InitAndEnableFeatureWithParameters(
+void ScopedFeatureList::InitAndEnableFeatureWithFieldTrialOverride(
     const Feature& feature,
-    const std::map<std::string, std::string>& feature_parameters) {
-  if (!FieldTrialList::IsFieldTrialListRegisteredForTesting()) {
-    field_trial_list_ = base::MakeUnique<base::FieldTrialList>(nullptr);
-  }
-
-  std::string kTrialName = "scoped_feature_list_trial_name";
-  std::string kTrialGroup = "scoped_feature_list_trial_group";
-  field_trial_override_ =
-      base::FieldTrialList::CreateFieldTrial(kTrialName, kTrialGroup);
-  DCHECK(field_trial_override_);
-  FieldTrialParamAssociator::GetInstance()->AssociateFieldTrialParams(
-      kTrialName, kTrialGroup, feature_parameters);
-  InitAndEnableFeatureWithFieldTrialOverride(feature,
-                                             field_trial_override_.get());
+    FieldTrial* trial) {
+  InitWithFeaturesAndFieldTrials({feature}, {trial}, {});
 }
 
 void ScopedFeatureList::InitAndDisableFeature(const Feature& feature) {
@@ -198,10 +185,22 @@
   InitFromCommandLine(enabled, disabled);
 }
 
-void ScopedFeatureList::InitAndEnableFeatureWithFieldTrialOverride(
+void ScopedFeatureList::InitAndEnableFeatureWithParameters(
     const Feature& feature,
-    FieldTrial* trial) {
-  InitWithFeaturesAndFieldTrials({feature}, {trial}, {});
+    const std::map<std::string, std::string>& feature_parameters) {
+  if (!FieldTrialList::IsGlobalSetForTesting()) {
+    field_trial_list_ = base::MakeUnique<base::FieldTrialList>(nullptr);
+  }
+
+  std::string kTrialName = "scoped_feature_list_trial_name";
+  std::string kTrialGroup = "scoped_feature_list_trial_group";
+  field_trial_override_ =
+      base::FieldTrialList::CreateFieldTrial(kTrialName, kTrialGroup);
+  DCHECK(field_trial_override_);
+  FieldTrialParamAssociator::GetInstance()->AssociateFieldTrialParams(
+      kTrialName, kTrialGroup, feature_parameters);
+  InitAndEnableFeatureWithFieldTrialOverride(feature,
+                                             field_trial_override_.get());
 }
 
 }  // namespace test
diff --git a/base/test/scoped_mock_time_message_loop_task_runner.cc b/base/test/scoped_mock_time_message_loop_task_runner.cc
index 15b07fc..ec9bfa18 100644
--- a/base/test/scoped_mock_time_message_loop_task_runner.cc
+++ b/base/test/scoped_mock_time_message_loop_task_runner.cc
@@ -34,7 +34,7 @@
 }
 
 ScopedMockTimeMessageLoopTaskRunner::~ScopedMockTimeMessageLoopTaskRunner() {
-  DCHECK(previous_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(previous_task_runner_->RunsTasksInCurrentSequence());
   DCHECK_EQ(task_runner_, ThreadTaskRunnerHandle::Get());
   for (auto& pending_task : task_runner_->TakePendingTasks()) {
     // TODO(tzik): Remove RunOnceClosure once TaskRunner migrates from Closure
diff --git a/base/test/task_runner_test_template.cc b/base/test/task_runner_test_template.cc
index 5983b8a..5a72d31a 100644
--- a/base/test/task_runner_test_template.cc
+++ b/base/test/task_runner_test_template.cc
@@ -37,9 +37,9 @@
     task_runs_cv_.Wait();
 }
 
-void ExpectRunsTasksOnCurrentThread(bool expected_value,
-                                    TaskRunner* task_runner) {
-  EXPECT_EQ(expected_value, task_runner->RunsTasksOnCurrentThread());
+void ExpectRunsTasksInCurrentSequence(bool expected_value,
+                                      TaskRunner* task_runner) {
+  EXPECT_EQ(expected_value, task_runner->RunsTasksInCurrentSequence());
 }
 
 }  // namespace test
diff --git a/base/test/task_runner_test_template.h b/base/test/task_runner_test_template.h
index ed04865..fdb9ae9d 100644
--- a/base/test/task_runner_test_template.h
+++ b/base/test/task_runner_test_template.h
@@ -173,10 +173,10 @@
 
 namespace test {
 
-// Calls RunsTasksOnCurrentThread() on |task_runner| and expects it to
+// Calls RunsTasksInCurrentSequence() on |task_runner| and expects it to
 // equal |expected_value|.
-void ExpectRunsTasksOnCurrentThread(bool expected_value,
-                                    TaskRunner* task_runner);
+void ExpectRunsTasksInCurrentSequence(bool expected_value,
+                                      TaskRunner* task_runner);
 
 }  // namespace test
 
@@ -186,10 +186,10 @@
 TYPED_TEST_CASE_P(TaskRunnerAffinityTest);
 
 // Post a bunch of tasks to the task runner as well as to a separate
-// thread, each checking the value of RunsTasksOnCurrentThread(),
+// thread, each checking the value of RunsTasksInCurrentSequence(),
 // which should return true for the tasks posted on the task runner
 // and false for the tasks posted on the separate thread.
-TYPED_TEST_P(TaskRunnerAffinityTest, RunsTasksOnCurrentThread) {
+TYPED_TEST_P(TaskRunnerAffinityTest, RunsTasksInCurrentSequence) {
   std::map<int, int> expected_task_run_counts;
 
   Thread thread("Non-task-runner thread");
@@ -201,11 +201,11 @@
   // the non-task-runner thread.
   for (int i = 0; i < 20; ++i) {
     const Closure& ith_task_runner_task = this->task_tracker_->WrapTask(
-        Bind(&test::ExpectRunsTasksOnCurrentThread, true,
+        Bind(&test::ExpectRunsTasksInCurrentSequence, true,
              base::RetainedRef(task_runner)),
         i);
     const Closure& ith_non_task_runner_task = this->task_tracker_->WrapTask(
-        Bind(&test::ExpectRunsTasksOnCurrentThread, false,
+        Bind(&test::ExpectRunsTasksInCurrentSequence, false,
              base::RetainedRef(task_runner)),
         i);
     for (int j = 0; j < i + 1; ++j) {
@@ -224,7 +224,7 @@
 
 // TaskRunnerAffinityTest tests that the TaskRunner implementation
 // can determine if tasks will never be run on a specific thread.
-REGISTER_TYPED_TEST_CASE_P(TaskRunnerAffinityTest, RunsTasksOnCurrentThread);
+REGISTER_TYPED_TEST_CASE_P(TaskRunnerAffinityTest, RunsTasksInCurrentSequence);
 
 }  // namespace base
 
diff --git a/base/test/test_mock_time_task_runner.cc b/base/test/test_mock_time_task_runner.cc
index dba3083..1926973 100644
--- a/base/test/test_mock_time_task_runner.cc
+++ b/base/test/test_mock_time_task_runner.cc
@@ -128,7 +128,7 @@
 // TestMockTimeTaskRunner -----------------------------------------------------
 
 // TODO(gab): This should also set the SequenceToken for the current thread.
-// Ref. TestMockTimeTaskRunner::RunsTasksOnCurrentThread().
+// Ref. TestMockTimeTaskRunner::RunsTasksInCurrentSequence().
 TestMockTimeTaskRunner::ScopedContext::ScopedContext(
     scoped_refptr<TestMockTimeTaskRunner> scope)
     : on_destroy_(ThreadTaskRunnerHandle::OverrideForTesting(scope)) {
diff --git a/base/test/test_mock_time_task_runner.h b/base/test/test_mock_time_task_runner.h
index 05867303..73b0e53 100644
--- a/base/test/test_mock_time_task_runner.h
+++ b/base/test/test_mock_time_task_runner.h
@@ -31,9 +31,9 @@
 //
 // TestMockTimeTaskRunner has the following properties:
 //
-//   - Methods RunsTasksOnCurrentThread() and Post[Delayed]Task() can be called
-//     from any thread, but the rest of the methods must be called on the same
-//     thread the TaskRunner was created on.
+//   - Methods RunsTasksInCurrentSequence() and Post[Delayed]Task() can be
+//     called from any thread, but the rest of the methods must be called on
+//     the same thread the TaskRunner was created on.
 //   - It allows for reentrancy, in that it handles the running of tasks that in
 //     turn call back into it (e.g., to post more tasks).
 //   - Tasks are stored in a priority queue, and executed in the increasing
@@ -51,8 +51,8 @@
  public:
   // Everything that is executed in the scope of a ScopedContext will behave as
   // though it ran under |scope| (i.e. ThreadTaskRunnerHandle,
-  // RunsTasksOnCurrentThread, etc.). This allows the test body to be all in one
-  // block when multiple TestMockTimeTaskRunners share the main thread. For
+  // RunsTasksInCurrentSequence, etc.). This allows the test body to be all in
+  // one block when multiple TestMockTimeTaskRunners share the main thread. For
   // example:
   //
   //   class ExampleFixture {
@@ -199,7 +199,7 @@
                        const TimeDelta& max_delta,
                        TestPendingTask* next_task);
 
-  // Also used for non-dcheck logic (RunsTasksOnCurrentThread()) and as such
+  // Also used for non-dcheck logic (RunsTasksInCurrentSequence()) and as such
   // needs to be a ThreadCheckerImpl.
   ThreadCheckerImpl thread_checker_;
 
diff --git a/base/threading/sequenced_task_runner_handle.cc b/base/threading/sequenced_task_runner_handle.cc
index 08ac1fb89..6bb11dc 100644
--- a/base/threading/sequenced_task_runner_handle.cc
+++ b/base/threading/sequenced_task_runner_handle.cc
@@ -61,7 +61,7 @@
   DCHECK(sequence_token.IsValid());
   scoped_refptr<SequencedTaskRunner> sequenced_task_runner(
       pool->GetSequencedTaskRunner(sequence_token));
-  DCHECK(sequenced_task_runner->RunsTasksOnCurrentThread());
+  DCHECK(sequenced_task_runner->RunsTasksInCurrentSequence());
   return sequenced_task_runner;
 }
 
@@ -75,13 +75,13 @@
 SequencedTaskRunnerHandle::SequencedTaskRunnerHandle(
     scoped_refptr<SequencedTaskRunner> task_runner)
     : task_runner_(std::move(task_runner)) {
-  DCHECK(task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
   DCHECK(!SequencedTaskRunnerHandle::IsSet());
   lazy_tls_ptr.Pointer()->Set(this);
 }
 
 SequencedTaskRunnerHandle::~SequencedTaskRunnerHandle() {
-  DCHECK(task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
   DCHECK_EQ(lazy_tls_ptr.Pointer()->Get(), this);
   lazy_tls_ptr.Pointer()->Set(nullptr);
 }
diff --git a/base/threading/sequenced_worker_pool.cc b/base/threading/sequenced_worker_pool.cc
index 43f7921..e36999a 100644
--- a/base/threading/sequenced_worker_pool.cc
+++ b/base/threading/sequenced_worker_pool.cc
@@ -875,7 +875,7 @@
       runs_tasks_on_verifier_ = CreateTaskRunnerWithTraits(
           {MayBlock(), WithBaseSyncPrimitives(), task_priority_});
     }
-    return runs_tasks_on_verifier_->RunsTasksOnCurrentThread();
+    return runs_tasks_on_verifier_->RunsTasksInCurrentSequence();
   } else {
     return ContainsKey(threads_, PlatformThread::CurrentId());
   }
@@ -891,7 +891,7 @@
     const auto sequenced_task_runner_it =
         sequenced_task_runner_map_.find(sequence_token.id_);
     return sequenced_task_runner_it != sequenced_task_runner_map_.end() &&
-           sequenced_task_runner_it->second->RunsTasksOnCurrentThread();
+           sequenced_task_runner_it->second->RunsTasksInCurrentSequence();
   } else {
     ThreadMap::const_iterator found =
         threads_.find(PlatformThread::CurrentId());
@@ -1502,7 +1502,7 @@
 
 void SequencedWorkerPool::OnDestruct() const {
   // Avoid deleting ourselves on a worker thread (which would deadlock).
-  if (RunsTasksOnCurrentThread()) {
+  if (RunsTasksInCurrentSequence()) {
     constructor_task_runner_->DeleteSoon(FROM_HERE, this);
   } else {
     delete this;
@@ -1604,7 +1604,7 @@
 }
 
 void SequencedWorkerPool::FlushForTesting() {
-  DCHECK(!RunsTasksOnCurrentThread());
+  DCHECK(!RunsTasksInCurrentSequence());
   base::ThreadRestrictions::ScopedAllowWait allow_wait;
   if (g_all_pools_state == AllPoolsState::REDIRECTED_TO_TASK_SCHEDULER) {
     // TODO(gab): Remove this if http://crbug.com/622400 fails.
@@ -1619,7 +1619,7 @@
 }
 
 void SequencedWorkerPool::Shutdown(int max_new_blocking_tasks_after_shutdown) {
-  DCHECK(constructor_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(constructor_task_runner_->RunsTasksInCurrentSequence());
   inner_->Shutdown(max_new_blocking_tasks_after_shutdown);
 }
 
diff --git a/base/threading/sequenced_worker_pool_unittest.cc b/base/threading/sequenced_worker_pool_unittest.cc
index ccc21d8..d2c0050 100644
--- a/base/threading/sequenced_worker_pool_unittest.cc
+++ b/base/threading/sequenced_worker_pool_unittest.cc
@@ -81,7 +81,7 @@
  protected:
   virtual ~DestructionDeadlockChecker() {
     // This method should not deadlock.
-    pool_->RunsTasksOnCurrentThread();
+    pool_->RunsTasksInCurrentSequence();
   }
 
  private:
@@ -884,16 +884,16 @@
     scoped_refptr<TaskRunner> test_negative_task_runner,
     SequencedWorkerPool* pool,
     SequencedWorkerPool* unused_pool) {
-  EXPECT_TRUE(test_positive_task_runner->RunsTasksOnCurrentThread());
-  EXPECT_FALSE(test_negative_task_runner->RunsTasksOnCurrentThread());
-  EXPECT_TRUE(pool->RunsTasksOnCurrentThread());
+  EXPECT_TRUE(test_positive_task_runner->RunsTasksInCurrentSequence());
+  EXPECT_FALSE(test_negative_task_runner->RunsTasksInCurrentSequence());
+  EXPECT_TRUE(pool->RunsTasksInCurrentSequence());
 
   // Tasks posted to different SequencedWorkerPools may run on the same
   // TaskScheduler threads.
   if (redirected_to_task_scheduler)
-    EXPECT_TRUE(unused_pool->RunsTasksOnCurrentThread());
+    EXPECT_TRUE(unused_pool->RunsTasksInCurrentSequence());
   else
-    EXPECT_FALSE(unused_pool->RunsTasksOnCurrentThread());
+    EXPECT_FALSE(unused_pool->RunsTasksInCurrentSequence());
 }
 
 // Verify correctness of the RunsTasksOnCurrentThread() method on
@@ -909,11 +909,11 @@
 
   SequencedWorkerPoolOwner unused_pool_owner(2, "unused_pool");
 
-  EXPECT_FALSE(pool()->RunsTasksOnCurrentThread());
-  EXPECT_FALSE(sequenced_task_runner_1->RunsTasksOnCurrentThread());
-  EXPECT_FALSE(sequenced_task_runner_2->RunsTasksOnCurrentThread());
-  EXPECT_FALSE(unsequenced_task_runner->RunsTasksOnCurrentThread());
-  EXPECT_FALSE(unused_pool_owner.pool()->RunsTasksOnCurrentThread());
+  EXPECT_FALSE(pool()->RunsTasksInCurrentSequence());
+  EXPECT_FALSE(sequenced_task_runner_1->RunsTasksInCurrentSequence());
+  EXPECT_FALSE(sequenced_task_runner_2->RunsTasksInCurrentSequence());
+  EXPECT_FALSE(unsequenced_task_runner->RunsTasksInCurrentSequence());
+  EXPECT_FALSE(unused_pool_owner.pool()->RunsTasksInCurrentSequence());
 
   // From a task posted to |sequenced_task_runner_1|:
   // - sequenced_task_runner_1->RunsTasksOnCurrentThread() returns true.
diff --git a/base/timer/timer_unittest.cc b/base/timer/timer_unittest.cc
index 75f353f..3e486d01d 100644
--- a/base/timer/timer_unittest.cc
+++ b/base/timer/timer_unittest.cc
@@ -774,7 +774,7 @@
   }
 
   static void VerifyAffinity(const SequencedTaskRunner* task_runner) {
-    EXPECT_TRUE(task_runner->RunsTasksOnCurrentThread());
+    EXPECT_TRUE(task_runner->RunsTasksInCurrentSequence());
   }
 
   // Delete the timer.
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc
index 87c6ead..75b38fa6 100644
--- a/base/trace_event/memory_dump_manager.cc
+++ b/base/trace_event/memory_dump_manager.cc
@@ -378,7 +378,7 @@
     // In all the other cases, it is not possible to guarantee that the
     // unregistration will not race with OnMemoryDump() calls.
     DCHECK((*mdp_iter)->task_runner &&
-           (*mdp_iter)->task_runner->RunsTasksOnCurrentThread())
+           (*mdp_iter)->task_runner->RunsTasksInCurrentSequence())
         << "MemoryDumpProvider \"" << (*mdp_iter)->name << "\" attempted to "
         << "unregister itself in a racy way. Please file a crbug.";
   }
@@ -540,7 +540,7 @@
   }
 
   if (mdpinfo->options.dumps_on_single_thread_task_runner &&
-      task_runner->RunsTasksOnCurrentThread()) {
+      task_runner->RunsTasksInCurrentSequence()) {
     // If |dumps_on_single_thread_task_runner| is true then no PostTask is
     // required if we are on the right thread.
     return InvokeOnMemoryDump(pmd_async_state.release());
@@ -598,7 +598,7 @@
       pmd_async_state->pending_dump_providers.back().get();
 
   DCHECK(!mdpinfo->task_runner ||
-         mdpinfo->task_runner->RunsTasksOnCurrentThread());
+         mdpinfo->task_runner->RunsTasksInCurrentSequence());
 
   bool should_dump;
   {
diff --git a/base/trace_event/memory_dump_manager_unittest.cc b/base/trace_event/memory_dump_manager_unittest.cc
index 28bb5d0..3e111a6 100644
--- a/base/trace_event/memory_dump_manager_unittest.cc
+++ b/base/trace_event/memory_dump_manager_unittest.cc
@@ -459,7 +459,7 @@
         .Times(i)
         .WillRepeatedly(Invoke(
             [task_runner](const MemoryDumpArgs&, ProcessMemoryDump*) -> bool {
-              EXPECT_TRUE(task_runner->RunsTasksOnCurrentThread());
+              EXPECT_TRUE(task_runner->RunsTasksInCurrentSequence());
               return true;
             }));
   }
diff --git a/base/trace_event/memory_dump_scheduler_unittest.cc b/base/trace_event/memory_dump_scheduler_unittest.cc
index b4e534a..02ceca0 100644
--- a/base/trace_event/memory_dump_scheduler_unittest.cc
+++ b/base/trace_event/memory_dump_scheduler_unittest.cc
@@ -187,7 +187,7 @@
   EXPECT_CALL(on_tick_, OnTick(_))
       .WillRepeatedly(
           Invoke([&evt, expected_task_runner](MemoryDumpLevelOfDetail) {
-            EXPECT_TRUE(expected_task_runner->RunsTasksOnCurrentThread());
+            EXPECT_TRUE(expected_task_runner->RunsTasksInCurrentSequence());
             evt.Signal();
           }));
 
@@ -204,7 +204,7 @@
   EXPECT_CALL(on_tick_, OnTick(_))
       .WillRepeatedly(
           Invoke([&evt, expected_task_runner](MemoryDumpLevelOfDetail) {
-            EXPECT_TRUE(expected_task_runner->RunsTasksOnCurrentThread());
+            EXPECT_TRUE(expected_task_runner->RunsTasksInCurrentSequence());
             evt.Signal();
           }));
   scheduler_->Start(config, bg_thread_->task_runner());
diff --git a/base/win/object_watcher.cc b/base/win/object_watcher.cc
index 6abc399..426f52e2 100644
--- a/base/win/object_watcher.cc
+++ b/base/win/object_watcher.cc
@@ -33,7 +33,7 @@
     return false;
 
   // Make sure ObjectWatcher is used in a sequenced fashion.
-  DCHECK(task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
 
   // Blocking call to cancel the wait. Any callbacks already in progress will
   // finish before we return from this call.
diff --git a/base/win/scoped_com_initializer.h b/base/win/scoped_com_initializer.h
index 8efff856..70deba490 100644
--- a/base/win/scoped_com_initializer.h
+++ b/base/win/scoped_com_initializer.h
@@ -9,6 +9,7 @@
 
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/threading/thread_checker.h"
 #include "build/build_config.h"
 
 namespace base {
@@ -37,10 +38,7 @@
   }
 
   ~ScopedCOMInitializer() {
-#ifndef NDEBUG
-    // Using the windows API directly to avoid dependency on platform_thread.
-    DCHECK_EQ(GetCurrentThreadId(), thread_id_);
-#endif
+    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
     if (succeeded())
       CoUninitialize();
   }
@@ -49,26 +47,13 @@
 
  private:
   void Initialize(COINIT init) {
-#ifndef NDEBUG
-    thread_id_ = GetCurrentThreadId();
-#endif
+    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
     hr_ = CoInitializeEx(NULL, init);
-#ifndef NDEBUG
-    if (hr_ == S_FALSE)
-      LOG(ERROR) << "Multiple CoInitialize() calls for thread " << thread_id_;
-    else
-      DCHECK_NE(RPC_E_CHANGED_MODE, hr_) << "Invalid COM thread model change";
-#endif
+    DCHECK_NE(RPC_E_CHANGED_MODE, hr_) << "Invalid COM thread model change";
   }
 
   HRESULT hr_;
-#ifndef NDEBUG
-  // In debug builds we use this variable to catch a potential bug where a
-  // ScopedCOMInitializer instance is deleted on a different thread than it
-  // was initially created on.  If that ever happens it can have bad
-  // consequences and the cause can be tricky to track down.
-  DWORD thread_id_;
-#endif
+  THREAD_CHECKER(thread_checker_);
 
   DISALLOW_COPY_AND_ASSIGN(ScopedCOMInitializer);
 };
diff --git a/base/win/scoped_comptr.h b/base/win/scoped_comptr.h
index 5f9dd41..a7b089e5f 100644
--- a/base/win/scoped_comptr.h
+++ b/base/win/scoped_comptr.h
@@ -216,6 +216,11 @@
   // Allows ScopedComPtr to be passed to functions as a pointer.
   operator T*() { return scoped_com_ptr_; }
 
+  // Equivalent to ComPtrRef's version of this operator.
+  operator typename T::InterfaceType**() {
+    return scoped_com_ptr_->GetAddressOf();
+  }
+
   // Allows IID_PPV_ARGS to perform __uuidof(**(ppType)).
   typename T::InterfaceType* operator*() { return scoped_com_ptr_->Get(); }
 
@@ -225,11 +230,6 @@
 
 }  // details
 
-template <typename T, typename U>
-bool operator==(const T* lhs, const ScopedComPtr<U>& rhs) {
-  return lhs == rhs.Get();
-}
-
 template <typename T>
 bool operator==(const ScopedComPtr<T>& lhs, std::nullptr_t null) {
   return !static_cast<bool>(lhs);
@@ -240,11 +240,6 @@
   return !static_cast<bool>(rhs);
 }
 
-template <typename T, typename U>
-bool operator!=(const T* lhs, const ScopedComPtr<U>& rhs) {
-  return !operator==(lhs, rhs);
-}
-
 template <typename T>
 bool operator!=(const ScopedComPtr<T>& lhs, std::nullptr_t null) {
   return !operator==(lhs, null);
@@ -255,11 +250,6 @@
   return !operator==(null, rhs);
 }
 
-template <typename T>
-std::ostream& operator<<(std::ostream& out, const ScopedComPtr<T>& p) {
-  return out << p.Get();
-}
-
 // Helper to make IID_PPV_ARGS work with ScopedComPtr.
 template <typename T>
 void** IID_PPV_ARGS_Helper(base::win::details::ScopedComPtrRef<T> pp) throw() {
diff --git a/build/toolchain/win/clang_name.gni b/build/toolchain/win/clang_name.gni
new file mode 100644
index 0000000..d72735c
--- /dev/null
+++ b/build/toolchain/win/clang_name.gni
@@ -0,0 +1,7 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# The name of the 64-bit win clang toolchain.
+# TODO(thakis): Remove this again soon, https://crbug.com/748501
+win_clang_x64_toolchain = "//build/toolchain/win:clang_x64"
diff --git a/cc/test/DEPS b/cc/test/DEPS
index fffeee2..c5c9556 100644
--- a/cc/test/DEPS
+++ b/cc/test/DEPS
@@ -14,7 +14,7 @@
 ]
 
 specific_include_rules = {
-  "run_all_unittests\.cc": [
+  "run_all_(perf|unit)tests\.cc": [
     "+mojo/edk/embedder/embedder.h",
   ],
 }
diff --git a/cc/test/run_all_perftests.cc b/cc/test/run_all_perftests.cc
index e2dfbcf2..d6fa7a0 100644
--- a/cc/test/run_all_perftests.cc
+++ b/cc/test/run_all_perftests.cc
@@ -7,10 +7,13 @@
 #include "base/test/launcher/unit_test_launcher.h"
 #include "base/test/test_suite.h"
 #include "cc/test/cc_test_suite.h"
+#include "mojo/edk/embedder/embedder.h"
 
 int main(int argc, char** argv) {
   cc::CCTestSuite test_suite(argc, argv);
 
+  mojo::edk::Init();
+
   // Always run the perf tests serially, to avoid distorting
   // perf measurements with randomness resulting from running
   // in parallel.
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index d0f747b..f801e77 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -1116,11 +1116,18 @@
                              client_name),
           base::saturated_cast<int>(total_memory / 1024));
     }
+
     // GetClientNameForMetrics only returns one non-null value over the lifetime
-    // of the process, so this histogram name is runtime constant.
+    // of the process, so these histogram names are runtime constant.
     UMA_HISTOGRAM_CUSTOM_COUNTS(
         base::StringPrintf("Compositing.%s.NumActiveLayers", client_name),
         base::saturated_cast<int>(active_tree_->NumLayers()), 1, 400, 20);
+
+    UMA_HISTOGRAM_CUSTOM_COUNTS(
+        base::StringPrintf("Compositing.%s.NumActivePictureLayers",
+                           client_name),
+        base::saturated_cast<int>(active_tree_->picture_layers().size()), 1,
+        400, 20);
   }
 
   bool ok = active_tree_->UpdateDrawProperties();
diff --git a/chrome/android/java/res/layout/bottom_control_container.xml b/chrome/android/java/res/layout/bottom_control_container.xml
index 34b469a..1689b55 100644
--- a/chrome/android/java/res/layout/bottom_control_container.xml
+++ b/chrome/android/java/res/layout/bottom_control_container.xml
@@ -9,6 +9,14 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content" >
 
+    <FrameLayout
+        android:id="@+id/bottom_sheet_content"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:paddingBottom="@dimen/bottom_nav_height"
+        android:background="@color/default_primary_color"
+        android:visibility="invisible" />
+
     <org.chromium.chrome.browser.toolbar.ToolbarControlContainer
         android:id="@+id/control_container"
         android:layout_width="match_parent"
@@ -62,13 +70,6 @@
         </view>
     </org.chromium.chrome.browser.toolbar.ToolbarControlContainer>
 
-    <FrameLayout
-        android:id="@+id/bottom_sheet_content"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:paddingBottom="@dimen/bottom_nav_height"
-        android:background="@color/default_primary_color" />
-
     <ViewStub
         android:id="@+id/bottom_omnibox_results_container_stub"
         android:layout_width="match_parent"
diff --git a/chrome/android/java/res/layout/date_divided_adapter_header_view_holder.xml b/chrome/android/java/res/layout/date_divided_adapter_header_view_holder.xml
new file mode 100644
index 0000000..d0bddb7
--- /dev/null
+++ b/chrome/android/java/res/layout/date_divided_adapter_header_view_holder.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content" />
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/history_clear_browsing_data_header.xml b/chrome/android/java/res/layout/history_clear_browsing_data_header.xml
new file mode 100644
index 0000000..207c6ce
--- /dev/null
+++ b/chrome/android/java/res/layout/history_clear_browsing_data_header.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingBottom="8dp"
+    android:background="@null" >
+
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@drawable/list_item_single" >
+        <!-- TODO(twellington): change start/end padding back to 16dp and remove duplicate
+                                FrameLayout when list item background is removed. -->
+        <Button
+            android:id="@+id/clear_browsing_data_button"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="top"
+            style="@style/ButtonCompatBorderless"
+            android:paddingTop="16dp"
+            android:paddingBottom="16dp"
+            android:paddingStart="17dp"
+            android:paddingEnd="17dp"
+            android:gravity="center_vertical|start"
+            android:text="@string/open_clear_browsing_data_dialog_button"
+            android:textAllCaps="true"
+            android:textColor="@color/blue_when_enabled"
+            android:textSize="14sp" />
+    </FrameLayout>
+</FrameLayout>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/history_header.xml b/chrome/android/java/res/layout/history_header.xml
deleted file mode 100644
index 68e401d..0000000
--- a/chrome/android/java/res/layout/history_header.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:layout_marginBottom="8dp" >
-
-    <LinearLayout
-        android:id="@+id/privacy_disclaimers"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical"
-        android:layout_marginTop="8dp"
-        android:visibility="gone"
-        android:layout_marginBottom="16dp" >
-
-        <org.chromium.ui.widget.TextViewWithClickableSpans
-            android:id="@+id/signed_in_not_synced"
-            style="@style/PrivacyDisclaimerText" />
-
-       <org.chromium.ui.widget.TextViewWithClickableSpans
-            android:id="@+id/signed_in_synced"
-            style="@style/PrivacyDisclaimerText" />
-
-       <org.chromium.ui.widget.TextViewWithClickableSpans
-            android:id="@+id/other_forms_of_browsing_history"
-            style="@style/PrivacyDisclaimerText" />
-
-    </LinearLayout>
-
-    <FrameLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:background="@drawable/list_item_single" >
-
-        <!-- TODO(twellington): change start/end padding back to 16dp
-                                when new assets with correct built in padding
-                                are available. -->
-        <Button
-            android:id="@+id/clear_browsing_data_button"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            style="@style/ButtonCompatBorderless"
-            android:paddingTop="16dp"
-            android:paddingBottom="16dp"
-            android:paddingStart="17dp"
-            android:paddingEnd="17dp"
-            android:gravity="center_vertical|start"
-            android:text="@string/open_clear_browsing_data_dialog_button"
-            android:textAllCaps="true"
-            android:textColor="@color/blue_when_enabled"
-            android:textSize="14sp" />
-
-    </FrameLayout>
-</LinearLayout>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/history_privacy_disclaimer_header.xml b/chrome/android/java/res/layout/history_privacy_disclaimer_header.xml
new file mode 100644
index 0000000..cad7fbd
--- /dev/null
+++ b/chrome/android/java/res/layout/history_privacy_disclaimer_header.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:paddingBottom="16dp" >
+
+    <org.chromium.ui.widget.TextViewWithClickableSpans
+        android:id="@+id/signed_in_not_synced"
+        style="@style/PrivacyDisclaimerText" />
+
+    <org.chromium.ui.widget.TextViewWithClickableSpans
+        android:id="@+id/signed_in_synced"
+        style="@style/PrivacyDisclaimerText" />
+
+    <org.chromium.ui.widget.TextViewWithClickableSpans
+        android:id="@+id/other_forms_of_browsing_history"
+        style="@style/PrivacyDisclaimerText" />
+
+    <Space
+        android:id="@+id/privacy_disclaimer_bottom_space"
+        android:layout_width="match_parent"
+        android:layout_height="8dp" />
+</LinearLayout>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/selectable_list_layout.xml b/chrome/android/java/res/layout/selectable_list_layout.xml
index de9117d..95f3b91d 100644
--- a/chrome/android/java/res/layout/selectable_list_layout.xml
+++ b/chrome/android/java/res/layout/selectable_list_layout.xml
@@ -21,6 +21,8 @@
             android:id="@+id/recycler_view"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
+            android:paddingTop="8dp"
+            android:clipToPadding="false"
             android:visibility="gone" />
 
         <TextView
diff --git a/chrome/android/java/res/layout/suggestions_bottom_sheet_content.xml b/chrome/android/java/res/layout/suggestions_bottom_sheet_content.xml
index 78d8cda..73dc38d 100644
--- a/chrome/android/java/res/layout/suggestions_bottom_sheet_content.xml
+++ b/chrome/android/java/res/layout/suggestions_bottom_sheet_content.xml
@@ -6,8 +6,11 @@
 <FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:paddingTop="@dimen/bottom_control_container_height" >
 
+    <!-- TODO(twellington): move padding to the recycler view and set
+         android:cliptoPadding="false" to draw beneath the toolbar. -->
     <org.chromium.chrome.browser.suggestions.SuggestionsRecyclerView
         android:id="@+id/recycler_view"
         android:layout_width="match_parent"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java
index a54b546..c979488 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java
@@ -374,7 +374,7 @@
     /**
      * Updates the request desktop site item's state.
      *
-     * @param requstMenuItem {@link MenuItem} for request desktop site.
+     * @param menu {@link Menu} for request desktop site.
      * @param currentTab      Current tab being displayed.
      */
     protected void updateRequestDesktopSiteMenuItem(Menu menu, Tab currentTab) {
@@ -386,7 +386,10 @@
         String url = currentTab.getUrl();
         boolean isChromeScheme = url.startsWith(UrlConstants.CHROME_URL_PREFIX)
                 || url.startsWith(UrlConstants.CHROME_NATIVE_URL_PREFIX);
-        requestMenuRow.setVisible(!isChromeScheme || currentTab.isNativePage());
+        // Also hide request desktop site on Reader Mode.
+        boolean isDistilledPage = DomDistillerUrlUtils.isDistilledPage(url);
+        requestMenuRow.setVisible(
+                (!isChromeScheme || currentTab.isNativePage()) && !isDistilledPage);
 
         // Mark the checkbox if RDS is activated on this page.
         requestMenuCheck.setChecked(currentTab.getUseDesktopUserAgent());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSheetContent.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSheetContent.java
index 5113024..2b0985a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSheetContent.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSheetContent.java
@@ -13,13 +13,14 @@
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet.BottomSheetContent;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetContentController;
 import org.chromium.chrome.browser.widget.selection.SelectableListToolbar;
+import org.chromium.components.bookmarks.BookmarkId;
 
 /**
  * A {@link BottomSheetContent} holding a {@link BookmarkManager} for display in the BottomSheet.
  */
 public class BookmarkSheetContent implements BottomSheetContent {
     private final View mContentView;
-    private final SelectableListToolbar mToolbarView;
+    private final SelectableListToolbar<BookmarkId> mToolbarView;
     private BookmarkManager mBookmarkManager;
 
     /**
@@ -83,4 +84,9 @@
     public int getType() {
         return BottomSheetContentController.TYPE_BOOKMARKS;
     }
+
+    @Override
+    public boolean applyDefaultTopPadding() {
+        return true;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java
index 7ac2d82..2e6394ff 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java
@@ -111,7 +111,7 @@
     private int mNextTabId = Tab.INVALID_TAB_ID;
 
     // The ratio of dp to px.
-    private final float mDpToPx;
+    protected final float mDpToPx;
 
     /**
      * The {@link Layout} is not usable until sizeChanged is called.
@@ -1082,4 +1082,15 @@
     public void finishAnimationsForTests() {
         if (mLayoutAnimations != null) mLayoutAnimations.updateAndFinish();
     }
+
+    /**
+     * Gets the full screen manager.
+     * @return The {@link ChromeFullscreenManager} manager, possibly null
+     */
+    public ChromeFullscreenManager getFullscreenManager() {
+        if (mTabModelSelector == null) return null;
+        if (mTabModelSelector.getCurrentTab() == null) return null;
+        if (mTabModelSelector.getCurrentTab().getActivity() == null) return null;
+        return mTabModelSelector.getCurrentTab().getActivity().getFullscreenManager();
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/ToolbarSwipeLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/ToolbarSwipeLayout.java
index 9aee397..647ae8ab 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/ToolbarSwipeLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/ToolbarSwipeLayout.java
@@ -195,6 +195,12 @@
     private void prepareLayoutTabForSwipe(LayoutTab layoutTab, boolean anonymizeToolbar) {
         assert layoutTab != null;
         if (layoutTab.shouldStall()) layoutTab.setSaturation(0.0f);
+        float heightDp = layoutTab.getOriginalContentHeight();
+        // Clip the layout tab so it doesn't leak into the toolbar if it's at the bottom
+        if (getFullscreenManager() != null && getFullscreenManager().areBrowserControlsAtBottom()) {
+            heightDp = heightDp - getFullscreenManager().getBottomControlsHeight() / mDpToPx;
+        }
+        layoutTab.setClipSize(layoutTab.getOriginalContentWidth(), heightDp);
         layoutTab.setScale(1.f);
         layoutTab.setBorderScale(1.f);
         layoutTab.setDecorationAlpha(0.f);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
index e958a60..cb8ae58 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.download;
 
+import static org.chromium.chrome.browser.download.DownloadNotificationFactory.buildActionIntent;
+
 import android.app.DownloadManager;
 import android.content.ActivityNotFoundException;
 import android.content.Context;
@@ -1364,7 +1366,7 @@
      */
     @Override
     public void broadcastDownloadAction(DownloadItem downloadItem, String action) {
-        Intent intent = DownloadNotificationService.buildActionIntent(mContext, action,
+        Intent intent = buildActionIntent(mContext, action,
                 LegacyHelpers.buildLegacyContentId(false, downloadItem.getId()),
                 downloadItem.getDownloadInfo().isOffTheRecord());
         mContext.sendBroadcast(intent);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationFactory.java
new file mode 100644
index 0000000..f294aac
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationFactory.java
@@ -0,0 +1,318 @@
+// 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;
+
+import static android.app.DownloadManager.ACTION_NOTIFICATION_CLICKED;
+import static android.app.DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS;
+
+import static org.chromium.chrome.browser.download.DownloadNotificationService.ACTION_DOWNLOAD_CANCEL;
+import static org.chromium.chrome.browser.download.DownloadNotificationService.ACTION_DOWNLOAD_OPEN;
+import static org.chromium.chrome.browser.download.DownloadNotificationService.ACTION_DOWNLOAD_PAUSE;
+import static org.chromium.chrome.browser.download.DownloadNotificationService.ACTION_DOWNLOAD_RESUME;
+import static org.chromium.chrome.browser.download.DownloadNotificationService.ACTION_DOWNLOAD_UPDATE_SUMMARY_ICON;
+import static org.chromium.chrome.browser.download.DownloadNotificationService.EXTRA_DOWNLOAD_CONTENTID_ID;
+import static org.chromium.chrome.browser.download.DownloadNotificationService.EXTRA_DOWNLOAD_CONTENTID_NAMESPACE;
+import static org.chromium.chrome.browser.download.DownloadNotificationService.EXTRA_DOWNLOAD_FILE_PATH;
+import static org.chromium.chrome.browser.download.DownloadNotificationService.EXTRA_IS_OFF_THE_RECORD;
+import static org.chromium.chrome.browser.download.DownloadNotificationService.EXTRA_IS_SUPPORTED_MIME_TYPE;
+import static org.chromium.chrome.browser.download.DownloadNotificationService.EXTRA_NOTIFICATION_BUNDLE_ICON_ID;
+import static org.chromium.chrome.browser.download.DownloadNotificationService.NOTIFICATION_NAMESPACE;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Build;
+import android.os.Bundle;
+
+import com.google.ipc.invalidation.util.Preconditions;
+
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.notifications.ChromeNotificationBuilder;
+import org.chromium.chrome.browser.notifications.NotificationBuilderFactory;
+import org.chromium.chrome.browser.notifications.NotificationConstants;
+import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions;
+import org.chromium.components.offline_items_collection.ContentId;
+import org.chromium.components.offline_items_collection.LegacyHelpers;
+
+/**
+ * Creates and updates notifications related to downloads.
+ */
+public final class DownloadNotificationFactory {
+    // Limit file name to 25 characters. TODO(qinmin): use different limit for different devices?
+    public static final int MAX_FILE_NAME_LENGTH = 25;
+
+    // TODO(jming): Eventually move this to DownloadNotificationStore.
+    enum DownloadStatus {
+        IN_PROGRESS,
+        PAUSED,
+        SUCCESSFUL,
+        FAILED,
+        DELETED,
+        SUMMARY // TODO(jming): Remove when summary notification is no longer in-use.
+    }
+
+    /**
+     * Call from the DownloadNotificationStore when downloads are updated (added, changed, deleted)
+     * to trigger the creation, display, or removal of a corresponding notification.
+     * NOTE: This is currently not being used because DownloadNotificationStore does not yet exist.
+     * @param context of the application.
+     * @param downloadStatus (in progress, paused, successful, failed, deleted, or summary).
+     * @param downloadUpdate information about the download (ie. contentId, fileName, icon, etc).
+     */
+    public static void updateDownloadStatus(
+            Context context, DownloadStatus downloadStatus, DownloadUpdate downloadUpdate) {
+        NotificationManager notificationManager =
+                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+        if (downloadStatus == DownloadStatus.DELETED) {
+            notificationManager.cancel(NOTIFICATION_NAMESPACE, downloadUpdate.getNotificationId());
+        } else {
+            Notification notification = buildNotification(context, downloadStatus, downloadUpdate);
+            notificationManager.notify(
+                    NOTIFICATION_NAMESPACE, downloadUpdate.getNotificationId(), notification);
+        }
+    }
+
+    /**
+     * Builds a downloads notification based on the status of the download and its information.
+     * @param context of the download.
+     * @param downloadStatus (in progress, paused, successful, failed, deleted, or summary).
+     * @param downloadUpdate information about the download (ie. contentId, fileName, icon, etc).
+     * @return Notification that is built based on these parameters.
+     */
+    public static Notification buildNotification(
+            Context context, DownloadStatus downloadStatus, DownloadUpdate downloadUpdate) {
+        ChromeNotificationBuilder builder =
+                NotificationBuilderFactory
+                        .createChromeNotificationBuilder(
+                                true /* preferCompat */, ChannelDefinitions.CHANNEL_ID_DOWNLOADS)
+                        .setLocalOnly(true)
+                        .setGroup(NotificationConstants.GROUP_DOWNLOADS);
+
+        String contentText;
+        int iconId;
+
+        switch (downloadStatus) {
+            case IN_PROGRESS:
+                Preconditions.checkNotNull(downloadUpdate.getProgress());
+                Preconditions.checkNotNull(downloadUpdate.getContentId());
+                Preconditions.checkArgument(downloadUpdate.getNotificationId() != -1);
+
+                boolean indeterminate = downloadUpdate.getProgress().isIndeterminate()
+                        || downloadUpdate.getIsDownloadPending();
+                if (downloadUpdate.getIsDownloadPending()) {
+                    contentText = context.getResources().getString(
+                            R.string.download_notification_pending);
+                } else if (indeterminate || downloadUpdate.getTimeRemainingInMillis() < 0) {
+                    // TODO(dimich): Enable the byte count back in M59. See bug 704049 for more info
+                    // and details of what was temporarily reverted (for M58).
+                    contentText = context.getResources().getString(R.string.download_started);
+                } else {
+                    contentText = DownloadUtils.getTimeOrFilesLeftString(context,
+                            downloadUpdate.getProgress(),
+                            downloadUpdate.getTimeRemainingInMillis());
+                }
+                iconId = downloadUpdate.getIsDownloadPending()
+                        ? R.drawable.ic_download_pending
+                        : android.R.drawable.stat_sys_download;
+
+                Intent pauseIntent = buildActionIntent(context, ACTION_DOWNLOAD_PAUSE,
+                        downloadUpdate.getContentId(), downloadUpdate.getIsOffTheRecord());
+                Intent cancelIntent = buildActionIntent(context, ACTION_DOWNLOAD_CANCEL,
+                        downloadUpdate.getContentId(), downloadUpdate.getIsOffTheRecord());
+
+                builder.setOngoing(true)
+                        .setPriority(Notification.PRIORITY_HIGH)
+                        .setAutoCancel(false)
+                        .setLargeIcon(downloadUpdate.getIcon())
+                        .addAction(R.drawable.ic_pause_white_24dp,
+                                context.getResources().getString(
+                                        R.string.download_notification_pause_button),
+                                buildPendingIntent(
+                                        context, pauseIntent, downloadUpdate.getNotificationId()))
+                        .addAction(R.drawable.btn_close_white,
+                                context.getResources().getString(
+                                        R.string.download_notification_cancel_button),
+                                buildPendingIntent(
+                                        context, cancelIntent, downloadUpdate.getNotificationId()));
+
+                if (!downloadUpdate.getIsDownloadPending()) {
+                    builder.setProgress(100,
+                            indeterminate ? -1 : downloadUpdate.getProgress().getPercentage(),
+                            indeterminate);
+                }
+
+                if (!indeterminate
+                        && !LegacyHelpers.isLegacyOfflinePage(downloadUpdate.getContentId())) {
+                    String percentText = DownloadUtils.getPercentageString(
+                            downloadUpdate.getProgress().getPercentage());
+                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+                        builder.setSubText(percentText);
+                    } else {
+                        builder.setContentInfo(percentText);
+                    }
+                }
+
+                if (downloadUpdate.getStartTime() > 0) {
+                    builder.setWhen(downloadUpdate.getStartTime());
+                }
+
+                break;
+            case PAUSED:
+                Preconditions.checkNotNull(downloadUpdate.getContentId());
+                Preconditions.checkArgument(downloadUpdate.getNotificationId() != -1);
+
+                contentText =
+                        context.getResources().getString(R.string.download_notification_paused);
+                iconId = R.drawable.ic_download_pause;
+
+                Intent resumeIntent = buildActionIntent(context, ACTION_DOWNLOAD_RESUME,
+                        downloadUpdate.getContentId(), downloadUpdate.getIsOffTheRecord());
+                cancelIntent = buildActionIntent(context, ACTION_DOWNLOAD_CANCEL,
+                        downloadUpdate.getContentId(), downloadUpdate.getIsOffTheRecord());
+
+                PendingIntent deleteIntent = downloadUpdate.getIsTransient()
+                        ? buildPendingIntent(
+                                  context, cancelIntent, downloadUpdate.getNotificationId())
+                        : buildSummaryIconIntent(context, downloadUpdate.getNotificationId());
+
+                builder.setAutoCancel(false)
+                        .setLargeIcon(downloadUpdate.getIcon())
+                        .addAction(R.drawable.ic_file_download_white_24dp,
+                                context.getResources().getString(
+                                        R.string.download_notification_resume_button),
+                                buildPendingIntent(
+                                        context, resumeIntent, downloadUpdate.getNotificationId()))
+                        .addAction(R.drawable.btn_close_white,
+                                context.getResources().getString(
+                                        R.string.download_notification_cancel_button),
+                                buildPendingIntent(
+                                        context, cancelIntent, downloadUpdate.getNotificationId()))
+                        .setDeleteIntent(deleteIntent);
+
+                break;
+            case SUCCESSFUL:
+                Preconditions.checkArgument(downloadUpdate.getNotificationId() != -1);
+
+                contentText =
+                        context.getResources().getString(R.string.download_notification_completed);
+                iconId = R.drawable.offline_pin;
+
+                if (downloadUpdate.getIsOpenable()) {
+                    Intent intent;
+                    if (LegacyHelpers.isLegacyDownload(downloadUpdate.getContentId())) {
+                        Preconditions.checkNotNull(downloadUpdate.getContentId());
+                        Preconditions.checkArgument(downloadUpdate.getSystemDownloadId() != -1);
+
+                        intent = new Intent(ACTION_NOTIFICATION_CLICKED);
+                        long[] idArray = {downloadUpdate.getSystemDownloadId()};
+                        intent.putExtra(EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS, idArray);
+                        intent.putExtra(EXTRA_DOWNLOAD_FILE_PATH, downloadUpdate.getFilePath());
+                        intent.putExtra(EXTRA_IS_SUPPORTED_MIME_TYPE,
+                                downloadUpdate.getIsSupportedMimeType());
+                        intent.putExtra(
+                                EXTRA_IS_OFF_THE_RECORD, downloadUpdate.getIsOffTheRecord());
+                        intent.putExtra(
+                                EXTRA_DOWNLOAD_CONTENTID_ID, downloadUpdate.getContentId().id);
+                        intent.putExtra(EXTRA_DOWNLOAD_CONTENTID_NAMESPACE,
+                                downloadUpdate.getContentId().namespace);
+                        intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_ID,
+                                downloadUpdate.getNotificationId());
+                    } else {
+                        intent = buildActionIntent(context, ACTION_DOWNLOAD_OPEN,
+                                downloadUpdate.getContentId(), false);
+                    }
+
+                    ComponentName component = new ComponentName(
+                            context.getPackageName(), DownloadBroadcastReceiver.class.getName());
+                    intent.setComponent(component);
+                    builder.setContentIntent(
+                            PendingIntent.getBroadcast(context, downloadUpdate.getNotificationId(),
+                                    intent, PendingIntent.FLAG_UPDATE_CURRENT));
+                }
+                builder.setDeleteIntent(
+                        buildSummaryIconIntent(context, downloadUpdate.getNotificationId()));
+                break;
+            case FAILED:
+                iconId = android.R.drawable.stat_sys_download_done;
+                contentText =
+                        context.getResources().getString(R.string.download_notification_failed);
+                break;
+            case SUMMARY:
+                Preconditions.checkArgument(downloadUpdate.getIconId() != -1);
+
+                iconId = downloadUpdate.getIconId();
+                contentText = "";
+                builder.setContentTitle(
+                               context.getString(R.string.download_notification_summary_title))
+                        .setSubText(context.getString(R.string.menu_downloads))
+                        .setSmallIcon(iconId)
+                        .setGroupSummary(true);
+                break;
+            default:
+                iconId = -1;
+                contentText = "";
+                break;
+        }
+
+        Bundle extras = new Bundle();
+        extras.putInt(EXTRA_NOTIFICATION_BUNDLE_ICON_ID, iconId);
+
+        builder.setContentText(contentText).setSmallIcon(iconId).addExtras(extras);
+
+        if (downloadUpdate.getFileName() != null) {
+            builder.setContentTitle(DownloadUtils.getAbbreviatedFileName(
+                    downloadUpdate.getFileName(), MAX_FILE_NAME_LENGTH));
+        }
+        if (downloadUpdate.getIcon() != null) builder.setLargeIcon(downloadUpdate.getIcon());
+        if (!downloadUpdate.getIsTransient() && downloadUpdate.getNotificationId() != -1) {
+            Intent downloadHomeIntent =
+                    buildActionIntent(context, ACTION_NOTIFICATION_CLICKED, null, false);
+            builder.setContentIntent(
+                    PendingIntent.getBroadcast(context, downloadUpdate.getNotificationId(),
+                            downloadHomeIntent, PendingIntent.FLAG_UPDATE_CURRENT));
+        }
+
+        return builder.build();
+    }
+
+    /**
+     * Helper method to build a PendingIntent from the provided intent.
+     * @param intent Intent to broadcast.
+     * @param notificationId ID of the notification.
+     */
+    private static PendingIntent buildPendingIntent(
+            Context context, Intent intent, int notificationId) {
+        return PendingIntent.getBroadcast(
+                context, notificationId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+    }
+
+    private static PendingIntent buildSummaryIconIntent(Context context, int notificationId) {
+        Intent intent = new Intent(context, DownloadBroadcastReceiver.class);
+        intent.setAction(ACTION_DOWNLOAD_UPDATE_SUMMARY_ICON);
+        return buildPendingIntent(context, intent, notificationId);
+    }
+
+    /**
+     * Helper method to build an download action Intent from the provided information.
+     * @param context {@link Context} to pull resources from.
+     * @param action Download action to perform.
+     * @param id The {@link ContentId} of the download.
+     * @param isOffTheRecord Whether the download is incognito.
+     */
+    public static Intent buildActionIntent(
+            Context context, String action, ContentId id, boolean isOffTheRecord) {
+        ComponentName component = new ComponentName(
+                context.getPackageName(), DownloadBroadcastReceiver.class.getName());
+        Intent intent = new Intent(action);
+        intent.setComponent(component);
+        intent.putExtra(EXTRA_DOWNLOAD_CONTENTID_ID, id != null ? id.id : "");
+        intent.putExtra(EXTRA_DOWNLOAD_CONTENTID_NAMESPACE, id != null ? id.namespace : "");
+        intent.putExtra(EXTRA_IS_OFF_THE_RECORD, isOffTheRecord);
+        return intent;
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
index e54ed5e..38a59e5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
@@ -6,10 +6,8 @@
 
 import android.annotation.SuppressLint;
 import android.annotation.TargetApi;
-import android.app.DownloadManager;
 import android.app.Notification;
 import android.app.NotificationManager;
-import android.app.PendingIntent;
 import android.app.Service;
 import android.content.ComponentName;
 import android.content.Context;
@@ -24,7 +22,6 @@
 import android.graphics.drawable.shapes.OvalShape;
 import android.os.Binder;
 import android.os.Build;
-import android.os.Bundle;
 import android.os.IBinder;
 import android.service.notification.StatusBarNotification;
 import android.text.TextUtils;
@@ -47,8 +44,6 @@
 import org.chromium.chrome.browser.init.BrowserParts;
 import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
 import org.chromium.chrome.browser.init.EmptyBrowserParts;
-import org.chromium.chrome.browser.notifications.ChromeNotificationBuilder;
-import org.chromium.chrome.browser.notifications.NotificationBuilderFactory;
 import org.chromium.chrome.browser.notifications.NotificationConstants;
 import org.chromium.chrome.browser.notifications.NotificationUmaTracker;
 import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions;
@@ -101,21 +96,19 @@
     public static final String ACTION_DOWNLOAD_FAIL_SAFE =
             "org.chromium.chrome.browser.download.ACTION_SUMMARY_FAIL_SAFE";
 
-    static final String NOTIFICATION_NAMESPACE = "DownloadNotificationService";
-    private static final String TAG = "DownloadNotification";
-    // Limit file name to 25 characters. TODO(qinmin): use different limit for different devices?
-    private static final int MAX_FILE_NAME_LENGTH = 25;
+    public static final String NOTIFICATION_NAMESPACE = "DownloadNotificationService";
 
-    /** Notification Id starting value, to avoid conflicts from IDs used in prior versions. */
-
-    private static final String EXTRA_NOTIFICATION_BUNDLE_ICON_ID =
+    public static final String EXTRA_NOTIFICATION_BUNDLE_ICON_ID =
             "Chrome.NotificationBundleIconIdExtra";
+    /** Notification Id starting value, to avoid conflicts from IDs used in prior versions. */
     private static final int STARTING_NOTIFICATION_ID = 1000000;
     private static final int MAX_RESUMPTION_ATTEMPT_LEFT = 5;
 
     private static final String KEY_AUTO_RESUMPTION_ATTEMPT_LEFT = "ResumptionAttemptLeft";
     private static final String KEY_NEXT_DOWNLOAD_NOTIFICATION_ID = "NextDownloadNotificationId";
 
+    private static final String TAG = "DownloadNotification";
+
     /**
      * An Observer interface that allows other classes to know when this class is canceling
      * downloads.
@@ -235,8 +228,10 @@
                 getSummaryIcon(context, manager, removedNotificationId, addedNotification);
         if (!icon.first || !hasDownloadNotifications(manager, removedNotificationId)) return;
 
-        manager.notify(NotificationConstants.NOTIFICATION_ID_DOWNLOAD_SUMMARY,
-                buildSummaryNotificationWithIcon(context, icon.second));
+        DownloadUpdate downloadUpdate = new DownloadUpdate.Builder().setIconId(icon.second).build();
+        Notification notification = DownloadNotificationFactory.buildNotification(
+                context, DownloadNotificationFactory.DownloadStatus.SUMMARY, downloadUpdate);
+        manager.notify(NotificationConstants.NOTIFICATION_ID_DOWNLOAD_SUMMARY, notification);
     }
 
     /**
@@ -351,41 +346,6 @@
     }
 
     /**
-     * Builds a summary notification that represents all downloads.
-     * {@see #buildSummaryNotification(Context)}.
-     * @param context A context used to query Android strings and resources.
-     * @param iconId  The id of an icon to use for the notification.
-     * @return        a {@link Notification} that represents the summary icon for all downloads.
-     */
-    private static Notification buildSummaryNotificationWithIcon(Context context, int iconId) {
-        ChromeNotificationBuilder builder =
-                NotificationBuilderFactory
-                        .createChromeNotificationBuilder(
-                                true /* preferCompat */, ChannelDefinitions.CHANNEL_ID_DOWNLOADS)
-                        .setContentTitle(
-                                context.getString(R.string.download_notification_summary_title))
-                        .setSubText(context.getString(R.string.menu_downloads))
-                        .setSmallIcon(iconId)
-                        .setLocalOnly(true)
-                        .setGroup(NotificationConstants.GROUP_DOWNLOADS)
-                        .setGroupSummary(true);
-        Bundle extras = new Bundle();
-        extras.putInt(EXTRA_NOTIFICATION_BUNDLE_ICON_ID, iconId);
-        builder.addExtras(extras);
-
-        // This notification should not actually be shown.  But if it is, set the click intent to
-        // open downloads home.
-        // TODO(dtrainor): Only do this if we have no transient downloads.
-        Intent downloadHomeIntent = buildActionIntent(
-                context, DownloadManager.ACTION_NOTIFICATION_CLICKED, null, false);
-        builder.setContentIntent(PendingIntent.getBroadcast(context,
-                NotificationConstants.NOTIFICATION_ID_DOWNLOAD_SUMMARY, downloadHomeIntent,
-                PendingIntent.FLAG_UPDATE_CURRENT));
-
-        return builder.build();
-    }
-
-    /**
      * Builds a summary notification that represents downloads.  This is the notification passed to
      * {@link #startForeground(int, Notification)}, which keeps this service in the foreground.
      * @param context The context used to build the notification and pull specific resources.
@@ -395,7 +355,9 @@
     private static Notification buildSummaryNotification(
             Context context, NotificationManager manager) {
         Pair<Boolean, Integer> icon = getSummaryIcon(context, manager, -1, null);
-        return buildSummaryNotificationWithIcon(context, icon.second);
+        DownloadUpdate downloadUpdate = new DownloadUpdate.Builder().setIconId(icon.second).build();
+        return DownloadNotificationFactory.buildNotification(
+                context, DownloadNotificationFactory.DownloadStatus.SUMMARY, downloadUpdate);
     }
 
     /**
@@ -802,62 +764,23 @@
             long bytesReceived, long timeRemainingInMillis, long startTime, boolean isOffTheRecord,
             boolean canDownloadWhileMetered, boolean isDownloadPending, boolean isTransient,
             Bitmap icon) {
-        boolean indeterminate = (progress.isIndeterminate() || isDownloadPending);
-        String contentText = null;
-        if (isDownloadPending) {
-            contentText = mContext.getResources().getString(R.string.download_notification_pending);
-        } else if (indeterminate || timeRemainingInMillis < 0) {
-            // TODO(dimich): Enable the byte count back in M59. See bug 704049 for more info and
-            // details of what was temporarily reverted (for M58).
-            contentText = mContext.getResources().getString(R.string.download_started);
-        } else {
-            contentText = DownloadUtils.getTimeOrFilesLeftString(
-                    mContext, progress, timeRemainingInMillis);
-        }
-        int resId = isDownloadPending ? R.drawable.ic_download_pending
-                : android.R.drawable.stat_sys_download;
-        ChromeNotificationBuilder builder = buildNotification(resId, fileName, contentText);
-        builder.setOngoing(true);
-        builder.setPriority(Notification.PRIORITY_HIGH);
-
-        // Avoid animations while the download isn't progressing.
-        if (!isDownloadPending) {
-            builder.setProgress(100, indeterminate ? -1 : progress.getPercentage(), indeterminate);
-        }
-
-        if (!indeterminate && !LegacyHelpers.isLegacyOfflinePage(id)) {
-            String percentText = DownloadUtils.getPercentageString(progress.getPercentage());
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-                builder.setSubText(percentText);
-            } else {
-                builder.setContentInfo(percentText);
-            }
-        }
         int notificationId = getNotificationId(id);
-        if (startTime > 0) builder.setWhen(startTime);
+        DownloadUpdate downloadUpdate = new DownloadUpdate.Builder()
+                                                .setContentId(id)
+                                                .setFileName(fileName)
+                                                .setProgress(progress)
+                                                .setTimeRemainingInMillis(timeRemainingInMillis)
+                                                .setStartTime(startTime)
+                                                .setIsOffTheRecord(isOffTheRecord)
+                                                .setIsDownloadPending(isDownloadPending)
+                                                .setIsTransient(isTransient)
+                                                .setIcon(icon)
+                                                .setNotificationId(notificationId)
+                                                .build();
+        Notification notification = DownloadNotificationFactory.buildNotification(
+                mContext, DownloadNotificationFactory.DownloadStatus.IN_PROGRESS, downloadUpdate);
 
-        if (!isTransient) {
-            // Clicking on an in-progress download sends the user to see all their downloads.
-            Intent downloadHomeIntent = buildActionIntent(
-                    mContext, DownloadManager.ACTION_NOTIFICATION_CLICKED, null, isOffTheRecord);
-            builder.setContentIntent(PendingIntent.getBroadcast(mContext, notificationId,
-                    downloadHomeIntent, PendingIntent.FLAG_UPDATE_CURRENT));
-        }
-        builder.setAutoCancel(false);
-        if (icon != null) builder.setLargeIcon(icon);
-
-        Intent pauseIntent = buildActionIntent(mContext, ACTION_DOWNLOAD_PAUSE, id, isOffTheRecord);
-        builder.addAction(R.drawable.ic_pause_white_24dp,
-                mContext.getResources().getString(R.string.download_notification_pause_button),
-                buildPendingIntent(pauseIntent, notificationId));
-
-        Intent cancelIntent =
-                buildActionIntent(mContext, ACTION_DOWNLOAD_CANCEL, id, isOffTheRecord);
-        builder.addAction(R.drawable.btn_close_white,
-                mContext.getResources().getString(R.string.download_notification_cancel_button),
-                buildPendingIntent(cancelIntent, notificationId));
-
-        updateNotification(notificationId, builder.build(), id,
+        updateNotification(notificationId, notification, id,
                 new DownloadSharedPreferenceEntry(id, notificationId, isOffTheRecord,
                         canDownloadWhileMetered, fileName, true, isTransient));
         startTrackingInProgressDownload(id);
@@ -925,39 +848,21 @@
             stopTrackingInProgressDownload(id, true);
             return;
         }
-
-        String contentText = mContext.getResources().getString(
-                R.string.download_notification_paused);
-        ChromeNotificationBuilder builder =
-                buildNotification(R.drawable.ic_download_pause, fileName, contentText);
         int notificationId = entry == null ? getNotificationId(id) : entry.notificationId;
-        if (!isTransient) {
-            // Clicking on an in-progress download sends the user to see all their downloads.
-            Intent downloadHomeIntent = buildActionIntent(
-                    mContext, DownloadManager.ACTION_NOTIFICATION_CLICKED, null, false);
-            builder.setContentIntent(PendingIntent.getBroadcast(mContext, notificationId,
-                    downloadHomeIntent, PendingIntent.FLAG_UPDATE_CURRENT));
-        }
-        builder.setAutoCancel(false);
-        if (icon != null) builder.setLargeIcon(icon);
 
-        Intent resumeIntent =
-                buildActionIntent(mContext, ACTION_DOWNLOAD_RESUME, id, isOffTheRecord);
-        builder.addAction(R.drawable.ic_file_download_white_24dp,
-                mContext.getResources().getString(R.string.download_notification_resume_button),
-                buildPendingIntent(resumeIntent, notificationId));
+        DownloadUpdate downloadUpdate = new DownloadUpdate.Builder()
+                                                .setContentId(id)
+                                                .setFileName(fileName)
+                                                .setIsOffTheRecord(isOffTheRecord)
+                                                .setIsTransient(isTransient)
+                                                .setIcon(icon)
+                                                .setNotificationId(notificationId)
+                                                .build();
 
-        Intent cancelIntent =
-                buildActionIntent(mContext, ACTION_DOWNLOAD_CANCEL, id, isOffTheRecord);
-        builder.addAction(R.drawable.btn_close_white,
-                mContext.getResources().getString(R.string.download_notification_cancel_button),
-                buildPendingIntent(cancelIntent, notificationId));
-        PendingIntent deleteIntent = isTransient
-                ? buildPendingIntent(cancelIntent, notificationId)
-                : buildSummaryIconIntent(notificationId);
-        builder.setDeleteIntent(deleteIntent);
+        Notification notification = DownloadNotificationFactory.buildNotification(
+                mContext, DownloadNotificationFactory.DownloadStatus.PAUSED, downloadUpdate);
 
-        updateNotification(notificationId, builder.build(), id,
+        updateNotification(notificationId, notification, id,
                 new DownloadSharedPreferenceEntry(id, notificationId, isOffTheRecord,
                         canDownloadWhileMetered, fileName, isAutoResumable, isTransient));
         stopTrackingInProgressDownload(id, true);
@@ -982,40 +887,28 @@
             long systemDownloadId, boolean isOffTheRecord, boolean isSupportedMimeType,
             boolean isOpenable, Bitmap icon, String originalUrl, String referrer) {
         int notificationId = getNotificationId(id);
-        ChromeNotificationBuilder builder = buildNotification(R.drawable.offline_pin, fileName,
-                mContext.getResources().getString(R.string.download_notification_completed));
-        ComponentName component = new ComponentName(
-                mContext.getPackageName(), DownloadBroadcastReceiver.class.getName());
-
-        if (isOpenable) {
-            Intent intent = null;
-            if (LegacyHelpers.isLegacyDownload(id)) {
-                intent = new Intent(DownloadManager.ACTION_NOTIFICATION_CLICKED);
-                long[] idArray = {systemDownloadId};
-                intent.putExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS, idArray);
-                intent.putExtra(EXTRA_DOWNLOAD_FILE_PATH, filePath);
-                intent.putExtra(EXTRA_IS_SUPPORTED_MIME_TYPE, isSupportedMimeType);
-                intent.putExtra(EXTRA_IS_OFF_THE_RECORD, isOffTheRecord);
-                intent.putExtra(EXTRA_DOWNLOAD_CONTENTID_ID, id.id);
-                intent.putExtra(EXTRA_DOWNLOAD_CONTENTID_NAMESPACE, id.namespace);
-                intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_ID, notificationId);
-                DownloadUtils.setOriginalUrlAndReferralExtraToIntent(intent, originalUrl, referrer);
-            } else {
-                intent = buildActionIntent(mContext, ACTION_DOWNLOAD_OPEN, id, false);
-            }
-
-            intent.setComponent(component);
-            builder.setContentIntent(PendingIntent.getBroadcast(
-                    mContext, notificationId, intent, PendingIntent.FLAG_UPDATE_CURRENT));
-        }
         if (icon == null && mDownloadSuccessLargeIcon == null) {
             Bitmap bitmap = BitmapFactory.decodeResource(
                     mContext.getResources(), R.drawable.offline_pin);
             mDownloadSuccessLargeIcon = getLargeNotificationIcon(bitmap);
         }
-        builder.setDeleteIntent(buildSummaryIconIntent(notificationId));
-        builder.setLargeIcon(icon != null ? icon : mDownloadSuccessLargeIcon);
-        updateNotification(notificationId, builder.build(), id, null);
+        if (icon == null) icon = mDownloadSuccessLargeIcon;
+
+        DownloadUpdate downloadUpdate = new DownloadUpdate.Builder()
+                                                .setContentId(id)
+                                                .setFileName(fileName)
+                                                .setFilePath(filePath)
+                                                .setSystemDownload(systemDownloadId)
+                                                .setIsOffTheRecord(isOffTheRecord)
+                                                .setIsSupportedMimeType(isSupportedMimeType)
+                                                .setIsOpenable(isOpenable)
+                                                .setIcon(icon)
+                                                .setNotificationId(notificationId)
+                                                .build();
+        Notification notification = DownloadNotificationFactory.buildNotification(
+                mContext, DownloadNotificationFactory.DownloadStatus.SUCCESSFUL, downloadUpdate);
+
+        updateNotification(notificationId, notification, id, null);
         stopTrackingInProgressDownload(id, true);
         return notificationId;
     }
@@ -1038,77 +931,19 @@
         }
 
         int notificationId = getNotificationId(id);
-        ChromeNotificationBuilder builder =
-                buildNotification(android.R.drawable.stat_sys_download_done, fileName,
-                        mContext.getResources().getString(R.string.download_notification_failed));
-        if (icon != null) builder.setLargeIcon(icon);
-        builder.setDeleteIntent(buildSummaryIconIntent(notificationId));
-        updateNotification(notificationId, builder.build(), id, null);
+
+        DownloadUpdate downloadUpdate = new DownloadUpdate.Builder()
+                                                .setContentId(id)
+                                                .setFileName(fileName)
+                                                .setIcon(icon)
+                                                .build();
+        Notification notification = DownloadNotificationFactory.buildNotification(
+                mContext, DownloadNotificationFactory.DownloadStatus.FAILED, downloadUpdate);
+
+        updateNotification(notificationId, notification, id, null);
         stopTrackingInProgressDownload(id, true);
     }
 
-    /**
-     * Helper method to build a PendingIntent from the provided intent.
-     * @param intent Intent to broadcast.
-     * @param notificationId ID of the notification.
-     */
-    private PendingIntent buildPendingIntent(Intent intent, int notificationId) {
-        return PendingIntent.getBroadcast(
-                mContext, notificationId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
-    }
-
-    private PendingIntent buildSummaryIconIntent(int notificationId) {
-        Intent intent = new Intent(mContext, DownloadBroadcastReceiver.class);
-        intent.setAction(ACTION_DOWNLOAD_UPDATE_SUMMARY_ICON);
-        return buildPendingIntent(intent, notificationId);
-    }
-
-    /**
-     * Helper method to build an download action Intent from the provided information.
-     * @param context {@link Context} to pull resources from.
-     * @param action Download action to perform.
-     * @param id The {@link ContentId} of the download.
-     * @param isOffTheRecord Whether the download is incognito.
-     */
-    static Intent buildActionIntent(
-            Context context, String action, ContentId id, boolean isOffTheRecord) {
-        ComponentName component = new ComponentName(
-                context.getPackageName(), DownloadBroadcastReceiver.class.getName());
-        Intent intent = new Intent(action);
-        intent.setComponent(component);
-        intent.putExtra(EXTRA_DOWNLOAD_CONTENTID_ID, id != null ? id.id : "");
-        intent.putExtra(EXTRA_DOWNLOAD_CONTENTID_NAMESPACE, id != null ? id.namespace : "");
-        intent.putExtra(EXTRA_IS_OFF_THE_RECORD, isOffTheRecord);
-        return intent;
-    }
-
-    /**
-     * Builds a notification to be displayed.
-     * @param iconId Id of the notification icon.
-     * @param title Title of the notification.
-     * @param contentText Notification content text to be displayed.
-     * @return notification builder that builds the notification to be displayed
-     */
-    private ChromeNotificationBuilder buildNotification(
-            int iconId, String title, String contentText) {
-        Bundle extras = new Bundle();
-        extras.putInt(EXTRA_NOTIFICATION_BUNDLE_ICON_ID, iconId);
-
-        ChromeNotificationBuilder builder =
-                NotificationBuilderFactory
-                        .createChromeNotificationBuilder(
-                                true /* preferCompat */, ChannelDefinitions.CHANNEL_ID_DOWNLOADS)
-                        .setContentTitle(
-                                DownloadUtils.getAbbreviatedFileName(title, MAX_FILE_NAME_LENGTH))
-                        .setSmallIcon(iconId)
-                        .setLocalOnly(true)
-                        .setAutoCancel(true)
-                        .setContentText(contentText)
-                        .setGroup(NotificationConstants.GROUP_DOWNLOADS)
-                        .addExtras(extras);
-        return builder;
-    }
-
     private Bitmap getLargeNotificationIcon(Bitmap bitmap) {
         Resources resources = mContext.getResources();
         int height = (int) resources.getDimension(android.R.dimen.notification_large_icon_height);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSheetContent.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSheetContent.java
index 6408a27fa..69aef96 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSheetContent.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSheetContent.java
@@ -12,6 +12,7 @@
 import org.chromium.base.ApplicationStatus.ActivityStateListener;
 import org.chromium.base.ThreadUtils;
 import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.download.ui.DownloadHistoryItemWrapper;
 import org.chromium.chrome.browser.download.ui.DownloadManagerUi;
 import org.chromium.chrome.browser.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.toolbar.BottomToolbarPhone;
@@ -25,7 +26,7 @@
  */
 public class DownloadSheetContent implements BottomSheetContent {
     private final View mContentView;
-    private final SelectableListToolbar mToolbarView;
+    private final SelectableListToolbar<DownloadHistoryItemWrapper> mToolbarView;
     private final ActivityStateListener mActivityStateListener;
     private DownloadManagerUi mDownloadManager;
 
@@ -111,4 +112,9 @@
     public int getType() {
         return BottomSheetContentController.TYPE_DOWNLOADS;
     }
+
+    @Override
+    public boolean applyDefaultTopPadding() {
+        return true;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUpdate.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUpdate.java
new file mode 100644
index 0000000..1ab3439
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUpdate.java
@@ -0,0 +1,210 @@
+// 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;
+
+import android.graphics.Bitmap;
+
+import org.chromium.components.offline_items_collection.ContentId;
+import org.chromium.components.offline_items_collection.OfflineItem.Progress;
+
+/**
+ * Class representing information relating to an update in download status.
+ * TODO(jming): Consolidate with other downloads-related objects (http://crbug.com/746692).
+ */
+public final class DownloadUpdate {
+    private final ContentId mContentId;
+    private final String mFileName;
+    private final String mFilePath;
+    private final Bitmap mIcon;
+    private final int mIconId;
+    private final boolean mIsDownloadPending;
+    private final boolean mIsOffTheRecord;
+    private final boolean mIsOpenable;
+    private final boolean mIsSupportedMimeType;
+    private final boolean mIsTransient;
+    private final int mNotificationId;
+    private final Progress mProgress;
+    private final long mStartTime;
+    private final long mSystemDownloadId;
+    private final long mTimeRemainingInMillis;
+
+    private DownloadUpdate(Builder builder) {
+        this.mContentId = builder.mContentId;
+        this.mFileName = builder.mFileName;
+        this.mFilePath = builder.mFilePath;
+        this.mIcon = builder.mIcon;
+        this.mIconId = builder.mIconId;
+        this.mIsDownloadPending = builder.mIsDownloadPending;
+        this.mIsOffTheRecord = builder.mIsOffTheRecord;
+        this.mIsOpenable = builder.mIsOpenable;
+        this.mIsSupportedMimeType = builder.mIsSupportedMimeType;
+        this.mIsTransient = builder.mIsTransient;
+        this.mNotificationId = builder.mNotificationId;
+        this.mProgress = builder.mProgress;
+        this.mStartTime = builder.mStartTime;
+        this.mSystemDownloadId = builder.mSystemDownloadId;
+        this.mTimeRemainingInMillis = builder.mTimeRemainingInMillis;
+    }
+
+    public ContentId getContentId() {
+        return mContentId;
+    }
+
+    public String getFileName() {
+        return mFileName;
+    }
+
+    public String getFilePath() {
+        return mFilePath;
+    }
+
+    public Bitmap getIcon() {
+        return mIcon;
+    }
+
+    public int getIconId() {
+        return mIconId;
+    }
+
+    public boolean getIsDownloadPending() {
+        return mIsDownloadPending;
+    }
+
+    public boolean getIsOffTheRecord() {
+        return mIsOffTheRecord;
+    }
+
+    public boolean getIsOpenable() {
+        return mIsOpenable;
+    }
+
+    public boolean getIsSupportedMimeType() {
+        return mIsSupportedMimeType;
+    }
+
+    public boolean getIsTransient() {
+        return mIsTransient;
+    }
+
+    public int getNotificationId() {
+        return mNotificationId;
+    }
+
+    public Progress getProgress() {
+        return mProgress;
+    }
+
+    public long getStartTime() {
+        return mStartTime;
+    }
+
+    public long getSystemDownloadId() {
+        return mSystemDownloadId;
+    }
+
+    public long getTimeRemainingInMillis() {
+        return mTimeRemainingInMillis;
+    }
+
+    /**
+     * Helper class for building the DownloadUpdate object.
+     */
+    public static class Builder {
+        private ContentId mContentId;
+        private String mFileName;
+        private String mFilePath;
+        private Bitmap mIcon;
+        private int mIconId = -1;
+        private boolean mIsDownloadPending;
+        private boolean mIsOffTheRecord;
+        private boolean mIsOpenable;
+        private boolean mIsSupportedMimeType;
+        private boolean mIsTransient;
+        private int mNotificationId = -1;
+        private Progress mProgress;
+        private long mStartTime;
+        private long mSystemDownloadId = -1;
+        private long mTimeRemainingInMillis;
+
+        public Builder setContentId(ContentId contentId) {
+            this.mContentId = contentId;
+            return this;
+        }
+
+        public Builder setFileName(String fileName) {
+            this.mFileName = fileName;
+            return this;
+        }
+
+        public Builder setFilePath(String filePath) {
+            this.mFilePath = filePath;
+            return this;
+        }
+
+        public Builder setIcon(Bitmap icon) {
+            this.mIcon = icon;
+            return this;
+        }
+
+        public Builder setIconId(int iconId) {
+            this.mIconId = iconId;
+            return this;
+        }
+
+        public Builder setIsDownloadPending(boolean isDownloadPending) {
+            this.mIsDownloadPending = isDownloadPending;
+            return this;
+        }
+
+        public Builder setIsOffTheRecord(boolean isOffTheRecord) {
+            this.mIsOffTheRecord = isOffTheRecord;
+            return this;
+        }
+
+        public Builder setIsOpenable(boolean isOpenable) {
+            this.mIsOpenable = isOpenable;
+            return this;
+        }
+
+        public Builder setIsSupportedMimeType(boolean isSupportedMimeType) {
+            this.mIsSupportedMimeType = isSupportedMimeType;
+            return this;
+        }
+
+        public Builder setIsTransient(boolean isTransient) {
+            this.mIsTransient = isTransient;
+            return this;
+        }
+
+        public Builder setNotificationId(int notificationId) {
+            this.mNotificationId = notificationId;
+            return this;
+        }
+
+        public Builder setProgress(Progress progress) {
+            this.mProgress = progress;
+            return this;
+        }
+
+        public Builder setStartTime(long startTime) {
+            this.mStartTime = startTime;
+            return this;
+        }
+
+        public Builder setSystemDownload(long systemDownload) {
+            this.mSystemDownloadId = systemDownload;
+            return this;
+        }
+
+        public Builder setTimeRemainingInMillis(long timeRemainingInMillis) {
+            this.mTimeRemainingInMillis = timeRemainingInMillis;
+            return this;
+        }
+
+        public DownloadUpdate build() {
+            return new DownloadUpdate(this);
+        }
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/BackendItems.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/BackendItems.java
index 6ceb6f54..4b3210c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/BackendItems.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/BackendItems.java
@@ -35,7 +35,7 @@
             if (item.isVisibleToUser(DownloadFilter.FILTER_ALL) && !filePaths.contains(path)) {
                 totalSize += item.getFileSize();
             }
-            if (!path.isEmpty()) filePaths.add(path);
+            if (path != null && !path.isEmpty()) filePaths.add(path);
         }
         return totalSize;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java
index 0e6ce56..d4bdf5f7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java
@@ -9,6 +9,7 @@
 import android.support.v7.widget.RecyclerView.ViewHolder;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
+import android.view.View;
 import android.view.ViewGroup;
 
 import org.chromium.base.ContextUtils;
@@ -167,6 +168,7 @@
     private int mFilter = DownloadFilter.FILTER_ALL;
     private String mSearchQuery = EMPTY_QUERY;
     private SpaceDisplay mSpaceDisplay;
+    private HeaderItem mSpaceDisplayHeaderItem;
     private boolean mIsSearching;
     private boolean mShouldShowStorageInfoHeader;
 
@@ -191,6 +193,8 @@
         mBackendProvider = provider;
         mUiConfig = uiConfig;
 
+        generateHeaderItems();
+
         DownloadItemSelectionDelegate selectionDelegate =
                 (DownloadItemSelectionDelegate) mBackendProvider.getSelectionDelegate();
         selectionDelegate.initialize(this);
@@ -364,26 +368,30 @@
     }
 
     @Override
+    protected void bindViewHolderForHeaderItem(ViewHolder viewHolder, HeaderItem headerItem) {
+        super.bindViewHolderForHeaderItem(viewHolder, headerItem);
+        mSpaceDisplay.onChanged();
+    }
+
+    @Override
     protected ItemGroup createGroup(long timeStamp) {
         return new DownloadItemGroup(timeStamp);
     }
 
-    @Override
-    protected BasicViewHolder createHeader(ViewGroup parent) {
-        if (mSpaceDisplay == null) {
-            mSpaceDisplay = new SpaceDisplay(parent, this);
-            registerAdapterDataObserver(mSpaceDisplay);
-            if (mUiConfig != null) {
-                MarginResizer.createAndAttach(mSpaceDisplay.getView(), mUiConfig,
-                        parent.getResources().getDimensionPixelSize(
-                                R.dimen.list_item_default_margin),
-                        SelectableListLayout.getDefaultListItemLateralShadowSizePx(
-                                parent.getResources()));
-            }
+    /**
+     * Initialize space display view in storage info header and generate header item for it.
+     */
+    void generateHeaderItems() {
+        mSpaceDisplay = new SpaceDisplay(null, this);
+        View view = mSpaceDisplay.getView();
+        registerAdapterDataObserver(mSpaceDisplay);
+        if (mUiConfig != null) {
+            MarginResizer.createAndAttach(view, mUiConfig,
+                    view.getResources().getDimensionPixelSize(R.dimen.list_item_default_margin),
+                    SelectableListLayout.getDefaultListItemLateralShadowSizePx(
+                            view.getResources()));
         }
-
-        mSpaceDisplay.onChanged();
-        return new BasicViewHolder(mSpaceDisplay.getView());
+        mSpaceDisplayHeaderItem = new HeaderItem(0, view);
     }
 
     /** Called when a new DownloadItem has been created by the native DownloadManager. */
@@ -598,7 +606,7 @@
 
         clear(false);
         if (!filteredTimedItems.isEmpty() && !mIsSearching && mShouldShowStorageInfoHeader) {
-            addHeader();
+            setHeaders(mSpaceDisplayHeaderItem);
         }
 
         loadItems(filteredTimedItems);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerToolbar.java
index bb1dc62..544b076 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerToolbar.java
@@ -24,6 +24,7 @@
 public class DownloadManagerToolbar extends SelectableListToolbar<DownloadHistoryItemWrapper>
         implements DownloadUiObserver {
     private Spinner mSpinner;
+    private DownloadManagerUi mManager;
 
     public DownloadManagerToolbar(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -31,6 +32,13 @@
     }
 
     /**
+     * @param manager The {@link DownloadManagerUi} associated with this toolbar.
+     */
+    public void setManager(DownloadManagerUi manager) {
+        mManager = manager;
+    }
+
+    /**
      * Initializes the spinner for the download filter.
      * @param adapter The adapter associated with the spinner.
      */
@@ -96,6 +104,12 @@
     }
 
     @Override
+    protected void showNormalView() {
+        super.showNormalView();
+        mManager.updateInfoButtonVisibility();
+    }
+
+    @Override
     public void showSearchView() {
         super.showSearchView();
         mSpinner.setVisibility(GONE);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java
index 417417a..061b7099 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java
@@ -9,6 +9,7 @@
 import android.content.Intent;
 import android.os.AsyncTask;
 import android.support.graphics.drawable.VectorDrawableCompat;
+import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.Toolbar.OnMenuItemClickListener;
 import android.view.LayoutInflater;
@@ -200,6 +201,13 @@
         // Prevent every progress update from causing a transition animation.
         mRecyclerView.getItemAnimator().setChangeDuration(0);
 
+        mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
+            @Override
+            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+                updateInfoButtonVisibility();
+            }
+        });
+
         mFilterAdapter = new FilterAdapter();
         mFilterAdapter.initialize(this);
         addObserver(mFilterAdapter);
@@ -207,6 +215,7 @@
         mToolbar = (DownloadManagerToolbar) mSelectableListLayout.initializeToolbar(
                 R.layout.download_manager_toolbar, mBackendProvider.getSelectionDelegate(), 0, null,
                 R.id.normal_menu_group, R.id.selection_mode_menu_group, null, this, true);
+        mToolbar.setManager(this);
         mToolbar.initializeFilterSpinner(mFilterAdapter);
         mToolbar.initializeSearchView(this, R.string.download_manager_search, R.id.search_menu_id);
         mToolbar.setInfoMenuItem(R.id.info_menu_id);
@@ -454,6 +463,23 @@
         mSnackbarManager.dismissSnackbars(mUndoDeletionSnackbarController);
     }
 
+    /**
+     * @return True if info menu item should be shown on download toolbar, false otherwise.
+     */
+    boolean shouldShowInfoButton() {
+        return mHistoryAdapter.getItemCount() > 0 && !mToolbar.isSearching();
+    }
+
+    /**
+     * Update info button visibility based on whether info header is visible on download page.
+     */
+    void updateInfoButtonVisibility() {
+        LinearLayoutManager layoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
+        boolean infoHeaderIsVisible = layoutManager.findFirstVisibleItemPosition() == 0;
+        mToolbar.updateInfoMenuItem(infoHeaderIsVisible && shouldShowInfoButton(),
+                mHistoryAdapter.shouldShowStorageInfoHeader());
+    }
+
     @VisibleForTesting
     public SnackbarManager getSnackbarManagerForTesting() {
         return mSnackbarManager;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/SpaceDisplay.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/SpaceDisplay.java
index c7bee88..1e599c1f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/SpaceDisplay.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/SpaceDisplay.java
@@ -15,6 +15,7 @@
 import android.widget.TextView;
 
 import org.chromium.base.ApiCompatibilityUtils;
+import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
 import org.chromium.base.ObserverList;
 import org.chromium.base.VisibleForTesting;
@@ -114,7 +115,7 @@
 
     SpaceDisplay(final ViewGroup parent, DownloadHistoryAdapter historyAdapter) {
         mHistoryAdapter = historyAdapter;
-        mView = (ViewGroup) LayoutInflater.from(parent.getContext())
+        mView = LayoutInflater.from(ContextUtils.getApplicationContext())
                         .inflate(R.layout.download_manager_ui_space_widget, parent, false);
         mSpaceUsedByDownloadsTextView = (TextView) mView.findViewById(R.id.size_downloaded);
         mSpaceUsedByOtherAppsTextView = (TextView) mView.findViewById(R.id.size_other_apps);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java
index 005e639..66eef39e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java
@@ -14,7 +14,7 @@
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.widget.Button;
-import android.widget.FrameLayout;
+import android.widget.Space;
 import android.widget.TextView;
 
 import org.chromium.base.VisibleForTesting;
@@ -53,22 +53,24 @@
     private final ArrayList<HistoryItemView> mItemViews;
     private RecyclerView mRecyclerView;
 
-    private ViewGroup mPrivacyDisclaimers;
     private TextView mSignedInNotSyncedTextView;
     private TextView mSignedInSyncedTextView;
     private TextView mOtherFormsOfBrowsingHistoryTextView;
+    private Space mPrivacyDisclaimerBottomSpace;
     private Button mClearBrowsingDataButton;
-    private FrameLayout mClearBrowsingDataButtonContainer;
+    private HeaderItem mPrivacyDisclaimerHeaderItem;
+    private HeaderItem mClearBrowsingDataButtonHeaderItem;
 
     private boolean mHasOtherFormsOfBrowsingData;
     private boolean mHasSyncedData;
-    private boolean mIsHeaderInflated;
     private boolean mIsDestroyed;
     private boolean mIsInitialized;
     private boolean mIsLoadingItems;
     private boolean mIsSearching;
     private boolean mHasMorePotentialItems;
     private boolean mClearOnNextQueryComplete;
+    private boolean mPrivacyDisclaimersVisible;
+    private boolean mClearBrowsingDataButtonVisible;
     private long mNextQueryEndTime;
     private String mQueryText = EMPTY_QUERY;
     private int mDefaultTextMargin;
@@ -194,6 +196,7 @@
         for (HistoryItemView itemView : mItemViews) {
             itemView.onSignInStateChange();
         }
+        initialize();
         updateClearBrowsingDataButtonVisibility();
         setPrivacyDisclaimerVisibility();
     }
@@ -252,7 +255,7 @@
 
         boolean wasInitialized = mIsInitialized;
         if (!mIsInitialized) {
-            if (items.size() > 0 && !mIsSearching) addHeader();
+            if (items.size() > 0 && !mIsSearching) setHeaders();
             mIsInitialized = true;
         }
 
@@ -298,28 +301,34 @@
     }
 
     @Override
-    protected BasicViewHolder createHeader(ViewGroup parent) {
-        ViewGroup v = (ViewGroup) LayoutInflater.from(parent.getContext()).inflate(
-                R.layout.history_header, parent, false);
-        Resources resources = v.getResources();
-        mIsHeaderInflated = true;
+    protected BasicViewHolder createFooter(ViewGroup parent) {
+        return new BasicViewHolder(
+                LayoutInflater.from(parent.getContext())
+                        .inflate(R.layout.indeterminate_progress_view, parent, false));
+    }
 
-        mClearBrowsingDataButton = (Button) v.findViewById(R.id.clear_browsing_data_button);
-        mClearBrowsingDataButton.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                mHistoryManager.openClearBrowsingDataPreference();
-            }
-        });
-        mClearBrowsingDataButtonContainer = (FrameLayout) mClearBrowsingDataButton.getParent();
-        MarginResizer.createAndAttach(mClearBrowsingDataButtonContainer,
+    @Override
+    protected DateViewHolder createDateViewHolder(ViewGroup parent) {
+        DateViewHolder viewHolder = super.createDateViewHolder(parent);
+        MarginResizer.createAndAttach(viewHolder.itemView,
                 mHistoryManager.getSelectableListLayout().getUiConfig(),
-                SelectableListLayout.getDefaultListItemLateralMarginPx(resources), 0);
-        updateClearBrowsingDataButtonVisibility();
+                getDefaultTextMargin(parent.getResources()),
+                SelectableListLayout.getDefaultListItemLateralShadowSizePx(parent.getResources()));
+        return viewHolder;
+    }
 
-        mPrivacyDisclaimers = (ViewGroup) v.findViewById(R.id.privacy_disclaimers);
+    /**
+     * Initialize clear browsing data and privacy disclaimer header views and generate header
+     * items for them.
+     */
+    void generateHeaderItems() {
+        ViewGroup privacyDisclaimers =
+                (ViewGroup) View.inflate(mHistoryManager.getSelectableListLayout().getContext(),
+                        R.layout.history_privacy_disclaimer_header, null);
+        Resources resources = privacyDisclaimers.getResources();
 
-        mSignedInNotSyncedTextView = (TextView) v.findViewById(R.id.signed_in_not_synced);
+        mSignedInNotSyncedTextView =
+                (TextView) privacyDisclaimers.findViewById(R.id.signed_in_not_synced);
         setPrivacyDisclaimerText(mSignedInNotSyncedTextView,
                 R.string.android_history_no_synced_results, LEARN_MORE_LINK);
         MarginResizer.createAndAttach(mSignedInNotSyncedTextView,
@@ -327,7 +336,7 @@
                 getDefaultTextMargin(resources),
                 SelectableListLayout.getDefaultListItemLateralShadowSizePx(resources));
 
-        mSignedInSyncedTextView = (TextView) v.findViewById(R.id.signed_in_synced);
+        mSignedInSyncedTextView = (TextView) privacyDisclaimers.findViewById(R.id.signed_in_synced);
         setPrivacyDisclaimerText(mSignedInSyncedTextView,
                 R.string.android_history_has_synced_results, LEARN_MORE_LINK);
         MarginResizer.createAndAttach(mSignedInSyncedTextView,
@@ -335,8 +344,8 @@
                 getDefaultTextMargin(resources),
                 SelectableListLayout.getDefaultListItemLateralShadowSizePx(resources));
 
-        mOtherFormsOfBrowsingHistoryTextView = (TextView) v.findViewById(
-                R.id.other_forms_of_browsing_history);
+        mOtherFormsOfBrowsingHistoryTextView =
+                (TextView) privacyDisclaimers.findViewById(R.id.other_forms_of_browsing_history);
         boolean flagEnabled = ChromeFeatureList.isEnabled(ChromeFeatureList.TABS_IN_CBD);
         int disclaimerTextId = flagEnabled ? R.string.android_history_other_forms_of_history_new
                                            : R.string.android_history_other_forms_of_history;
@@ -348,25 +357,39 @@
                 getDefaultTextMargin(resources),
                 SelectableListLayout.getDefaultListItemLateralShadowSizePx(resources));
 
-        setPrivacyDisclaimerVisibility();
+        mPrivacyDisclaimerBottomSpace =
+                (Space) privacyDisclaimers.findViewById(R.id.privacy_disclaimer_bottom_space);
 
-        return new BasicViewHolder(v);
-    }
+        ViewGroup clearBrowsingDataButtonContainer =
+                (ViewGroup) View.inflate(mHistoryManager.getSelectableListLayout().getContext(),
+                        R.layout.history_clear_browsing_data_header, null);
 
-    @Override
-    protected BasicViewHolder createFooter(ViewGroup parent) {
-        return new BasicViewHolder(LayoutInflater.from(parent.getContext()).inflate(
-                R.layout.indeterminate_progress_view, parent, false));
-    }
-
-    @Override
-    protected DateViewHolder createDateViewHolder(ViewGroup parent) {
-        DateViewHolder viewHolder = super.createDateViewHolder(parent);
-        MarginResizer.createAndAttach(viewHolder.itemView,
+        mClearBrowsingDataButton = (Button) clearBrowsingDataButtonContainer.findViewById(
+                R.id.clear_browsing_data_button);
+        mClearBrowsingDataButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                mHistoryManager.openClearBrowsingDataPreference();
+            }
+        });
+        MarginResizer.createAndAttach(clearBrowsingDataButtonContainer,
                 mHistoryManager.getSelectableListLayout().getUiConfig(),
-                getDefaultTextMargin(parent.getResources()),
-                SelectableListLayout.getDefaultListItemLateralShadowSizePx(parent.getResources()));
-        return viewHolder;
+                SelectableListLayout.getDefaultListItemLateralMarginPx(resources), 0);
+
+        mPrivacyDisclaimerHeaderItem = new HeaderItem(0, privacyDisclaimers);
+        mClearBrowsingDataButtonHeaderItem = new HeaderItem(1, clearBrowsingDataButtonContainer);
+        updateClearBrowsingDataButtonVisibility();
+        setPrivacyDisclaimerVisibility();
+    }
+
+    /**
+     * Pass header items to {@link #setHeaders(HeaderItem...)} as parameters.
+     */
+    private void setHeaders() {
+        ArrayList<HeaderItem> args = new ArrayList<>();
+        if (mPrivacyDisclaimersVisible) args.add(mPrivacyDisclaimerHeaderItem);
+        if (mClearBrowsingDataButtonVisible) args.add(mClearBrowsingDataButtonHeaderItem);
+        setHeaders(args.toArray(new HeaderItem[args.size()]));
     }
 
     private void setPrivacyDisclaimerText(TextView view, int stringId, final  String url) {
@@ -396,26 +419,29 @@
      * Set visibility for privacy disclaimer layout and views.
      */
     void setPrivacyDisclaimerVisibility() {
-        if (!mIsHeaderInflated) return;
-
-        boolean show = hasPrivacyDisclaimers() && mHistoryManager.shouldShowInfoHeaderIfAvailable();
         boolean isSignedIn = ChromeSigninController.get().isSignedIn();
+        boolean shouldShowPrivacyDisclaimers =
+                hasPrivacyDisclaimers() && mHistoryManager.shouldShowInfoHeaderIfAvailable();
         mSignedInNotSyncedTextView.setVisibility(
                 !mHasSyncedData && isSignedIn ? View.VISIBLE : View.GONE);
         mSignedInSyncedTextView.setVisibility(mHasSyncedData ? View.VISIBLE : View.GONE);
         mOtherFormsOfBrowsingHistoryTextView.setVisibility(
                 mHasOtherFormsOfBrowsingData ? View.VISIBLE : View.GONE);
-        mPrivacyDisclaimers.setVisibility(show ? View.VISIBLE : View.GONE);
+        // Prevent from refreshing the recycler view if header visibility is not changed.
+        if (mPrivacyDisclaimersVisible == shouldShowPrivacyDisclaimers) return;
+        mPrivacyDisclaimersVisible = shouldShowPrivacyDisclaimers;
+        if (mIsInitialized) setHeaders();
     }
 
     private void updateClearBrowsingDataButtonVisibility() {
         // If the history header is not showing (e.g. when there is no browsing history),
         // mClearBrowsingDataButton will be null.
         if (mClearBrowsingDataButton == null) return;
-
-        mClearBrowsingDataButtonContainer.setVisibility(
-                !PrefServiceBridge.getInstance().canDeleteBrowsingHistory() ? View.GONE :
-                    View.VISIBLE);
+        boolean shouldShowButton = PrefServiceBridge.getInstance().canDeleteBrowsingHistory();
+        if (mClearBrowsingDataButtonVisible == shouldShowButton) return;
+        mClearBrowsingDataButtonVisible = shouldShowButton;
+        mPrivacyDisclaimerBottomSpace.setVisibility(shouldShowButton ? View.GONE : View.VISIBLE);
+        if (mIsInitialized) setHeaders();
     }
 
     private int getDefaultTextMargin(Resources resources) {
@@ -441,12 +467,27 @@
     }
 
     @VisibleForTesting
-    ViewGroup getPrivacyDisclaimersForTests() {
-        return mPrivacyDisclaimers;
+    ItemGroup getFirstGroupForTests() {
+        return getGroupAt(0).first;
+    }
+
+    @VisibleForTesting
+    void setClearBrowsingDataButtonVisibilityForTest(boolean isVisible) {
+        if (mClearBrowsingDataButton == null) return;
+        if (mClearBrowsingDataButtonVisible == isVisible) return;
+        mClearBrowsingDataButtonVisible = isVisible;
+        if (mIsInitialized) setHeaders();
     }
 
     @VisibleForTesting
     public ArrayList<HistoryItemView> getItemViewsForTests() {
         return mItemViews;
     }
+
+    @VisibleForTesting
+    void generateHeaderItemsForTest() {
+        mPrivacyDisclaimerHeaderItem = new HeaderItem(0, null);
+        mClearBrowsingDataButtonHeaderItem = new HeaderItem(1, null);
+        mClearBrowsingDataButtonVisible = true;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
index 67d71ce..0371c324 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
@@ -134,17 +134,23 @@
         mLargeIconBridge.createCache(maxSize);
 
         // 7. Initialize the adapter to load items.
+        mHistoryAdapter.generateHeaderItems();
         mHistoryAdapter.initialize();
 
-        // 8. Add scroll listener to page in more items when necessary.
+        // 8. Add scroll listener to show/hide info button on scroll and page in more items
+        // when necessary.
         mRecyclerView.addOnScrollListener(new OnScrollListener() {
             @Override
             public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
-                if (!mHistoryAdapter.canLoadMoreItems()) return;
-
-                // Load more items if the scroll position is close to the bottom of the list.
                 LinearLayoutManager layoutManager =
                         (LinearLayoutManager) recyclerView.getLayoutManager();
+                // Show info button if available if first visible position is close to info header;
+                // otherwise hide info button.
+                mToolbar.updateInfoMenuItem(infoHeaderIsVisible() && shouldShowInfoButton(),
+                        shouldShowInfoHeaderIfAvailable());
+
+                if (!mHistoryAdapter.canLoadMoreItems()) return;
+                // Load more items if the scroll position is close to the bottom of the list.
                 if (layoutManager.findLastVisibleItemPosition()
                         > (mHistoryAdapter.getItemCount() - 25)) {
                     mHistoryAdapter.loadMoreItems();
@@ -414,7 +420,8 @@
      * @return True if info menu item should be shown on history toolbar, false otherwise.
      */
     boolean shouldShowInfoButton() {
-        return mHistoryAdapter.hasPrivacyDisclaimers();
+        return mHistoryAdapter.hasPrivacyDisclaimers() && mHistoryAdapter.getItemCount() > 0
+                && !mToolbar.isSearching();
     }
 
     /**
@@ -425,6 +432,14 @@
         return mShouldShowInfoHeader;
     }
 
+    /**
+     * @return True if info header is visible on history page.
+     */
+    boolean infoHeaderIsVisible() {
+        LinearLayoutManager layoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
+        return (layoutManager.findFirstVisibleItemPosition() == 0);
+    }
+
     @Override
     public void onSignedIn() {
         mToolbar.onSignInStateChange();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManagerToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManagerToolbar.java
index 0f99ce6..b1f1050 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManagerToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManagerToolbar.java
@@ -44,8 +44,8 @@
     @Override
     protected void showNormalView() {
         super.showNormalView();
-        updateInfoMenuItem(
-                mManager.shouldShowInfoButton(), mManager.shouldShowInfoHeaderIfAvailable());
+        updateInfoMenuItem(mManager.infoHeaderIsVisible() && mManager.shouldShowInfoButton(),
+                mManager.shouldShowInfoHeaderIfAvailable());
     }
 
     @Override
@@ -77,9 +77,7 @@
     @Override
     protected void onDataChanged(int numItems) {
         super.onDataChanged(numItems);
-        getMenu()
-                .findItem(R.id.info_menu_id)
-                .setVisible(mManager.shouldShowInfoButton() && !mIsSearching && numItems > 0);
+        getMenu().findItem(R.id.info_menu_id).setVisible(mManager.shouldShowInfoButton());
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistorySheetContent.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistorySheetContent.java
index e96940c..fec7ffd3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistorySheetContent.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistorySheetContent.java
@@ -19,7 +19,7 @@
  */
 public class HistorySheetContent implements BottomSheetContent {
     private final View mContentView;
-    private final SelectableListToolbar mToolbarView;
+    private final SelectableListToolbar<HistoryItem> mToolbarView;
     private HistoryManager mHistoryManager;
 
     /**
@@ -83,4 +83,9 @@
     public int getType() {
         return BottomSheetContentController.TYPE_HISTORY;
     }
+
+    @Override
+    public boolean applyDefaultTopPadding() {
+        return true;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoBottomSheetContent.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoBottomSheetContent.java
index 1550780..999eb3c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoBottomSheetContent.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoBottomSheetContent.java
@@ -92,4 +92,9 @@
     public int getType() {
         return BottomSheetContentController.TYPE_INCOGNITO_HOME;
     }
+
+    @Override
+    public boolean applyDefaultTopPadding() {
+        return true;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetContent.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetContent.java
index ee05368..876566e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetContent.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsBottomSheetContent.java
@@ -32,6 +32,7 @@
 import org.chromium.chrome.browser.widget.FadingShadowView;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetContentController;
+import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetNewTabController;
 import org.chromium.chrome.browser.widget.displaystyle.UiConfig;
 import org.chromium.ui.widget.Toast;
 
@@ -41,7 +42,8 @@
 /**
  * Provides content to be displayed inside of the Home tab of bottom sheet.
  */
-public class SuggestionsBottomSheetContent implements BottomSheet.BottomSheetContent {
+public class SuggestionsBottomSheetContent
+        implements BottomSheet.BottomSheetContent, BottomSheetNewTabController.Observer {
     private final View mView;
     private final FadingShadowView mShadowView;
     private final SuggestionsRecyclerView mRecyclerView;
@@ -166,6 +168,8 @@
                 return false;
             }
         });
+
+        sheet.getNewTabController().addObserver(this);
     }
 
     @Override
@@ -205,6 +209,17 @@
         return BottomSheetContentController.TYPE_SUGGESTIONS;
     }
 
+    @Override
+    public boolean applyDefaultTopPadding() {
+        return false;
+    }
+
+    @Override
+    public void onNewTabShown() {}
+
+    @Override
+    public void onNewTabHidden() {}
+
     private void maybeUpdateContextualSuggestions() {
         if (mSuggestionsCarousel == null) return;
         assert ChromeFeatureList.isEnabled(ChromeFeatureList.CONTEXTUAL_SUGGESTIONS_CAROUSEL);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/DateDividedAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/DateDividedAdapter.java
index 7cf149e..9e94bb31 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/DateDividedAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/DateDividedAdapter.java
@@ -106,6 +106,41 @@
     }
 
     /**
+     * Contains information of a single header that this adapter uses to manage headers.
+     */
+    public static class HeaderItem extends TimedItem {
+        private final long mStableId;
+        private final View mView;
+
+        /**
+         * Initialize stable id and view associated with this HeaderItem.
+         * @param position Position of this HeaderItem in the header group.
+         * @param view View associated with this HeaderItem.
+         */
+        public HeaderItem(int position, View view) {
+            mStableId = getTimestamp() - position;
+            mView = view;
+        }
+
+        @Override
+        public long getTimestamp() {
+            return Long.MAX_VALUE;
+        }
+
+        @Override
+        public long getStableId() {
+            return mStableId;
+        }
+
+        /**
+         * @return The View associated with this HeaderItem.
+         */
+        public View getView() {
+            return mView;
+        }
+    }
+
+    /**
      * A {@link RecyclerView.ViewHolder} that displays a date header.
      */
     public static class DateViewHolder extends RecyclerView.ViewHolder {
@@ -193,6 +228,10 @@
             mItems.remove(item);
         }
 
+        public void removeAllItems() {
+            mItems.clear();
+        }
+
         /** Records the position of all the TimedItems in this group, relative to the full list. */
         public void setPosition(int index) {
             assert mIndex == 0 || mIndex == TimedItem.INVALID_POSITION;
@@ -225,15 +264,18 @@
          * @return The size of this group.
          */
         public int size() {
-            if (mIsListHeader || mIsListFooter) return 1;
+            if (mIsListHeader) return mItems.size();
+            if (mIsListFooter) return 1;
 
             // Plus 1 to account for the date header.
             return mItems.size() + 1;
         }
 
         public TimedItem getItemAt(int index) {
-            // 0 is allocated to the date header. The list header has no items.
-            if (index <= 0 || mIsListHeader || mIsListFooter) return null;
+            // 0 is allocated to the date header. Return item if list header has
+            // header items, otherwise return null.
+            if (mIsListHeader) return mItems.get(index);
+            if (index <= 0 || mIsListFooter) return null;
 
             sortIfNeeded();
             return mItems.get(index - 1);
@@ -305,12 +347,15 @@
     protected abstract ViewHolder createViewHolder(ViewGroup parent);
 
     /**
-     * Creates a {@link BasicViewHolder} in the given view parent for the header.
+     * Creates a {@link BasicViewHolder} in the given view parent for the header. The default
+     * implementation will create an empty FrameLayout container as the view holder.
      * @see #onCreateViewHolder(ViewGroup, int)
      */
-    @Nullable
     protected BasicViewHolder createHeader(ViewGroup parent) {
-        return null;
+        // Create an empty layout as a container for the header view.
+        View v = LayoutInflater.from(parent.getContext())
+                         .inflate(R.layout.date_divided_adapter_header_view_holder, parent, false);
+        return new BasicViewHolder(v);
     }
 
     /**
@@ -363,6 +408,18 @@
             SubsectionHeaderViewHolder holder, TimedItem timedItem) {}
 
     /**
+     * Binds the {@link BasicViewHolder} with the given {@link HeaderItem}.
+     * @see #onBindViewHolder(ViewHolder, int)
+     */
+    protected void bindViewHolderForHeaderItem(ViewHolder viewHolder, HeaderItem headerItem) {
+        BasicViewHolder basicViewHolder = (BasicViewHolder) viewHolder;
+        View v = headerItem.getView();
+        ((ViewGroup) basicViewHolder.itemView).removeAllViews();
+        if (v.getParent() != null) ((ViewGroup) v.getParent()).removeView(v);
+        ((ViewGroup) basicViewHolder.itemView).addView(v);
+    }
+
+    /**
      * Gets the resource id of the view showing the date header.
      * Contract for subclasses: this view should be a {@link TextView}.
      */
@@ -420,17 +477,40 @@
     }
 
     /**
-     * Adds a header as the first group in this adapter.
+     * Add a list of headers as the first group in this adapter. If headerItems has no items,
+     * the header group will not be created. Otherwise, header items will be added as child items
+     * to the header group. Note that any previously added header items will be removed.
+     * {@link #bindViewHolderForHeaderItem(ViewHolder, HeaderItem)} will bind the HeaderItem views
+     * to the given ViewHolder. Sub-classes may override #bindViewHolderForHeaderItem and
+     * (@link #createHeader(ViewGroup)} if custom behavior is needed.
+     *
+     * @param headerItems Zero or more header items to be add to the header item group.
      */
-    public void addHeader() {
-        assert mSize == 0;
+    public void setHeaders(HeaderItem... headerItems) {
+        if (headerItems == null || headerItems.length == 0) {
+            removeHeader();
+            return;
+        }
 
-        ItemGroup header = new ItemGroup(Long.MAX_VALUE);
-        header.mIsListHeader = true;
+        ItemGroup header;
+        if (mHasListHeader) {
+            header = mGroups.first();
+            mSize -= header.size();
+            header.removeAllItems();
+        } else {
+            header = new ItemGroup(Long.MAX_VALUE);
+            header.mIsListHeader = true;
+            mGroups.add(header);
+        }
 
-        mGroups.add(header);
-        mSize++;
+        for (HeaderItem item : headerItems) {
+            header.addItem(item);
+            mSize++;
+        }
         mHasListHeader = true;
+
+        setGroupPositions();
+        notifyDataSetChanged();
     }
 
     /**
@@ -439,8 +519,8 @@
     public void removeHeader() {
         if (!mHasListHeader) return;
 
+        mSize -= mGroups.first().size();
         mGroups.remove(mGroups.first());
-        mSize--;
         mHasListHeader = false;
 
         setGroupPositions();
@@ -510,7 +590,8 @@
     public Pair<Date, TimedItem> getItemAt(int position) {
         Pair<ItemGroup, Integer> pair = getGroupAt(position);
         ItemGroup group = pair.first;
-        return new Pair<>(group.mDate, group.getItemAt(pair.second));
+        return new Pair<>(group.mDate,
+                group.mIsListHeader ? group.getItemAt(position) : group.getItemAt(pair.second));
     }
 
     @Override
@@ -556,6 +637,8 @@
             bindViewHolderForSubsectionHeader((SubsectionHeaderViewHolder) holder, pair.second);
         } else if (!(holder instanceof BasicViewHolder)) {
             bindViewHolderForTimedItem(holder, pair.second);
+        } else if (pair.second instanceof HeaderItem) {
+            bindViewHolderForHeaderItem(holder, (HeaderItem) pair.second);
         }
     }
 
@@ -569,7 +652,7 @@
      */
     protected Pair<ItemGroup, Integer> getGroupAt(int position) {
         // TODO(ianwen): Optimize the performance if the number of groups becomes too large.
-        if (mHasListHeader && position == 0) {
+        if (mHasListHeader && position < mGroups.first().size()) {
             assert mGroups.first().mIsListHeader;
             return new Pair<>(mGroups.first(), TYPE_HEADER);
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
index e626ec5..b19aac8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
@@ -296,6 +296,11 @@
          */
         @ContentType
         int getType();
+
+        /**
+         * @return Whether the default top padding should be applied to the content view.
+         */
+        boolean applyDefaultTopPadding();
     }
 
     /**
@@ -927,6 +932,13 @@
     }
 
     /**
+     * @return The {@link BottomSheetNewTabController} used to present the new tab UI.
+     */
+    public BottomSheetNewTabController getNewTabController() {
+        return mNtpController;
+    }
+
+    /**
      * Show content in the bottom sheet's content area.
      * @param content The {@link BottomSheetContent} to show.
      */
@@ -961,11 +973,17 @@
             }
         });
 
+        View contentView = content.getContentView();
+        if (content.applyDefaultTopPadding()) {
+            contentView.setPadding(contentView.getPaddingLeft(), mToolbarHolder.getHeight(),
+                    contentView.getPaddingRight(), contentView.getPaddingBottom());
+        }
+
         // For the toolbar transition, make sure we don't detach the default toolbar view.
         animators.add(getViewTransitionAnimator(
                 newToolbar, oldToolbar, mToolbarHolder, mDefaultToolbarView != oldToolbar));
         animators.add(getViewTransitionAnimator(
-                content.getContentView(), oldContent, mBottomSheetContentContainer, true));
+                contentView, oldContent, mBottomSheetContentContainer, true));
 
         // Temporarily make the background of the toolbar holder a solid color so the transition
         // doesn't appear to show a hole in the toolbar.
@@ -1053,6 +1071,8 @@
             tab.updateBrowserControlsState(BrowserControlsState.SHOWN, false);
         }
 
+        mBottomSheetContentContainer.setVisibility(View.VISIBLE);
+
         mIsSheetOpen = true;
         dismissSelectedText();
         for (BottomSheetObserver o : mObservers) o.onSheetOpened();
@@ -1071,7 +1091,7 @@
      */
     private void onSheetClosed() {
         if (!mIsSheetOpen) return;
-
+        mBottomSheetContentContainer.setVisibility(View.INVISIBLE);
         mBackButtonDismissesChrome = false;
         mIsSheetOpen = false;
         for (BottomSheetObserver o : mObservers) o.onSheetClosed();
@@ -1112,14 +1132,11 @@
         // The max height ratio will be greater than 1 to account for the toolbar shadow.
         mStateRatios[2] = (mContainerHeight + mToolbarShadowHeight) / mContainerHeight;
 
-        // Compute the height that the content section of the bottom sheet.
-        float contentHeight = (mContainerHeight * getFullRatio()) - mToolbarHeight;
-
         MarginLayoutParams sheetContentParams =
                 (MarginLayoutParams) mBottomSheetContentContainer.getLayoutParams();
         sheetContentParams.width = (int) mContainerWidth;
-        sheetContentParams.height = (int) contentHeight;
-        sheetContentParams.topMargin = (int) mToolbarHeight;
+        sheetContentParams.height = (int) mContainerHeight;
+        sheetContentParams.topMargin = mToolbarShadowHeight;
 
         MarginLayoutParams toolbarShadowParams =
                 (MarginLayoutParams) findViewById(R.id.toolbar_shadow).getLayoutParams();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetNewTabController.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetNewTabController.java
index 4bfcb28..9383653 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetNewTabController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetNewTabController.java
@@ -13,13 +13,26 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.toolbar.BottomToolbarPhone;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
- * A class that handles showing and hiding the Chrome Home new tab UI.
+ * A class that handles showing and hiding the bottom sheet new tab UI.
  */
 public class BottomSheetNewTabController extends EmptyBottomSheetObserver {
+    /** Observe events related to the bottom sheet new tab UI. **/
+    public interface Observer {
+        /** Called when the bottom sheet NTP UI is shown. */
+        void onNewTabShown();
+
+        /** Called when the bottom sheet NTP UI is hidden. */
+        void onNewTabHidden();
+    }
+
     private final BottomSheet mBottomSheet;
     private final BottomToolbarPhone mToolbar;
     private final ChromeActivity mActivity;
+    private final List<Observer> mObservers = new ArrayList<>();
 
     private LayoutManagerChrome mLayoutManager;
     private OverviewModeObserver mOverviewModeObserver;
@@ -46,6 +59,20 @@
     }
 
     /**
+     * @param observer An {@link Observer} to be notified of events related to the new tab UI.
+     */
+    public void addObserver(Observer observer) {
+        mObservers.add(observer);
+    }
+
+    /**
+     * @param observer The {@link Observer} to remove.
+     */
+    public void removeObserver(Observer observer) {
+        mObservers.remove(observer);
+    }
+
+    /**
      * @param tabModelSelector A TabModelSelector for getting the current tab and activity.
      */
     public void setTabModelSelector(TabModelSelector tabModelSelector) {
@@ -123,6 +150,8 @@
             mBottomSheet.getBottomSheetMetrics().recordSheetOpenReason(
                     BottomSheetMetrics.OPENED_BY_NEW_TAB_CREATION);
         }
+
+        for (Observer observer : mObservers) observer.onNewTabShown();
     }
 
     /**
@@ -200,6 +229,8 @@
         }
 
         mHideOverviewOnClose = false;
+
+        for (Observer observer : mObservers) observer.onNewTabHidden();
     }
 
     private void showTabSwitcherToolbarIfNecessary() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/PlaceholderSheetContent.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/PlaceholderSheetContent.java
index 7a20a78..a5f83c5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/PlaceholderSheetContent.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/PlaceholderSheetContent.java
@@ -78,4 +78,9 @@
     public int getType() {
         return BottomSheetContentController.TYPE_PLACEHOLDER;
     }
+
+    @Override
+    public boolean applyDefaultTopPadding() {
+        return true;
+    }
 }
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index f0998b1..c86f240 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -329,6 +329,7 @@
   "java/src/org/chromium/chrome/browser/download/DownloadItem.java",
   "java/src/org/chromium/chrome/browser/download/DownloadManagerDelegate.java",
   "java/src/org/chromium/chrome/browser/download/DownloadManagerService.java",
+  "java/src/org/chromium/chrome/browser/download/DownloadNotificationFactory.java",
   "java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java",
   "java/src/org/chromium/chrome/browser/download/DownloadNotifier.java",
   "java/src/org/chromium/chrome/browser/download/DownloadPage.java",
@@ -339,6 +340,7 @@
   "java/src/org/chromium/chrome/browser/download/DownloadSheetContent.java",
   "java/src/org/chromium/chrome/browser/download/DownloadSnackbarController.java",
   "java/src/org/chromium/chrome/browser/download/DownloadUmaStatsEntry.java",
+  "java/src/org/chromium/chrome/browser/download/DownloadUpdate.java",
   "java/src/org/chromium/chrome/browser/download/DownloadUtils.java",
   "java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java",
   "java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapterTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapterTest.java
index a624e56..830ab81 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapterTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapterTest.java
@@ -90,7 +90,7 @@
         editor.putBoolean(PREF_SHOW_STORAGE_INFO_HEADER, true).apply();
     }
 
-    private void initializeAdapter(boolean showOffTheRecord) throws Exception {
+    private void initializeAdapter(boolean showOffTheRecord, boolean hasHeader) throws Exception {
         mObserver = new Observer();
         mAdapter = new DownloadHistoryAdapter(showOffTheRecord, null);
         mAdapter.registerAdapterDataObserver(mObserver);
@@ -106,14 +106,17 @@
             }
         });
         mDownloadDelegate.addCallback.waitForCallback(0);
-        mObserver.onChangedCallback.waitForCallback(callCount, 1);
+        // If header should be added, onChanged() will be called twice because both setHeaders()
+        // and loadMoreItems() will call notifyDataSetChanged(). Otherwise, setHeaders() will not
+        // be called and onChanged() will only be called once.
+        mObserver.onChangedCallback.waitForCallback(callCount, hasHeader ? 2 : 1);
     }
 
     /** Nothing downloaded, nothing shown. */
     @Test
     @SmallTest
     public void testInitialize_Empty() throws Exception {
-        initializeAdapter(false);
+        initializeAdapter(false, false);
         Assert.assertEquals(0, mAdapter.getItemCount());
         Assert.assertEquals(0, mAdapter.getTotalDownloadSize());
 
@@ -133,7 +136,7 @@
     public void testInitialize_SingleItem() throws Exception {
         DownloadItem item = StubbedProvider.createDownloadItem(0, "19840116 12:00");
         mDownloadDelegate.regularItems.add(item);
-        initializeAdapter(false);
+        initializeAdapter(false, true);
         checkAdapterContents(HEADER, null, item);
         Assert.assertEquals(1, mAdapter.getTotalDownloadSize());
     }
@@ -146,7 +149,7 @@
         DownloadItem item1 = StubbedProvider.createDownloadItem(1, "19840116 12:01");
         mDownloadDelegate.regularItems.add(item0);
         mDownloadDelegate.regularItems.add(item1);
-        initializeAdapter(false);
+        initializeAdapter(false, true);
         checkAdapterContents(HEADER, null, item1, item0);
         Assert.assertEquals(11, mAdapter.getTotalDownloadSize());
     }
@@ -159,7 +162,7 @@
         DownloadItem item1 = StubbedProvider.createDownloadItem(1, "19840117 12:00");
         mDownloadDelegate.regularItems.add(item0);
         mDownloadDelegate.regularItems.add(item1);
-        initializeAdapter(false);
+        initializeAdapter(false, true);
         checkAdapterContents(HEADER, null, item1, null, item0);
         Assert.assertEquals(11, mAdapter.getTotalDownloadSize());
     }
@@ -172,7 +175,7 @@
         editor.putBoolean(PREF_SHOW_STORAGE_INFO_HEADER, false).apply();
         DownloadItem item = StubbedProvider.createDownloadItem(0, "19840116 12:00");
         mDownloadDelegate.regularItems.add(item);
-        initializeAdapter(false);
+        initializeAdapter(false, false);
         checkAdapterContents(null, item);
         Assert.assertEquals(1, mAdapter.getTotalDownloadSize());
     }
@@ -185,7 +188,7 @@
         DownloadItem item1 = StubbedProvider.createDownloadItem(1, "19840116 12:01");
         mDownloadDelegate.regularItems.add(item0);
         mDownloadDelegate.regularItems.add(item1);
-        initializeAdapter(false);
+        initializeAdapter(false, true);
         checkAdapterContents(HEADER, null, item1, item0);
         Assert.assertEquals(11, mAdapter.getTotalDownloadSize());
 
@@ -216,7 +219,7 @@
         DownloadItem item1 = StubbedProvider.createDownloadItem(1, "19840116 12:01");
         mDownloadDelegate.regularItems.add(item0);
         mDownloadDelegate.offTheRecordItems.add(item1);
-        initializeAdapter(false);
+        initializeAdapter(false, true);
         checkAdapterContents(HEADER, null, item0);
         Assert.assertEquals(1, mAdapter.getTotalDownloadSize());
     }
@@ -229,7 +232,7 @@
         DownloadItem item1 = StubbedProvider.createDownloadItem(1, "19840116 12:00");
         mDownloadDelegate.regularItems.add(item0);
         mDownloadDelegate.offTheRecordItems.add(item1);
-        initializeAdapter(true);
+        initializeAdapter(true, true);
         checkAdapterContents(HEADER, null, item0, item1);
         Assert.assertEquals(11, mAdapter.getTotalDownloadSize());
     }
@@ -244,7 +247,7 @@
         mDownloadDelegate.regularItems.add(item0);
         mDownloadDelegate.offTheRecordItems.add(item1);
         mOfflineDelegate.items.add(item2);
-        initializeAdapter(true);
+        initializeAdapter(true, true);
         checkAdapterContents(HEADER, null, item2, null, item0, item1);
         Assert.assertEquals(100011, mAdapter.getTotalDownloadSize());
     }
@@ -254,7 +257,7 @@
     @SmallTest
     public void testUpdate_UpdateItems() throws Exception {
         // Start with an empty Adapter.
-        initializeAdapter(false);
+        initializeAdapter(false, false);
         Assert.assertEquals(0, mAdapter.getItemCount());
         Assert.assertEquals(0, mAdapter.getTotalDownloadSize());
 
@@ -267,7 +270,7 @@
         Assert.assertEquals(1, mAdapter.getTotalDownloadSize());
 
         // Add a second item with a different date.
-        Assert.assertEquals(2, mObserver.onChangedCallback.getCallCount());
+        Assert.assertEquals(3, mObserver.onChangedCallback.getCallCount());
         DownloadItem item1 = StubbedProvider.createDownloadItem(1, "19840117 12:00");
         mAdapter.onDownloadItemCreated(item1);
         mObserver.onChangedCallback.waitForCallback(2);
@@ -323,26 +326,28 @@
         mDownloadDelegate.regularItems.add(regularItem);
         mDownloadDelegate.offTheRecordItems.add(offTheRecordItem);
         mOfflineDelegate.items.add(offlineItem);
-        initializeAdapter(true);
+        initializeAdapter(true, true);
         checkAdapterContents(HEADER, null, offlineItem, null, regularItem, offTheRecordItem);
         Assert.assertEquals(100011, mAdapter.getTotalDownloadSize());
 
-        // Remove an item from the date bucket with two items.
-        Assert.assertEquals(1, mObserver.onChangedCallback.getCallCount());
+        // Remove an item from the date bucket with two items. Wait for two callbacks as
+        // notifyDataSetChanged() is called once when setHeaders() is called and once when items
+        // are loaded.
+        Assert.assertEquals(2, mObserver.onChangedCallback.getCallCount());
         mAdapter.onDownloadItemRemoved(offTheRecordItem.getId(), true);
         mObserver.onChangedCallback.waitForCallback(1);
         checkAdapterContents(HEADER, null, offlineItem, null, regularItem);
         Assert.assertEquals(100001, mAdapter.getTotalDownloadSize());
 
         // Remove an item from the second bucket, which removes the bucket entirely.
-        Assert.assertEquals(2, mObserver.onChangedCallback.getCallCount());
+        Assert.assertEquals(4, mObserver.onChangedCallback.getCallCount());
         mOfflineDelegate.observer.onItemDeleted(offlineItem.getGuid());
         mObserver.onChangedCallback.waitForCallback(2);
         checkAdapterContents(HEADER, null, regularItem);
         Assert.assertEquals(1, mAdapter.getTotalDownloadSize());
 
         // Remove the last item in the list.
-        Assert.assertEquals(3, mObserver.onChangedCallback.getCallCount());
+        Assert.assertEquals(6, mObserver.onChangedCallback.getCallCount());
         mAdapter.onDownloadItemRemoved(regularItem.getId(), false);
         mObserver.onChangedCallback.waitForCallback(3);
         Assert.assertEquals(0, mAdapter.getItemCount());
@@ -367,7 +372,7 @@
         mDownloadDelegate.offTheRecordItems.add(item4);
         mDownloadDelegate.regularItems.add(item5);
         mOfflineDelegate.items.add(item6);
-        initializeAdapter(true);
+        initializeAdapter(true, true);
         checkAdapterContents(
                 HEADER, null, item5, item4, item6, null, item3, item2, null, item1, item0);
         Assert.assertEquals(1666, mAdapter.getTotalDownloadSize());
@@ -401,7 +406,7 @@
         mOfflineDelegate.items.add(item0);
         mOfflineDelegate.items.add(item1);
         mOfflineDelegate.items.add(item2);
-        initializeAdapter(false);
+        initializeAdapter(false, true);
         checkAdapterContents(HEADER, null, item2, null, item1, item0);
         Assert.assertEquals(111000, mAdapter.getTotalDownloadSize());
 
@@ -427,7 +432,7 @@
     public void testInProgress_FilePathMapAccurate() throws Exception {
         Set<DownloadHistoryItemWrapper> toDelete;
 
-        initializeAdapter(false);
+        initializeAdapter(false, false);
         Assert.assertEquals(0, mAdapter.getItemCount());
         Assert.assertEquals(0, mAdapter.getTotalDownloadSize());
 
@@ -486,7 +491,7 @@
         mDownloadDelegate.offTheRecordItems.add(item4);
         mDownloadDelegate.regularItems.add(item5);
         mOfflineDelegate.items.add(item6);
-        initializeAdapter(true);
+        initializeAdapter(true, true);
         checkAdapterContents(
                 HEADER, null, item5, item4, item6, null, item3, item2, null, item1, item0);
 
@@ -540,7 +545,7 @@
         mDownloadDelegate.offTheRecordItems.add(item4);
         mDownloadDelegate.regularItems.add(item5);
         mOfflineDelegate.items.add(item6);
-        initializeAdapter(true);
+        initializeAdapter(true, true);
         checkAdapterContents(
                 HEADER, null, item5, item4, item6, null, item3, item2, null, item1, item0);
 
@@ -586,7 +591,7 @@
         mDownloadDelegate.offTheRecordItems.add(item4);
         mDownloadDelegate.regularItems.add(item5);
         mOfflineDelegate.items.add(item6);
-        initializeAdapter(true);
+        initializeAdapter(true, true);
         checkAdapterContents(
                 HEADER, null, item5, item4, item6, null, item3, item2, null, item1, item0);
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
index 2071f3f..e0a19ea 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
@@ -34,6 +34,7 @@
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.signin.SigninManager;
 import org.chromium.chrome.browser.signin.SigninManager.SignInStateObserver;
+import org.chromium.chrome.browser.widget.DateDividedAdapter;
 import org.chromium.chrome.browser.widget.TintedImageButton;
 import org.chromium.chrome.browser.widget.selection.SelectableItemView;
 import org.chromium.chrome.browser.widget.selection.SelectableItemViewHolder;
@@ -442,11 +443,10 @@
         // Not signed in
         ChromeSigninController signinController = ChromeSigninController.get();
         signinController.setSignedInAccountName(null);
-        assertEquals(false, infoMenuItem.isVisible());
-        assertEquals(View.GONE, mAdapter.getSignedInNotSyncedViewForTests().getVisibility());
-        assertEquals(View.GONE, mAdapter.getSignedInSyncedViewForTests().getVisibility());
-        assertEquals(
-                View.GONE, mAdapter.getOtherFormsOfBrowsingHistoryViewForTests().getVisibility());
+        assertFalse(infoMenuItem.isVisible());
+        DateDividedAdapter.ItemGroup headerGroup = mAdapter.getFirstGroupForTests();
+        assertTrue(mAdapter.hasListHeader());
+        assertEquals(1, headerGroup.size());
 
         // Signed in but not synced and history has items
         signinController.setSignedInAccountName("test@gmail.com");
@@ -457,22 +457,100 @@
                 toolbar.onSignInStateChange();
             }
         });
-        assertEquals(true, infoMenuItem.isVisible());
+        assertTrue(infoMenuItem.isVisible());
 
         // Signed in, synced, has other forms and has items
         // Privacy disclaimers should be shown by default
         setHasOtherFormsOfBrowsingData(true, true);
-        assertEquals(true, infoMenuItem.isVisible());
-        assertEquals(View.VISIBLE, mAdapter.getPrivacyDisclaimersForTests().getVisibility());
+        assertTrue(infoMenuItem.isVisible());
+        headerGroup = mAdapter.getFirstGroupForTests();
+        assertTrue(mAdapter.hasListHeader());
+        assertEquals(2, headerGroup.size());
 
-        // Toggle Info Menu Item
+        // Toggle Info Menu Item to off
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
                 mHistoryManager.onMenuItemClick(infoMenuItem);
             }
         });
-        assertEquals(View.GONE, mAdapter.getPrivacyDisclaimersForTests().getVisibility());
+        headerGroup = mAdapter.getFirstGroupForTests();
+        assertTrue(mAdapter.hasListHeader());
+        assertEquals(1, headerGroup.size());
+
+        // Toggle Info Menu Item to on
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                mHistoryManager.onMenuItemClick(infoMenuItem);
+            }
+        });
+        headerGroup = mAdapter.getFirstGroupForTests();
+        assertTrue(mAdapter.hasListHeader());
+        assertEquals(2, headerGroup.size());
+
+        signinController.setSignedInAccountName(null);
+    }
+
+    @SmallTest
+    public void testInfoHeaderInSearchMode() throws Exception {
+        final HistoryManagerToolbar toolbar = mHistoryManager.getToolbarForTests();
+        final MenuItem infoMenuItem = toolbar.getItemById(R.id.info_menu_id);
+
+        // Sign in
+        int callCount = mTestObserver.onSelectionCallback.getCallCount();
+        ChromeSigninController signinController = ChromeSigninController.get();
+        signinController.setSignedInAccountName("test@gmail.com");
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                toolbar.onSignInStateChange();
+                mAdapter.onSignInStateChange();
+            }
+        });
+        mTestObserver.onChangedCallback.waitForCallback(callCount, 1);
+        DateDividedAdapter.ItemGroup firstGroup = mAdapter.getFirstGroupForTests();
+        assertTrue(infoMenuItem.isVisible());
+        assertTrue(mAdapter.hasListHeader());
+        assertEquals(2, firstGroup.size());
+
+        // Enter search mode
+        callCount = mTestObserver.onSelectionCallback.getCallCount();
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                toolbar.getMenu().performIdentifierAction(R.id.search_menu_id, 0);
+            }
+        });
+
+        mTestObserver.onSelectionCallback.waitForCallback(callCount, 1);
+        firstGroup = mAdapter.getFirstGroupForTests();
+        assertFalse(infoMenuItem.isVisible());
+        // The first group should be the history item group from SetUp()
+        assertFalse(mAdapter.hasListHeader());
+        assertEquals(3, firstGroup.size());
+
+        signinController.setSignedInAccountName(null);
+    }
+
+    @SmallTest
+    public void testInvisibleHeader() throws Exception {
+        assertTrue(mAdapter.hasListHeader());
+
+        // Not sign in and set clear browsing data button to invisible
+        ChromeSigninController signinController = ChromeSigninController.get();
+        signinController.setSignedInAccountName(null);
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                mAdapter.setClearBrowsingDataButtonVisibilityForTest(false);
+                mAdapter.setPrivacyDisclaimerVisibility();
+            }
+        });
+
+        DateDividedAdapter.ItemGroup firstGroup = mAdapter.getFirstGroupForTests();
+        assertFalse(mAdapter.hasListHeader());
+        assertEquals(3, firstGroup.size());
     }
 
     @SmallTest
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryAdapterTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryAdapterTest.java
index 78d54128..a547d4f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryAdapterTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryAdapterTest.java
@@ -36,6 +36,7 @@
     public void setUp() throws Exception {
         mHistoryProvider = new StubbedHistoryProvider();
         mAdapter = new HistoryAdapter(new SelectionDelegate<HistoryItem>(), null, mHistoryProvider);
+        mAdapter.generateHeaderItemsForTest();
     }
 
     private void initializeAdapter() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OWNERS
index f5f6e7ea..6d22a37 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OWNERS
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OWNERS
@@ -1 +1,4 @@
+bsazonov@chromium.org
 gogerald@chromium.org
+
+# COMPONENT: Services>Signin
diff --git a/chrome/android/webapk/libs/common/BUILD.gn b/chrome/android/webapk/libs/common/BUILD.gn
index 812295c..9d279cd 100644
--- a/chrome/android/webapk/libs/common/BUILD.gn
+++ b/chrome/android/webapk/libs/common/BUILD.gn
@@ -10,4 +10,14 @@
     "src/org/chromium/webapk/lib/common/WebApkMetaDataKeys.java",
     "src/org/chromium/webapk/lib/common/WebApkVersionUtils.java",
   ]
+  srcjar_deps = [ "//chrome/android/webapk/libs/common:identity_service_aidl" ]
+}
+
+android_aidl("identity_service_aidl") {
+  import_include = [ "src/org/chromium/webapk/lib/common/identity_service" ]
+  interface_file =
+      "src/org/chromium/webapk/lib/common/identity_service/common.aidl"
+  sources = [
+    "src/org/chromium/webapk/lib/common/identity_service/IIdentityService.aidl",
+  ]
 }
diff --git a/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/identity_service/IIdentityService.aidl b/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/identity_service/IIdentityService.aidl
new file mode 100644
index 0000000..778fec8
--- /dev/null
+++ b/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/identity_service/IIdentityService.aidl
@@ -0,0 +1,11 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.webapk.lib.common.identity_service;
+
+/** IdentityService allows browsers to query information about the WebAPK. */
+interface IIdentityService {
+    // Gets the package name of its runtime host browser.
+    String getRuntimeHostBrowserPackageName();
+}
diff --git a/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/identity_service/OWNERS b/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/identity_service/OWNERS
new file mode 100644
index 0000000..8f094e0
--- /dev/null
+++ b/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/identity_service/OWNERS
@@ -0,0 +1,2 @@
+per-file *.aidl=set noparent
+per-file *.aidl=file://ipc/SECURITY_OWNERS
diff --git a/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/identity_service/common.aidl b/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/identity_service/common.aidl
new file mode 100644
index 0000000..ab840204
--- /dev/null
+++ b/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/identity_service/common.aidl
@@ -0,0 +1,5 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+interface org.chromium.webapk.lib.common.identity_service.IIdentityServiceApi;
diff --git a/chrome/android/webapk/shell_apk/AndroidManifest.xml b/chrome/android/webapk/shell_apk/AndroidManifest.xml
index 9aa46e77..7f5379b8 100644
--- a/chrome/android/webapk/shell_apk/AndroidManifest.xml
+++ b/chrome/android/webapk/shell_apk/AndroidManifest.xml
@@ -71,5 +71,13 @@
             android:process=":webapk_sandboxed_process2"
             android:exported="true"
             tools:ignore="ExportedService"/>
+        <service
+            android:name="org.chromium.webapk.shell_apk.IdentityService"
+            android:exported="true"
+            tools:ignore="ExportedService">
+            <intent-filter>
+              <action android:name="org.webapk.IDENTITY_SERVICE_API" />
+            </intent-filter>
+        </service>
     </application>
 </manifest>
diff --git a/chrome/android/webapk/shell_apk/BUILD.gn b/chrome/android/webapk/shell_apk/BUILD.gn
index 1bac854..3052045 100644
--- a/chrome/android/webapk/shell_apk/BUILD.gn
+++ b/chrome/android/webapk/shell_apk/BUILD.gn
@@ -142,6 +142,7 @@
     "src/org/chromium/webapk/shell_apk/HostBrowserClassLoader.java",
     "src/org/chromium/webapk/shell_apk/ChooseHostBrowserDialog.java",
     "src/org/chromium/webapk/shell_apk/MainActivity.java",
+    "src/org/chromium/webapk/shell_apk/IdentityService.java",
     "src/org/chromium/webapk/shell_apk/InstallHostBrowserDialog.java",
     "src/org/chromium/webapk/shell_apk/WebApkSandboxedProcessService.java",
     "src/org/chromium/webapk/shell_apk/WebApkSandboxedProcessService0.java",
diff --git a/chrome/android/webapk/shell_apk/shell_apk_version.gni b/chrome/android/webapk/shell_apk/shell_apk_version.gni
index def53e2..c2c0b44 100644
--- a/chrome/android/webapk/shell_apk/shell_apk_version.gni
+++ b/chrome/android/webapk/shell_apk/shell_apk_version.gni
@@ -6,7 +6,7 @@
 # (including AndroidManifest.xml) is updated. This version should be incremented
 # prior to uploading a new ShellAPK to the WebAPK Minting Server.
 # Does not affect Chrome.apk
-template_shell_apk_version = 15
+template_shell_apk_version = 16
 
 # The ShellAPK version expected by Chrome. Chrome will try to update the WebAPK
 # if the WebAPK's ShellAPK version is less than |expected_shell_apk_version|.
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/IdentityService.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/IdentityService.java
new file mode 100644
index 0000000..2204431
--- /dev/null
+++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/IdentityService.java
@@ -0,0 +1,31 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.webapk.shell_apk;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.StrictMode;
+
+import org.chromium.webapk.lib.common.identity_service.IIdentityService;
+
+/** IdentityService allows browsers to query information about the WebAPK. */
+public class IdentityService extends Service {
+    private final IIdentityService.Stub mBinder = new IIdentityService.Stub() {
+        public String getRuntimeHostBrowserPackageName() {
+            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
+            try {
+                return WebApkUtils.getHostBrowserPackageName(getApplicationContext());
+            } finally {
+                StrictMode.setThreadPolicy(oldPolicy);
+            }
+        }
+    };
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mBinder;
+    }
+}
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 4cb4ae5..e6ba5950 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -68,6 +68,7 @@
 #include "components/search_provider_logos/features.h"
 #include "components/security_state/core/security_state.h"
 #include "components/security_state/core/switches.h"
+#include "components/signin/core/common/profile_management_switches.h"
 #include "components/signin/core/common/signin_features.h"
 #include "components/signin/core/common/signin_switches.h"
 #include "components/spellcheck/common/spellcheck_features.h"
@@ -309,15 +310,34 @@
      "1024"}};
 
 #if !BUILDFLAG(ENABLE_MIRROR)
-const FeatureEntry::Choice kAccountConsistencyChoices[] = {
-    {flags_ui::kGenericExperimentChoiceDefault, "", ""},
-    {flag_descriptions::kAccountConsistencyChoiceMirror,
-     switches::kAccountConsistency, switches ::kAccountConsistencyMirror},
+
+const FeatureEntry::FeatureParam kAccountConsistencyMirror[] = {
+    {signin::kAccountConsistencyFeatureMethodParameter,
+     signin::kAccountConsistencyFeatureMethodMirror}};
+
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
-    {flag_descriptions::kAccountConsistencyChoiceDice,
-     switches::kAccountConsistency, switches::kAccountConsistencyDice},
+const FeatureEntry::FeatureParam kAccountConsistencyDice[] = {
+    {signin::kAccountConsistencyFeatureMethodParameter,
+     signin::kAccountConsistencyFeatureMethodDice}};
+
+const FeatureEntry::FeatureParam kAccountConsistencyDiceFixAuthErrors[] = {
+    {signin::kAccountConsistencyFeatureMethodParameter,
+     signin::kAccountConsistencyFeatureMethodDiceFixAuthErrors}};
+#endif  // BUILDFLAG(ENABLE_DICE_SUPPORT)
+
+const FeatureEntry::FeatureVariation kAccountConsistencyFeatureVariations[] = {
+    {"Mirror", kAccountConsistencyMirror, arraysize(kAccountConsistencyMirror),
+     nullptr /* variation_id */}
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
+    ,
+    {"Dice", kAccountConsistencyDice, arraysize(kAccountConsistencyDice),
+     nullptr /* variation_id */},
+    {"Dice (fix auth errors)", kAccountConsistencyDiceFixAuthErrors,
+     arraysize(kAccountConsistencyDiceFixAuthErrors),
+     nullptr /* variation_id */}
 #endif  // BUILDFLAG(ENABLE_DICE_SUPPORT)
 };
+
 #endif  // !BUILDFLAG(ENABLE_MIRROR)
 
 const FeatureEntry::Choice kSimpleCacheBackendChoices[] = {
@@ -1722,7 +1742,9 @@
 #if !BUILDFLAG(ENABLE_MIRROR)
     {"account-consistency", flag_descriptions::kAccountConsistencyName,
      flag_descriptions::kAccountConsistencyDescription, kOsAll,
-     MULTI_VALUE_TYPE(kAccountConsistencyChoices)},
+     FEATURE_WITH_PARAMS_VALUE_TYPE(signin::kAccountConsistencyFeature,
+                                    kAccountConsistencyFeatureVariations,
+                                    "AccountConsistencyVariations")},
 #endif
 #if BUILDFLAG(ENABLE_APP_LIST)
     {"reset-app-list-install-state",
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc
index 95672e5..633a98e 100644
--- a/chrome/browser/android/chrome_feature_list.cc
+++ b/chrome/browser/android/chrome_feature_list.cc
@@ -275,7 +275,7 @@
     "WebPaymentsSingleAppUiSkip", base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kWebVrAutopresent{"WebVrAutopresent",
-                                      base::FEATURE_ENABLED_BY_DEFAULT};
+                                      base::FEATURE_DISABLED_BY_DEFAULT};
 
 const base::Feature kWebVRCardboardSupport{"WebVRCardboardSupport",
                                            base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/chrome/browser/android/signin/OWNERS b/chrome/browser/android/signin/OWNERS
index f5f6e7ea..a75aa30 100644
--- a/chrome/browser/android/signin/OWNERS
+++ b/chrome/browser/android/signin/OWNERS
@@ -1 +1,2 @@
+bsazonov@chromium.org
 gogerald@chromium.org
diff --git a/chrome/browser/android/signin/signin_manager_android.cc b/chrome/browser/android/signin/signin_manager_android.cc
index eac88f72..3eb49613 100644
--- a/chrome/browser/android/signin/signin_manager_android.cc
+++ b/chrome/browser/android/signin/signin_manager_android.cc
@@ -54,6 +54,12 @@
 
 namespace {
 
+// Clears the information about the last signed-in user from |profile|.
+void ClearLastSignedInUserForProfile(Profile* profile) {
+  profile->GetPrefs()->ClearPref(prefs::kGoogleServicesLastAccountId);
+  profile->GetPrefs()->ClearPref(prefs::kGoogleServicesLastUsername);
+}
+
 // A BrowsingDataRemover::Observer that clears Profile data and then invokes
 // a callback and deletes itself. It can be configured to delete all data
 // (for enterprise users) or only Google's service workers (for all users).
@@ -62,7 +68,9 @@
   ProfileDataRemover(Profile* profile,
                      bool all_data,
                      const base::Closure& callback)
-      : callback_(callback),
+      : profile_(profile),
+        all_data_(all_data),
+        callback_(callback),
         origin_runner_(base::ThreadTaskRunnerHandle::Get()),
         remover_(content::BrowserContext::GetBrowsingDataRemover(profile)) {
     remover_->AddObserver(this);
@@ -96,11 +104,25 @@
 
   void OnBrowsingDataRemoverDone() override {
     remover_->RemoveObserver(this);
+
+    if (all_data_) {
+      BookmarkModel* model =
+          BookmarkModelFactory::GetForBrowserContext(profile_);
+      model->RemoveAllUserBookmarks();
+
+      // All the Profile data has been wiped. Clear the last signed in username
+      // as well, so that the next signin doesn't trigger the account
+      // change dialog.
+      ClearLastSignedInUserForProfile(profile_);
+    }
+
     origin_runner_->PostTask(FROM_HERE, callback_);
     origin_runner_->DeleteSoon(FROM_HERE, this);
   }
 
  private:
+  Profile* profile_;
+  bool all_data_;
   base::Closure callback_;
   scoped_refptr<base::SingleThreadTaskRunner> origin_runner_;
   content::BrowsingDataRemover* remover_;
@@ -268,13 +290,6 @@
 
 void SigninManagerAndroid::OnBrowsingDataRemoverDone(
     const base::android::ScopedJavaGlobalRef<jobject>& callback) {
-  BookmarkModel* model = BookmarkModelFactory::GetForBrowserContext(profile_);
-  model->RemoveAllUserBookmarks();
-
-  // All the Profile data has been wiped. Clear the last signed in username as
-  // well, so that the next signin doesn't trigger the acount change dialog.
-  ClearLastSignedInUser();
-
   Java_SigninManager_onProfileDataWiped(base::android::AttachCurrentThread(),
                                         java_signin_manager_, callback);
 }
@@ -282,12 +297,7 @@
 void SigninManagerAndroid::ClearLastSignedInUser(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj) {
-  ClearLastSignedInUser();
-}
-
-void SigninManagerAndroid::ClearLastSignedInUser() {
-  profile_->GetPrefs()->ClearPref(prefs::kGoogleServicesLastAccountId);
-  profile_->GetPrefs()->ClearPref(prefs::kGoogleServicesLastUsername);
+  ClearLastSignedInUserForProfile(profile_);
 }
 
 void SigninManagerAndroid::LogInSignedInUser(JNIEnv* env,
diff --git a/chrome/browser/android/signin/signin_manager_android.h b/chrome/browser/android/signin/signin_manager_android.h
index 6a50bba..af443d51 100644
--- a/chrome/browser/android/signin/signin_manager_android.h
+++ b/chrome/browser/android/signin/signin_manager_android.h
@@ -92,6 +92,7 @@
                        const std::string& username) override;
 
  private:
+  friend class SigninManagerAndroidTest;
   FRIEND_TEST_ALL_PREFIXES(SigninManagerAndroidTest,
                            DeleteGoogleServiceWorkerCaches);
 
@@ -104,8 +105,6 @@
   void OnBrowsingDataRemoverDone(
       const base::android::ScopedJavaGlobalRef<jobject>& callback);
 
-  void ClearLastSignedInUser();
-
   void OnSigninAllowedPrefChanged();
 
   static void WipeData(Profile* profile,
diff --git a/chrome/browser/android/signin/signin_manager_android_unittest.cc b/chrome/browser/android/signin/signin_manager_android_unittest.cc
index 6119fefb..d54c75c 100644
--- a/chrome/browser/android/signin/signin_manager_android_unittest.cc
+++ b/chrome/browser/android/signin/signin_manager_android_unittest.cc
@@ -9,9 +9,15 @@
 
 #include "base/memory/ref_counted.h"
 #include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/browsing_data/browsing_data_cache_storage_helper.h"
+#include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_factory.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
+#include "components/bookmarks/browser/bookmark_model.h"
+#include "components/bookmarks/test/bookmark_test_helpers.h"
+#include "components/keyed_service/core/keyed_service.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browsing_data_remover.h"
 #include "content/public/browser/storage_partition.h"
@@ -31,6 +37,47 @@
 
   TestingProfile* profile() { return profile_; }
 
+  static std::unique_ptr<KeyedService> GetEmptyBrowsingDataRemoverDelegate(
+      content::BrowserContext* context) {
+    return nullptr;
+  }
+
+  // Adds two testing bookmarks to |profile_|.
+  bookmarks::BookmarkModel* AddTestBookmarks() {
+    profile_->CreateBookmarkModel(true);
+    bookmarks::BookmarkModel* bookmark_model =
+        BookmarkModelFactory::GetForBrowserContext(profile_);
+    bookmarks::test::WaitForBookmarkModelToLoad(bookmark_model);
+
+    bookmark_model->AddURL(bookmark_model->bookmark_bar_node(), 0,
+                           base::ASCIIToUTF16("Example 1"),
+                           GURL("https://example.org/1"));
+    bookmark_model->AddURL(bookmark_model->bookmark_bar_node(), 1,
+                           base::ASCIIToUTF16("Example 2"),
+                           GURL("https://example.com/2"));
+
+    return bookmark_model;
+  }
+
+  // Calls SigninManager::WipeData(|all_data|) and waits for its completion.
+  void WipeData(bool all_data) {
+    // ChromeBrowsingDataRemoverDelegate deletes a lot of data storage backends
+    // that will not work correctly in a unittest. Remove it. Note that
+    // bookmarks deletion is currently not performed in the delegate, so this
+    // test remains valid.
+    // TODO(crbug.com/748484): Make ChromeBrowsingDataRemoverDelegate usable
+    // in unittests.
+    ChromeBrowsingDataRemoverDelegateFactory::GetInstance()
+        ->SetTestingFactoryAndUse(
+            profile(),
+            SigninManagerAndroidTest::GetEmptyBrowsingDataRemoverDelegate);
+
+    std::unique_ptr<base::RunLoop> run_loop(new base::RunLoop());
+    SigninManagerAndroid::WipeData(profile(), all_data,
+                                   run_loop->QuitClosure());
+    run_loop->Run();
+  }
+
  private:
   content::TestBrowserThreadBundle thread_bundle_;
   TestingProfileManager profile_manager_;
@@ -95,3 +142,21 @@
         << (test_case.should_be_deleted ? "NOT" : "") << ".";
   }
 }
+
+// Tests that wiping all data also deletes bookmarks.
+TEST_F(SigninManagerAndroidTest, DeleteBookmarksWhenWipingAllData) {
+  bookmarks::BookmarkModel* bookmark_model = AddTestBookmarks();
+  ASSERT_GE(bookmark_model->bookmark_bar_node()->child_count(), 0);
+  WipeData(true);
+  EXPECT_EQ(0, bookmark_model->bookmark_bar_node()->child_count());
+}
+
+// Tests that wiping Google service worker caches does not delete bookmarks.
+TEST_F(SigninManagerAndroidTest, DontDeleteBookmarksWhenDeletingSWCaches) {
+  bookmarks::BookmarkModel* bookmark_model = AddTestBookmarks();
+  int bookmarks_count = bookmark_model->bookmark_bar_node()->child_count();
+  ASSERT_GE(bookmarks_count, 0);
+  WipeData(false);
+  EXPECT_EQ(bookmarks_count,
+            bookmark_model->bookmark_bar_node()->child_count());
+}
diff --git a/chrome/browser/extensions/api/identity/identity_api.cc b/chrome/browser/extensions/api/identity/identity_api.cc
index ace8a51..a6a8e4f1 100644
--- a/chrome/browser/extensions/api/identity/identity_api.cc
+++ b/chrome/browser/extensions/api/identity/identity_api.cc
@@ -36,7 +36,6 @@
 #include "components/signin/core/browser/account_tracker_service.h"
 #include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "components/signin/core/browser/signin_manager.h"
-#include "components/signin/core/common/profile_management_switches.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_function_dispatcher.h"
 #include "extensions/common/extension.h"
diff --git a/chrome/browser/extensions/api/identity/identity_apitest.cc b/chrome/browser/extensions/api/identity/identity_apitest.cc
index b52b1870..3805952 100644
--- a/chrome/browser/extensions/api/identity/identity_apitest.cc
+++ b/chrome/browser/extensions/api/identity/identity_apitest.cc
@@ -555,7 +555,7 @@
 };
 
 IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest, MultiAccountOn) {
-  EXPECT_TRUE(switches::IsExtensionsMultiAccount());
+  EXPECT_TRUE(signin::IsExtensionsMultiAccount());
 }
 
 IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest, NoneSignedIn) {
@@ -589,7 +589,7 @@
 
 IN_PROC_BROWSER_TEST_F(IdentityOldProfilesGetAccountsFunctionTest,
                        MultiAccountOff) {
-  EXPECT_FALSE(switches::IsExtensionsMultiAccount());
+  EXPECT_FALSE(signin::IsExtensionsMultiAccount());
 }
 
 IN_PROC_BROWSER_TEST_F(IdentityOldProfilesGetAccountsFunctionTest,
diff --git a/chrome/browser/extensions/api/identity/identity_get_accounts_function.cc b/chrome/browser/extensions/api/identity/identity_get_accounts_function.cc
index 3b121318..f1c76e00 100644
--- a/chrome/browser/extensions/api/identity/identity_get_accounts_function.cc
+++ b/chrome/browser/extensions/api/identity/identity_get_accounts_function.cc
@@ -52,7 +52,7 @@
   infos->Append(primary_account_info.ToValue());
 
   // If extensions are not multi-account, ignore any other accounts.
-  if (!switches::IsExtensionsMultiAccount())
+  if (!signin::IsExtensionsMultiAccount())
     return RespondNow(OneArgument(std::move(infos)));
 
   // Otherwise, add the other accounts.
diff --git a/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc b/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc
index b304dbc..b31a79c5 100644
--- a/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc
+++ b/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc
@@ -4,6 +4,11 @@
 
 #include "chrome/browser/extensions/api/identity/identity_get_auth_token_function.h"
 
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
 #include "base/strings/string_number_conversions.h"
 #include "build/build_config.h"
 #include "chrome/browser/extensions/api/identity/identity_api.h"
@@ -140,7 +145,7 @@
   // Detect and handle the case where the extension is using an account other
   // than the primary account.
   if (!extension_gaia_id.empty() && extension_gaia_id != primary_gaia_id) {
-    if (!switches::IsExtensionsMultiAccount()) {
+    if (!signin::IsExtensionsMultiAccount()) {
       // TODO(courage): should this be a different error?
       CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
       return;
diff --git a/chrome/browser/extensions/extension_uninstall_dialog.h b/chrome/browser/extensions/extension_uninstall_dialog.h
index 77622426..292d74c8 100644
--- a/chrome/browser/extensions/extension_uninstall_dialog.h
+++ b/chrome/browser/extensions/extension_uninstall_dialog.h
@@ -59,6 +59,12 @@
                                           gfx::NativeWindow parent,
                                           Delegate* delegate);
 
+  // Create the Views implementation of ExtensionUninstallDialog, for use on
+  // platforms where that is not the native platform implementation.
+  static ExtensionUninstallDialog* CreateViews(Profile* profile,
+                                               gfx::NativeWindow parent,
+                                               Delegate* delegate);
+
   ~ExtensionUninstallDialog() override;
 
   // This is called to verify whether the uninstallation should proceed.
diff --git a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate_browsertest.cc b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate_browsertest.cc
index da7486f..aceba182 100644
--- a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate_browsertest.cc
+++ b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate_browsertest.cc
@@ -39,6 +39,7 @@
 #include "components/policy/core/common/cloud/policy_header_service.h"
 #include "components/policy/core/common/policy_switches.h"
 #include "components/prefs/pref_service.h"
+#include "components/signin/core/browser/scoped_account_consistency.h"
 #include "components/signin/core/browser/signin_header_helper.h"
 #include "components/signin/core/common/profile_management_switches.h"
 #include "components/signin/core/common/signin_pref_names.h"
@@ -471,8 +472,7 @@
                        MirrorRequestHeader) {
   // Enable account consistency so that mirror actually sets the
   // X-Chrome-Connected header in requests to Google.
-  switches::EnableAccountConsistencyMirrorForTesting(
-      base::CommandLine::ForCurrentProcess());
+  signin::ScopedAccountConsistencyMirror scoped_mirror;
 
   browser()->profile()->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
                                               "user@gmail.com");
diff --git a/chrome/browser/media/encrypted_media_browsertest.cc b/chrome/browser/media/encrypted_media_browsertest.cc
index 44f2b5f..53abc6af 100644
--- a/chrome/browser/media/encrypted_media_browsertest.cc
+++ b/chrome/browser/media/encrypted_media_browsertest.cc
@@ -176,17 +176,17 @@
                              PlayCount play_count,
                              const std::string& expected_title) {
     base::StringPairs query_params;
-    query_params.push_back(std::make_pair("mediaFile", media_file));
-    query_params.push_back(std::make_pair("mediaType", media_type));
-    query_params.push_back(std::make_pair("keySystem", key_system));
+    query_params.emplace_back("mediaFile", media_file);
+    query_params.emplace_back("mediaType", media_type);
+    query_params.emplace_back("keySystem", key_system);
     if (src_type == SrcType::MSE)
-      query_params.push_back(std::make_pair("useMSE", "1"));
+      query_params.emplace_back("useMSE", "1");
     if (force_invalid_response)
-      query_params.push_back(std::make_pair("forceInvalidResponse", "1"));
+      query_params.emplace_back("forceInvalidResponse", "1");
     if (!session_to_load.empty())
-      query_params.push_back(std::make_pair("sessionToLoad", session_to_load));
+      query_params.emplace_back("sessionToLoad", session_to_load);
     if (play_count == PlayCount::TWICE)
-      query_params.push_back(std::make_pair("playTwice", "1"));
+      query_params.emplace_back("playTwice", "1");
     RunEncryptedMediaTestPage(html_page, key_system, query_params,
                               expected_title);
   }
@@ -442,10 +442,10 @@
     }
 
     base::StringPairs query_params;
-    query_params.push_back(std::make_pair("keySystem", CurrentKeySystem()));
-    query_params.push_back(std::make_pair(
+    query_params.emplace_back("keySystem", CurrentKeySystem());
+    query_params.emplace_back(
         "configChangeType",
-        base::IntToString(static_cast<int>(config_change_type))));
+        base::IntToString(static_cast<int>(config_change_type)));
     RunEncryptedMediaTestPage("mse_config_change.html", CurrentKeySystem(),
                               query_params, kEnded);
   }
@@ -453,12 +453,12 @@
   void TestPolicyCheck() {
     base::StringPairs query_params;
     // We do not care about playback so choose an arbitrary media file.
-    query_params.push_back(std::make_pair("mediaFile", "bear-a_enc-a.webm"));
-    query_params.push_back(std::make_pair("mediaType", kWebMVorbisAudioOnly));
+    query_params.emplace_back("mediaFile", "bear-a_enc-a.webm");
+    query_params.emplace_back("mediaType", kWebMVorbisAudioOnly);
     if (CurrentSourceType() == SrcType::MSE)
-      query_params.push_back(std::make_pair("useMSE", "1"));
-    query_params.push_back(std::make_pair("keySystem", CurrentKeySystem()));
-    query_params.push_back(std::make_pair("policyCheck", "1"));
+      query_params.emplace_back("useMSE", "1");
+    query_params.emplace_back("keySystem", CurrentKeySystem());
+    query_params.emplace_back("policyCheck", "1");
     RunEncryptedMediaTestPage(kDefaultEmePlayer, CurrentKeySystem(),
                               query_params, kUnitTestSuccess);
   }
@@ -481,8 +481,8 @@
   void TestDifferentContainers(EncryptedContainer video_format,
                                EncryptedContainer audio_format) {
     base::StringPairs query_params;
-    query_params.push_back(std::make_pair("keySystem", CurrentKeySystem()));
-    query_params.push_back(std::make_pair("runEncrypted", "1"));
+    query_params.emplace_back("keySystem", CurrentKeySystem());
+    query_params.emplace_back("runEncrypted", "1");
     query_params.push_back(
         std::make_pair("videoFormat", ConvertContainerFormat(video_format)));
     query_params.push_back(
diff --git a/chrome/browser/page_load_metrics/observers/protocol_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/protocol_page_load_metrics_observer.cc
index ef5904e..b0e41f09 100644
--- a/chrome/browser/page_load_metrics/observers/protocol_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/protocol_page_load_metrics_observer.cc
@@ -62,6 +62,7 @@
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_38:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_39:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_40:
+    case net::HttpResponseInfo::CONNECTION_INFO_QUIC_41:
       PAGE_LOAD_HISTOGRAM(
           "PageLoad.Clients.Protocol.QUIC.ParseTiming.NavigationToParseStart",
           timing.parse_timing->parse_start.value());
@@ -114,6 +115,7 @@
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_38:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_39:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_40:
+    case net::HttpResponseInfo::CONNECTION_INFO_QUIC_41:
       PAGE_LOAD_HISTOGRAM(
           "PageLoad.Clients.Protocol.QUIC.PaintTiming."
           "NavigationToFirstContentfulPaint",
@@ -172,6 +174,7 @@
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_38:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_39:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_40:
+    case net::HttpResponseInfo::CONNECTION_INFO_QUIC_41:
       PAGE_LOAD_HISTOGRAM(
           "PageLoad.Clients.Protocol.QUIC.Experimental.PaintTiming."
           "NavigationToFirstMeaningfulPaint",
@@ -220,6 +223,7 @@
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_38:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_39:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_40:
+    case net::HttpResponseInfo::CONNECTION_INFO_QUIC_41:
       PAGE_LOAD_HISTOGRAM(
           "PageLoad.Clients.Protocol.QUIC.DocumentTiming."
           "NavigationToDOMContentLoadedEventFired",
@@ -263,6 +267,7 @@
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_38:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_39:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_40:
+    case net::HttpResponseInfo::CONNECTION_INFO_QUIC_41:
       PAGE_LOAD_HISTOGRAM(
           "PageLoad.Clients.Protocol.QUIC.DocumentTiming."
           "NavigationToLoadEventFired",
diff --git a/chrome/browser/printing/print_dialog_cloud.cc b/chrome/browser/printing/print_dialog_cloud.cc
index c01239d..ff1c8c7 100644
--- a/chrome/browser/printing/print_dialog_cloud.cc
+++ b/chrome/browser/printing/print_dialog_cloud.cc
@@ -71,7 +71,7 @@
                                bool add_account,
                                const base::Closure& callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  if (switches::IsAccountConsistencyMirrorEnabled() &&
+  if (signin::IsAccountConsistencyMirrorEnabled() &&
       !browser->profile()->IsOffTheRecord()) {
     browser->window()->ShowAvatarBubbleFromAvatarButton(
         add_account ? BrowserWindow::AVATAR_BUBBLE_MODE_ADD_ACCOUNT
diff --git a/chrome/browser/resources/print_preview/common/overlay.js b/chrome/browser/resources/print_preview/common/overlay.js
index dc08306..2680aad 100644
--- a/chrome/browser/resources/print_preview/common/overlay.js
+++ b/chrome/browser/resources/print_preview/common/overlay.js
@@ -71,9 +71,9 @@
         return;
       if (isVisible) {
         setIsVisible(this.getElement(), true);
-        setTimeout(function(element) {
-          element.classList.remove('transparent');
-        }.bind(this, this.getElement()), 0);
+        setTimeout(() => {
+          this.getElement().classList.remove('transparent');
+        }, 0);
       } else {
         this.getElement().classList.add('transparent');
       }
diff --git a/chrome/browser/resources/print_preview/data/destination_store.js b/chrome/browser/resources/print_preview/data/destination_store.js
index 236ea49..748e17a 100644
--- a/chrome/browser/resources/print_preview/data/destination_store.js
+++ b/chrome/browser/resources/print_preview/data/destination_store.js
@@ -1017,35 +1017,33 @@
           destination.provisionalType ==
               print_preview.DestinationProvisionalType.NEEDS_USB_PERMISSION,
           'Provisional type cannot be resolved.');
-      this.nativeLayer_.grantExtensionPrinterAccess(destination.id).then(
-          /**
-           * @param {!print_preview.ProvisionalDestinationInfo}
-           *     destinationInfo Information about the resolved printer.
-           */
-          function(destinationInfo) {
-            /**
-             * Removes the destination from the store and replaces it with a
-             * destination created from the resolved destination properties, if
-             * any are reported. Then sends a PROVISIONAL_DESTINATION_RESOLVED
-             * event.
-             */
-            this.removeProvisionalDestination_(destination.id);
-            var parsedDestination =
-                print_preview.ExtensionDestinationParser.parse(destinationInfo);
-            this.insertIntoStore_(parsedDestination);
-            this.dispatchProvisionalDestinationResolvedEvent_(
-                destination.id, parsedDestination);
-          }.bind(this),
-          function() {
-            /**
-             * The provisional destination is removed from the store and a
-             * PROVISIONAL_DESTINATION_RESOLVED event is dispatched with a null
-             * destination.
-             */
-            this.removeProvisionalDestination_(destination.id);
-            this.dispatchProvisionalDestinationResolvedEvent_(destination.id,
-                                                              null);
-          }.bind(this));
+      this.nativeLayer_.grantExtensionPrinterAccess(destination.id)
+          .then(
+              destinationInfo => {
+                /**
+                 * Removes the destination from the store and replaces it with a
+                 * destination created from the resolved destination properties,
+                 * if any are reported. Then sends a
+                 * PROVISIONAL_DESTINATION_RESOLVED event.
+                 */
+                this.removeProvisionalDestination_(destination.id);
+                var parsedDestination =
+                    print_preview.ExtensionDestinationParser.parse(
+                        destinationInfo);
+                this.insertIntoStore_(parsedDestination);
+                this.dispatchProvisionalDestinationResolvedEvent_(
+                    destination.id, parsedDestination);
+              },
+              () => {
+                /**
+                 * The provisional destination is removed from the store and a
+                 * PROVISIONAL_DESTINATION_RESOLVED event is dispatched with a
+                 * null destination.
+                 */
+                this.removeProvisionalDestination_(destination.id);
+                this.dispatchProvisionalDestinationResolvedEvent_(
+                    destination.id, null);
+              });
     },
 
     /**
@@ -1099,11 +1097,11 @@
         return;
       this.isPrivetDestinationSearchInProgress_ = true;
       this.nativeLayer_.getPrivetPrinters().then(
-          this.endPrivetPrinterSearch_.bind(this), function() {
+          this.endPrivetPrinterSearch_.bind(this), () => {
             // Rejected by C++, indicating privet printing is disabled.
             this.hasLoadedAllPrivetDestinations_ = true;
             this.isPrivetDestinationSearchInProgress_ = false;
-          }.bind(this));
+          });
       cr.dispatchSimpleEvent(
           this, DestinationStore.EventType.DESTINATION_SEARCH_STARTED);
     },
diff --git a/chrome/browser/resources/print_preview/previewarea/preview_area.js b/chrome/browser/resources/print_preview/previewarea/preview_area.js
index 8d41ff9..4fea711 100644
--- a/chrome/browser/resources/print_preview/previewarea/preview_area.js
+++ b/chrome/browser/resources/print_preview/previewarea/preview_area.js
@@ -320,11 +320,11 @@
       var TicketStoreEvent = print_preview.PrintTicketStore.EventType;
       [TicketStoreEvent.INITIALIZE, TicketStoreEvent.TICKET_CHANGE,
        TicketStoreEvent.CAPABILITIES_CHANGE, TicketStoreEvent.DOCUMENT_CHANGE]
-          .forEach(function(eventType) {
+          .forEach(eventType => {
             this.tracker.add(
                 this.printTicketStore_, eventType,
                 this.onTicketChange_.bind(this));
-          }.bind(this));
+          });
 
       [this.printTicketStore_.color, this.printTicketStore_.cssBackground,
        this.printTicketStore_.customMargins, this.printTicketStore_.fitToPage,
@@ -332,11 +332,11 @@
        this.printTicketStore_.marginsType, this.printTicketStore_.pageRange,
        this.printTicketStore_.rasterize, this.printTicketStore_.selectionOnly,
        this.printTicketStore_.scaling]
-          .forEach(function(setting) {
+          .forEach(setting => {
             this.tracker.add(
                 setting, print_preview.ticket_items.TicketItem.EventType.CHANGE,
                 this.onTicketChange_.bind(this));
-          }.bind(this));
+          });
 
       if (this.checkPluginCompatibility_()) {
         this.previewGenerator_ = new print_preview.PreviewGenerator(
@@ -534,16 +534,11 @@
             PreviewArea.LOADING_TIMEOUT_);
       }
       previewRequest.request.then(
-          /** @param {number} previewUid The unique id of the preview. */
-          function(previewUid) {
+          previewUid => {
             this.previewGenerator_.onPreviewGenerationDone(
                 previewRequest.id, previewUid);
-          }.bind(this),
-          /**
-           * @param {*} type The type of print preview failure that
-           *     occurred.
-           */
-          function(type) {
+          },
+          type => {
             if (/** @type{string} */ (type) == 'CANCELLED')
               return;  // overriden by a new request, do nothing.
             if (/** @type{string} */ (type) == 'SETTINGS_INVALID') {
@@ -555,7 +550,7 @@
             } else {
               this.onPreviewGenerationFail_();
             }
-          }.bind(this));
+          });
     },
 
     /**
diff --git a/chrome/browser/resources/print_preview/print_preview.js b/chrome/browser/resources/print_preview/print_preview.js
index 3c67556..8e6a9208 100644
--- a/chrome/browser/resources/print_preview/print_preview.js
+++ b/chrome/browser/resources/print_preview/print_preview.js
@@ -579,9 +579,9 @@
                print_preview.Destination.GooglePromotedId.SAVE_AS_PDF)) {
         // Local printers resolve when print is ready to start. Hide the
         // dialog. Mac "Open in Preview" is treated as a local printer.
-        var boundHideDialog = function() {
+        var boundHideDialog = () => {
           this.nativeLayer_.hidePreview();
-        }.bind(this);
+        };
         whenPrintDone.then(boundHideDialog, boundHideDialog);
       } else if (!destination.isLocal) {
         // Cloud print resolves when print data is returned to submit to cloud
diff --git a/chrome/browser/resources/print_preview/search/destination_list.js b/chrome/browser/resources/print_preview/search/destination_list.js
index 5d0d666..9c1a2ef 100644
--- a/chrome/browser/resources/print_preview/search/destination_list.js
+++ b/chrome/browser/resources/print_preview/search/destination_list.js
@@ -287,12 +287,12 @@
         setIsVisible(this.getChildElement('.destination-list > footer'), true);
       }
       // Remove obsolete list items (those with no corresponding destinations).
-      this.listItems_ = this.listItems_.filter(function(item) {
+      this.listItems_ = this.listItems_.filter(item => {
         var isValid = this.destinationIds_.hasOwnProperty(item.destination.id);
         if (!isValid)
           this.removeChild(item);
         return isValid;
-      }.bind(this));
+      });
       // Prepare id -> list item cache for visible destinations.
       var visibleListItems = {};
       for (var i = 0; i < numItems; i++)
diff --git a/chrome/browser/resources/print_preview/search/destination_search.js b/chrome/browser/resources/print_preview/search/destination_search.js
index 741d3c5e..7876776 100644
--- a/chrome/browser/resources/print_preview/search/destination_search.js
+++ b/chrome/browser/resources/print_preview/search/destination_search.js
@@ -222,10 +222,10 @@
       this.tracker.add(
           this,
           print_preview.DestinationListItem.EventType.REGISTER_PROMO_CLICKED,
-          function() {
+          () => {
             this.metrics_.record(print_preview.Metrics.DestinationSearchBucket
                                      .REGISTER_PROMO_SELECTED);
-          }.bind(this));
+          });
 
       this.tracker.add(
           this.destinationStore_,
@@ -608,20 +608,17 @@
       this.destinationInConfiguring_ = destination;
       this.destinationStore_.resolveCrosDestination(destination)
           .then(
-              /**
-               * @param {!print_preview.PrinterSetupResponse} response
-               */
-              function(response) {
+              response => {
                 this.destinationInConfiguring_ = null;
                 this.localList_.getDestinationItem(destination.id)
                     .onConfigureResolved(response);
-              }.bind(this),
-              function() {
+              },
+              () => {
                 this.destinationInConfiguring_ = null;
                 this.localList_.getDestinationItem(destination.id)
                     .onConfigureResolved(
                         {printerId: destination.id, success: false});
-              }.bind(this));
+              });
     },
 
     /**
@@ -656,21 +653,15 @@
         var lastFocusedElement = document.activeElement;
         this.addChild(this.provisionalDestinationResolver_);
         this.provisionalDestinationResolver_.run(this.getElement())
-            .then(
-                /**
-                 * @param {!print_preview.Destination} resolvedDestination
-                 *    Destination to which the provisional destination was
-                 *    resolved.
-                 */
-                function(resolvedDestination) {
-                  this.handleOnDestinationSelect_(resolvedDestination);
-                }.bind(this))
+            .then(resolvedDestination => {
+              this.handleOnDestinationSelect_(resolvedDestination);
+            })
             .catch(function() {
               console.error(
                   'Failed to resolve provisional destination: ' +
                   destination.id);
             })
-            .then(function() {
+            .then(() => {
               this.removeChild(assert(this.provisionalDestinationResolver_));
               this.provisionalDestinationResolver_ = null;
 
@@ -681,7 +672,7 @@
                   this.getElement().contains(lastFocusedElement)) {
                 lastFocusedElement.focus();
               }
-            }.bind(this));
+            });
         return;
       }
 
diff --git a/chrome/browser/resources/print_preview/settings/advanced_options_settings.js b/chrome/browser/resources/print_preview/settings/advanced_options_settings.js
index 2469dbe..0bc41f4 100644
--- a/chrome/browser/resources/print_preview/settings/advanced_options_settings.js
+++ b/chrome/browser/resources/print_preview/settings/advanced_options_settings.js
@@ -60,10 +60,10 @@
     enterDocument: function() {
       print_preview.SettingsSection.prototype.enterDocument.call(this);
 
-      this.tracker.add(this.getButton_(), 'click', function() {
+      this.tracker.add(this.getButton_(), 'click', () => {
         cr.dispatchSimpleEvent(
             this, AdvancedOptionsSettings.EventType.BUTTON_ACTIVATED);
-      }.bind(this));
+      });
       this.tracker.add(
           this.destinationStore_,
           print_preview.DestinationStore.EventType.DESTINATION_SELECT,
diff --git a/chrome/browser/resources/print_preview/settings/advanced_settings/advanced_settings.js b/chrome/browser/resources/print_preview/settings/advanced_settings/advanced_settings.js
index 42edd3a9..799f206 100644
--- a/chrome/browser/resources/print_preview/settings/advanced_settings/advanced_settings.js
+++ b/chrome/browser/resources/print_preview/settings/advanced_settings/advanced_settings.js
@@ -163,9 +163,9 @@
      */
     renderSettings_: function() {
       // Remove all children settings elements.
-      this.items_.forEach(function(item) {
+      this.items_.forEach(item => {
         this.removeChild(item);
-      }.bind(this));
+      });
       this.items_ = [];
 
       var extraPadding = this.element_.querySelector(
@@ -182,13 +182,13 @@
       containerEl.style.maxHeight = availableHeight + 'px';
       var settingsEl = this.getChildElement('.settings');
 
-      vendorCapabilities.forEach(function(capability) {
+      vendorCapabilities.forEach(capability => {
         var item = new print_preview.AdvancedSettingsItem(
             this.printTicketStore_, capability);
         this.addChild(item);
         item.render(settingsEl);
         this.items_.push(item);
-      }.bind(this));
+      });
 
       var searchBoxArea = this.getChildElement('.search-box-area');
       if (this.items_.length <= 1) {
@@ -222,10 +222,10 @@
       this.setIsVisible(false);
 
       var values = {};
-      this.items_.forEach(function(item) {
+      this.items_.forEach(item => {
         if (item.isModified())
           values[item.id] = item.selectedValue;
-      }.bind(this));
+      });
 
       this.printTicketStore_.vendorItems.updateValue(values);
     }
diff --git a/chrome/browser/resources/print_preview/settings/copies_settings.js b/chrome/browser/resources/print_preview/settings/copies_settings.js
index 6aaab6ed..1dbcc74 100644
--- a/chrome/browser/resources/print_preview/settings/copies_settings.js
+++ b/chrome/browser/resources/print_preview/settings/copies_settings.js
@@ -189,11 +189,9 @@
           // No need to update the ticket, but change the display to match.
           this.inputField_.value = '1';
         } else {
-          setTimeout(
-              (function() {
-                this.copiesTicketItem_.updateValue('1');
-              }).bind(this),
-              0);
+          setTimeout(() => {
+            this.copiesTicketItem_.updateValue('1');
+          }, 0);
         }
       }
     },
diff --git a/chrome/browser/resources/print_preview/settings/more_settings.js b/chrome/browser/resources/print_preview/settings/more_settings.js
index 25bb73933..3c044fd 100644
--- a/chrome/browser/resources/print_preview/settings/more_settings.js
+++ b/chrome/browser/resources/print_preview/settings/more_settings.js
@@ -9,7 +9,7 @@
    * Toggles visibility of the specified printing options sections.
    * @param {!print_preview.DestinationStore} destinationStore To listen for
    *     destination changes.
-   * @param {!Array<print_preview.SettingsSection>} settingsSections Sections
+   * @param {!Array<!print_preview.SettingsSection>} settingsSections Sections
    *     to toggle by this component.
    * @constructor
    * @extends {print_preview.Component}
@@ -20,7 +20,7 @@
     /** @private {!print_preview.DestinationStore} */
     this.destinationStore_ = destinationStore;
 
-    /** @private {!Array<print_preview.SettingsSection>} */
+    /** @private {!Array<!print_preview.SettingsSection>} */
     this.settingsSections_ = settingsSections;
 
     /** @private {boolean} */
@@ -61,12 +61,12 @@
           print_preview.DestinationStore.EventType
               .SELECTED_DESTINATION_CAPABILITIES_READY,
           this.onDestinationCapabilitiesReady_.bind(this));
-      this.settingsSections_.forEach(function(section) {
+      this.settingsSections_.forEach(section => {
         this.tracker.add(
             section,
             print_preview.SettingsSection.EventType.COLLAPSIBLE_CONTENT_CHANGED,
             this.updateState_.bind(this));
-      }.bind(this));
+      });
 
       this.updateState_(true);
     },
diff --git a/chrome/browser/signin/chrome_signin_client.cc b/chrome/browser/signin/chrome_signin_client.cc
index 161c030..daaf634 100644
--- a/chrome/browser/signin/chrome_signin_client.cc
+++ b/chrome/browser/signin/chrome_signin_client.cc
@@ -5,6 +5,9 @@
 #include "chrome/browser/signin/chrome_signin_client.h"
 
 #include <stddef.h>
+
+#include <memory>
+#include <string>
 #include <utility>
 
 #include "base/bind.h"
@@ -197,7 +200,7 @@
 }
 
 bool ChromeSigninClient::ShouldMergeSigninCredentialsIntoCookieJar() {
-  return !switches::IsAccountConsistencyMirrorEnabled();
+  return !signin::IsAccountConsistencyMirrorEnabled();
 }
 
 std::string ChromeSigninClient::GetProductVersion() {
diff --git a/chrome/browser/signin/chrome_signin_helper.cc b/chrome/browser/signin/chrome_signin_helper.cc
index 6fe62ed83..31817c8 100644
--- a/chrome/browser/signin/chrome_signin_helper.cc
+++ b/chrome/browser/signin/chrome_signin_helper.cc
@@ -54,8 +54,8 @@
     const content::ResourceRequestInfo::WebContentsGetter&
         web_contents_getter) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  DCHECK_EQ(switches::AccountConsistencyMethod::kMirror,
-            switches::GetAccountConsistencyMethod());
+  DCHECK_EQ(signin::AccountConsistencyMethod::kMirror,
+            signin::GetAccountConsistencyMethod());
 
   GAIAServiceType service_type = manage_accounts_params.service_type;
   DCHECK_NE(GAIA_SERVICE_TYPE_NONE, service_type);
@@ -115,8 +115,8 @@
     const content::ResourceRequestInfo::WebContentsGetter&
         web_contents_getter) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  DCHECK_EQ(switches::AccountConsistencyMethod::kDice,
-            switches::GetAccountConsistencyMethod());
+  DCHECK_EQ(signin::AccountConsistencyMethod::kDice,
+            signin::GetAccountConsistencyMethod());
 
   content::WebContents* web_contents = web_contents_getter.Run();
   if (!web_contents)
@@ -163,8 +163,8 @@
     return;
   }
 
-  if (switches::GetAccountConsistencyMethod() !=
-      switches::AccountConsistencyMethod::kMirror) {
+  if (signin::GetAccountConsistencyMethod() !=
+      signin::AccountConsistencyMethod::kMirror) {
     NOTREACHED() << "Gaia should not send the X-Chrome-Manage-Accounts header "
                  << "when Mirror is disabled.";
     return;
@@ -198,8 +198,8 @@
   if (!gaia::IsGaiaSignonRealm(request->url().GetOrigin()))
     return;
 
-  if (switches::GetAccountConsistencyMethod() !=
-      switches::AccountConsistencyMethod::kDice) {
+  if (signin::GetAccountConsistencyMethod() !=
+      signin::AccountConsistencyMethod::kDice) {
     return;
   }
 
diff --git a/chrome/browser/signin/chrome_signin_helper_unittest.cc b/chrome/browser/signin/chrome_signin_helper_unittest.cc
index d5003b9..4e92a0e3 100644
--- a/chrome/browser/signin/chrome_signin_helper_unittest.cc
+++ b/chrome/browser/signin/chrome_signin_helper_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/command_line.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
+#include "components/signin/core/browser/scoped_account_consistency.h"
 #include "components/signin/core/common/profile_management_switches.h"
 #include "components/signin/core/common/signin_features.h"
 #include "content/public/browser/browser_thread.h"
@@ -145,8 +146,7 @@
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
 // Tests that Dice response headers are removed after being processed.
 TEST_F(ChromeSigninHelperTest, RemoveDiceSigninHeader) {
-  switches::EnableAccountConsistencyDiceForTesting(
-      base::CommandLine::ForCurrentProcess());
+  signin::ScopedAccountConsistencyDice scoped_dice;
 
   TestResponseHelper test_response_helper;
   test_response_helper.CreateRequestWithResponseHeaders();
diff --git a/chrome/browser/signin/dice_browsertest.cc b/chrome/browser/signin/dice_browsertest.cc
index a554a3ac..aa52616f 100644
--- a/chrome/browser/signin/dice_browsertest.cc
+++ b/chrome/browser/signin/dice_browsertest.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/command_line.h"
+#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
@@ -21,6 +22,7 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/signin/core/browser/account_tracker_service.h"
 #include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/scoped_account_consistency.h"
 #include "components/signin/core/browser/signin_header_helper.h"
 #include "components/signin/core/browser/signin_manager.h"
 #include "components/signin/core/common/profile_management_switches.h"
@@ -276,11 +278,11 @@
     command_line->AppendSwitchASCII(switches::kGaiaUrl, base_url.spec());
     command_line->AppendSwitchASCII(switches::kGoogleApisUrl, base_url.spec());
     command_line->AppendSwitchASCII(switches::kLsoUrl, base_url.spec());
-    switches::EnableAccountConsistencyDiceForTesting(command_line);
   }
 
   void SetUpOnMainThread() override {
     InProcessBrowserTest::SetUpOnMainThread();
+    scoped_dice_ = base::MakeUnique<signin::ScopedAccountConsistencyDice>();
     https_server_.StartAcceptingConnections();
     GetTokenService()->AddObserver(this);
   }
@@ -300,6 +302,7 @@
   }
 
   net::EmbeddedTestServer https_server_;
+  std::unique_ptr<signin::ScopedAccountConsistencyDice> scoped_dice_;
   bool token_requested_;
   bool refresh_token_available_;
   int token_revoked_notification_count_;
diff --git a/chrome/browser/signin/dice_response_handler.cc b/chrome/browser/signin/dice_response_handler.cc
index 042f222a..b46e18c 100644
--- a/chrome/browser/signin/dice_response_handler.cc
+++ b/chrome/browser/signin/dice_response_handler.cc
@@ -159,8 +159,8 @@
 
 void DiceResponseHandler::ProcessDiceHeader(
     const signin::DiceResponseParams& dice_params) {
-  DCHECK_EQ(switches::AccountConsistencyMethod::kDice,
-            switches::GetAccountConsistencyMethod());
+  DCHECK_EQ(signin::AccountConsistencyMethod::kDice,
+            signin::GetAccountConsistencyMethod());
 
   switch (dice_params.user_intention) {
     case signin::DiceAction::SIGNIN:
diff --git a/chrome/browser/signin/dice_response_handler_unittest.cc b/chrome/browser/signin/dice_response_handler_unittest.cc
index 87fbfa8..46a3111 100644
--- a/chrome/browser/signin/dice_response_handler_unittest.cc
+++ b/chrome/browser/signin/dice_response_handler_unittest.cc
@@ -14,6 +14,7 @@
 #include "components/signin/core/browser/account_tracker_service.h"
 #include "components/signin/core/browser/fake_signin_manager.h"
 #include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/scoped_account_consistency.h"
 #include "components/signin/core/browser/signin_header_helper.h"
 #include "components/signin/core/browser/test_signin_client.h"
 #include "components/signin/core/common/profile_management_switches.h"
@@ -79,8 +80,6 @@
                                &account_tracker_service_) {
     loop_.SetTaskRunner(task_runner_);
     DCHECK_EQ(task_runner_, base::ThreadTaskRunnerHandle::Get());
-    switches::EnableAccountConsistencyDiceForTesting(
-        base::CommandLine::ForCurrentProcess());
     signin_client_.SetURLRequestContext(request_context_getter_.get());
     AccountTrackerService::RegisterPrefs(pref_service_.registry());
     SigninManager::RegisterProfilePrefs(pref_service_.registry());
@@ -109,6 +108,7 @@
   scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
   scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
   sync_preferences::TestingPrefServiceSyncable pref_service_;
+  signin::ScopedAccountConsistencyDice scoped_dice_;
   DiceTestSigninClient signin_client_;
   ProfileOAuth2TokenService token_service_;
   AccountTrackerService account_tracker_service_;
diff --git a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.cc b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.cc
index d837c66..b5d2a8a 100644
--- a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.cc
+++ b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.cc
@@ -6,6 +6,9 @@
 
 #include <stddef.h>
 
+#include <map>
+#include <string>
+
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/profiler/scoped_tracker.h"
@@ -281,7 +284,7 @@
 
   load_credentials_state_ = LOAD_CREDENTIALS_IN_PROGRESS;
   if (primary_account_id.empty() &&
-      !switches::IsAccountConsistencyDiceEnabled()) {
+      !signin::IsAccountConsistencyDiceEnabled()) {
     load_credentials_state_ = LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS;
     FireRefreshTokensLoaded();
     return;
@@ -321,7 +324,8 @@
     WebDataServiceBase::Handle handle,
     std::unique_ptr<WDTypedResult> result) {
   VLOG(1) << "MutablePO2TS::OnWebDataServiceRequestDone. Result type: "
-          << (result.get() == nullptr ? -1 : (int)result->GetType());
+          << (result.get() == nullptr ? -1
+                                      : static_cast<int>(result->GetType()));
 
   // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
   // fixed.
@@ -348,7 +352,7 @@
   // map.  The entry could be missing if there is a corruption in the token DB
   // while this profile is connected to an account.
   DCHECK(!loading_primary_account_id_.empty() ||
-         switches::IsAccountConsistencyDiceEnabled());
+         signin::IsAccountConsistencyDiceEnabled());
   if (!loading_primary_account_id_.empty() &&
       refresh_tokens_.count(loading_primary_account_id_) == 0) {
     refresh_tokens_[loading_primary_account_id_].reset(new AccountStatus(
@@ -435,8 +439,8 @@
 
         // Only load secondary accounts when account consistency is enabled.
         if (account_id == loading_primary_account_id_ ||
-            switches::IsAccountConsistencyDiceEnabled() ||
-            switches::IsAccountConsistencyMirrorEnabled()) {
+            signin::IsAccountConsistencyDiceEnabled() ||
+            signin::IsAccountConsistencyMirrorEnabled()) {
           refresh_tokens_[account_id].reset(new AccountStatus(
               signin_error_controller_, account_id, refresh_token));
           FireRefreshTokenAvailable(account_id);
diff --git a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate_unittest.cc b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate_unittest.cc
index 5818f17b..c63f3ba 100644
--- a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate_unittest.cc
+++ b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate_unittest.cc
@@ -20,6 +20,7 @@
 #include "components/prefs/scoped_user_pref_update.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/scoped_account_consistency.h"
 #include "components/signin/core/browser/signin_error_controller.h"
 #include "components/signin/core/browser/test_signin_client.h"
 #include "components/signin/core/browser/webdata/token_web_data.h"
@@ -181,9 +182,7 @@
   AddAuthTokenManually(kLSOService, "lsoToken");
   AddAuthTokenManually(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
                        main_refresh_token);
-
-  switches::EnableAccountConsistencyMirrorForTesting(
-      base::CommandLine::ForCurrentProcess());
+  signin::ScopedAccountConsistencyMirror scoped_mirror;
 
   // Force LoadCredentials.
   oauth2_service_delegate_->LoadCredentials(main_account_id);
@@ -297,8 +296,7 @@
 
 TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
        PersistenceLoadCredentials) {
-  switches::EnableAccountConsistencyMirrorForTesting(
-      base::CommandLine::ForCurrentProcess());
+  signin::ScopedAccountConsistencyMirror scoped_mirror;
 
   // Ensure DB is clean.
   oauth2_service_delegate_->RevokeAllCredentials();
@@ -357,8 +355,7 @@
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
 TEST_F(MutableProfileOAuth2TokenServiceDelegateTest,
        PersistenceLoadCredentialsEmptyPrimaryAccountId_DiceEnabled) {
-  switches::EnableAccountConsistencyDiceForTesting(
-      base::CommandLine::ForCurrentProcess());
+  signin::ScopedAccountConsistencyDice scoped_dice;
 
   // Ensure DB is clean.
   oauth2_service_delegate_->RevokeAllCredentials();
@@ -598,8 +595,7 @@
   tokens["AccountId-Foo.Bar@gmail.com"] = "refresh_token";
   tokens["AccountId-12345"] = "refresh_token";
 
-  switches::EnableAccountConsistencyMirrorForTesting(
-      base::CommandLine::ForCurrentProcess());
+  signin::ScopedAccountConsistencyMirror scoped_mirror;
   oauth2_service_delegate_->LoadAllCredentialsIntoMemory(tokens);
 
   EXPECT_TRUE(
@@ -615,8 +611,7 @@
   tokens["AccountId-Foo.Bar@gmail.com"] = "bad_token";
   tokens["AccountId-foobar@gmail.com"] = "good_token";
 
-  switches::EnableAccountConsistencyMirrorForTesting(
-      base::CommandLine::ForCurrentProcess());
+  signin::ScopedAccountConsistencyMirror scoped_mirror;
   oauth2_service_delegate_->LoadAllCredentialsIntoMemory(tokens);
 
   EXPECT_EQ(1u, oauth2_service_delegate_->GetAccounts().size());
@@ -628,8 +623,7 @@
 }
 
 TEST_F(MutableProfileOAuth2TokenServiceDelegateTest, ShutdownService) {
-  switches::EnableAccountConsistencyMirrorForTesting(
-      base::CommandLine::ForCurrentProcess());
+  signin::ScopedAccountConsistencyMirror scoped_mirror;
   EXPECT_TRUE(oauth2_service_delegate_->GetAccounts().empty());
   oauth2_service_delegate_->UpdateCredentials("account_id1", "refresh_token1");
   oauth2_service_delegate_->UpdateCredentials("account_id2", "refresh_token2");
@@ -651,8 +645,7 @@
     std::string email = "foo@gmail.com";
     std::string gaia_id = "foo's gaia id";
 
-    switches::EnableAccountConsistencyMirrorForTesting(
-        base::CommandLine::ForCurrentProcess());
+    signin::ScopedAccountConsistencyMirror scoped_mirror;
     pref_service_.SetInteger(prefs::kAccountIdMigrationState,
                              AccountTrackerService::MIGRATION_NOT_STARTED);
 
@@ -710,8 +703,7 @@
     std::string email2 = "bar@gmail.com";
     std::string gaia_id2 = "bar's gaia id";
 
-    switches::EnableAccountConsistencyMirrorForTesting(
-        base::CommandLine::ForCurrentProcess());
+    signin::ScopedAccountConsistencyMirror scoped_mirror;
     pref_service_.SetInteger(prefs::kAccountIdMigrationState,
                              AccountTrackerService::MIGRATION_NOT_STARTED);
 
@@ -797,8 +789,7 @@
   ResetObserverCounts();
   AddAuthTokenManually("AccountId-" + primary_account, "refresh_token");
   AddAuthTokenManually("AccountId-" + secondary_account, "refresh_token");
-  switches::EnableAccountConsistencyMirrorForTesting(
-      base::CommandLine::ForCurrentProcess());
+  signin::ScopedAccountConsistencyMirror scoped_mirror;
   oauth2_service_delegate_->LoadCredentials(primary_account);
   base::RunLoop().RunUntilIdle();
 
diff --git a/chrome/browser/signin/signin_promo.cc b/chrome/browser/signin/signin_promo.cc
index 968fd3f..4dd2f65 100644
--- a/chrome/browser/signin/signin_promo.cc
+++ b/chrome/browser/signin/signin_promo.cc
@@ -316,7 +316,7 @@
           url, kSignInPromoQueryKeyShowAccountManagement, &value)) {
     int enabled = 0;
     if (base::StringToInt(value, &enabled) && enabled == 1)
-      return switches::IsAccountConsistencyMirrorEnabled();
+      return IsAccountConsistencyMirrorEnabled();
   }
   return false;
 }
diff --git a/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc b/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc
index dc252aaf..4768657 100644
--- a/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc
+++ b/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc
@@ -158,36 +158,37 @@
   EXPECT_TRUE(expired_explanation.insecure_explanations[0].has_certificate);
 }
 
-// Checks that the given |secure_explanations| contains an appropriate
+// Checks that the given |explanation| contains an appropriate
 // explanation if the certificate status is valid.
-void CheckSecureExplanations(
-    const std::vector<content::SecurityStyleExplanation>& secure_explanations,
-    CertificateStatus cert_status,
+void CheckSecureCertificateExplanation(
+    const content::SecurityStyleExplanation& explanation,
     Browser* browser,
     net::X509Certificate* expected_cert) {
-  ASSERT_EQ(cert_status == VALID_CERTIFICATE ? 2u : 1u,
-            secure_explanations.size());
-  if (cert_status == VALID_CERTIFICATE) {
-    ASSERT_EQ(kTestCertificateIssuerName,
-              expected_cert->issuer().GetDisplayName());
-    EXPECT_EQ(l10n_util::GetStringUTF8(IDS_VALID_SERVER_CERTIFICATE),
-              secure_explanations[0].summary);
-    EXPECT_EQ(l10n_util::GetStringFUTF8(
-                  IDS_VALID_SERVER_CERTIFICATE_DESCRIPTION,
-                  base::UTF8ToUTF16(kTestCertificateIssuerName)),
-              secure_explanations[0].description);
-    net::X509Certificate* cert = browser->tab_strip_model()
-                                     ->GetActiveWebContents()
-                                     ->GetController()
-                                     .GetActiveEntry()
-                                     ->GetSSL()
-                                     .certificate.get();
-    EXPECT_TRUE(cert->Equals(expected_cert));
-    EXPECT_TRUE(secure_explanations[0].has_certificate);
-  }
+  ASSERT_EQ(kTestCertificateIssuerName,
+            expected_cert->issuer().GetDisplayName());
+  EXPECT_EQ(l10n_util::GetStringUTF8(IDS_VALID_SERVER_CERTIFICATE),
+            explanation.summary);
+  EXPECT_EQ(
+      l10n_util::GetStringFUTF8(IDS_VALID_SERVER_CERTIFICATE_DESCRIPTION,
+                                base::UTF8ToUTF16(kTestCertificateIssuerName)),
+      explanation.description);
+  net::X509Certificate* cert = browser->tab_strip_model()
+                                   ->GetActiveWebContents()
+                                   ->GetController()
+                                   .GetActiveEntry()
+                                   ->GetSSL()
+                                   .certificate.get();
+  EXPECT_TRUE(cert->Equals(expected_cert));
+  EXPECT_TRUE(explanation.has_certificate);
+}
 
+// Checks that the given |explanation| contains an appropriate
+// explanation that the connection is secure.
+void CheckSecureConnectionExplanation(
+    const content::SecurityStyleExplanation& explanation,
+    Browser* browser) {
   EXPECT_EQ(l10n_util::GetStringUTF8(IDS_STRONG_SSL_SUMMARY),
-            secure_explanations.back().summary);
+            explanation.summary);
 
   content::WebContents* web_contents =
       browser->tab_strip_model()->GetActiveWebContents();
@@ -223,8 +224,17 @@
   base::string16 secure_description = l10n_util::GetStringFUTF16(
       IDS_STRONG_SSL_DESCRIPTION, description_replacements, nullptr);
 
-  EXPECT_EQ(secure_description,
-            base::ASCIIToUTF16(secure_explanations.back().description));
+  EXPECT_EQ(secure_description, base::ASCIIToUTF16(explanation.description));
+}
+
+// Checks that the given |explanation| contains an appropriate
+// explanation that the subresources are secure.
+void CheckSecureSubresourcesExplanation(
+    const content::SecurityStyleExplanation& explanation) {
+  EXPECT_EQ(l10n_util::GetStringUTF8(IDS_SECURE_RESOURCES_SUMMARY),
+            explanation.summary);
+  EXPECT_EQ(l10n_util::GetStringUTF8(IDS_SECURE_RESOURCES_DESCRIPTION),
+            explanation.description);
 }
 
 void CheckSecurityInfoForSecure(
@@ -1560,11 +1570,14 @@
 
   const content::SecurityStyleExplanations& mixed_content_explanation =
       observer.latest_explanations();
-  ASSERT_EQ(0u, mixed_content_explanation.neutral_explanations.size());
+  ASSERT_EQ(1u, mixed_content_explanation.neutral_explanations.size());
   ASSERT_EQ(0u, mixed_content_explanation.insecure_explanations.size());
-  CheckSecureExplanations(mixed_content_explanation.secure_explanations,
-                          VALID_CERTIFICATE, browser(),
-                          https_server_.GetCertificate().get());
+  ASSERT_EQ(2u, mixed_content_explanation.secure_explanations.size());
+  CheckSecureCertificateExplanation(
+      mixed_content_explanation.secure_explanations[0], browser(),
+      https_server_.GetCertificate().get());
+  CheckSecureConnectionExplanation(
+      mixed_content_explanation.secure_explanations[1], browser());
   EXPECT_TRUE(mixed_content_explanation.scheme_is_cryptographic);
   EXPECT_FALSE(observer.latest_explanations().pkp_bypassed);
   EXPECT_TRUE(observer.latest_explanations().info_explanations.empty());
@@ -1586,9 +1599,11 @@
   EXPECT_TRUE(web_contents->ShowingInterstitialPage());
   CheckBrokenSecurityStyle(observer, net::ERR_CERT_DATE_INVALID, browser(),
                            https_test_server_expired.GetCertificate().get());
-  CheckSecureExplanations(observer.latest_explanations().secure_explanations,
-                          INVALID_CERTIFICATE, browser(),
-                          https_test_server_expired.GetCertificate().get());
+  ASSERT_EQ(2u, observer.latest_explanations().secure_explanations.size());
+  CheckSecureConnectionExplanation(
+      observer.latest_explanations().secure_explanations[0], browser());
+  CheckSecureSubresourcesExplanation(
+      observer.latest_explanations().secure_explanations[1]);
   EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic);
   EXPECT_FALSE(observer.latest_explanations().pkp_bypassed);
   EXPECT_TRUE(observer.latest_explanations().info_explanations.empty());
@@ -1603,9 +1618,14 @@
   EXPECT_EQ(blink::kWebSecurityStyleSecure, observer.latest_security_style());
   EXPECT_EQ(0u, observer.latest_explanations().neutral_explanations.size());
   EXPECT_EQ(0u, observer.latest_explanations().insecure_explanations.size());
-  CheckSecureExplanations(observer.latest_explanations().secure_explanations,
-                          VALID_CERTIFICATE, browser(),
-                          https_server_.GetCertificate().get());
+  ASSERT_EQ(3u, observer.latest_explanations().secure_explanations.size());
+  CheckSecureCertificateExplanation(
+      observer.latest_explanations().secure_explanations[0], browser(),
+      https_server_.GetCertificate().get());
+  CheckSecureConnectionExplanation(
+      observer.latest_explanations().secure_explanations[1], browser());
+  CheckSecureSubresourcesExplanation(
+      observer.latest_explanations().secure_explanations[2]);
   EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic);
   EXPECT_FALSE(observer.latest_explanations().pkp_bypassed);
   EXPECT_TRUE(observer.latest_explanations().info_explanations.empty());
@@ -1620,9 +1640,11 @@
   EXPECT_TRUE(web_contents->ShowingInterstitialPage());
   CheckBrokenSecurityStyle(observer, net::ERR_CERT_DATE_INVALID, browser(),
                            https_test_server_expired.GetCertificate().get());
-  CheckSecureExplanations(observer.latest_explanations().secure_explanations,
-                          INVALID_CERTIFICATE, browser(),
-                          https_test_server_expired.GetCertificate().get());
+  ASSERT_EQ(2u, observer.latest_explanations().secure_explanations.size());
+  CheckSecureConnectionExplanation(
+      observer.latest_explanations().secure_explanations[0], browser());
+  CheckSecureSubresourcesExplanation(
+      observer.latest_explanations().secure_explanations[1]);
   EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic);
   EXPECT_FALSE(observer.latest_explanations().pkp_bypassed);
   EXPECT_TRUE(observer.latest_explanations().info_explanations.empty());
@@ -1641,9 +1663,11 @@
   ProceedThroughInterstitial(web_contents);
   CheckBrokenSecurityStyle(observer, net::ERR_CERT_DATE_INVALID, browser(),
                            https_test_server_expired.GetCertificate().get());
-  CheckSecureExplanations(observer.latest_explanations().secure_explanations,
-                          INVALID_CERTIFICATE, browser(),
-                          https_test_server_expired.GetCertificate().get());
+  ASSERT_EQ(2u, observer.latest_explanations().secure_explanations.size());
+  CheckSecureConnectionExplanation(
+      observer.latest_explanations().secure_explanations[0], browser());
+  CheckSecureSubresourcesExplanation(
+      observer.latest_explanations().secure_explanations[1]);
   EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic);
   EXPECT_FALSE(observer.latest_explanations().pkp_bypassed);
   EXPECT_TRUE(observer.latest_explanations().info_explanations.empty());
@@ -1939,9 +1963,14 @@
   EXPECT_EQ(blink::kWebSecurityStyleSecure, observer.latest_security_style());
   EXPECT_EQ(0u, observer.latest_explanations().neutral_explanations.size());
   EXPECT_EQ(0u, observer.latest_explanations().insecure_explanations.size());
-  CheckSecureExplanations(observer.latest_explanations().secure_explanations,
-                          VALID_CERTIFICATE, browser(),
-                          https_server_.GetCertificate().get());
+  ASSERT_EQ(3u, observer.latest_explanations().secure_explanations.size());
+  CheckSecureCertificateExplanation(
+      observer.latest_explanations().secure_explanations[0], browser(),
+      https_server_.GetCertificate().get());
+  CheckSecureConnectionExplanation(
+      observer.latest_explanations().secure_explanations[1], browser());
+  CheckSecureSubresourcesExplanation(
+      observer.latest_explanations().secure_explanations[2]);
   EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic);
   EXPECT_FALSE(observer.latest_explanations().pkp_bypassed);
   EXPECT_TRUE(observer.latest_explanations().info_explanations.empty());
@@ -1967,9 +1996,11 @@
   CheckBrokenSecurityStyle(observer, net::ERR_CERT_COMMON_NAME_INVALID,
                            browser(),
                            https_test_server_expired.GetCertificate().get());
-  CheckSecureExplanations(observer.latest_explanations().secure_explanations,
-                          INVALID_CERTIFICATE, browser(),
-                          https_test_server_expired.GetCertificate().get());
+  ASSERT_EQ(2u, observer.latest_explanations().secure_explanations.size());
+  CheckSecureConnectionExplanation(
+      observer.latest_explanations().secure_explanations[0], browser());
+  CheckSecureSubresourcesExplanation(
+      observer.latest_explanations().secure_explanations[1]);
   EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic);
   EXPECT_FALSE(observer.latest_explanations().pkp_bypassed);
   EXPECT_TRUE(observer.latest_explanations().info_explanations.empty());
@@ -1986,9 +2017,14 @@
   EXPECT_EQ(blink::kWebSecurityStyleSecure, observer.latest_security_style());
   EXPECT_EQ(0u, observer.latest_explanations().neutral_explanations.size());
   EXPECT_EQ(0u, observer.latest_explanations().insecure_explanations.size());
-  CheckSecureExplanations(observer.latest_explanations().secure_explanations,
-                          VALID_CERTIFICATE, browser(),
-                          https_server_.GetCertificate().get());
+  ASSERT_EQ(3u, observer.latest_explanations().secure_explanations.size());
+  CheckSecureCertificateExplanation(
+      observer.latest_explanations().secure_explanations[0], browser(),
+      https_server_.GetCertificate().get());
+  CheckSecureConnectionExplanation(
+      observer.latest_explanations().secure_explanations[1], browser());
+  CheckSecureSubresourcesExplanation(
+      observer.latest_explanations().secure_explanations[2]);
   EXPECT_TRUE(observer.latest_explanations().scheme_is_cryptographic);
   EXPECT_FALSE(observer.latest_explanations().pkp_bypassed);
   EXPECT_TRUE(observer.latest_explanations().info_explanations.empty());
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 226cb3ea..46e5b39 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1531,6 +1531,7 @@
       "views/extensions/extension_install_dialog_view.h",
       "views/extensions/extension_keybinding_registry_views.cc",
       "views/extensions/extension_keybinding_registry_views.h",
+      "views/extensions/extension_uninstall_dialog_view.cc",
       "views/frame/native_widget_mac_frameless_nswindow.h",
       "views/frame/native_widget_mac_frameless_nswindow.mm",
       "views/fullscreen_control/fullscreen_control_host.cc",
@@ -1714,7 +1715,6 @@
         "views/extensions/extension_installed_bubble_view.cc",
         "views/extensions/extension_popup.cc",
         "views/extensions/extension_popup.h",
-        "views/extensions/extension_uninstall_dialog_view.cc",
         "views/extensions/extension_view_views.cc",
         "views/extensions/extension_view_views.h",
         "views/extensions/media_galleries_dialog_views.cc",
diff --git a/chrome/browser/ui/cocoa/extensions/extension_uninstall_dialog_cocoa.mm b/chrome/browser/ui/cocoa/extensions/extension_uninstall_dialog_cocoa.mm
index d2211be6..86db988 100644
--- a/chrome/browser/ui/cocoa/extensions/extension_uninstall_dialog_cocoa.mm
+++ b/chrome/browser/ui/cocoa/extensions/extension_uninstall_dialog_cocoa.mm
@@ -16,6 +16,7 @@
 #include "extensions/common/extension.h"
 #include "skia/ext/skia_utils_mac.h"
 #include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/material_design/material_design_controller.h"
 #include "ui/gfx/image/image_skia_util_mac.h"
 
 namespace {
@@ -85,5 +86,9 @@
 extensions::ExtensionUninstallDialog::Create(Profile* profile,
                                              gfx::NativeWindow parent,
                                              Delegate* delegate) {
+  if (ui::MaterialDesignController::IsSecondaryUiMaterial()) {
+    return extensions::ExtensionUninstallDialog::CreateViews(profile, parent,
+                                                             delegate);
+  }
   return new ExtensionUninstallDialogCocoa(profile, delegate);
 }
diff --git a/chrome/browser/ui/cocoa/fullscreen/fullscreen_menubar_tracker.mm b/chrome/browser/ui/cocoa/fullscreen/fullscreen_menubar_tracker.mm
index f7c326e..3347548 100644
--- a/chrome/browser/ui/cocoa/fullscreen/fullscreen_menubar_tracker.mm
+++ b/chrome/browser/ui/cocoa/fullscreen/fullscreen_menubar_tracker.mm
@@ -5,6 +5,7 @@
 #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_menubar_tracker.h"
 
 #include <Carbon/Carbon.h>
+#include <QuartzCore/QuartzCore.h>
 
 #include "base/mac/mac_util.h"
 #include "base/macros.h"
@@ -141,21 +142,9 @@
   menubarFraction_ = progress;
   [owner_ updateToolbarLayout];
 
-  // In 10.12. the toolbar to be janky since the UI doesn't update until the
-  // menubar finished revealing itself. To smooth things out, animate the
-  // toolbar in/out by locking/releasing its visibility instead of relying on
-  // the menubar fraction.
-  // TODO(spqchan): Figure out why it's not updating and make the toolbar drop
-  // down in sync with the menubar. See crbug.com/672254.
-  if (base::mac::IsOS10_12()) {
-    if (state_ == FullscreenMenubarState::SHOWING) {
-      [[owner_ visibilityLockController] lockToolbarVisibilityForOwner:self
-                                                         withAnimation:YES];
-    } else if (state_ == FullscreenMenubarState::HIDING) {
-      [[owner_ visibilityLockController] releaseToolbarVisibilityForOwner:self
-                                                            withAnimation:YES];
-    }
-  }
+  // AppKit drives the menu bar animation from a nested run loop. Flush
+  // explicitly so that Chrome's UI updates during the animation.
+  [CATransaction flush];
 }
 
 - (BOOL)isMouseOnScreen {
diff --git a/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm b/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm
index 2284ab1..cdb7a2e 100644
--- a/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm
+++ b/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm
@@ -369,7 +369,7 @@
         viewMode == profiles::BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT ||
         viewMode == profiles::BUBBLE_VIEW_MODE_GAIA_REAUTH) {
       [controller_ initMenuContentsWithView:
-                       switches::IsAccountConsistencyMirrorEnabled()
+                       signin::IsAccountConsistencyMirrorEnabled()
                            ? profiles::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT
                            : profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER];
     }
@@ -845,7 +845,7 @@
   std::string primaryAccount = SigninManagerFactory::GetForProfile(
       browser_->profile())->GetAuthenticatedAccountId();
   bool hasAccountManagement =
-      !primaryAccount.empty() && switches::IsAccountConsistencyMirrorEnabled();
+      !primaryAccount.empty() && signin::IsAccountConsistencyMirrorEnabled();
   [self initMenuContentsWithView:hasAccountManagement ?
       profiles::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT :
       profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER];
@@ -992,7 +992,7 @@
     // ACCOUNT_MANAGEMENT mode.
     if (viewMode_ == profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER &&
         HasAuthError(browser_->profile()) &&
-        switches::IsAccountConsistencyMirrorEnabled() &&
+        signin::IsAccountConsistencyMirrorEnabled() &&
         avatarMenu_->GetItemAt(avatarMenu_->GetActiveProfileIndex())
             .signed_in) {
       viewMode_ = profiles::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT;
@@ -1313,7 +1313,7 @@
   SigninManagerBase* signinManager = SigninManagerFactory::GetForProfile(
       browser_->profile()->GetOriginalProfile());
   NSRect profileLinksBound = NSZeroRect;
-  if (item.signed_in && switches::IsAccountConsistencyMirrorEnabled()) {
+  if (item.signed_in && signin::IsAccountConsistencyMirrorEnabled()) {
     profileLinksBound = NSMakeRect(0, 0, kFixedMenuWidth, kVerticalSpacing);
   } else if (!item.signed_in && signinManager->IsSigninAllowed()) {
     profileLinksBound = NSMakeRect(xOffset, kRelatedControllVerticalSpacing,
@@ -1413,7 +1413,7 @@
 
   // Username, aligned to the leading edge of the  profile icon and
   // below the profile name.
-  if (item.signed_in && !switches::IsAccountConsistencyMirrorEnabled()) {
+  if (item.signed_in && !signin::IsAccountConsistencyMirrorEnabled()) {
     // Adjust the y-position of profile name to leave space for username.
     cardYOffset += kMdImageSide / 2 - [profileName frame].size.height;
     [profileName setFrameOrigin:NSMakePoint(xOffset, cardYOffset)];
@@ -1447,7 +1447,7 @@
   // here.
   SigninManagerBase* signinManager = SigninManagerFactory::GetForProfile(
       browser_->profile()->GetOriginalProfile());
-  DCHECK((item.signed_in && switches::IsAccountConsistencyMirrorEnabled()) ||
+  DCHECK((item.signed_in && signin::IsAccountConsistencyMirrorEnabled()) ||
          (!item.signed_in && signinManager->IsSigninAllowed()));
 
   base::scoped_nsobject<NSView> container([[NSView alloc] initWithFrame:rect]);
@@ -1462,7 +1462,7 @@
   // The available links depend on the type of profile that is active.
   if (item.signed_in) {
     NSButton* link = nil;
-    if (switches::IsAccountConsistencyMirrorEnabled()) {
+    if (signin::IsAccountConsistencyMirrorEnabled()) {
       NSString* linkTitle = l10n_util::GetNSString(
           viewMode_ == profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER ?
               IDS_PROFILES_PROFILE_MANAGE_ACCOUNTS_BUTTON :
diff --git a/chrome/browser/ui/cocoa/profiles/profile_chooser_controller_unittest.mm b/chrome/browser/ui/cocoa/profiles/profile_chooser_controller_unittest.mm
index aa229b81..a5e17dc1 100644
--- a/chrome/browser/ui/cocoa/profiles/profile_chooser_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/profiles/profile_chooser_controller_unittest.mm
@@ -36,6 +36,7 @@
 #include "components/signin/core/browser/fake_account_fetcher_service.h"
 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
 #include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/scoped_account_consistency.h"
 #include "components/signin/core/browser/signin_manager.h"
 #include "components/signin/core/common/profile_management_switches.h"
 #include "components/signin/core/common/signin_pref_names.h"
@@ -251,8 +252,7 @@
 
 TEST_F(ProfileChooserControllerTest,
        SignedInProfileActiveCardLinksWithAccountConsistency) {
-  switches::EnableAccountConsistencyMirrorForTesting(
-      base::CommandLine::ForCurrentProcess());
+  signin::ScopedAccountConsistencyMirror scoped_mirror;
 
   SignInFirstProfile();
 
@@ -295,8 +295,7 @@
 }
 
 TEST_F(ProfileChooserControllerTest, AccountManagementLayout) {
-  switches::EnableAccountConsistencyMirrorForTesting(
-      base::CommandLine::ForCurrentProcess());
+  signin::ScopedAccountConsistencyMirror scoped_mirror;
 
   SignInFirstProfile();
 
diff --git a/chrome/browser/ui/cocoa/profiles/signin_view_controller_delegate_mac.h b/chrome/browser/ui/cocoa/profiles/signin_view_controller_delegate_mac.h
index 58e18486..c0f41ff 100644
--- a/chrome/browser/ui/cocoa/profiles/signin_view_controller_delegate_mac.h
+++ b/chrome/browser/ui/cocoa/profiles/signin_view_controller_delegate_mac.h
@@ -92,7 +92,6 @@
   // The web contents displayed in the constrained window.
   std::unique_ptr<content::WebContents> web_contents_;
   base::scoped_nsobject<ConstrainedWindowCustomWindow> window_;
-  Browser* browser_;
 
   // The dialog modal presentation type.
   ui::ModalType dialog_modal_type_;
diff --git a/chrome/browser/ui/cocoa/profiles/signin_view_controller_delegate_mac.mm b/chrome/browser/ui/cocoa/profiles/signin_view_controller_delegate_mac.mm
index a0391e65..3aadba62 100644
--- a/chrome/browser/ui/cocoa/profiles/signin_view_controller_delegate_mac.mm
+++ b/chrome/browser/ui/cocoa/profiles/signin_view_controller_delegate_mac.mm
@@ -52,15 +52,12 @@
     NSRect frame,
     ui::ModalType dialog_modal_type,
     bool wait_for_size)
-    : SigninViewControllerDelegate(signin_view_controller, web_contents.get()),
+    : SigninViewControllerDelegate(signin_view_controller,
+                                   web_contents.get(),
+                                   browser),
       web_contents_(std::move(web_contents)),
-      browser_(browser),
       dialog_modal_type_(dialog_modal_type),
       window_frame_(frame) {
-  DCHECK(browser_);
-  DCHECK(browser_->tab_strip_model()->GetActiveWebContents())
-      << "A tab must be active to present the sign-in modal dialog.";
-
   if (!wait_for_size)
     DisplayModal();
 }
@@ -170,7 +167,7 @@
   DCHECK(!window_);
 
   content::WebContents* host_web_contents =
-      browser_->tab_strip_model()->GetActiveWebContents();
+      browser()->tab_strip_model()->GetActiveWebContents();
 
   // Avoid displaying the sign-in modal view if there are no active web
   // contents. This happens if the user closes the browser window before this
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.h b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.h
index 862d37b..0dd086c 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.h
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.h
@@ -12,6 +12,7 @@
 #include "base/mac/scoped_nsobject.h"
 #import "chrome/browser/ui/cocoa/has_weak_browser_pointer.h"
 #import "chrome/browser/ui/cocoa/tabs/tab_controller_target.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h"
 #import "chrome/browser/ui/cocoa/url_drop_target.h"
 #include "chrome/browser/ui/tabs/hover_tab_selector.h"
 #include "chrome/browser/ui/tabs/tab_utils.h"
@@ -25,7 +26,6 @@
 @class TabStripView;
 
 class Browser;
-class TabStripModelObserverBridge;
 class TabStripModel;
 
 namespace content {
@@ -36,7 +36,7 @@
 // Delegating TabStripModelObserverBridge's events (in lieu of directly
 // subscribing to TabStripModelObserverBridge events, as TabStripController
 // does) is necessary to guarantee a proper order of subviews layout updates,
-// otherwise it might trigger unnesessary content relayout, UI flickering etc.
+// otherwise it might trigger unnecessary content relayout, UI flickering etc.
 @protocol TabStripControllerDelegate
 
 // Stripped down version of TabStripModelObserverBridge:selectTabWithContents.
@@ -65,7 +65,8 @@
 // http://www.chromium.org/developers/design-documents/tab-strip-mac
 @interface TabStripController : NSObject<TabControllerTarget,
                                          URLDropTargetController,
-                                         HasWeakBrowserPointer> {
+                                         HasWeakBrowserPointer,
+                                         TabStripModelBridge> {
  @private
   base::scoped_nsobject<TabStripView> tabStripView_;
   NSView* switchView_;  // weak
@@ -260,7 +261,7 @@
 - (BOOL)inRapidClosureMode;
 
 // Returns YES if the user is allowed to drag tabs on the strip at this moment.
-// For example, this returns NO if there are any pending tab close animtations.
+// For example, this returns NO if there are any pending tab close animations.
 - (BOOL)tabDraggingAllowed;
 
 // Default height for tabs.
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
index 25cf1b6..aaebe9b 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
@@ -39,7 +39,6 @@
 #import "chrome/browser/ui/cocoa/tabs/alert_indicator_button_cocoa.h"
 #import "chrome/browser/ui/cocoa/tabs/tab_controller.h"
 #import "chrome/browser/ui/cocoa/tabs/tab_strip_drag_controller.h"
-#import "chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h"
 #import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h"
 #import "chrome/browser/ui/cocoa/tabs/tab_view.h"
 #import "chrome/browser/ui/cocoa/themed_window.h"
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h b/chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h
index 69a4b96..5e386f7 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h
@@ -62,10 +62,10 @@
   TabStripModel* model_;  // weak, owned by Browser
 };
 
-// A collection of methods which can be selectively implemented by any
-// Cocoa object to receive updates about changes to a tab strip model. It is
-// ok to not implement them, the calling code checks before calling.
-@interface NSObject(TabStripModelBridge)
+// A protocol which can be selectively implemented by any Cocoa object to
+// receive updates about changes to a tab strip model. All methods are optional.
+@protocol TabStripModelBridge
+@optional
 - (void)insertTabWithContents:(content::WebContents*)contents
                       atIndex:(NSInteger)index
                  inForeground:(bool)inForeground;
diff --git a/chrome/browser/ui/signin_view_controller.cc b/chrome/browser/ui/signin_view_controller.cc
index 3ca9a8b..f7bb63a 100644
--- a/chrome/browser/ui/signin_view_controller.cc
+++ b/chrome/browser/ui/signin_view_controller.cc
@@ -24,6 +24,11 @@
   signin_view_controller_delegate_ =
       SigninViewControllerDelegate::CreateModalSigninDelegate(
           this, mode, browser, access_point);
+
+  // When the user has a proxy that requires HTTP auth, loading the sign-in
+  // dialog can trigger the HTTP auth dialog.  This means the signin view
+  // controller needs a dialog manager to handle any such dialog.
+  signin_view_controller_delegate_->AttachDialogManager();
   chrome::RecordDialogCreation(chrome::DialogIdentifier::SIGN_IN);
 }
 
diff --git a/chrome/browser/ui/signin_view_controller_delegate.cc b/chrome/browser/ui/signin_view_controller_delegate.cc
index 23d4148..bfbdde4 100644
--- a/chrome/browser/ui/signin_view_controller_delegate.cc
+++ b/chrome/browser/ui/signin_view_controller_delegate.cc
@@ -6,8 +6,13 @@
 
 #include "base/bind.h"
 #include "base/values.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/signin_view_controller.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/webui/signin/signin_utils.h"
+#include "components/web_modal/web_contents_modal_dialog_host.h"
+#include "components/web_modal/web_contents_modal_dialog_manager.h"
 #include "content/public/browser/web_contents.h"
 
 namespace {
@@ -21,15 +26,27 @@
 
 SigninViewControllerDelegate::SigninViewControllerDelegate(
     SigninViewController* signin_view_controller,
-    content::WebContents* web_contents)
+    content::WebContents* web_contents,
+    Browser* browser)
     : signin_view_controller_(signin_view_controller),
-      web_contents_(web_contents) {
+      web_contents_(web_contents),
+      browser_(browser) {
   DCHECK(web_contents_);
+  DCHECK(browser_);
+  DCHECK(browser_->tab_strip_model()->GetActiveWebContents())
+      << "A tab must be active to present the sign-in modal dialog.";
   web_contents_->SetDelegate(this);
 }
 
 SigninViewControllerDelegate::~SigninViewControllerDelegate() {}
 
+void SigninViewControllerDelegate::AttachDialogManager() {
+  web_modal::WebContentsModalDialogManager::CreateForWebContents(web_contents_);
+  web_modal::WebContentsModalDialogManager* manager =
+      web_modal::WebContentsModalDialogManager::FromWebContents(web_contents_);
+  manager->SetDelegate(this);
+}
+
 void SigninViewControllerDelegate::CloseModalSignin() {
   ResetSigninViewControllerDelegate();
   PerformClose();
@@ -48,6 +65,11 @@
   return true;
 }
 
+web_modal::WebContentsModalDialogHost*
+SigninViewControllerDelegate::GetWebContentsModalDialogHost() {
+  return browser()->window()->GetWebContentsModalDialogHost();
+}
+
 void SigninViewControllerDelegate::ResetSigninViewControllerDelegate() {
   if (signin_view_controller_) {
     signin_view_controller_->ResetModalSigninDelegate();
diff --git a/chrome/browser/ui/signin_view_controller_delegate.h b/chrome/browser/ui/signin_view_controller_delegate.h
index 021070d..b6c7c129 100644
--- a/chrome/browser/ui/signin_view_controller_delegate.h
+++ b/chrome/browser/ui/signin_view_controller_delegate.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_UI_SIGNIN_VIEW_CONTROLLER_DELEGATE_H_
 #define CHROME_BROWSER_UI_SIGNIN_VIEW_CONTROLLER_DELEGATE_H_
 
+#include "chrome/browser/ui/chrome_web_modal_dialog_manager_delegate.h"
 #include "chrome/browser/ui/profile_chooser_constants.h"
 #include "content/public/browser/web_contents_delegate.h"
 
@@ -21,7 +22,9 @@
 // as well as managing the navigation inside them.
 // Subclasses are responsible for deleting themselves when the window they're
 // managing closes.
-class SigninViewControllerDelegate : public content::WebContentsDelegate {
+class SigninViewControllerDelegate
+    : public content::WebContentsDelegate,
+      public ChromeWebModalDialogManagerDelegate {
  public:
   // Returns a platform-specific SigninViewControllerDelegate instance that
   // displays the sign in flow. The returned object should delete itself when
@@ -46,6 +49,11 @@
       SigninViewController* signin_view_controller,
       Browser* browser);
 
+  // Attaches a dialog manager to this sign-in view controller dialog.
+  // Should be called by subclasses when a different dialog may need to be
+  // presented on top of the sign-in dialog.
+  void AttachDialogManager();
+
   // Closes the sign-in dialog. Note that this method may destroy this object,
   // so the caller should no longer use this object after calling this method.
   void CloseModalSignin();
@@ -64,15 +72,22 @@
   // content::WebContentsDelegate:
   bool HandleContextMenu(const content::ContextMenuParams& params) override;
 
+  // ChromeWebModalDialogManagerDelegate:
+  web_modal::WebContentsModalDialogHost* GetWebContentsModalDialogHost()
+      override;
+
   // WebContents is used for executing javascript in the context of a modal sync
   // confirmation dialog.
   content::WebContents* web_contents_for_testing() { return web_contents_; }
 
  protected:
   SigninViewControllerDelegate(SigninViewController* signin_view_controller,
-                               content::WebContents* web_contents);
+                               content::WebContents* web_contents,
+                               Browser* browser);
   ~SigninViewControllerDelegate() override;
 
+  Browser* browser() { return browser_; }
+
   // Notifies the SigninViewController that this instance is being deleted.
   void ResetSigninViewControllerDelegate();
 
@@ -91,7 +106,8 @@
   bool CanGoBack(content::WebContents* web_ui_web_contents) const;
 
   SigninViewController* signin_view_controller_;  // Not owned.
-  content::WebContents* web_contents_;  // Not owned.
+  content::WebContents* web_contents_;            // Not owned.
+  Browser* browser_;                              // Not owned.
   DISALLOW_COPY_AND_ASSIGN(SigninViewControllerDelegate);
 };
 
diff --git a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc b/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
index 52a8f90..62629c531 100644
--- a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
+++ b/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
@@ -116,7 +116,7 @@
   BrowserList::AddObserver(this);
   Initialize(profile, browser);
 
-  DCHECK(!refresh_token.empty() || switches::IsAccountConsistencyDiceEnabled());
+  DCHECK(!refresh_token.empty() || signin::IsAccountConsistencyDiceEnabled());
   SigninManagerFactory::GetForProfile(profile_)->StartSignInWithRefreshToken(
       refresh_token, gaia_id, email, password,
       base::Bind(&OneClickSigninSyncStarter::ConfirmSignin,
@@ -177,7 +177,7 @@
       policy::UserPolicySigninService* policy_service =
           policy::UserPolicySigninServiceFactory::GetForProfile(profile_);
       if (oauth_token.empty()) {
-        DCHECK(switches::IsAccountConsistencyDiceEnabled());
+        DCHECK(signin::IsAccountConsistencyDiceEnabled());
         policy_service->RegisterForPolicyWithAccountId(
             signin->GetUsernameForAuthInProgress(),
             signin->GetAccountIdForAuthInProgress(),
diff --git a/chrome/browser/ui/views/extensions/extension_popup.cc b/chrome/browser/ui/views/extensions/extension_popup.cc
index fab316f..296a4db 100644
--- a/chrome/browser/ui/views/extensions/extension_popup.cc
+++ b/chrome/browser/ui/views/extensions/extension_popup.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/ui/views/extensions/extension_popup.h"
 
-#include "base/bind.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/devtools/devtools_window.h"
 #include "chrome/browser/extensions/extension_view_host.h"
@@ -16,17 +15,13 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/gfx/geometry/insets.h"
+#include "ui/views/bubble/bubble_frame_view.h"
+#include "ui/views/controls/native/native_view_host.h"
 #include "ui/views/layout/fill_layout.h"
 #include "ui/views/widget/widget.h"
 
 namespace {
 
-// Override the default margin provided by views::kPanel*Margin so that the
-// hosted WebContents fill more of the bubble. However, it can't fill the entire
-// bubble since that would draw over the rounded corners and make the bubble
-// square. See http://crbug.com/593203.
-const int kBubbleMargin = 2;
-
 ExtensionViewViews* GetExtensionView(extensions::ExtensionViewHost* host) {
   return static_cast<ExtensionViewViews*>(host->view());
 }
@@ -57,11 +52,9 @@
                                views::View* anchor_view,
                                views::BubbleBorder::Arrow arrow,
                                ShowAction show_action)
-    : BubbleDialogDelegateView(anchor_view, arrow),
-      host_(host),
-      widget_initialized_(false) {
+    : BubbleDialogDelegateView(anchor_view, arrow), host_(host) {
   inspect_with_devtools_ = show_action == SHOW_AND_INSPECT;
-  set_margins(gfx::Insets(kBubbleMargin));
+  set_margins(gfx::Insets());
   SetLayoutManager(new views::FillLayout());
   AddChildView(GetExtensionView(host));
   GetExtensionView(host)->set_container(this);
@@ -152,12 +145,13 @@
   return sz;
 }
 
-void ExtensionPopup::ViewHierarchyChanged(
-  const ViewHierarchyChangedDetails& details) {
-  // TODO(msw): Find any remaining crashes related to http://crbug.com/327776
-  // No view hierarchy changes are expected if the widget no longer exists.
-  widget_initialized_ |= details.child == this && details.is_add && GetWidget();
-  CHECK(GetWidget() || !widget_initialized_);
+void ExtensionPopup::AddedToWidget() {
+  const int radius =
+      GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius();
+  const bool contents_has_rounded_corners =
+      GetExtensionView(host_.get())->holder()->SetCornerRadius(radius);
+  SetBorder(views::CreateEmptyBorder(
+      gfx::Insets(contents_has_rounded_corners ? 0 : radius, 0)));
 }
 
 void ExtensionPopup::OnWidgetActivationChanged(views::Widget* widget,
@@ -174,11 +168,6 @@
 }
 
 void ExtensionPopup::OnAnchorWindowActivation() {
-  // TODO(msw): Find any remaining crashes related to http://crbug.com/327776
-  // No calls are expected if the widget isn't initialized or no longer exists.
-  CHECK(widget_initialized_);
-  CHECK(GetWidget());
-
   if (!inspect_with_devtools_)
     GetWidget()->Close();
 }
diff --git a/chrome/browser/ui/views/extensions/extension_popup.h b/chrome/browser/ui/views/extensions/extension_popup.h
index d3071a7..0b01c8fd 100644
--- a/chrome/browser/ui/views/extensions/extension_popup.h
+++ b/chrome/browser/ui/views/extensions/extension_popup.h
@@ -71,8 +71,7 @@
 
   // views::View overrides.
   gfx::Size CalculatePreferredSize() const override;
-  void ViewHierarchyChanged(
-      const ViewHierarchyChangedDetails& details) override;
+  void AddedToWidget() override;
 
   // views::WidgetObserver overrides.
   void OnWidgetActivationChanged(views::Widget* widget, bool active) override;
@@ -122,8 +121,6 @@
 
   content::NotificationRegistrar registrar_;
 
-  bool widget_initialized_;
-
   DISALLOW_COPY_AND_ASSIGN(ExtensionPopup);
 };
 
diff --git a/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc b/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc
index 45afa82..06941e9 100644
--- a/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc
+++ b/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view.cc
@@ -8,6 +8,7 @@
 #include "base/macros.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
 #include "chrome/browser/extensions/extension_uninstall_dialog.h"
 #include "chrome/browser/ui/app_list/app_list_service.h"
 #include "chrome/browser/ui/browser_dialogs.h"
@@ -17,6 +18,7 @@
 #include "components/strings/grit/components_strings.h"
 #include "extensions/common/extension.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/ui_features.h"
 #include "ui/compositor/compositor.h"
 #include "ui/compositor/layer.h"
 #include "ui/gfx/geometry/insets.h"
@@ -227,10 +229,22 @@
 
 }  // namespace
 
+#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
+
 // static
 extensions::ExtensionUninstallDialog*
 extensions::ExtensionUninstallDialog::Create(Profile* profile,
                                              gfx::NativeWindow parent,
                                              Delegate* delegate) {
+  return CreateViews(profile, parent, delegate);
+}
+
+#endif  // !OS_MACOSX || MAC_VIEWS_BROWSER
+
+// static
+extensions::ExtensionUninstallDialog*
+extensions::ExtensionUninstallDialog::CreateViews(Profile* profile,
+                                                  gfx::NativeWindow parent,
+                                                  Delegate* delegate) {
   return new ExtensionUninstallDialogViews(profile, parent, delegate);
 }
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
index e7f808fe..52115c8 100644
--- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -4,6 +4,10 @@
 
 #include "chrome/browser/ui/views/profiles/profile_chooser_view.h"
 
+#include <algorithm>
+#include <memory>
+#include <string>
+
 #include "base/macros.h"
 #include "base/metrics/user_metrics.h"
 #include "base/strings/utf_string_conversions.h"
@@ -463,7 +467,8 @@
         views::GridLayout::FIXED, available_width, available_width);
     columns->AddPaddingColumn(1, dialog_insets.right());
     layout->AddColumnSet(1)->AddColumn(views::GridLayout::FILL,
-        views::GridLayout::FILL, 0,views::GridLayout::FIXED, width, width);
+                                       views::GridLayout::FILL, 0,
+                                       views::GridLayout::FIXED, width, width);
 
     layout->StartRowWithPadding(1, 0, 0, kVerticalSpacing);
     layout->AddView(title_card);
@@ -625,7 +630,7 @@
   // If view mode is PROFILE_CHOOSER but there is an auth error, force
   // ACCOUNT_MANAGEMENT mode.
   if (IsProfileChooser(view_mode_) && HasAuthError(browser_->profile()) &&
-      switches::IsAccountConsistencyMirrorEnabled() &&
+      signin::IsAccountConsistencyMirrorEnabled() &&
       avatar_menu_->GetItemAt(avatar_menu_->GetActiveProfileIndex())
           .signed_in) {
     view_mode_ = profiles::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT;
@@ -663,7 +668,7 @@
       view_mode_ == profiles::BUBBLE_VIEW_MODE_GAIA_REAUTH) {
     // The account management UI is only available through the
     // --account-consistency=mirror flag.
-    ShowViewFromMode(switches::IsAccountConsistencyMirrorEnabled()
+    ShowViewFromMode(signin::IsAccountConsistencyMirrorEnabled()
                          ? profiles::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT
                          : profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER);
   }
@@ -681,7 +686,7 @@
   // The account management view should only be displayed if the active profile
   // is signed in.
   if (view_to_display == profiles::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT) {
-    DCHECK(switches::IsAccountConsistencyMirrorEnabled());
+    DCHECK(signin::IsAccountConsistencyMirrorEnabled());
     const AvatarMenu::Item& active_item = avatar_menu->GetItemAt(
         avatar_menu->GetActiveProfileIndex());
     if (!active_item.signed_in) {
@@ -842,7 +847,7 @@
     bool account_management_available =
         SigninManagerFactory::GetForProfile(browser_->profile())
             ->IsAuthenticated() &&
-        switches::IsAccountConsistencyMirrorEnabled();
+        signin::IsAccountConsistencyMirrorEnabled();
     ShowViewFromMode(account_management_available ?
         profiles::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT :
         profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER);
@@ -1121,7 +1126,7 @@
                      views::GridLayout::USE_PREF, 0, 0);
   grid_layout->AddPaddingRow(0, 0);
   const int num_labels =
-      (avatar_item.signed_in && !switches::IsAccountConsistencyMirrorEnabled())
+      (avatar_item.signed_in && !signin::IsAccountConsistencyMirrorEnabled())
           ? 2
           : 1;
   int profile_card_height =
@@ -1167,7 +1172,7 @@
 
   // The available links depend on the type of profile that is active.
   if (avatar_item.signed_in) {
-    if (switches::IsAccountConsistencyMirrorEnabled()) {
+    if (signin::IsAccountConsistencyMirrorEnabled()) {
       base::string16 button_text = l10n_util::GetStringUTF16(
           IsProfileChooser(view_mode_)
               ? IDS_PROFILES_PROFILE_MANAGE_ACCOUNTS_BUTTON
diff --git a/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.cc b/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.cc
index 2851cdf..fb41b47 100644
--- a/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.cc
+++ b/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.cc
@@ -43,14 +43,11 @@
     ui::ModalType dialog_modal_type,
     bool wait_for_size)
     : SigninViewControllerDelegate(signin_view_controller,
-                                   content_view->GetWebContents()),
+                                   content_view->GetWebContents(),
+                                   browser),
       content_view_(content_view.release()),
       modal_signin_widget_(nullptr),
-      dialog_modal_type_(dialog_modal_type),
-      browser_(browser) {
-  DCHECK(browser_);
-  DCHECK(browser_->tab_strip_model()->GetActiveWebContents())
-      << "A tab must be active to present the sign-in modal dialog.";
+      dialog_modal_type_(dialog_modal_type) {
   DCHECK(dialog_modal_type == ui::MODAL_TYPE_CHILD ||
          dialog_modal_type == ui::MODAL_TYPE_WINDOW)
       << "Unsupported dialog modal type " << dialog_modal_type;
@@ -96,10 +93,11 @@
 }
 
 void SigninViewControllerDelegateViews::ResizeNativeView(int height) {
-  int max_height = browser_
-      ->window()
-      ->GetWebContentsModalDialogHost()
-      ->GetMaximumDialogSize().height();
+  int max_height = browser()
+                       ->window()
+                       ->GetWebContentsModalDialogHost()
+                       ->GetMaximumDialogSize()
+                       .height();
   content_view_->SetPreferredSize(
       gfx::Size(kModalDialogWidth, std::min(height, max_height)));
 
@@ -114,7 +112,7 @@
   DCHECK(!modal_signin_widget_);
 
   content::WebContents* host_web_contents =
-      browser_->tab_strip_model()->GetActiveWebContents();
+      browser()->tab_strip_model()->GetActiveWebContents();
 
   // Avoid displaying the sign-in modal view if there are no active web
   // contents. This happens if the user closes the browser window before this
@@ -131,7 +129,7 @@
       break;
     case ui::MODAL_TYPE_CHILD:
       modal_signin_widget_ = constrained_window::ShowWebModalDialogViews(
-          this, browser_->tab_strip_model()->GetActiveWebContents());
+          this, browser()->tab_strip_model()->GetActiveWebContents());
       break;
     default:
       NOTREACHED() << "Unsupported dialog modal type " << dialog_modal_type_;
diff --git a/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.h b/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.h
index dd990e2..e2b982c 100644
--- a/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.h
+++ b/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.h
@@ -83,7 +83,6 @@
   views::WebView* content_view_;
   views::Widget* modal_signin_widget_;  // Not owned.
   ui::ModalType dialog_modal_type_;
-  Browser* browser_;
 
   DISALLOW_COPY_AND_ASSIGN(SigninViewControllerDelegateViews);
 };
diff --git a/chrome/browser/ui/webui/bidi_checker_web_ui_test.cc b/chrome/browser/ui/webui/bidi_checker_web_ui_test.cc
deleted file mode 100644
index acd5bd3..0000000
--- a/chrome/browser/ui/webui/bidi_checker_web_ui_test.cc
+++ /dev/null
@@ -1,726 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/webui/bidi_checker_web_ui_test.h"
-
-#include "base/base_paths.h"
-#include "base/i18n/rtl.h"
-#include "base/message_loop/message_loop.h"
-#include "base/path_service.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
-#include "base/values.h"
-#include "build/build_config.h"
-#include "chrome/browser/autofill/personal_data_manager_factory.h"
-#include "chrome/browser/history/history_service_factory.h"
-#include "chrome/browser/prefs/session_startup_pref.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/common/url_constants.h"
-#include "chrome/test/base/ui_test_utils.h"
-#include "components/autofill/core/browser/autofill_profile.h"
-#include "components/autofill/core/browser/autofill_test_utils.h"
-#include "components/autofill/core/browser/personal_data_manager.h"
-#include "components/history/core/browser/history_service.h"
-#include "components/prefs/pref_service.h"
-#include "content/public/browser/browser_thread.h"
-#include "ui/base/resource/resource_bundle.h"
-
-// Test cases here are disabled on all platforms due to http://crbug.com/511439
-
-using autofill::AutofillProfile;
-using autofill::PersonalDataManager;
-
-static const base::FilePath::CharType* kWebUIBidiCheckerLibraryJS =
-    FILE_PATH_LITERAL("third_party/bidichecker/bidichecker_packaged.js");
-
-namespace {
-base::FilePath WebUIBidiCheckerLibraryJSPath() {
-  base::FilePath src_root;
-  if (!PathService::Get(base::DIR_SOURCE_ROOT, &src_root))
-    LOG(ERROR) << "Couldn't find source root";
-  return src_root.Append(kWebUIBidiCheckerLibraryJS);
-}
-
-// Since synchronization isn't complete for the ResourceBundle class, reload
-// locale resources on the IO thread.
-// crbug.com/95425, crbug.com/132752
-void ReloadLocaleResourcesOnIOThread(const std::string& new_locale) {
-  if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)) {
-    LOG(ERROR)
-        << content::BrowserThread::IO
-        << " != " << base::PlatformThread::CurrentId();
-    NOTREACHED();
-  }
-
-  std::string locale;
-  {
-    base::ThreadRestrictions::ScopedAllowIO allow_io_scope;
-    locale.assign(
-        ResourceBundle::GetSharedInstance().ReloadLocaleResources(new_locale));
-  }
-  ASSERT_FALSE(locale.empty());
-}
-
-// Since synchronization isn't complete for the ResourceBundle class, reload
-// locale resources on the IO thread.
-// crbug.com/95425, crbug.com/132752
-void ReloadLocaleResources(const std::string& new_locale) {
-  content::BrowserThread::PostTaskAndReply(
-      content::BrowserThread::IO, FROM_HERE,
-      base::BindOnce(&ReloadLocaleResourcesOnIOThread,
-                     base::ConstRef(new_locale)),
-      base::MessageLoop::QuitWhenIdleClosure());
-  content::RunMessageLoop();
-}
-
-}  // namespace
-
-static const base::FilePath::CharType* kBidiCheckerTestsJS =
-    FILE_PATH_LITERAL("bidichecker_tests.js");
-
-void WebUIBidiCheckerBrowserTest::SetUp() {
-  argv_ = base::CommandLine::ForCurrentProcess()->GetArgs();
-}
-
-void WebUIBidiCheckerBrowserTest::TearDown() {
-  // Reset command line to the way it was before the test was run.
-  base::CommandLine::ForCurrentProcess()->InitFromArgv(argv_);
-}
-
-WebUIBidiCheckerBrowserTest::~WebUIBidiCheckerBrowserTest() {}
-
-WebUIBidiCheckerBrowserTest::WebUIBidiCheckerBrowserTest() {}
-
-void WebUIBidiCheckerBrowserTest::SetUpInProcessBrowserTestFixture() {
-  WebUIBrowserTest::SetUpInProcessBrowserTestFixture();
-  WebUIBrowserTest::AddLibrary(WebUIBidiCheckerLibraryJSPath());
-  WebUIBrowserTest::AddLibrary(base::FilePath(kBidiCheckerTestsJS));
-}
-
-void WebUIBidiCheckerBrowserTest::RunBidiCheckerOnPage(
-    const std::string& page_url, bool is_rtl) {
-  ui_test_utils::NavigateToURL(browser(), GURL(page_url));
-  ASSERT_TRUE(RunJavascriptTest("runBidiChecker", base::Value(page_url),
-                                base::Value(is_rtl)));
-}
-
-void DISABLED_WebUIBidiCheckerBrowserTestLTR::RunBidiCheckerOnPage(
-    const std::string& page_url) {
-  WebUIBidiCheckerBrowserTest::RunBidiCheckerOnPage(page_url, false);
-}
-
-void DISABLED_WebUIBidiCheckerBrowserTestRTL::RunBidiCheckerOnPage(
-    const std::string& page_url) {
-  WebUIBidiCheckerBrowserTest::RunBidiCheckerOnPage(page_url, true);
-}
-
-void DISABLED_WebUIBidiCheckerBrowserTestRTL::SetUpOnMainThread() {
-  WebUIBidiCheckerBrowserTest::SetUpOnMainThread();
-  base::FilePath pak_path;
-  app_locale_ = base::i18n::GetConfiguredLocale();
-  ASSERT_TRUE(PathService::Get(base::FILE_MODULE, &pak_path));
-  pak_path = pak_path.DirName();
-  pak_path = pak_path.AppendASCII("pseudo_locales");
-  pak_path = pak_path.AppendASCII("fake-bidi");
-  pak_path = pak_path.ReplaceExtension(FILE_PATH_LITERAL("pak"));
-  ResourceBundle::GetSharedInstance().OverrideLocalePakForTest(pak_path);
-  ReloadLocaleResources("he");
-  base::i18n::SetICUDefaultLocale("he");
-}
-
-void DISABLED_WebUIBidiCheckerBrowserTestRTL::TearDownOnMainThread() {
-  WebUIBidiCheckerBrowserTest::TearDownOnMainThread();
-
-  base::i18n::SetICUDefaultLocale(app_locale_);
-  ResourceBundle::GetSharedInstance().OverrideLocalePakForTest(
-      base::FilePath());
-  ReloadLocaleResources(app_locale_);
-}
-
-// Tests
-
-//==============================
-// chrome://history
-//==============================
-
-static void SetupHistoryPageTest(Browser* browser,
-                                 const std::string& page_url,
-                                 const std::string& page_title) {
-  history::HistoryService* history_service =
-      HistoryServiceFactory::GetForProfile(browser->profile(),
-                                           ServiceAccessType::IMPLICIT_ACCESS);
-  const GURL history_url = GURL(page_url);
-  history_service->AddPage(
-      history_url, base::Time::Now(), history::SOURCE_BROWSED);
-  history_service->SetPageTitle(history_url, base::UTF8ToUTF16(page_title));
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestHistoryPage) {
-  // Test an Israeli news site with a Hebrew title.
-  SetupHistoryPageTest(browser(),
-                       "http://www.ynet.co.il",
-                       "\xD7\x91\xD7\x93\xD7\x99\xD7\xA7\xD7\x94\x21");
-  RunBidiCheckerOnPage(chrome::kChromeUIHistoryURL);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestHistoryPage) {
-  SetupHistoryPageTest(browser(), "http://www.google.com", "Google");
-  RunBidiCheckerOnPage(chrome::kChromeUIHistoryURL);
-}
-
-//==============================
-// chrome://about
-//==============================
-
-// This page isn't localized to an RTL language so we test it only in English.
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR, TestAboutPage) {
-  RunBidiCheckerOnPage(chrome::kChromeUIAboutURL);
-}
-
-//==============================
-// chrome://crashes
-//==============================
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestCrashesPage) {
-  RunBidiCheckerOnPage(chrome::kChromeUICrashesURL);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestCrashesPage) {
-  RunBidiCheckerOnPage(chrome::kChromeUICrashesURL);
-}
-
-//==============================
-// chrome://downloads
-//==============================
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestDownloadsPageLTR) {
-  RunBidiCheckerOnPage(chrome::kChromeUIDownloadsURL);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestDownloadsPageRTL) {
-  RunBidiCheckerOnPage(chrome::kChromeUIDownloadsURL);
-}
-
-//==============================
-// chrome://newtab
-//==============================
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestNewTabPage) {
-  RunBidiCheckerOnPage(chrome::kChromeUINewTabURL);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestNewTabPage) {
-  RunBidiCheckerOnPage(chrome::kChromeUINewTabURL);
-}
-
-//==============================
-// chrome://settings-frame
-//==============================
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestSettingsPage) {
-  RunBidiCheckerOnPage(chrome::kChromeUISettingsFrameURL);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestSettingsPage) {
-  RunBidiCheckerOnPage(chrome::kChromeUISettingsFrameURL);
-}
-
-static void SetupSettingsAutofillPageTest(Profile* profile,
-                                          const char* first_name,
-                                          const char* middle_name,
-                                          const char* last_name,
-                                          const char* email,
-                                          const char* company,
-                                          const char* address1,
-                                          const char* address2,
-                                          const char* city,
-                                          const char* state,
-                                          const char* zipcode,
-                                          const char* country,
-                                          const char* phone) {
-  autofill::test::DisableSystemServices(profile->GetPrefs());
-  AutofillProfile autofill_profile;
-  autofill::test::SetProfileInfo(&autofill_profile,
-                                 first_name,
-                                 middle_name,
-                                 last_name,
-                                 email,
-                                 company,
-                                 address1,
-                                 address2,
-                                 city,
-                                 state,
-                                 zipcode,
-                                 country,
-                                 phone);
-  PersonalDataManager* personal_data_manager =
-      autofill::PersonalDataManagerFactory::GetForProfile(profile);
-  ASSERT_TRUE(personal_data_manager);
-  personal_data_manager->AddProfile(autofill_profile);
-}
-
-static void TearDownSettingsAutofillPageTest() {
-  autofill::test::ReenableSystemServices();
-}
-
-// http://crbug.com/94642
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       DISABLED_TestSettingsAutofillPage) {
-  SetupSettingsAutofillPageTest(browser()->profile(),
-                                "\xD7\x9E\xD7\xA9\xD7\x94",
-                                "\xD7\x91",
-                                "\xD7\x9B\xD7\x94\xD7\x9F",
-                                "moshe.b.cohen@biditest.com",
-                                "\xD7\x91\xD7\x93\xD7\x99\xD7\xA7\xD7\x94\x20"
-                                "\xD7\x91\xD7\xA2\xD7\x9E",
-                                "\xD7\x93\xD7\xA8\xD7\x9A\x20\xD7\x9E\xD7\xA0"
-                                "\xD7\x97\xD7\x9D\x20\xD7\x91\xD7\x92\xD7"
-                                "\x99\xD7\x9F\x20\x32\x33",
-                                "\xD7\xA7\xD7\x95\xD7\x9E\xD7\x94\x20\x32\x36",
-                                "\xD7\xAA\xD7\x9C\x20\xD7\x90\xD7\x91\xD7\x99"
-                                "\xD7\x91",
-                                "",
-                                "66183",
-                                "\xD7\x99\xD7\xA9\xD7\xA8\xD7\x90\xD7\x9C",
-                                "0000");
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += std::string(chrome::kAutofillSubPage);
-  RunBidiCheckerOnPage(url);
-  TearDownSettingsAutofillPageTest();
-}
-
-// http://crbug.com/94642
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       DISABLED_TestSettingsAutofillPage) {
-  SetupSettingsAutofillPageTest(browser()->profile(),
-                                "Milton",
-                                "C.",
-                                "Waddams",
-                                "red.swingline@initech.com",
-                                "Initech",
-                                "4120 Freidrich Lane",
-                                "Basement",
-                                "Austin",
-                                "Texas",
-                                "78744",
-                                "United States",
-                                "5125551234");
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += std::string(chrome::kAutofillSubPage);
-  RunBidiCheckerOnPage(url);
-  TearDownSettingsAutofillPageTest();
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestSettingsClearBrowserDataPage) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += std::string(chrome::kClearBrowserDataSubPage);
-  RunBidiCheckerOnPage(url);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestSettingsClearBrowserDataPage) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += std::string(chrome::kClearBrowserDataSubPage);
-  RunBidiCheckerOnPage(url);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestSettingsContentSettingsPage) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += std::string(chrome::kContentSettingsSubPage);
-  RunBidiCheckerOnPage(url);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestSettingsContentSettingsPage) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += std::string(chrome::kContentSettingsSubPage);
-  RunBidiCheckerOnPage(url);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestSettingsContentSettingsExceptionsPage) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url +=
-      std::string(chrome::kDeprecatedOptionsContentSettingsExceptionsSubPage);
-  RunBidiCheckerOnPage(url);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestSettingsContentSettingsExceptionsPage) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url +=
-      std::string(chrome::kDeprecatedOptionsContentSettingsExceptionsSubPage);
-  RunBidiCheckerOnPage(url);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestSettingsLanguageOptionsPage) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += std::string(chrome::kLanguageOptionsSubPage);
-  RunBidiCheckerOnPage(url);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestSettingsLanguageOptionsPage) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += std::string(chrome::kLanguageOptionsSubPage);
-  RunBidiCheckerOnPage(url);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestSettingsSearchEnginesOptionsPage) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += std::string(chrome::kSearchEnginesSubPage);
-  RunBidiCheckerOnPage(url);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestSettingsSearchEnginesOptionsPage) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += std::string(chrome::kSearchEnginesSubPage);
-  RunBidiCheckerOnPage(url);
-}
-
-//===================================
-// chrome://settings-frame/startup
-//===================================
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestSettingsFrameStartup) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += "startup";
-  RunBidiCheckerOnPage(url);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestSettingsFrameStartup) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += "startup";
-  RunBidiCheckerOnPage(url);
-}
-
-//===================================
-// chrome://settings-frame/importData
-//===================================
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestSettingsFrameImportData) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += chrome::kImportDataSubPage;
-  RunBidiCheckerOnPage(url);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestSettingsFrameImportData) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += chrome::kImportDataSubPage;
-  RunBidiCheckerOnPage(url);
-}
-
-#if !defined(OS_CHROMEOS)
-//========================================
-// chrome://settings-frame/manageProfile
-//========================================
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestSettingsFrameMangageProfile) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += chrome::kManageProfileSubPage;
-  RunBidiCheckerOnPage(url);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestSettingsFrameMangageProfile) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += chrome::kManageProfileSubPage;
-  RunBidiCheckerOnPage(url);
-}
-#endif  // !defined(OS_CHROMEOS)
-
-//===================================================
-// chrome://settings-frame/contentExceptions#cookies
-//===================================================
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestSettingsFrameContentExceptionsCookies) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += chrome::kDeprecatedOptionsContentSettingsExceptionsSubPage;
-  url += "#cookies";
-  RunBidiCheckerOnPage(url);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestSettingsFrameContentExceptionsCookies) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += chrome::kDeprecatedOptionsContentSettingsExceptionsSubPage;
-  url += "#cookies";
-  RunBidiCheckerOnPage(url);
-}
-
-//===================================================
-// chrome://settings-frame/contentExceptions#images
-//===================================================
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestSettingsFrameContentExceptionsImages) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += chrome::kDeprecatedOptionsContentSettingsExceptionsSubPage;
-  url += "#images";
-  RunBidiCheckerOnPage(url);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestSettingsFrameContentExceptionsImages) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += chrome::kDeprecatedOptionsContentSettingsExceptionsSubPage;
-  url += "#images";
-  RunBidiCheckerOnPage(url);
-}
-
-//======================================================
-// chrome://settings-frame/contentExceptions#javascript
-//======================================================
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestSettingsFrameContentExceptionsJavascript) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += chrome::kDeprecatedOptionsContentSettingsExceptionsSubPage;
-  url += "#javascript";
-  RunBidiCheckerOnPage(url);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestSettingsFrameContentExceptionsJavascript) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += chrome::kDeprecatedOptionsContentSettingsExceptionsSubPage;
-  url += "#javascript";
-  RunBidiCheckerOnPage(url);
-}
-
-//===================================================
-// chrome://settings-frame/contentExceptions#plugins
-//===================================================
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestSettingsFrameContentExceptionsPlugins) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += chrome::kDeprecatedOptionsContentSettingsExceptionsSubPage;
-  url += "#plugins";
-  RunBidiCheckerOnPage(url);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestSettingsFrameContentExceptionsPlugins) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += chrome::kDeprecatedOptionsContentSettingsExceptionsSubPage;
-  url += "#plugins";
-  RunBidiCheckerOnPage(url);
-}
-
-//===================================================
-// chrome://settings-frame/contentExceptions#popups
-//===================================================
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestSettingsFrameContentExceptionsPopups) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += chrome::kDeprecatedOptionsContentSettingsExceptionsSubPage;
-  url += "#popups";
-  RunBidiCheckerOnPage(url);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestSettingsFrameContentExceptionsPopups) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += chrome::kDeprecatedOptionsContentSettingsExceptionsSubPage;
-  url += "#popups";
-  RunBidiCheckerOnPage(url);
-}
-
-//===================================================
-// chrome://settings-frame/contentExceptions#location
-//===================================================
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestSettingsFrameContentExceptionsLocation) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += chrome::kDeprecatedOptionsContentSettingsExceptionsSubPage;
-  url += "#location";
-  RunBidiCheckerOnPage(url);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestSettingsFrameContentExceptionsLocation) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += chrome::kDeprecatedOptionsContentSettingsExceptionsSubPage;
-  url += "#location";
-  RunBidiCheckerOnPage(url);
-}
-
-//===================================================
-// chrome://settings-frame/contentExceptions#notifications
-//===================================================
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestSettingsFrameContentExceptionsNotifications) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += chrome::kDeprecatedOptionsContentSettingsExceptionsSubPage;
-  url += "#notifications";
-  RunBidiCheckerOnPage(url);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestSettingsFrameContentExceptionsNotifications) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += chrome::kDeprecatedOptionsContentSettingsExceptionsSubPage;
-  url += "#notifications";
-  RunBidiCheckerOnPage(url);
-}
-
-//===================================================
-// chrome://settings-frame/contentExceptions#mouselock
-//===================================================
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestSettingsFrameContentExceptionsMouseLock) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += chrome::kDeprecatedOptionsContentSettingsExceptionsSubPage;
-  url += "#mouselock";
-  RunBidiCheckerOnPage(url);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestSettingsFrameContentExceptionsMouseLock) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += chrome::kDeprecatedOptionsContentSettingsExceptionsSubPage;
-  url += "#mouselock";
-  RunBidiCheckerOnPage(url);
-}
-
-//========================================
-// chrome://settings-frame/handlers
-//========================================
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestSettingsFrameHandler) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += chrome::kHandlerSettingsSubPage;
-  RunBidiCheckerOnPage(url);
-}
-
-// Fails on chromeos. http://crbug.com/125367
-#if defined(OS_CHROMEOS)
-#define MAYBE_TestSettingsFrameHandler DISABLED_TestSettingsFrameHandler
-#else
-#define MAYBE_TestSettingsFrameHandler TestSettingsFrameHandler
-#endif
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       MAYBE_TestSettingsFrameHandler) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += chrome::kHandlerSettingsSubPage;
-  RunBidiCheckerOnPage(url);
-}
-
-//========================================
-// chrome://settings-frame/cookies
-//========================================
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestSettingsFrameCookies) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += "cookies";
-  RunBidiCheckerOnPage(url);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestSettingsFrameCookies) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += "cookies";
-  RunBidiCheckerOnPage(url);
-}
-
-//========================================
-// chrome://settings-frame/passwords
-//========================================
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestSettingsFramePasswords) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += "passwords";
-  RunBidiCheckerOnPage(url);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestSettingsFramePasswords) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += "passwords";
-  RunBidiCheckerOnPage(url);
-}
-
-//========================================
-// chrome://settings-frame/fonts
-//========================================
-
-#if defined(OS_MACOSX)
-#define MAYBE_TestSettingsFrameFonts DISABLED_TestSettingsFrameFonts
-#else
-#define MAYBE_TestSettingsFrameFonts TestSettingsFrameFonts
-#endif
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       MAYBE_TestSettingsFrameFonts) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += "fonts";
-  RunBidiCheckerOnPage(url);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestSettingsFrameFonts) {
-  std::string url(chrome::kChromeUISettingsFrameURL);
-  url += "fonts";
-  RunBidiCheckerOnPage(url);
-}
-
-// Test other uber iframes.
-
-//==============================
-// chrome://extensions-frame
-//==============================
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR,
-                       TestExtensionsFrame) {
-  RunBidiCheckerOnPage(chrome::kChromeUIExtensionsFrameURL);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL,
-                       TestExtensionsFrame) {
-  RunBidiCheckerOnPage(chrome::kChromeUIExtensionsFrameURL);
-}
-
-//==============================
-// chrome://help-frame
-//==============================
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestLTR, TestHelpFrame) {
-  RunBidiCheckerOnPage(chrome::kChromeUIHelpFrameURL);
-}
-
-IN_PROC_BROWSER_TEST_F(DISABLED_WebUIBidiCheckerBrowserTestRTL, TestHelpFrame) {
-  RunBidiCheckerOnPage(chrome::kChromeUIHelpFrameURL);
-}
diff --git a/chrome/browser/ui/webui/bidi_checker_web_ui_test.h b/chrome/browser/ui/webui/bidi_checker_web_ui_test.h
deleted file mode 100644
index affa5d8..0000000
--- a/chrome/browser/ui/webui/bidi_checker_web_ui_test.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_WEBUI_BIDI_CHECKER_WEB_UI_TEST_H_
-#define CHROME_BROWSER_UI_WEBUI_BIDI_CHECKER_WEB_UI_TEST_H_
-
-#include "base/command_line.h"
-#include "chrome/test/base/web_ui_browser_test.h"
-
-// Base class for BidiChecker-based tests. Preloads the BidiChecker JS library
-// for each test.
-class WebUIBidiCheckerBrowserTest : public WebUIBrowserTest {
- public:
-  ~WebUIBidiCheckerBrowserTest() override;
-
-  // testing::Test implementation.
-  void SetUp() override;
-  void TearDown() override;
-
- protected:
-  WebUIBidiCheckerBrowserTest();
-
-  // Runs the Bidi Checker on the given page URL. |is_rtl| should be true when
-  // the active page locale is RTL.
-  void RunBidiCheckerOnPage(const std::string& page_url, bool is_rtl);
-
-  // Setup test path.
-  void SetUpInProcessBrowserTestFixture() override;
-
- private:
-  // The command line args used to run the test before being changed in SetUp().
-  base::CommandLine::StringVector argv_;
-};
-
-// Base class for BidiChecker-based tests that run with an LTR UI.
-// Disabled on all platforms due to http://crbug.com/511439
-class DISABLED_WebUIBidiCheckerBrowserTestLTR
-    : public WebUIBidiCheckerBrowserTest {
- public:
-  void RunBidiCheckerOnPage(const std::string& page_url);
-};
-
-// Base class for BidiChecker-based tests that run with an RTL UI.
-// Disabled on all platforms due to http://crbug.com/511439
-class DISABLED_WebUIBidiCheckerBrowserTestRTL
-    : public WebUIBidiCheckerBrowserTest {
- public:
-  void RunBidiCheckerOnPage(const std::string& page_url);
-
- protected:
-  void SetUpOnMainThread() override;
-  void TearDownOnMainThread() override;
-
-  // The app locale before we change it
-  std::string app_locale_;
-};
-
-#endif  // CHROME_BROWSER_UI_WEBUI_BIDI_CHECKER_WEB_UI_TEST_H_
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
index 0315af60..6cd7bbde 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -574,8 +574,7 @@
 #endif
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
   if (url.host() == chrome::kChromeUISigninDiceInternalsHost &&
-      !profile->IsOffTheRecord() &&
-      switches::IsAccountConsistencyDiceEnabled()) {
+      !profile->IsOffTheRecord() && signin::IsAccountConsistencyDiceEnabled()) {
     return &NewWebUI<SigninDiceInternalsUI>;
   }
 #endif
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
index 5f8c4f8..f3e6f90 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -1921,7 +1921,7 @@
 void PrintPreviewHandler::RegisterForGaiaCookieChanges() {
   DCHECK(!gaia_cookie_manager_service_);
   Profile* profile = Profile::FromWebUI(web_ui());
-  if (switches::IsAccountConsistencyMirrorEnabled() &&
+  if (signin::IsAccountConsistencyMirrorEnabled() &&
       !profile->IsOffTheRecord()) {
     gaia_cookie_manager_service_ =
         GaiaCookieManagerServiceFactory::GetForProfile(profile);
diff --git a/chrome/common/stack_sampling_configuration.cc b/chrome/common/stack_sampling_configuration.cc
index d1ab011..b88ac1a9 100644
--- a/chrome/common/stack_sampling_configuration.cc
+++ b/chrome/common/stack_sampling_configuration.cc
@@ -13,6 +13,10 @@
 #include "components/version_info/version_info.h"
 #include "content/public/common/content_switches.h"
 
+#if defined(OS_MACOSX)
+#include "base/mac/mac_util.h"
+#endif
+
 namespace {
 
 base::LazyInstance<StackSamplingConfiguration>::Leaky g_configuration =
@@ -32,9 +36,11 @@
 #elif defined(OS_MACOSX)
   // Only run on canary for now.
   #if defined(GOOGLE_CHROME_BUILD)
-    return chrome::GetChannel() == version_info::Channel::CANARY;
+    // TODO(lgrey): Reenable for 10.13 when crbug.com/748254 is fixed.
+    return base::mac::IsAtMostOS10_12() &&
+         chrome::GetChannel() == version_info::Channel::CANARY;
   #else
-    return true;
+    return base::mac::IsAtMostOS10_12();
   #endif
 #else
   return false;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index f0ff6ff..463227be 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1099,19 +1099,6 @@
   }
 }
 
-# Used only by chrome/browser/ui/webui/bidi_checker_web_ui_test.cc
-chrome_repack_locales("repack_pseudo_locales") {
-  visibility = [ ":*" ]
-
-  input_locales = [ "fake-bidi" ]
-
-  if (is_mac) {
-    output_locales = [ "fake_bidi" ]  # Mac uses underscores.
-  } else {
-    output_locales = [ "fake-bidi" ]
-  }
-}
-
 test("browser_tests") {
   sources = [
     # TODO(jbudorick): Move tests here from other lists as Android support is
@@ -1122,7 +1109,6 @@
 
   deps = [
     ":browser_tests_runner",
-    ":repack_pseudo_locales",
     ":test_support",
     "//base",
     "//components/spellcheck:build_features",
@@ -1544,8 +1530,6 @@
       "../browser/ui/views/chrome_cleaner_dialog_browsertest_win.cc",
       "../browser/ui/views/extensions/chooser_dialog_view_browsertest.cc",
       "../browser/ui/views/hung_renderer_view_browsertest.cc",
-      "../browser/ui/webui/bidi_checker_web_ui_test.cc",
-      "../browser/ui/webui/bidi_checker_web_ui_test.h",
       "../browser/ui/webui/bookmarks_ui_browsertest.cc",
       "../browser/ui/webui/chrome_url_data_manager_browsertest.cc",
       "../browser/ui/webui/chromeos/bluetooth_pairing_ui_browsertest-inl.h",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/OWNERS b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/OWNERS
index f5f6e7ea..a75aa30 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/OWNERS
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/OWNERS
@@ -1 +1,2 @@
+bsazonov@chromium.org
 gogerald@chromium.org
diff --git a/chrome/test/chromedriver/window_commands.cc b/chrome/test/chromedriver/window_commands.cc
index 5a4e99c..b40eaa2 100644
--- a/chrome/test/chromedriver/window_commands.cc
+++ b/chrome/test/chromedriver/window_commands.cc
@@ -11,6 +11,7 @@
 #include <utility>
 
 #include "base/callback.h"
+#include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/platform_thread.h"
@@ -36,7 +37,7 @@
 
 namespace {
 
-const std::string kUnreachableWebDataURL = "data:text/html,chromewebdata";
+static const char kUnreachableWebDataURL[] = "data:text/html,chromewebdata";
 
 // Defaults to 20 years into the future when adding a cookie.
 const double kDefaultCookieExpiryTime = 20*365*24*60*60;
@@ -730,6 +731,47 @@
   return web_view->SynthesizePinchGesture(location.x, location.y, scale_factor);
 }
 
+Status ProcessInputActionSequence(Session* session,
+                                  const base::DictionaryValue* action_sequence,
+                                  std::unique_ptr<base::ListValue>* result) {
+  return Status(kOk);
+}
+
+Status ExecutePerformActions(Session* session,
+                             WebView* web_view,
+                             const base::DictionaryValue& params,
+                             std::unique_ptr<base::Value>* value,
+                             Timeout* timeout) {
+  // TODO(kereliuk): check if the current browsing context is still open
+  // or if this error check is handled elsewhere
+
+  // TODO(kereliuk): handle prompts
+
+  // extract action sequence
+  const base::ListValue* actions;
+  if (!params.GetList("actions", &actions))
+    return Status(kInvalidArgument, "'actions' must be an array");
+
+  base::ListValue actions_by_tick;
+  std::unique_ptr<base::ListValue> input_source_actions(new base::ListValue());
+  for (size_t i = 0; i < actions->GetSize(); i++) {
+    // proccess input action sequence
+    const base::DictionaryValue* action_sequence;
+    if (!actions->GetDictionary(i, &action_sequence))
+      return Status(kInvalidArgument, "each argument must be a dictionary");
+
+    Status status = ProcessInputActionSequence(session, action_sequence,
+                                               &input_source_actions);
+    actions_by_tick.Append(std::move(input_source_actions));
+    if (status.IsError())
+      return Status(kInvalidArgument, status);
+  }
+
+  // TODO(kereliuk): dispatch actions
+
+  return Status(kOk);
+}
+
 Status ExecuteSendCommand(Session* session,
                           WebView* web_view,
                           const base::DictionaryValue& params,
diff --git a/chrome/test/chromedriver/window_commands.h b/chrome/test/chromedriver/window_commands.h
index ddf7ec3..176df8d 100644
--- a/chrome/test/chromedriver/window_commands.h
+++ b/chrome/test/chromedriver/window_commands.h
@@ -9,6 +9,8 @@
 #include <string>
 
 #include "base/callback_forward.h"
+#include "base/values.h"
+#include "chrome/test/chromedriver/session.h"
 
 namespace base {
 class DictionaryValue;
@@ -340,4 +342,13 @@
                                std::unique_ptr<base::Value>* value,
                                Timeout* timeout);
 
+Status ExecutePerformActions(Session* session,
+                             WebView* web_view,
+                             const base::DictionaryValue& params,
+                             std::unique_ptr<base::Value>* value,
+                             Timeout* timeout);
+
+Status ProcessInputActionSequence(Session* session,
+                                  const base::DictionaryValue* action_sequence,
+                                  std::unique_ptr<base::ListValue>* result);
 #endif  // CHROME_TEST_CHROMEDRIVER_WINDOW_COMMANDS_H_
diff --git a/components/autofill/core/browser/autofill_profile.cc b/components/autofill/core/browser/autofill_profile.cc
index 35bc590..6f70f4d 100644
--- a/components/autofill/core/browser/autofill_profile.cc
+++ b/components/autofill/core/browser/autofill_profile.cc
@@ -18,6 +18,7 @@
 #include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/sha1.h"
+#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversion_utils.h"
 #include "base/strings/utf_string_conversions.h"
@@ -717,6 +718,26 @@
   RecordUse();
 }
 
+AutofillProfile::ValidityState AutofillProfile::GetValidityState(
+    ServerFieldType type) {
+  if (!base::ContainsKey(validity_states_, type))
+    return UNVALIDATED;
+
+  return validity_states_[type];
+}
+
+void AutofillProfile::SetValidityState(ServerFieldType type,
+                                       ValidityState validity) {
+  std::map<ServerFieldType, ValidityState>::iterator it =
+      validity_states_.find(type);
+
+  if (it != validity_states_.end()) {
+    it->second = validity;
+  } else {
+    validity_states_.insert(std::make_pair(type, validity));
+  }
+}
+
 // static
 void AutofillProfile::CreateInferredLabelsHelper(
     const std::vector<AutofillProfile*>& profiles,
diff --git a/components/autofill/core/browser/autofill_profile.h b/components/autofill/core/browser/autofill_profile.h
index de33113..33ab3fa 100644
--- a/components/autofill/core/browser/autofill_profile.h
+++ b/components/autofill/core/browser/autofill_profile.h
@@ -40,6 +40,17 @@
     AUXILIARY_PROFILE,
   };
 
+  enum ValidityState {
+    // The field has not been validated.
+    UNVALIDATED,
+
+    // The field is invalid.
+    INVALID,
+
+    // The field is valid.
+    VALID,
+  };
+
   AutofillProfile(const std::string& guid, const std::string& origin);
 
   // Server profile constructor. The type must be SERVER_PROFILE (this serves
@@ -189,6 +200,12 @@
   bool has_converted() const { return has_converted_; }
   void set_has_converted(bool has_converted) { has_converted_ = has_converted; }
 
+  // Returns the validity state of the specified autofill type.
+  ValidityState GetValidityState(ServerFieldType type);
+
+  // Sets the validity state of the specified autofill type.
+  void SetValidityState(ServerFieldType type, ValidityState validity);
+
  private:
   typedef std::vector<const FormGroup*> FormGroupList;
 
@@ -236,6 +253,9 @@
   // Only useful for SERVER_PROFILEs. Whether this server profile has been
   // converted to a local profile.
   bool has_converted_;
+
+  // A map identifying what fields are valid.
+  std::map<ServerFieldType, ValidityState> validity_states_;
 };
 
 // So we can compare AutofillProfiles with EXPECT_EQ().
diff --git a/components/autofill/core/browser/autofill_profile_unittest.cc b/components/autofill/core/browser/autofill_profile_unittest.cc
index ee55bc0..e94cfe0 100644
--- a/components/autofill/core/browser/autofill_profile_unittest.cc
+++ b/components/autofill/core/browser/autofill_profile_unittest.cc
@@ -1100,4 +1100,20 @@
             a.GetRawInfo(NAME_FULL));
 }
 
+TEST(AutofillProfileTest, ValidityStates) {
+  AutofillProfile profile;
+
+  // The default validity state should be UNVALIDATED.
+  EXPECT_EQ(AutofillProfile::UNVALIDATED,
+            profile.GetValidityState(ADDRESS_HOME_LINE1));
+
+  // Make sure setting the validity state works.
+  profile.SetValidityState(ADDRESS_HOME_LINE1, AutofillProfile::VALID);
+  profile.SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::INVALID);
+  EXPECT_EQ(AutofillProfile::VALID,
+            profile.GetValidityState(ADDRESS_HOME_LINE1));
+  EXPECT_EQ(AutofillProfile::INVALID,
+            profile.GetValidityState(ADDRESS_HOME_CITY));
+}
+
 }  // namespace autofill
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc
index c654b1b..26ec8c53 100644
--- a/components/browser_sync/profile_sync_service.cc
+++ b/components/browser_sync/profile_sync_service.cc
@@ -1926,7 +1926,7 @@
     is_auth_in_progress_ = true;
   }
 
-  if (switches::IsAccountConsistencyDiceEnabled() &&
+  if (signin::IsAccountConsistencyDiceEnabled() &&
       oauth2_token_service_->RefreshTokenIsAvailable(account_id)) {
     // When Dice is enabled, the refresh token may be available before the user
     // enables sync. Start sync if the refresh token is already available in the
diff --git a/components/domain_reliability/util.cc b/components/domain_reliability/util.cc
index 9c4406f..8a9eb54 100644
--- a/components/domain_reliability/util.cc
+++ b/components/domain_reliability/util.cc
@@ -128,6 +128,7 @@
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_38:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_39:
     case net::HttpResponseInfo::CONNECTION_INFO_QUIC_40:
+    case net::HttpResponseInfo::CONNECTION_INFO_QUIC_41:
       return "QUIC";
     case net::HttpResponseInfo::NUM_OF_CONNECTION_INFOS:
       NOTREACHED();
diff --git a/components/feature_engagement_tracker/public/event_constants.h b/components/feature_engagement_tracker/public/event_constants.h
index fbe217c..24e64ad 100644
--- a/components/feature_engagement_tracker/public/event_constants.h
+++ b/components/feature_engagement_tracker/public/event_constants.h
@@ -39,7 +39,8 @@
 // described above, but it is also used on iOS, so it must be compiled
 // separately.
 
-// The user has opened a new tab.
+// The user has explicitly opened a new tab via an entry point from inside of
+// Chrome.
 extern const char kNewTabOpened[];
 
 #endif  // defined(OS_WIN) || defined(OS_LINUX) || defined(OS_IOS)
diff --git a/components/ntp_snippets/content_suggestion.h b/components/ntp_snippets/content_suggestion.h
index 312c710..a3fcf3d 100644
--- a/components/ntp_snippets/content_suggestion.h
+++ b/components/ntp_snippets/content_suggestion.h
@@ -49,8 +49,6 @@
 // ReadingListSuggestionExtra contains additional data which is only available
 // for Reading List suggestions.
 struct ReadingListSuggestionExtra {
-  // State of the distillation of the suggestion.
-  bool distilled = false;
   // URL of the page whose favicon should be displayed for this suggestion.
   GURL favicon_page_url;
 };
diff --git a/components/ntp_snippets/reading_list/reading_list_suggestions_provider.cc b/components/ntp_snippets/reading_list/reading_list_suggestions_provider.cc
index 9bf791c..2b28842 100644
--- a/components/ntp_snippets/reading_list/reading_list_suggestions_provider.cc
+++ b/components/ntp_snippets/reading_list/reading_list_suggestions_provider.cc
@@ -227,7 +227,6 @@
       base::Time::FromDoubleT(entry_time / base::Time::kMicrosecondsPerSecond));
 
   auto extra = base::MakeUnique<ReadingListSuggestionExtra>();
-  extra->distilled = entry->DistilledState() == ReadingListEntry::PROCESSED;
   extra->favicon_page_url =
       entry->DistilledURL().is_valid() ? entry->DistilledURL() : entry->URL();
   suggestion.set_reading_list_suggestion_extra(std::move(extra));
diff --git a/components/offline_pages/core/BUILD.gn b/components/offline_pages/core/BUILD.gn
index 90eb73a..3d66f1f 100644
--- a/components/offline_pages/core/BUILD.gn
+++ b/components/offline_pages/core/BUILD.gn
@@ -112,6 +112,7 @@
     ":test_support",
     "prefetch:unit_tests",
     "recent_tabs:unit_tests",
+    "renovations:unit_tests",
     "//base",
     "//base/test:test_support",
     "//sql:sql",
diff --git a/components/offline_pages/core/renovations/BUILD.gn b/components/offline_pages/core/renovations/BUILD.gn
new file mode 100644
index 0000000..cffcbf6
--- /dev/null
+++ b/components/offline_pages/core/renovations/BUILD.gn
@@ -0,0 +1,33 @@
+# 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.
+
+if (is_android) {
+  import("//build/config/android/rules.gni")
+}
+
+static_library("renovations") {
+  sources = [
+    "page_renovation.h",
+    "page_renovation_loader.cc",
+    "page_renovation_loader.h",
+  ]
+
+  deps = [
+    "//base",
+    "//url",
+  ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [
+    "page_renovation_loader_unittest.cc",
+  ]
+
+  deps = [
+    ":renovations",
+    "//base",
+    "//testing/gtest",
+  ]
+}
diff --git a/components/offline_pages/core/renovations/page_renovation.h b/components/offline_pages/core/renovations/page_renovation.h
new file mode 100644
index 0000000..1107d4b
--- /dev/null
+++ b/components/offline_pages/core/renovations/page_renovation.h
@@ -0,0 +1,27 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_OFFLINE_PAGES_CORE_PAGE_RENOVATION_H_
+#define COMPONENTS_OFFLINE_PAGES_CORE_PAGE_RENOVATION_H_
+
+#include <string>
+
+#include "url/gurl.h"
+
+namespace offline_pages {
+
+// Objects implementing this interface represent individual renovations
+// that can be run in a page pre-snapshot.
+class PageRenovation {
+ public:
+  // Returns |true| if this renovation should run in the page from |url|.
+  virtual bool ShouldRun(const GURL& url) const = 0;
+  // Returns an ID that identifies this renovation's script. This ID
+  // can be passed to the PageRenovationLoader.
+  virtual std::string GetID() const = 0;
+};
+
+}  // namespace offline_pages
+
+#endif  // COMPONENTS_OFFLINE_PAGES_CORE_PAGE_RENOVATION_H_
diff --git a/components/offline_pages/core/renovations/page_renovation_loader.cc b/components/offline_pages/core/renovations/page_renovation_loader.cc
new file mode 100644
index 0000000..04bdb4c7
--- /dev/null
+++ b/components/offline_pages/core/renovations/page_renovation_loader.cc
@@ -0,0 +1,88 @@
+// 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 "components/offline_pages/core/renovations/page_renovation_loader.h"
+
+#include <utility>
+
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+
+namespace offline_pages {
+
+namespace {
+
+// Construct list of implemented renovations
+std::vector<std::unique_ptr<PageRenovation>> makeRenovationList() {
+  // TODO(collinbaker): Create PageRenovation instances and put them
+  // in this list.
+  return std::vector<std::unique_ptr<PageRenovation>>();
+}
+
+// "Null" script placeholder until we load scripts from storage.
+// TODO(collinbaker): remove this after implmenting loading.
+const char kEmptyScript[] = "function run_renovations(flist){}";
+
+}  // namespace
+
+PageRenovationLoader::PageRenovationLoader()
+    : renovations_(makeRenovationList()),
+      is_loaded_(false),
+      combined_source_(base::UTF8ToUTF16(kEmptyScript)) {}
+
+PageRenovationLoader::~PageRenovationLoader() {}
+
+bool PageRenovationLoader::GetRenovationScript(
+    const std::vector<std::string>& renovation_ids,
+    base::string16* script) {
+  if (!LoadSource()) {
+    return false;
+  }
+
+  // The loaded script contains a function called run_renovations
+  // which takes an array of renovation names and runs all the
+  // associated renovation code. Create call to run_renovations
+  // function in JavaScript file.
+  std::string jsCall = "\nrun_renovations([";
+  for (const std::string& renovation_id : renovation_ids) {
+    jsCall += "\"";
+    jsCall += renovation_id;
+    jsCall += "\",";
+  }
+  jsCall += "]);";
+
+  // Append run_renovations call to combined_source_, which contains
+  // the definition of run_renovations.
+  *script = combined_source_;
+  *script += base::UTF8ToUTF16(jsCall);
+
+  return true;
+}
+
+bool PageRenovationLoader::LoadSource() {
+  // We only need to load the script from storage once.
+  if (is_loaded_) {
+    return true;
+  }
+
+  // TODO(collinbaker): Load file with renovations using
+  // ui::ResourceBundle. For now, using temporary script that does
+  // nothing.
+  combined_source_ = base::UTF8ToUTF16(kEmptyScript);
+
+  is_loaded_ = true;
+  return true;
+}
+
+void PageRenovationLoader::SetSourceForTest(base::string16 combined_source) {
+  combined_source_ = std::move(combined_source);
+  is_loaded_ = true;
+}
+
+void PageRenovationLoader::SetRenovationsForTest(
+    std::vector<std::unique_ptr<PageRenovation>> renovations) {
+  renovations_ = std::move(renovations);
+}
+
+}  // namespace offline_pages
diff --git a/components/offline_pages/core/renovations/page_renovation_loader.h b/components/offline_pages/core/renovations/page_renovation_loader.h
new file mode 100644
index 0000000..3e58f285
--- /dev/null
+++ b/components/offline_pages/core/renovations/page_renovation_loader.h
@@ -0,0 +1,64 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_OFFLINE_PAGES_CORE_RENOVATIONS_PAGE_RENOVATION_LOADER_H_
+#define COMPONENTS_OFFLINE_PAGES_CORE_RENOVATIONS_PAGE_RENOVATION_LOADER_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/strings/string16.h"
+#include "components/offline_pages/core/renovations/page_renovation.h"
+
+namespace offline_pages {
+
+// Class for preparing page renovation scripts. Handles loading
+// JavaScript from storage and creating script to run particular
+// renovations.
+class PageRenovationLoader {
+ public:
+  PageRenovationLoader();
+  ~PageRenovationLoader();
+
+  // Takes a list of renovation IDs and outputs a script to be run in
+  // page. Returns whether loading was successful. The script is a
+  // string16 to match the rest of Chrome.
+  bool GetRenovationScript(const std::vector<std::string>& renovation_ids,
+                           base::string16* script);
+
+  // Returns the list of known renovations.
+  const std::vector<std::unique_ptr<PageRenovation>>& renovations() {
+    return renovations_;
+  }
+
+ private:
+  // Called to load JavaScript source from storage.
+  bool LoadSource();
+
+  // Set combined_source_ for unit tests.
+  void SetSourceForTest(base::string16 combined_source);
+
+  // Set renovations_ for unit tests.
+  void SetRenovationsForTest(
+      std::vector<std::unique_ptr<PageRenovation>> renovations);
+
+  // List of registered page renovations
+  std::vector<std::unique_ptr<PageRenovation>> renovations_;
+
+  // Whether JavaScript source has been loaded.
+  bool is_loaded_;
+  // Contains JavaScript source.
+  base::string16 combined_source_;
+
+  // Friend class for unit tests.
+  friend class PageRenovationLoaderTest;
+
+  DISALLOW_COPY_AND_ASSIGN(PageRenovationLoader);
+};
+
+}  // namespace offline_pages
+
+#endif  // COMPONENTS_OFFLINE_PAGES_CORE_RENOVATIONS_PAGE_RENOVATION_LOADER_H_
diff --git a/components/offline_pages/core/renovations/page_renovation_loader_unittest.cc b/components/offline_pages/core/renovations/page_renovation_loader_unittest.cc
new file mode 100644
index 0000000..66ad606
--- /dev/null
+++ b/components/offline_pages/core/renovations/page_renovation_loader_unittest.cc
@@ -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.
+
+#include "components/offline_pages/core/renovations/page_renovation_loader.h"
+
+#include <memory>
+
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace offline_pages {
+
+namespace {
+const char kTestRenovationKey1[] = "abc_renovation";
+const char kTestRenovationKey2[] = "xyz_renovation";
+const char kTestRenovationScript[] =
+    "\nrun_renovations([\"abc_renovation\",\"xyz_renovation\",]);";
+}  // namespace
+
+class PageRenovationLoaderTest : public testing::Test {
+ public:
+  void SetUp() override;
+  void TearDown() override;
+
+ protected:
+  std::unique_ptr<PageRenovationLoader> page_renovation_loader_;
+};
+
+void PageRenovationLoaderTest::SetUp() {
+  page_renovation_loader_.reset(new PageRenovationLoader);
+  page_renovation_loader_->SetSourceForTest(base::string16());
+}
+
+void PageRenovationLoaderTest::TearDown() {
+  page_renovation_loader_.reset();
+}
+
+TEST_F(PageRenovationLoaderTest, NoRenovations) {
+  std::vector<std::string> renovation_keys;
+  // Pass empty list
+  base::string16 script;
+  EXPECT_TRUE(
+      page_renovation_loader_->GetRenovationScript(renovation_keys, &script));
+
+  EXPECT_EQ(script, base::UTF8ToUTF16("\nrun_renovations([]);"));
+}
+
+TEST_F(PageRenovationLoaderTest, TestRenovations) {
+  std::vector<std::string> renovation_keys;
+  renovation_keys.push_back(kTestRenovationKey1);
+  renovation_keys.push_back(kTestRenovationKey2);
+
+  base::string16 script;
+  EXPECT_TRUE(
+      page_renovation_loader_->GetRenovationScript(renovation_keys, &script));
+
+  EXPECT_EQ(script, base::UTF8ToUTF16(kTestRenovationScript));
+}
+
+TEST_F(PageRenovationLoaderTest, ReturnsSameScript) {
+  std::vector<std::string> renovation_keys;
+  renovation_keys.push_back(kTestRenovationKey1);
+  renovation_keys.push_back(kTestRenovationKey2);
+
+  base::string16 script1, script2;
+  EXPECT_TRUE(
+      page_renovation_loader_->GetRenovationScript(renovation_keys, &script1));
+  EXPECT_TRUE(
+      page_renovation_loader_->GetRenovationScript(renovation_keys, &script2));
+
+  EXPECT_EQ(script1, script2);
+}
+
+}  // namespace offline_pages
diff --git a/components/password_manager/core/common/password_manager_features.cc b/components/password_manager/core/common/password_manager_features.cc
index 5dce1e7e..4a3b9ac1 100644
--- a/components/password_manager/core/common/password_manager_features.cc
+++ b/components/password_manager/core/common/password_manager_features.cc
@@ -4,6 +4,8 @@
 
 #include "components/password_manager/core/common/password_manager_features.h"
 
+#include "build/build_config.h"
+
 namespace password_manager {
 
 namespace features {
@@ -47,7 +49,13 @@
 // mobile, the desktop version of Chrome always allows users to view
 // passwords.
 const base::Feature kViewPasswords = {"view-passwords",
+// TODO(crbug.com/739404): Remove this ifdef once the feature spends a couple
+// of releases in stable on iOS or once it also gets enabled on Android.
+#if defined(OS_IOS)
+                                      base::FEATURE_ENABLED_BY_DEFAULT};
+#else
                                       base::FEATURE_DISABLED_BY_DEFAULT};
+#endif
 
 // Enables the experiment for the password manager to only fill on account
 // selection, rather than autofilling on page load, with highlighting of fields.
diff --git a/components/security_state/content/BUILD.gn b/components/security_state/content/BUILD.gn
index 7d3f503..cb1c23a 100644
--- a/components/security_state/content/BUILD.gn
+++ b/components/security_state/content/BUILD.gn
@@ -34,6 +34,7 @@
     "//base",
     "//base/test:test_support",
     "//components/security_state/core",
+    "//components/strings",
     "//content/public/browser",
     "//content/test:test_support",
     "//net",
diff --git a/components/security_state/content/content_utils.cc b/components/security_state/content/content_utils.cc
index 2832bf0..395cd66 100644
--- a/components/security_state/content/content_utils.cc
+++ b/components/security_state/content/content_utils.cc
@@ -254,21 +254,46 @@
       SecurityLevelToSecurityStyle(
           security_state::kDisplayedInsecureContentLevel);
 
-  // Record the presence of mixed content (HTTP subresources on an HTTPS
-  // page).
+  // Add the secure explanation unless there is an issue.
+  bool add_secure_explanation = true;
+
   security_style_explanations->ran_mixed_content =
       security_info.mixed_content_status ==
           security_state::CONTENT_STATUS_RAN ||
       security_info.mixed_content_status ==
           security_state::CONTENT_STATUS_DISPLAYED_AND_RAN;
+  if (security_style_explanations->ran_mixed_content) {
+    add_secure_explanation = false;
+    security_style_explanations->insecure_explanations.push_back(
+        content::SecurityStyleExplanation(
+            l10n_util::GetStringUTF8(IDS_MIXED_ACTIVE_CONTENT_SUMMARY),
+            l10n_util::GetStringUTF8(IDS_MIXED_ACTIVE_CONTENT_DESCRIPTION),
+            false, blink::WebMixedContentContextType::kBlockable));
+  }
+
   security_style_explanations->displayed_mixed_content =
       security_info.mixed_content_status ==
           security_state::CONTENT_STATUS_DISPLAYED ||
       security_info.mixed_content_status ==
           security_state::CONTENT_STATUS_DISPLAYED_AND_RAN;
+  if (security_style_explanations->displayed_mixed_content) {
+    add_secure_explanation = false;
+    security_style_explanations->neutral_explanations.push_back(
+        content::SecurityStyleExplanation(
+            l10n_util::GetStringUTF8(IDS_MIXED_PASSIVE_CONTENT_SUMMARY),
+            l10n_util::GetStringUTF8(IDS_MIXED_PASSIVE_CONTENT_DESCRIPTION),
+            false, blink::WebMixedContentContextType::kOptionallyBlockable));
+  }
 
   security_style_explanations->contained_mixed_form =
       security_info.contained_mixed_form;
+  if (security_style_explanations->contained_mixed_form) {
+    add_secure_explanation = false;
+    security_style_explanations->neutral_explanations.push_back(
+        content::SecurityStyleExplanation(
+            l10n_util::GetStringUTF8(IDS_NON_SECURE_FORM_SUMMARY),
+            l10n_util::GetStringUTF8(IDS_NON_SECURE_FORM_DESCRIPTION)));
+  }
 
   // If the main resource was loaded with no certificate errors or only minor
   // certificate errors, then record the presence of subresources with
@@ -285,11 +310,36 @@
             security_state::CONTENT_STATUS_RAN ||
         security_info.content_with_cert_errors_status ==
             security_state::CONTENT_STATUS_DISPLAYED_AND_RAN;
+    if (security_style_explanations->ran_content_with_cert_errors) {
+      add_secure_explanation = false;
+      security_style_explanations->insecure_explanations.push_back(
+          content::SecurityStyleExplanation(
+              l10n_util::GetStringUTF8(IDS_CERT_ERROR_ACTIVE_CONTENT_SUMMARY),
+              l10n_util::GetStringUTF8(
+                  IDS_CERT_ERROR_ACTIVE_CONTENT_DESCRIPTION)));
+    }
+
     security_style_explanations->displayed_content_with_cert_errors =
         security_info.content_with_cert_errors_status ==
             security_state::CONTENT_STATUS_DISPLAYED ||
         security_info.content_with_cert_errors_status ==
             security_state::CONTENT_STATUS_DISPLAYED_AND_RAN;
+    if (security_style_explanations->displayed_content_with_cert_errors) {
+      add_secure_explanation = false;
+      security_style_explanations->neutral_explanations.push_back(
+          content::SecurityStyleExplanation(
+              l10n_util::GetStringUTF8(IDS_CERT_ERROR_PASSIVE_CONTENT_SUMMARY),
+              l10n_util::GetStringUTF8(
+                  IDS_CERT_ERROR_PASSIVE_CONTENT_DESCRIPTION)));
+    }
+  }
+
+  if (add_secure_explanation) {
+    DCHECK(security_info.scheme_is_cryptographic);
+    security_style_explanations->secure_explanations.push_back(
+        content::SecurityStyleExplanation(
+            l10n_util::GetStringUTF8(IDS_SECURE_RESOURCES_SUMMARY),
+            l10n_util::GetStringUTF8(IDS_SECURE_RESOURCES_DESCRIPTION)));
   }
 }
 
diff --git a/components/security_state/content/content_utils_unittest.cc b/components/security_state/content/content_utils_unittest.cc
index e031970..d52ac7d 100644
--- a/components/security_state/content/content_utils_unittest.cc
+++ b/components/security_state/content/content_utils_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/test/histogram_tester.h"
 #include "components/security_state/core/security_state.h"
 #include "components/security_state/core/switches.h"
+#include "components/strings/grit/components_strings.h"
 #include "content/public/browser/security_style_explanation.h"
 #include "content/public/browser/security_style_explanations.h"
 #include "net/cert/cert_status_flags.h"
@@ -19,6 +20,7 @@
 #include "net/test/test_data_directory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/public/platform/WebMixedContentContextType.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace {
 
@@ -151,9 +153,26 @@
   EXPECT_TRUE(explanations.displayed_mixed_content);
 }
 
+// Tests that malicious safe browsing data in SecurityInfo triggers an
+// appropriate summary in SecurityStyleExplanations.
+TEST(SecurityStateContentUtilsTest, GetSecurityStyleForSafeBrowsing) {
+  content::SecurityStyleExplanations explanations;
+  security_state::SecurityInfo security_info;
+  security_info.cert_status = 0;
+  security_info.scheme_is_cryptographic = true;
+  security_info.malicious_content_status =
+      security_state::MALICIOUS_CONTENT_STATUS_MALWARE;
+
+  security_info.content_with_cert_errors_status =
+      security_state::CONTENT_STATUS_DISPLAYED_AND_RAN;
+  GetSecurityStyle(security_info, &explanations);
+  EXPECT_EQ(l10n_util::GetStringUTF8(IDS_SAFEBROWSING_WARNING),
+            explanations.summary);
+}
+
 bool FindSecurityStyleExplanation(
     const std::vector<content::SecurityStyleExplanation>& explanations,
-    const char* summary,
+    const std::string& summary,
     content::SecurityStyleExplanation* explanation) {
   for (const auto& entry : explanations) {
     if (entry.summary == summary) {
@@ -257,6 +276,218 @@
   }
 }
 
+// Test that a secure content explanation is added as expected.
+TEST(SecurityStateContentUtilsTest, SecureContentExplanation) {
+  // Test a modern configuration with a key exchange group.
+  security_state::SecurityInfo security_info;
+  security_info.cert_status = net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;
+  security_info.scheme_is_cryptographic = true;
+  net::SSLConnectionStatusSetCipherSuite(
+      0xcca8 /* TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 */,
+      &security_info.connection_status);
+  net::SSLConnectionStatusSetVersion(net::SSL_CONNECTION_VERSION_TLS1_2,
+                                     &security_info.connection_status);
+  security_info.key_exchange_group = 29;  // X25519
+
+  {
+    content::SecurityStyleExplanations explanations;
+    GetSecurityStyle(security_info, &explanations);
+    content::SecurityStyleExplanation explanation;
+    EXPECT_TRUE(FindSecurityStyleExplanation(
+        explanations.secure_explanations,
+        l10n_util::GetStringUTF8(IDS_SECURE_RESOURCES_SUMMARY), &explanation));
+    EXPECT_EQ(l10n_util::GetStringUTF8(IDS_SECURE_RESOURCES_DESCRIPTION),
+              explanation.description);
+  }
+}
+
+// Test that mixed content explanations are added as expected.
+TEST(SecurityStateContentUtilsTest, MixedContentExplanations) {
+  // Test a modern configuration with a key exchange group.
+  security_state::SecurityInfo security_info;
+  security_info.cert_status = net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;
+  security_info.scheme_is_cryptographic = true;
+  net::SSLConnectionStatusSetCipherSuite(
+      0xcca8 /* TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 */,
+      &security_info.connection_status);
+  net::SSLConnectionStatusSetVersion(net::SSL_CONNECTION_VERSION_TLS1_2,
+                                     &security_info.connection_status);
+  security_info.key_exchange_group = 29;  // X25519
+
+  security_info.mixed_content_status =
+      security_state::CONTENT_STATUS_DISPLAYED_AND_RAN;
+  {
+    content::SecurityStyleExplanations explanations;
+    GetSecurityStyle(security_info, &explanations);
+    content::SecurityStyleExplanation explanation;
+    EXPECT_TRUE(FindSecurityStyleExplanation(
+        explanations.neutral_explanations,
+        l10n_util::GetStringUTF8(IDS_MIXED_PASSIVE_CONTENT_SUMMARY),
+        &explanation));
+    EXPECT_EQ(l10n_util::GetStringUTF8(IDS_MIXED_PASSIVE_CONTENT_DESCRIPTION),
+              explanation.description);
+    EXPECT_TRUE(FindSecurityStyleExplanation(
+        explanations.insecure_explanations,
+        l10n_util::GetStringUTF8(IDS_MIXED_ACTIVE_CONTENT_SUMMARY),
+        &explanation));
+    EXPECT_EQ(l10n_util::GetStringUTF8(IDS_MIXED_ACTIVE_CONTENT_DESCRIPTION),
+              explanation.description);
+  }
+
+  security_info.mixed_content_status = security_state::CONTENT_STATUS_DISPLAYED;
+  {
+    content::SecurityStyleExplanations explanations;
+    GetSecurityStyle(security_info, &explanations);
+    content::SecurityStyleExplanation explanation;
+    EXPECT_TRUE(FindSecurityStyleExplanation(
+        explanations.neutral_explanations,
+        l10n_util::GetStringUTF8(IDS_MIXED_PASSIVE_CONTENT_SUMMARY),
+        &explanation));
+    EXPECT_FALSE(FindSecurityStyleExplanation(
+        explanations.insecure_explanations,
+        l10n_util::GetStringUTF8(IDS_MIXED_ACTIVE_CONTENT_SUMMARY),
+        &explanation));
+  }
+
+  security_info.mixed_content_status = security_state::CONTENT_STATUS_RAN;
+  {
+    content::SecurityStyleExplanations explanations;
+    GetSecurityStyle(security_info, &explanations);
+    content::SecurityStyleExplanation explanation;
+    EXPECT_FALSE(FindSecurityStyleExplanation(
+        explanations.neutral_explanations,
+        l10n_util::GetStringUTF8(IDS_MIXED_PASSIVE_CONTENT_SUMMARY),
+        &explanation));
+    EXPECT_TRUE(FindSecurityStyleExplanation(
+        explanations.insecure_explanations,
+        l10n_util::GetStringUTF8(IDS_MIXED_ACTIVE_CONTENT_SUMMARY),
+        &explanation));
+  }
+
+  security_info.contained_mixed_form = true;
+  {
+    content::SecurityStyleExplanations explanations;
+    GetSecurityStyle(security_info, &explanations);
+    content::SecurityStyleExplanation explanation;
+    EXPECT_TRUE(FindSecurityStyleExplanation(
+        explanations.neutral_explanations,
+        l10n_util::GetStringUTF8(IDS_NON_SECURE_FORM_SUMMARY), &explanation));
+    EXPECT_EQ(l10n_util::GetStringUTF8(IDS_NON_SECURE_FORM_DESCRIPTION),
+              explanation.description);
+  }
+}
+
+// Test that cert error explanations are formatted as expected.
+TEST(SecurityStateContentUtilsTest, CertErrorContentExplanations) {
+  // Test a modern configuration with a key exchange group.
+  security_state::SecurityInfo security_info;
+  security_info.cert_status = net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;
+  security_info.scheme_is_cryptographic = true;
+  net::SSLConnectionStatusSetCipherSuite(
+      0xcca8 /* TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 */,
+      &security_info.connection_status);
+  net::SSLConnectionStatusSetVersion(net::SSL_CONNECTION_VERSION_TLS1_2,
+                                     &security_info.connection_status);
+  security_info.key_exchange_group = 29;  // X25519
+
+  security_info.content_with_cert_errors_status =
+      security_state::CONTENT_STATUS_DISPLAYED_AND_RAN;
+  {
+    content::SecurityStyleExplanations explanations;
+    GetSecurityStyle(security_info, &explanations);
+    content::SecurityStyleExplanation explanation;
+    EXPECT_TRUE(FindSecurityStyleExplanation(
+        explanations.neutral_explanations,
+        l10n_util::GetStringUTF8(IDS_CERT_ERROR_PASSIVE_CONTENT_SUMMARY),
+        &explanation));
+    EXPECT_EQ(
+        l10n_util::GetStringUTF8(IDS_CERT_ERROR_PASSIVE_CONTENT_DESCRIPTION),
+        explanation.description);
+    EXPECT_TRUE(FindSecurityStyleExplanation(
+        explanations.insecure_explanations,
+        l10n_util::GetStringUTF8(IDS_CERT_ERROR_ACTIVE_CONTENT_SUMMARY),
+        &explanation));
+    EXPECT_EQ(
+        l10n_util::GetStringUTF8(IDS_CERT_ERROR_ACTIVE_CONTENT_DESCRIPTION),
+        explanation.description);
+  }
+
+  security_info.content_with_cert_errors_status =
+      security_state::CONTENT_STATUS_DISPLAYED;
+  {
+    content::SecurityStyleExplanations explanations;
+    GetSecurityStyle(security_info, &explanations);
+    content::SecurityStyleExplanation explanation;
+    EXPECT_TRUE(FindSecurityStyleExplanation(
+        explanations.neutral_explanations,
+        l10n_util::GetStringUTF8(IDS_CERT_ERROR_PASSIVE_CONTENT_SUMMARY),
+        &explanation));
+    ASSERT_FALSE(FindSecurityStyleExplanation(
+        explanations.insecure_explanations,
+        l10n_util::GetStringUTF8(IDS_CERT_ERROR_ACTIVE_CONTENT_SUMMARY),
+        &explanation));
+  }
+
+  security_info.content_with_cert_errors_status =
+      security_state::CONTENT_STATUS_RAN;
+  {
+    content::SecurityStyleExplanations explanations;
+    GetSecurityStyle(security_info, &explanations);
+    content::SecurityStyleExplanation explanation;
+    ASSERT_FALSE(FindSecurityStyleExplanation(
+        explanations.neutral_explanations,
+        l10n_util::GetStringUTF8(IDS_CERT_ERROR_PASSIVE_CONTENT_SUMMARY),
+        &explanation));
+    EXPECT_TRUE(FindSecurityStyleExplanation(
+        explanations.insecure_explanations,
+        l10n_util::GetStringUTF8(IDS_CERT_ERROR_ACTIVE_CONTENT_SUMMARY),
+        &explanation));
+    EXPECT_EQ(
+        l10n_util::GetStringUTF8(IDS_CERT_ERROR_ACTIVE_CONTENT_DESCRIPTION),
+        explanation.description);
+  }
+}
+
+// Test that all mixed content explanations can appear together.
+TEST(SecurityStateContentUtilsTest, MixedContentAndCertErrorExplanations) {
+  // Test a modern configuration with a key exchange group.
+  security_state::SecurityInfo security_info;
+  security_info.cert_status = net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;
+  security_info.scheme_is_cryptographic = true;
+  net::SSLConnectionStatusSetCipherSuite(
+      0xcca8 /* TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 */,
+      &security_info.connection_status);
+  net::SSLConnectionStatusSetVersion(net::SSL_CONNECTION_VERSION_TLS1_2,
+                                     &security_info.connection_status);
+  security_info.key_exchange_group = 29;  // X25519
+
+  security_info.mixed_content_status =
+      security_state::CONTENT_STATUS_DISPLAYED_AND_RAN;
+  security_info.content_with_cert_errors_status =
+      security_state::CONTENT_STATUS_DISPLAYED_AND_RAN;
+  {
+    content::SecurityStyleExplanations explanations;
+    GetSecurityStyle(security_info, &explanations);
+    content::SecurityStyleExplanation explanation;
+    EXPECT_TRUE(FindSecurityStyleExplanation(
+        explanations.neutral_explanations,
+        l10n_util::GetStringUTF8(IDS_MIXED_PASSIVE_CONTENT_SUMMARY),
+        &explanation));
+    EXPECT_TRUE(FindSecurityStyleExplanation(
+        explanations.insecure_explanations,
+        l10n_util::GetStringUTF8(IDS_MIXED_ACTIVE_CONTENT_SUMMARY),
+        &explanation));
+    EXPECT_TRUE(FindSecurityStyleExplanation(
+        explanations.neutral_explanations,
+        l10n_util::GetStringUTF8(IDS_CERT_ERROR_PASSIVE_CONTENT_SUMMARY),
+        &explanation));
+    EXPECT_TRUE(FindSecurityStyleExplanation(
+        explanations.insecure_explanations,
+        l10n_util::GetStringUTF8(IDS_CERT_ERROR_ACTIVE_CONTENT_SUMMARY),
+        &explanation));
+  }
+}
+
 // Tests that a security level of HTTP_SHOW_WARNING produces
 // blink::WebSecurityStyleNeutral and an explanation if appropriate.
 TEST(SecurityStateContentUtilsTest, HTTPWarning) {
diff --git a/components/security_state_strings.grdp b/components/security_state_strings.grdp
index 6094c157..bf8f07e 100644
--- a/components/security_state_strings.grdp
+++ b/components/security_state_strings.grdp
@@ -82,4 +82,42 @@
   <message name="IDS_SSL_KEY_EXCHANGE_WITH_GROUP" desc="A phrase to describe an SSL/TLS ECDHE-based key exchange with a group." translateable="false">
     <ph name="A_KEY_EXCHANGE">$1<ex>ECDHE_RSA</ex></ph> with <ph name="A_GROUP">$2<ex>X25519</ex></ph>
   </message>
+
+  <!-- Mixed Content -->
+  <message name="IDS_SECURE_RESOURCES_SUMMARY" desc="" translateable="false">
+    Secure resources
+  </message>
+  <message name="IDS_SECURE_RESOURCES_DESCRIPTION" desc="" translateable="false">
+    All resources on this page are served securely.
+  </message>
+  <message name="IDS_MIXED_PASSIVE_CONTENT_SUMMARY" desc="" translateable="false">
+    Mixed content
+  </message>
+  <message name="IDS_MIXED_PASSIVE_CONTENT_DESCRIPTION" desc="" translateable="false">
+    This page includes HTTP resources.
+  </message>
+  <message name="IDS_MIXED_ACTIVE_CONTENT_SUMMARY" desc="" translateable="false">
+    Active mixed content
+  </message>
+  <message name="IDS_MIXED_ACTIVE_CONTENT_DESCRIPTION" desc="" translateable="false">
+    You have recently allowed non-secure content (such as scripts or iframes) to run on this site.
+  </message>
+  <message name="IDS_CERT_ERROR_PASSIVE_CONTENT_SUMMARY" desc="" translateable="false">
+    Content with certificate errors
+  </message>
+  <message name="IDS_CERT_ERROR_PASSIVE_CONTENT_DESCRIPTION" desc="" translateable="false">
+    This page includes resources that were loaded with certificate errors.
+  </message>
+  <message name="IDS_CERT_ERROR_ACTIVE_CONTENT_SUMMARY" desc="" translateable="false">
+    Active content with certificate errors
+  </message>
+  <message name="IDS_CERT_ERROR_ACTIVE_CONTENT_DESCRIPTION" desc="" translateable="false">
+    You have recently allowed content loaded with certificate errors (such as scripts or iframes) to run on this site.
+  </message>
+  <message name="IDS_NON_SECURE_FORM_SUMMARY" desc="" translateable="false">
+    Non-secure form
+  </message>
+  <message name="IDS_NON_SECURE_FORM_DESCRIPTION" desc="" translateable="false">
+    This page includes a form with a non-secure "action" attribute.
+  </message>
 </grit-part>
diff --git a/components/signin/core/browser/BUILD.gn b/components/signin/core/browser/BUILD.gn
index b900638..5c4616a 100644
--- a/components/signin/core/browser/BUILD.gn
+++ b/components/signin/core/browser/BUILD.gn
@@ -152,10 +152,16 @@
     "fake_profile_oauth2_token_service.h",
     "fake_signin_manager.cc",
     "fake_signin_manager.h",
+    "scoped_account_consistency.cc",
+    "scoped_account_consistency.h",
     "test_signin_client.cc",
     "test_signin_client.h",
   ]
 
+  deps = [
+    "//base/test:test_support",
+  ]
+
   public_deps = [
     ":browser",
     "//base",
diff --git a/components/signin/core/browser/about_signin_internals.cc b/components/signin/core/browser/about_signin_internals.cc
index fca6fbe..8d932a5 100644
--- a/components/signin/core/browser/about_signin_internals.cc
+++ b/components/signin/core/browser/about_signin_internals.cc
@@ -6,8 +6,10 @@
 
 #include <stddef.h>
 
+#include <algorithm>
 #include <tuple>
 #include <utility>
+#include <vector>
 
 #include "base/command_line.h"
 #include "base/hash.h"
@@ -131,7 +133,7 @@
   NOTREACHED();
   return "Error";
 }
-#endif // !defined (OS_CHROMEOS)
+#endif  // !defined (OS_CHROMEOS)
 
 void SetPref(PrefService* prefs,
              TimedSigninStatusField field,
@@ -534,7 +536,7 @@
   AddSectionEntry(basic_info, "Chrome Version", product_version);
   AddSectionEntry(
       basic_info, "Account Consistency?",
-      switches::IsAccountConsistencyMirrorEnabled() == true ? "On" : "Off");
+      signin::IsAccountConsistencyMirrorEnabled() == true ? "On" : "Off");
   AddSectionEntry(basic_info, "Signin Status",
       signin_manager->IsAuthenticated() ? "Signed In" : "Not Signed In");
   OAuth2TokenServiceDelegate::LoadCredentialsState load_tokens_state =
@@ -632,7 +634,7 @@
                   "");
   }
 
-#endif // !defined(OS_CHROMEOS)
+#endif  // !defined(OS_CHROMEOS)
 
   // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
   // fixed.
diff --git a/components/signin/core/browser/account_reconcilor.cc b/components/signin/core/browser/account_reconcilor.cc
index 3393ef7..3d02ebb2a 100644
--- a/components/signin/core/browser/account_reconcilor.cc
+++ b/components/signin/core/browser/account_reconcilor.cc
@@ -240,7 +240,7 @@
 }
 
 void AccountReconcilor::PerformMergeAction(const std::string& account_id) {
-  if (!switches::IsAccountConsistencyMirrorEnabled()) {
+  if (!signin::IsAccountConsistencyMirrorEnabled()) {
     MarkAccountAsAddedToCookie(account_id);
     return;
   }
@@ -249,7 +249,7 @@
 }
 
 void AccountReconcilor::PerformLogoutAllAccountsAction() {
-  if (!switches::IsAccountConsistencyMirrorEnabled())
+  if (!signin::IsAccountConsistencyMirrorEnabled())
     return;
   VLOG(1) << "AccountReconcilor::PerformLogoutAllAccountsAction";
   cookie_manager_service_->LogOutAllAccounts(kSource);
diff --git a/components/signin/core/browser/chrome_connected_header_helper.cc b/components/signin/core/browser/chrome_connected_header_helper.cc
index 12486b6..dde5fb6 100644
--- a/components/signin/core/browser/chrome_connected_header_helper.cc
+++ b/components/signin/core/browser/chrome_connected_header_helper.cc
@@ -131,8 +131,7 @@
     return false;
 
   GURL origin(url.GetOrigin());
-  bool is_enable_account_consistency =
-      switches::IsAccountConsistencyMirrorEnabled();
+  bool is_enable_account_consistency = IsAccountConsistencyMirrorEnabled();
   bool is_google_url = is_enable_account_consistency &&
                        (google_util::IsGoogleDomainUrl(
                             url, google_util::ALLOW_SUBDOMAIN,
@@ -163,7 +162,7 @@
                          base::IntToString(profile_mode_mask).c_str()));
   parts.push_back(base::StringPrintf(
       "%s=%s", kEnableAccountConsistencyAttrName,
-      switches::IsAccountConsistencyMirrorEnabled() ? "true" : "false"));
+      IsAccountConsistencyMirrorEnabled() ? "true" : "false"));
 
   return base::JoinString(parts, is_header_request ? "," : ":");
 }
diff --git a/components/signin/core/browser/dice_header_helper.cc b/components/signin/core/browser/dice_header_helper.cc
index 4d8aade0..3591649 100644
--- a/components/signin/core/browser/dice_header_helper.cc
+++ b/components/signin/core/browser/dice_header_helper.cc
@@ -127,8 +127,7 @@
 }
 
 bool DiceHeaderHelper::IsUrlEligibleForRequestHeader(const GURL& url) {
-  if (switches::GetAccountConsistencyMethod() !=
-      switches::AccountConsistencyMethod::kDice) {
+  if (GetAccountConsistencyMethod() != AccountConsistencyMethod::kDice) {
     return false;
   }
   return gaia::IsGaiaSignonRealm(url.GetOrigin());
diff --git a/components/signin/core/browser/scoped_account_consistency.cc b/components/signin/core/browser/scoped_account_consistency.cc
new file mode 100644
index 0000000..69c9488
--- /dev/null
+++ b/components/signin/core/browser/scoped_account_consistency.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 "components/signin/core/browser/scoped_account_consistency.h"
+
+#include <map>
+#include <string>
+#include <utility>
+
+#include "base/feature_list.h"
+#include "base/logging.h"
+#include "base/test/scoped_feature_list.h"
+#include "components/signin/core/common/signin_features.h"
+
+namespace signin {
+
+ScopedAccountConsistency::ScopedAccountConsistency(
+    AccountConsistencyMethod method) {
+#if !BUILDFLAG(ENABLE_DICE_SUPPORT)
+  DCHECK_NE(AccountConsistencyMethod::kDice, method);
+  DCHECK_NE(AccountConsistencyMethod::kDiceFixAuthErrors, method);
+#endif
+
+#if BUILDFLAG(ENABLE_MIRROR)
+  DCHECK_EQ(AccountConsistencyMethod::kMirror, method);
+  return;
+#endif
+
+  if (method == AccountConsistencyMethod::kDisabled) {
+    scoped_feature_list_.InitAndDisableFeature(kAccountConsistencyFeature);
+    DCHECK_EQ(method, GetAccountConsistencyMethod());
+    return;
+  }
+
+  // Set up the account consistency method.
+  std::string feature_value;
+  switch (method) {
+    case AccountConsistencyMethod::kDisabled:
+      NOTREACHED();
+      break;
+    case AccountConsistencyMethod::kMirror:
+      feature_value = kAccountConsistencyFeatureMethodMirror;
+      break;
+    case AccountConsistencyMethod::kDiceFixAuthErrors:
+      feature_value = kAccountConsistencyFeatureMethodDiceFixAuthErrors;
+      break;
+    case AccountConsistencyMethod::kDice:
+      feature_value = kAccountConsistencyFeatureMethodDice;
+      break;
+  }
+
+  std::map<std::string, std::string> feature_params;
+  feature_params[kAccountConsistencyFeatureMethodParameter] = feature_value;
+
+  scoped_feature_list_.InitAndEnableFeatureWithParameters(
+      kAccountConsistencyFeature, feature_params);
+  DCHECK_EQ(method, GetAccountConsistencyMethod());
+}
+
+ScopedAccountConsistency::~ScopedAccountConsistency() {}
+
+ScopedAccountConsistencyMirror::ScopedAccountConsistencyMirror()
+    : scoped_mirror_(AccountConsistencyMethod::kMirror) {}
+
+ScopedAccountConsistencyDice::ScopedAccountConsistencyDice()
+    : scoped_dice_(AccountConsistencyMethod::kDice) {}
+
+}  // namespace signin
diff --git a/components/signin/core/browser/scoped_account_consistency.h b/components/signin/core/browser/scoped_account_consistency.h
new file mode 100644
index 0000000..21e5808
--- /dev/null
+++ b/components/signin/core/browser/scoped_account_consistency.h
@@ -0,0 +1,52 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_SCOPED_ACCOUNT_CONSISTENCY_H_
+#define COMPONENTS_SIGNIN_CORE_BROWSER_SCOPED_ACCOUNT_CONSISTENCY_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/test/scoped_feature_list.h"
+#include "components/signin/core/common/profile_management_switches.h"
+
+namespace signin {
+
+// Changes the account consistency method while it is in scope. Useful for
+// tests.
+class ScopedAccountConsistency {
+ public:
+  ScopedAccountConsistency(AccountConsistencyMethod method);
+
+  ~ScopedAccountConsistency();
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedAccountConsistency);
+};
+
+class ScopedAccountConsistencyMirror {
+ public:
+  ScopedAccountConsistencyMirror();
+
+ private:
+  ScopedAccountConsistency scoped_mirror_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedAccountConsistencyMirror);
+};
+
+class ScopedAccountConsistencyDice {
+ public:
+  ScopedAccountConsistencyDice();
+
+ private:
+  ScopedAccountConsistency scoped_dice_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedAccountConsistencyDice);
+};
+
+}  // namespace signin
+
+#endif  // COMPONENTS_SIGNIN_CORE_BROWSER_SCOPED_ACCOUNT_CONSISTENCY_H_
diff --git a/components/signin/core/browser/signin_header_helper_unittest.cc b/components/signin/core/browser/signin_header_helper_unittest.cc
index bade766e..3f5756ac 100644
--- a/components/signin/core/browser/signin_header_helper_unittest.cc
+++ b/components/signin/core/browser/signin_header_helper_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/strings/stringprintf.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
 #include "components/signin/core/browser/chrome_connected_header_helper.h"
+#include "components/signin/core/browser/scoped_account_consistency.h"
 #include "components/signin/core/common/profile_management_switches.h"
 #include "components/signin/core/common/signin_features.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
@@ -113,8 +114,7 @@
 // Tests that no Mirror request is returned when the user is not signed in (no
 // account id).
 TEST_F(SigninHeaderHelperTest, TestNoMirrorRequestNoAccountId) {
-  switches::EnableAccountConsistencyMirrorForTesting(
-      base::CommandLine::ForCurrentProcess());
+  ScopedAccountConsistencyMirror scoped_mirror;
   CheckMirrorHeaderRequest(GURL("https://docs.google.com"), "", "");
   CheckMirrorCookieRequest(GURL("https://docs.google.com"), "", "");
 }
@@ -122,8 +122,7 @@
 // Tests that no Mirror request is returned when the cookies aren't allowed to
 // be set.
 TEST_F(SigninHeaderHelperTest, TestNoMirrorRequestCookieSettingBlocked) {
-  switches::EnableAccountConsistencyMirrorForTesting(
-      base::CommandLine::ForCurrentProcess());
+  ScopedAccountConsistencyMirror scoped_mirror;
   cookie_settings_->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
   CheckMirrorHeaderRequest(GURL("https://docs.google.com"), "0123456789", "");
   CheckMirrorCookieRequest(GURL("https://docs.google.com"), "0123456789", "");
@@ -131,8 +130,7 @@
 
 // Tests that no Mirror request is returned when the target is a non-Google URL.
 TEST_F(SigninHeaderHelperTest, TestNoMirrorRequestExternalURL) {
-  switches::EnableAccountConsistencyMirrorForTesting(
-      base::CommandLine::ForCurrentProcess());
+  ScopedAccountConsistencyMirror scoped_mirror;
   CheckMirrorHeaderRequest(GURL("https://foo.com"), "0123456789", "");
   CheckMirrorCookieRequest(GURL("https://foo.com"), "0123456789", "");
 }
@@ -140,8 +138,7 @@
 // Tests that the Mirror request is returned without the GAIA Id when the target
 // is a google TLD domain.
 TEST_F(SigninHeaderHelperTest, TestMirrorRequestGoogleTLD) {
-  switches::EnableAccountConsistencyMirrorForTesting(
-      base::CommandLine::ForCurrentProcess());
+  ScopedAccountConsistencyMirror scoped_mirror;
   CheckMirrorHeaderRequest(GURL("https://google.fr"), "0123456789",
                            "mode=0,enable_account_consistency=true");
   CheckMirrorCookieRequest(GURL("https://google.de"), "0123456789",
@@ -151,8 +148,7 @@
 // Tests that the Mirror request is returned when the target is the domain
 // google.com, and that the GAIA Id is only attached for the cookie.
 TEST_F(SigninHeaderHelperTest, TestMirrorRequestGoogleCom) {
-  switches::EnableAccountConsistencyMirrorForTesting(
-      base::CommandLine::ForCurrentProcess());
+  ScopedAccountConsistencyMirror scoped_mirror;
   CheckMirrorHeaderRequest(GURL("https://www.google.com"), "0123456789",
                            "mode=0,enable_account_consistency=true");
   CheckMirrorCookieRequest(
@@ -167,7 +163,7 @@
 // Tests that the Mirror request is returned when the target is a Gaia URL, even
 // if account consistency is disabled.
 TEST_F(SigninHeaderHelperTest, TestMirrorRequestGaiaURL) {
-  ASSERT_FALSE(switches::IsAccountConsistencyMirrorEnabled());
+  ASSERT_FALSE(IsAccountConsistencyMirrorEnabled());
   CheckMirrorHeaderRequest(GURL("https://accounts.google.com"), "0123456789",
                            "mode=0,enable_account_consistency=false");
   CheckMirrorCookieRequest(
@@ -177,8 +173,7 @@
 
 // Tests Dice requests.
 TEST_F(SigninHeaderHelperTest, TestDiceRequest) {
-  switches::EnableAccountConsistencyDiceForTesting(
-      base::CommandLine::ForCurrentProcess());
+  ScopedAccountConsistencyDice scoped_dice;
   // ChromeConnected but no Dice for Docs URLs.
   CheckDiceHeaderRequest(
       GURL("https://docs.google.com"), "0123456789", false /* sync_enabled */,
@@ -206,8 +201,7 @@
 
 // Tests that no Dice request is returned when Dice is not enabled.
 TEST_F(SigninHeaderHelperTest, TestNoDiceRequestWhenDisabled) {
-  switches::EnableAccountConsistencyMirrorForTesting(
-      base::CommandLine::ForCurrentProcess());
+  ScopedAccountConsistencyMirror scoped_mirror;
   CheckDiceHeaderRequest(GURL("https://accounts.google.com"), "0123456789",
                          false /* sync_enabled */,
                          "mode=0,enable_account_consistency=true", "");
@@ -216,7 +210,7 @@
 // Tests that the Mirror request is returned with the GAIA Id on Drive origin,
 // even if account consistency is disabled.
 TEST_F(SigninHeaderHelperTest, TestMirrorRequestDrive) {
-  ASSERT_FALSE(switches::IsAccountConsistencyMirrorEnabled());
+  ASSERT_FALSE(IsAccountConsistencyMirrorEnabled());
   CheckMirrorHeaderRequest(
       GURL("https://docs.google.com/document"), "0123456789",
       "id=0123456789,mode=0,enable_account_consistency=false");
@@ -225,8 +219,7 @@
       "id=0123456789:mode=0:enable_account_consistency=false");
 
   // Enable Account Consistency will override the disable.
-  switches::EnableAccountConsistencyMirrorForTesting(
-      base::CommandLine::ForCurrentProcess());
+  ScopedAccountConsistencyMirror scoped_mirror;
   CheckMirrorHeaderRequest(
       GURL("https://docs.google.com/document"), "0123456789",
       "id=0123456789,mode=0,enable_account_consistency=true");
@@ -329,8 +322,7 @@
 // Tests that the Mirror header request is returned normally when the redirect
 // URL is eligible.
 TEST_F(SigninHeaderHelperTest, TestMirrorHeaderEligibleRedirectURL) {
-  switches::EnableAccountConsistencyMirrorForTesting(
-      base::CommandLine::ForCurrentProcess());
+  ScopedAccountConsistencyMirror scoped_mirror;
   const GURL url("https://docs.google.com/document");
   const GURL redirect_url("https://www.google.com");
   const std::string account_id = "0123456789";
@@ -347,8 +339,7 @@
 // Tests that the Mirror header request is stripped when the redirect URL is not
 // eligible.
 TEST_F(SigninHeaderHelperTest, TestMirrorHeaderNonEligibleRedirectURL) {
-  switches::EnableAccountConsistencyMirrorForTesting(
-      base::CommandLine::ForCurrentProcess());
+  ScopedAccountConsistencyMirror scoped_mirror;
   const GURL url("https://docs.google.com/document");
   const GURL redirect_url("http://www.foo.com");
   const std::string account_id = "0123456789";
@@ -365,8 +356,7 @@
 // Tests that the Mirror header, whatever its value is, is untouched when both
 // the current and the redirect URL are non-eligible.
 TEST_F(SigninHeaderHelperTest, TestIgnoreMirrorHeaderNonEligibleURLs) {
-  switches::EnableAccountConsistencyMirrorForTesting(
-      base::CommandLine::ForCurrentProcess());
+  ScopedAccountConsistencyMirror scoped_mirror;
   const GURL url("https://www.bar.com");
   const GURL redirect_url("http://www.foo.com");
   const std::string account_id = "0123456789";
diff --git a/components/signin/core/common/profile_management_switches.cc b/components/signin/core/common/profile_management_switches.cc
index 61dd356..7cb7313 100644
--- a/components/signin/core/common/profile_management_switches.cc
+++ b/components/signin/core/common/profile_management_switches.cc
@@ -7,25 +7,39 @@
 #include <string>
 
 #include "base/command_line.h"
-#include "base/feature_list.h"
-#include "base/metrics/field_trial.h"
+#include "base/metrics/field_trial_params.h"
 #include "build/build_config.h"
+#include "components/signin/core/common/signin_features.h"
 #include "components/signin/core/common/signin_switches.h"
 
-namespace switches {
+namespace signin {
+
+// base::Feature definitions.
+const base::Feature kAccountConsistencyFeature{
+    "AccountConsistency", base::FEATURE_DISABLED_BY_DEFAULT};
+const char kAccountConsistencyFeatureMethodParameter[] = "method";
+const char kAccountConsistencyFeatureMethodMirror[] = "mirror";
+const char kAccountConsistencyFeatureMethodDiceFixAuthErrors[] =
+    "dice_fix_auth_errors";
+const char kAccountConsistencyFeatureMethodDice[] = "dice";
 
 AccountConsistencyMethod GetAccountConsistencyMethod() {
 #if BUILDFLAG(ENABLE_MIRROR)
-  // Mirror is enabled on Android and iOS.
+  // Mirror is always enabled on Android and iOS.
   return AccountConsistencyMethod::kMirror;
 #else
-  base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
-  std::string method = cmd->GetSwitchValueASCII(switches::kAccountConsistency);
-  if (method == switches::kAccountConsistencyMirror)
-    return AccountConsistencyMethod::kMirror;
+  if (!base::FeatureList::IsEnabled(kAccountConsistencyFeature))
+    return AccountConsistencyMethod::kDisabled;
 
+  std::string method_value = base::GetFieldTrialParamValueByFeature(
+      kAccountConsistencyFeature, kAccountConsistencyFeatureMethodParameter);
+
+  if (method_value == kAccountConsistencyFeatureMethodMirror)
+    return AccountConsistencyMethod::kMirror;
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
-  if (method == switches::kAccountConsistencyDice)
+  else if (method_value == kAccountConsistencyFeatureMethodDiceFixAuthErrors)
+    return AccountConsistencyMethod::kDiceFixAuthErrors;
+  else if (method_value == kAccountConsistencyFeatureMethodDice)
     return AccountConsistencyMethod::kDice;
 #endif
 
@@ -38,7 +52,7 @@
 }
 
 bool IsAccountConsistencyDiceEnabled() {
-  return GetAccountConsistencyMethod() == AccountConsistencyMethod::kDice;
+  return (GetAccountConsistencyMethod() == AccountConsistencyMethod::kDice);
 }
 
 bool IsExtensionsMultiAccount() {
@@ -53,18 +67,4 @@
          GetAccountConsistencyMethod() == AccountConsistencyMethod::kMirror;
 }
 
-void EnableAccountConsistencyMirrorForTesting(base::CommandLine* command_line) {
-#if !BUILDFLAG(ENABLE_MIRROR)
-  command_line->AppendSwitchASCII(switches::kAccountConsistency,
-                                  switches::kAccountConsistencyMirror);
-#endif
-}
-
-#if BUILDFLAG(ENABLE_DICE_SUPPORT)
-void EnableAccountConsistencyDiceForTesting(base::CommandLine* command_line) {
-  command_line->AppendSwitchASCII(switches::kAccountConsistency,
-                                  switches::kAccountConsistencyDice);
-}
-#endif
-
-}  // namespace switches
+}  // namespace signin
diff --git a/components/signin/core/common/profile_management_switches.h b/components/signin/core/common/profile_management_switches.h
index 9642ef5..9677250 100644
--- a/components/signin/core/common/profile_management_switches.h
+++ b/components/signin/core/common/profile_management_switches.h
@@ -9,18 +9,28 @@
 #ifndef COMPONENTS_SIGNIN_CORE_COMMON_PROFILE_MANAGEMENT_SWITCHES_H_
 #define COMPONENTS_SIGNIN_CORE_COMMON_PROFILE_MANAGEMENT_SWITCHES_H_
 
-#include "components/signin/core/common/signin_features.h"
+#include "base/feature_list.h"
 
-namespace base {
-class CommandLine;
-}
+namespace signin {
 
-namespace switches {
+// Account consistency feature. Only used on platforms where Mirror is not
+// always enabled (ENABLE_MIRROR is false).
+extern const base::Feature kAccountConsistencyFeature;
+
+// The account consistency method parameter name.
+extern const char kAccountConsistencyFeatureMethodParameter[];
+
+// Account consistency method values.
+extern const char kAccountConsistencyFeatureMethodMirror[];
+extern const char kAccountConsistencyFeatureMethodDiceFixAuthErrors[];
+extern const char kAccountConsistencyFeatureMethodDice[];
 
 enum class AccountConsistencyMethod {
-  kDisabled,  // No account consistency.
-  kMirror,    // Account management UI in the avatar bubble.
-  kDice       // Account management UI on Gaia webpages.
+  kDisabled,           // No account consistency.
+  kMirror,             // Account management UI in the avatar bubble.
+  kDiceFixAuthErrors,  // No account consistency, but Dice fixes authentication
+                       // errors.
+  kDice                // Account management UI on Gaia webpages.
 };
 
 // Returns the account consistency method.
@@ -32,19 +42,12 @@
 
 // Checks whether Dice account consistency is enabled. If enabled, then account
 // management UI is available on the Gaia webpages.
+// Returns true when the account consistency method is kDice.
 bool IsAccountConsistencyDiceEnabled();
 
 // Whether the chrome.identity API should be multi-account.
 bool IsExtensionsMultiAccount();
 
-// Called in tests to force enable Mirror account consistency.
-void EnableAccountConsistencyMirrorForTesting(base::CommandLine* command_line);
-
-#if BUILDFLAG(ENABLE_DICE_SUPPORT)
-// Called in tests to force enable Dice account consistency.
-void EnableAccountConsistencyDiceForTesting(base::CommandLine* command_line);
-#endif
-
-}  // namespace switches
+}  // namespace signin
 
 #endif  // COMPONENTS_SIGNIN_CORE_COMMON_PROFILE_MANAGEMENT_SWITCHES_H_
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc
index 5c578c41..80e4a02 100644
--- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc
+++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc
@@ -113,6 +113,8 @@
     NotifyResult();
     return content::NavigationThrottle::ThrottleCheckResult::PROCEED;
   }
+  CHECK(!deferring_);
+  deferring_ = true;
   defer_time_ = base::TimeTicks::Now();
   return content::NavigationThrottle::ThrottleCheckResult::DEFER;
 }
@@ -129,10 +131,12 @@
   DCHECK_LT(request_id, check_results_.size());
 
   auto& stored_result = check_results_.at(request_id);
-  DCHECK(!stored_result.finished);
+  CHECK(!stored_result.finished);
   stored_result = result;
-  if (!defer_time_.is_null() && request_id == check_results_.size() - 1) {
+  if (deferring_ && request_id == check_results_.size() - 1) {
     NotifyResult();
+
+    deferring_ = false;
     Resume();
   }
 }
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.h b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.h
index 774ec62..f7c179c8 100644
--- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.h
+++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.h
@@ -80,7 +80,6 @@
 
   std::vector<SubresourceFilterSafeBrowsingClient::CheckResult> check_results_;
 
-  scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> database_manager_;
   scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
 
   std::unique_ptr<SubresourceFilterSafeBrowsingClient,
@@ -94,6 +93,10 @@
   // WillProcessResponse. If deferral was not necessary, will remain null.
   base::TimeTicks defer_time_;
 
+  // Whether this throttle is deferring the navigation. Only set to true in
+  // WillProcessResponse if there are ongoing safe browsing checks.
+  bool deferring_ = false;
+
   // Added to investigate crbug.com/733099.
   bool will_start_request_called_ = false;
 
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc
index 93ec0ff..81743ad6 100644
--- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc
+++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc
@@ -947,14 +947,9 @@
   tester().ExpectTotalCount(kSafeBrowsingCheckTime, 1);
 }
 
-// Flaky on Win only.  http://crbug.com/748524
-#if defined(OS_WIN)
-#define MAYBE_ListMatchedOnStart_NoDelay DISABLED_ListMatchedOnStart_NoDelay
-#else
-#define MAYBE_ListMatchedOnStart_NoDelay ListMatchedOnStart_NoDelay
-#endif
+// Flaky on Win, Chromium and Linux. http://crbug.com/748524
 TEST_P(SubresourceFilterSafeBrowsingActivationThrottleParamTest,
-       MAYBE_ListMatchedOnStart_NoDelay) {
+       DISABLED_ListMatchedOnStart_NoDelay) {
   const ActivationListTestData& test_data = GetParam();
   const GURL url(kURL);
   ConfigureForMatchParam(url);
@@ -977,15 +972,9 @@
   tester().ExpectTotalCount(kSafeBrowsingNavigationDelayNoSpeculation, 1);
 }
 
-// Flaky on Win only.  http://crbug.com/748524
-#if defined(OS_WIN)
-#define MAYBE_ListMatchedOnRedirect_NoDelay \
-  DISABLED_ListMatchedOnRedirect_NoDelay
-#else
-#define MAYBE_ListMatchedOnRedirect_NoDelay ListMatchedOnRedirect_NoDelay
-#endif
+// Flaky on Win, Chromium and Linux. http://crbug.com/748524
 TEST_P(SubresourceFilterSafeBrowsingActivationThrottleParamTest,
-       MAYBE_ListMatchedOnRedirect_NoDelay) {
+       DISABLED_ListMatchedOnRedirect_NoDelay) {
   const ActivationListTestData& test_data = GetParam();
   const GURL url(kURL);
   const GURL redirect_url(kRedirectURL);
diff --git a/components/sync/user_events/user_event_sync_bridge.cc b/components/sync/user_events/user_event_sync_bridge.cc
index fe469cca..892bd20 100644
--- a/components/sync/user_events/user_event_sync_bridge.cc
+++ b/components/sync/user_events/user_event_sync_bridge.cc
@@ -149,6 +149,11 @@
 
 void UserEventSyncBridge::RecordUserEvent(
     std::unique_ptr<UserEventSpecifics> specifics) {
+  // TODO(skym): Remove this when ModelTypeStore synchronously returns a
+  // partially initialized reference, see crbug.com/709094.
+  if (!store_) {
+    return;
+  }
   std::string storage_key = GetStorageKeyFromSpecifics(*specifics);
 
   // There are two scenarios we need to guard against here. First, the given
diff --git a/content/browser/accessibility/accessibility_event_recorder_win.cc b/content/browser/accessibility/accessibility_event_recorder_win.cc
index c236671..77f6715a6 100644
--- a/content/browser/accessibility/accessibility_event_recorder_win.cc
+++ b/content/browser/accessibility/accessibility_event_recorder_win.cc
@@ -180,7 +180,7 @@
   hr = browser_accessible->get_accChild(childid_variant,
                                         dispatch.GetAddressOf());
   if (!SUCCEEDED(hr) || !dispatch) {
-    VLOG(1) << "Ignoring result " << hr << " and result " << dispatch
+    VLOG(1) << "Ignoring result " << hr << " and result " << dispatch.Get()
             << " from get_accChild";
     return;
   }
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc
index 6a01f3d4..3824914 100644
--- a/content/browser/accessibility/browser_accessibility.cc
+++ b/content/browser/accessibility/browser_accessibility.cc
@@ -17,11 +17,20 @@
 #include "content/common/accessibility_messages.h"
 #include "ui/accessibility/ax_role_properties.h"
 #include "ui/accessibility/ax_text_utils.h"
+#include "ui/accessibility/platform/ax_platform_unique_id.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 #include "ui/gfx/geometry/rect_f.h"
 
 namespace content {
 
+namespace {
+
+// Map from unique_id to BrowserAccessibility
+using UniqueIDMap = base::hash_map<int32_t, BrowserAccessibility*>;
+base::LazyInstance<UniqueIDMap>::DestructorAtExit g_unique_id_map =
+    LAZY_INSTANCE_INITIALIZER;
+}
+
 #if !defined(PLATFORM_HAS_NATIVE_ACCESSIBILITY_IMPL)
 // static
 BrowserAccessibility* BrowserAccessibility::Create() {
@@ -30,9 +39,24 @@
 #endif
 
 BrowserAccessibility::BrowserAccessibility()
-    : manager_(nullptr), node_(nullptr) {}
+    : manager_(nullptr),
+      node_(nullptr),
+      unique_id_(ui::GetNextAXPlatformNodeUniqueId()) {
+  g_unique_id_map.Get()[unique_id_] = this;
+}
 
 BrowserAccessibility::~BrowserAccessibility() {
+  if (unique_id_)
+    g_unique_id_map.Get().erase(unique_id_);
+}
+
+// static
+BrowserAccessibility* BrowserAccessibility::GetFromUniqueID(int32_t unique_id) {
+  auto iter = g_unique_id_map.Get().find(unique_id);
+  if (iter == g_unique_id_map.Get().end())
+    return nullptr;
+
+  return iter->second;
 }
 
 void BrowserAccessibility::Init(BrowserAccessibilityManager* manager,
@@ -549,6 +573,10 @@
   node_ = NULL;
   manager_ = NULL;
 
+  if (unique_id_)
+    g_unique_id_map.Get().erase(unique_id_);
+  unique_id_ = 0;
+
   NativeReleaseReference();
 }
 
diff --git a/content/browser/accessibility/browser_accessibility.h b/content/browser/accessibility/browser_accessibility.h
index 7801e01..e790989 100644
--- a/content/browser/accessibility/browser_accessibility.h
+++ b/content/browser/accessibility/browser_accessibility.h
@@ -75,6 +75,8 @@
 
   virtual ~BrowserAccessibility();
 
+  static BrowserAccessibility* GetFromUniqueID(int32_t unique_id);
+
   // Called only once, immediately after construction. The constructor doesn't
   // take any arguments because in the Windows subclass we use a special
   // function to construct a COM object.
@@ -205,6 +207,7 @@
   BrowserAccessibilityManager* manager() const { return manager_; }
   bool instance_active() const { return node_ && manager_; }
   ui::AXNode* node() const { return node_; }
+  int32_t unique_id() const { return unique_id_; }
 
   // These access the internal accessibility tree, which doesn't necessarily
   // reflect the accessibility tree that should be exposed on each platform.
diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc
index e51f201..66c5910 100644
--- a/content/browser/accessibility/browser_accessibility_android.cc
+++ b/content/browser/accessibility/browser_accessibility_android.cc
@@ -4,9 +4,7 @@
 
 #include "content/browser/accessibility/browser_accessibility_android.h"
 
-#include "base/containers/hash_tables.h"
 #include "base/i18n/break_iterator.h"
-#include "base/lazy_instance.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
@@ -18,7 +16,6 @@
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/accessibility/ax_role_properties.h"
 #include "ui/accessibility/platform/ax_android_constants.h"
-#include "ui/accessibility/platform/ax_platform_unique_id.h"
 #include "ui/accessibility/platform/ax_snapshot_node_android_platform.h"
 
 namespace aria_strings {
@@ -65,33 +62,10 @@
   return new BrowserAccessibilityAndroid();
 }
 
-using UniqueIdMap = base::hash_map<int32_t, BrowserAccessibilityAndroid*>;
-// Map from each AXPlatformNode's unique id to its instance.
-base::LazyInstance<UniqueIdMap>::DestructorAtExit g_unique_id_map =
-    LAZY_INSTANCE_INITIALIZER;
-
-// static
-BrowserAccessibilityAndroid* BrowserAccessibilityAndroid::GetFromUniqueId(
-    int32_t unique_id) {
-  UniqueIdMap* unique_ids = g_unique_id_map.Pointer();
-  auto iter = unique_ids->find(unique_id);
-  if (iter != unique_ids->end())
-    return iter->second;
-
-  return nullptr;
-}
-
-BrowserAccessibilityAndroid::BrowserAccessibilityAndroid()
-    : unique_id_(ui::GetNextAXPlatformNodeUniqueId()) {
-  g_unique_id_map.Get()[unique_id_] = this;
+BrowserAccessibilityAndroid::BrowserAccessibilityAndroid() {
   first_time_ = true;
 }
 
-BrowserAccessibilityAndroid::~BrowserAccessibilityAndroid() {
-  if (unique_id_)
-    g_unique_id_map.Get().erase(unique_id_);
-}
-
 bool BrowserAccessibilityAndroid::IsNative() const {
   return true;
 }
diff --git a/content/browser/accessibility/browser_accessibility_android.h b/content/browser/accessibility/browser_accessibility_android.h
index 823a18c..d9e5ad0 100644
--- a/content/browser/accessibility/browser_accessibility_android.h
+++ b/content/browser/accessibility/browser_accessibility_android.h
@@ -11,15 +11,11 @@
 #include "base/android/scoped_java_ref.h"
 #include "base/macros.h"
 #include "content/browser/accessibility/browser_accessibility.h"
-#include "ui/accessibility/platform/ax_platform_node.h"
 
 namespace content {
 
 class CONTENT_EXPORT BrowserAccessibilityAndroid : public BrowserAccessibility {
  public:
-  static BrowserAccessibilityAndroid* GetFromUniqueId(int32_t unique_id);
-  int32_t unique_id() const { return unique_id_; }
-
   // Overrides from BrowserAccessibility.
   void OnDataChanged() override;
   bool IsNative() const override;
@@ -141,7 +137,6 @@
   friend class BrowserAccessibility;
 
   BrowserAccessibilityAndroid();
-  ~BrowserAccessibilityAndroid() override;
 
   bool HasOnlyTextChildren() const;
   bool HasOnlyTextAndImageChildren() const;
@@ -162,7 +157,6 @@
   bool first_time_;
   base::string16 old_value_;
   base::string16 new_value_;
-  int32_t unique_id_;
 
   DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityAndroid);
 };
diff --git a/content/browser/accessibility/browser_accessibility_com_win.cc b/content/browser/accessibility/browser_accessibility_com_win.cc
index 41d1523..2abae58 100644
--- a/content/browser/accessibility/browser_accessibility_com_win.cc
+++ b/content/browser/accessibility/browser_accessibility_com_win.cc
@@ -137,7 +137,7 @@
   if (!unique_id)
     return E_INVALIDARG;
 
-  *unique_id = -AXPlatformNodeWin::unique_id();
+  *unique_id = -owner()->unique_id();
   return S_OK;
 }
 
@@ -1249,8 +1249,8 @@
   }
 
   int32_t id = hyperlinks()[index];
-  auto* link = static_cast<BrowserAccessibilityComWin*>(
-      AXPlatformNodeWin::GetFromUniqueId(id));
+  BrowserAccessibilityComWin* link =
+      ToBrowserAccessibilityComWin(owner()->GetFromUniqueID(id));
   if (!link)
     return E_FAIL;
 
@@ -1708,7 +1708,7 @@
   *name_space_id = 0;
   *node_value = SysAllocString(value().c_str());
   *num_children = owner()->PlatformChildCount();
-  *unique_id = -AXPlatformNodeWin::unique_id();
+  *unique_id = -owner()->unique_id();
 
   if (owner()->IsDocument()) {
     *node_type = NODETYPE_DOCUMENT;
@@ -2462,7 +2462,7 @@
       win_attributes_->hypertext += child->name();
     } else {
       int32_t char_offset = static_cast<int32_t>(owner()->GetText().size());
-      int32_t child_unique_id = child->unique_id();
+      int32_t child_unique_id = child->owner()->unique_id();
       int32_t index = hyperlinks().size();
       win_attributes_->hyperlink_offset_to_index[char_offset] = index;
       win_attributes_->hyperlinks.push_back(child_unique_id);
@@ -2577,6 +2577,12 @@
   AXPlatformNodeBase::Init(delegate);
 }
 
+ui::AXPlatformNode* BrowserAccessibilityComWin::GetFromUniqueId(
+    int32_t unique_id) {
+  return ToBrowserAccessibilityComWin(
+      BrowserAccessibility::GetFromUniqueID(unique_id));
+}
+
 std::vector<base::string16> BrowserAccessibilityComWin::ComputeTextAttributes()
     const {
   std::vector<base::string16> attributes;
@@ -2825,8 +2831,8 @@
     return ToBrowserAccessibilityComWin(
         owner()->PlatformGetChild(child_id - 1));
 
-  auto* child = static_cast<BrowserAccessibilityComWin*>(
-      AXPlatformNodeWin::GetFromUniqueId(-child_id));
+  BrowserAccessibilityComWin* child = ToBrowserAccessibilityComWin(
+      BrowserAccessibility::GetFromUniqueID(-child_id));
   if (child && child->owner()->IsDescendantOf(owner()))
     return child;
 
@@ -2900,8 +2906,8 @@
   DCHECK_GE(index, 0);
   DCHECK_LT(index, static_cast<int32_t>(hyperlinks().size()));
   int32_t id = hyperlinks()[index];
-  auto* hyperlink = static_cast<BrowserAccessibilityComWin*>(
-      AXPlatformNodeWin::GetFromUniqueId(id));
+  BrowserAccessibilityComWin* hyperlink =
+      ToBrowserAccessibilityComWin(owner()->GetFromUniqueID(id));
   if (!hyperlink)
     return nullptr;
   return hyperlink;
@@ -2912,8 +2918,8 @@
   if (hyperlinks().empty())
     return -1;
 
-  auto iterator =
-      std::find(hyperlinks().begin(), hyperlinks().end(), child.unique_id());
+  auto iterator = std::find(hyperlinks().begin(), hyperlinks().end(),
+                            child.owner()->unique_id());
   if (iterator == hyperlinks().end())
     return -1;
 
diff --git a/content/browser/accessibility/browser_accessibility_com_win.h b/content/browser/accessibility/browser_accessibility_com_win.h
index ac269da..22e13a6 100644
--- a/content/browser/accessibility/browser_accessibility_com_win.h
+++ b/content/browser/accessibility/browser_accessibility_com_win.h
@@ -654,6 +654,7 @@
   //
   void Destroy() override;
   void Init(ui::AXPlatformNodeDelegate* delegate) override;
+  AXPlatformNode* GetFromUniqueId(int32_t unique_id) override;
 
   // Returns the IA2 text attributes for this object.
   std::vector<base::string16> ComputeTextAttributes() const;
diff --git a/content/browser/accessibility/browser_accessibility_event.cc b/content/browser/accessibility/browser_accessibility_event.cc
index 555688d..24fa9ed 100644
--- a/content/browser/accessibility/browser_accessibility_event.cc
+++ b/content/browser/accessibility/browser_accessibility_event.cc
@@ -140,6 +140,7 @@
           << " " << event_name
           << " result=" << result_str
           << " source=" << source_str
+          << " unique_id=" << target_->unique_id()
           << " target=[["
           << ReplaceNewlines(target_->GetData().ToString()) << "]]"
           << original_target_str;
diff --git a/content/browser/accessibility/browser_accessibility_manager_android.cc b/content/browser/accessibility/browser_accessibility_manager_android.cc
index 1677bb11..5221f93 100644
--- a/content/browser/accessibility/browser_accessibility_manager_android.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -113,7 +113,7 @@
   // Always send AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED to notify
   // the Android system that the accessibility hierarchy rooted at this
   // node has changed.
-  wcax->HandleContentChanged(android_node->unique_id());
+  wcax->HandleContentChanged(node->unique_id());
 
   // Ignore load complete events on iframes.
   if (event_type == ui::AX_EVENT_LOAD_COMPLETE &&
@@ -122,25 +122,23 @@
   }
 
   switch (event_type) {
-    case ui::AX_EVENT_LOAD_COMPLETE: {
-      auto* android_focused =
-          static_cast<BrowserAccessibilityAndroid*>(GetFocus());
-      wcax->HandlePageLoaded(android_focused->unique_id());
-    } break;
+    case ui::AX_EVENT_LOAD_COMPLETE:
+      wcax->HandlePageLoaded(GetFocus()->unique_id());
+      break;
     case ui::AX_EVENT_FOCUS:
-      wcax->HandleFocusChanged(android_node->unique_id());
+      wcax->HandleFocusChanged(node->unique_id());
       break;
     case ui::AX_EVENT_CHECKED_STATE_CHANGED:
-      wcax->HandleCheckStateChanged(android_node->unique_id());
+      wcax->HandleCheckStateChanged(node->unique_id());
       break;
     case ui::AX_EVENT_CLICKED:
-      wcax->HandleClicked(android_node->unique_id());
+      wcax->HandleClicked(node->unique_id());
       break;
     case ui::AX_EVENT_SCROLL_POSITION_CHANGED:
-      wcax->HandleScrollPositionChanged(android_node->unique_id());
+      wcax->HandleScrollPositionChanged(node->unique_id());
       break;
     case ui::AX_EVENT_SCROLLED_TO_ANCHOR:
-      wcax->HandleScrolledToAnchor(android_node->unique_id());
+      wcax->HandleScrolledToAnchor(node->unique_id());
       break;
     case ui::AX_EVENT_ALERT:
       // An alert is a special case of live region. Fall through to the
@@ -153,14 +151,14 @@
       break;
     }
     case ui::AX_EVENT_TEXT_SELECTION_CHANGED:
-      wcax->HandleTextSelectionChanged(android_node->unique_id());
+      wcax->HandleTextSelectionChanged(node->unique_id());
       break;
     case ui::AX_EVENT_TEXT_CHANGED:
     case ui::AX_EVENT_VALUE_CHANGED:
       if (android_node->IsEditableText() && GetFocus() == node) {
-        wcax->HandleEditableTextChanged(android_node->unique_id());
+        wcax->HandleEditableTextChanged(node->unique_id());
       } else if (android_node->IsSlider()) {
-        wcax->HandleSliderChanged(android_node->unique_id());
+        wcax->HandleSliderChanged(node->unique_id());
       }
       break;
     default:
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.cc b/content/browser/accessibility/browser_accessibility_manager_win.cc
index 8ca0562..bc7c074 100644
--- a/content/browser/accessibility/browser_accessibility_manager_win.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -202,7 +202,7 @@
   // argument to NotifyWinEvent; the AT client will then call get_accChild
   // on the HWND's accessibility object and pass it that same id, which
   // we can use to retrieve the IAccessible for this node.
-  LONG child_id = -(ToBrowserAccessibilityWin(target)->GetCOM()->unique_id());
+  LONG child_id = -target->unique_id();
   ::NotifyWinEvent(win_event_type, hwnd, OBJID_CLIENT, child_id);
   return BrowserAccessibilityEvent::Sent;
 }
diff --git a/content/browser/accessibility/browser_accessibility_win_unittest.cc b/content/browser/accessibility/browser_accessibility_win_unittest.cc
index a043878..c3b9672 100644
--- a/content/browser/accessibility/browser_accessibility_win_unittest.cc
+++ b/content/browser/accessibility/browser_accessibility_win_unittest.cc
@@ -22,7 +22,6 @@
 #include "content/common/accessibility_messages.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/accessibility/platform/ax_platform_node_win.h"
 #include "ui/base/win/atl_module.h"
 
 namespace content {
@@ -705,11 +704,6 @@
   manager.reset();
 }
 
-int32_t GetUniqueId(BrowserAccessibility* accessibility) {
-  BrowserAccessibilityWin* win_root = ToBrowserAccessibilityWin(accessibility);
-  return win_root->GetCOM()->unique_id();
-}
-
 // This is a regression test for a bug where the initial empty document
 // loaded by a BrowserAccessibilityManagerWin couldn't be looked up by
 // its UniqueIDWin, because the AX Tree was loaded in
@@ -727,14 +721,8 @@
   EXPECT_EQ(ui::AX_ROLE_ROOT_WEB_AREA, root->GetRole());
   EXPECT_EQ(1 << ui::AX_STATE_BUSY, root->GetState());
 
-  BrowserAccessibilityWin* win_root = ToBrowserAccessibilityWin(root);
-
-  ui::AXPlatformNode* node = static_cast<ui::AXPlatformNode*>(
-      ui::AXPlatformNodeWin::GetFromUniqueId(GetUniqueId(win_root)));
-
-  ui::AXPlatformNode* other_node =
-      static_cast<ui::AXPlatformNode*>(win_root->GetCOM());
-  ASSERT_EQ(node, other_node);
+  int32_t unique_id = ToBrowserAccessibilityWin(root)->unique_id();
+  ASSERT_EQ(root, BrowserAccessibility::GetFromUniqueID(unique_id));
 }
 
 TEST_F(BrowserAccessibilityTest, TestIA2Attributes) {
@@ -2189,18 +2177,18 @@
           new BrowserAccessibilityFactory()));
 
   BrowserAccessibility* root = manager->GetRoot();
-  int32_t root_unique_id = GetUniqueId(root);
+  int32_t root_unique_id = root->unique_id();
   BrowserAccessibility* child = root->PlatformGetChild(0);
-  int32_t child_unique_id = GetUniqueId(child);
+  int32_t child_unique_id = child->unique_id();
 
   // Now destroy that original tree and create a new tree.
   manager.reset(new BrowserAccessibilityManagerWin(
       MakeAXTreeUpdate(root_node, child_node), nullptr,
       new BrowserAccessibilityFactory()));
   root = manager->GetRoot();
-  int32_t root_unique_id_2 = GetUniqueId(root);
+  int32_t root_unique_id_2 = root->unique_id();
   child = root->PlatformGetChild(0);
-  int32_t child_unique_id_2 = GetUniqueId(child);
+  int32_t child_unique_id_2 = child->unique_id();
 
   // The nodes in the new tree should not have the same ids.
   EXPECT_NE(root_unique_id, root_unique_id_2);
@@ -2250,13 +2238,13 @@
   BrowserAccessibility* root = manager->GetRoot();
   BrowserAccessibility* child = root->PlatformGetChild(0);
 
-  base::win::ScopedVariant root_unique_id_variant(-GetUniqueId(root));
+  base::win::ScopedVariant root_unique_id_variant(-root->unique_id());
   base::win::ScopedComPtr<IDispatch> result;
   EXPECT_EQ(E_INVALIDARG,
             ToBrowserAccessibilityWin(child)->GetCOM()->get_accChild(
                 root_unique_id_variant, result.GetAddressOf()));
 
-  base::win::ScopedVariant child_unique_id_variant(-GetUniqueId(child));
+  base::win::ScopedVariant child_unique_id_variant(-child->unique_id());
   EXPECT_EQ(S_OK, ToBrowserAccessibilityWin(root)->GetCOM()->get_accChild(
                       child_unique_id_variant, result.GetAddressOf()));
 }
@@ -2320,7 +2308,7 @@
       describedby_relation->get_target(0, target.GetAddressOf()));
   target.CopyTo(ax_target.GetAddressOf());
   EXPECT_HRESULT_SUCCEEDED(ax_target->get_uniqueID(&unique_id));
-  EXPECT_EQ(-GetUniqueId(ax_child1), unique_id);
+  EXPECT_EQ(-ax_child1->unique_id(), unique_id);
   ax_target.Reset();
   target.Reset();
 
@@ -2328,7 +2316,7 @@
       describedby_relation->get_target(1, target.GetAddressOf()));
   target.CopyTo(ax_target.GetAddressOf());
   EXPECT_HRESULT_SUCCEEDED(ax_target->get_uniqueID(&unique_id));
-  EXPECT_EQ(-GetUniqueId(ax_child2), unique_id);
+  EXPECT_EQ(-ax_child2->unique_id(), unique_id);
   ax_target.Reset();
   target.Reset();
   describedby_relation.Reset();
@@ -2351,7 +2339,7 @@
       description_for_relation->get_target(0, target.GetAddressOf()));
   target.CopyTo(ax_target.GetAddressOf());
   EXPECT_HRESULT_SUCCEEDED(ax_target->get_uniqueID(&unique_id));
-  EXPECT_EQ(-GetUniqueId(ax_root), unique_id);
+  EXPECT_EQ(-ax_root->unique_id(), unique_id);
   ax_target.Reset();
   target.Reset();
   description_for_relation.Reset();
@@ -2373,7 +2361,7 @@
       description_for_relation->get_target(0, target.GetAddressOf()));
   target.CopyTo(ax_target.GetAddressOf());
   EXPECT_HRESULT_SUCCEEDED(ax_target->get_uniqueID(&unique_id));
-  EXPECT_EQ(-GetUniqueId(ax_root), unique_id);
+  EXPECT_EQ(-ax_root->unique_id(), unique_id);
   ax_target.Reset();
   target.Reset();
 
diff --git a/content/browser/accessibility/web_contents_accessibility_android.cc b/content/browser/accessibility/web_contents_accessibility_android.cc
index 427acc2..82b82293 100644
--- a/content/browser/accessibility/web_contents_accessibility_android.cc
+++ b/content/browser/accessibility/web_contents_accessibility_android.cc
@@ -564,8 +564,7 @@
     JNIEnv* env,
     const JavaParamRef<jobject>& obj) {
   if (root_manager_) {
-    auto* root =
-        static_cast<BrowserAccessibilityAndroid*>(root_manager_->GetRoot());
+    auto* root = root_manager_->GetRoot();
     if (root)
       return static_cast<jint>(root->unique_id());
   }
@@ -641,16 +640,12 @@
     return false;
 
   if (node->PlatformGetParent()) {
-    auto* android_node =
-        static_cast<BrowserAccessibilityAndroid*>(node->PlatformGetParent());
     Java_WebContentsAccessibility_setAccessibilityNodeInfoParent(
-        env, obj, info, android_node->unique_id());
+        env, obj, info, node->PlatformGetParent()->unique_id());
   }
   for (unsigned i = 0; i < node->PlatformChildCount(); ++i) {
-    auto* android_node =
-        static_cast<BrowserAccessibilityAndroid*>(node->PlatformGetChild(i));
     Java_WebContentsAccessibility_addAccessibilityNodeInfoChild(
-        env, obj, info, android_node->unique_id());
+        env, obj, info, node->PlatformGetChild(i)->unique_id());
   }
   Java_WebContentsAccessibility_setAccessibilityNodeInfoBooleanAttributes(
       env, obj, info, unique_id, node->IsCheckable(), node->IsChecked(),
@@ -930,9 +925,7 @@
   if (tree_search.CountMatches() == 0)
     return 0;
 
-  auto* android_node =
-      static_cast<BrowserAccessibilityAndroid*>(tree_search.GetMatchAtIndex(0));
-  int32_t element_id = android_node->unique_id();
+  int32_t element_id = tree_search.GetMatchAtIndex(0)->unique_id();
 
   // Navigate forwards to the autofill popup's proxy node if focus is currently
   // on the element hosting the autofill popup. Once within the popup, a back
@@ -943,9 +936,7 @@
   if (forwards && start_id == g_element_hosting_autofill_popup_unique_id &&
       g_autofill_popup_proxy_node) {
     g_element_after_element_hosting_autofill_popup_unique_id = element_id;
-    auto* android_node =
-        static_cast<BrowserAccessibilityAndroid*>(g_autofill_popup_proxy_node);
-    return android_node->unique_id();
+    return g_autofill_popup_proxy_node->unique_id();
   }
 
   return element_id;
@@ -1048,9 +1039,7 @@
   g_autofill_popup_proxy_node->Init(root_manager_,
                                     g_autofill_popup_proxy_node_ax_node);
 
-  auto* android_node = static_cast<BrowserAccessibilityAndroid*>(current_focus);
-
-  g_element_hosting_autofill_popup_unique_id = android_node->unique_id();
+  g_element_hosting_autofill_popup_unique_id = current_focus->unique_id();
 }
 
 void WebContentsAccessibilityAndroid::OnAutofillPopupDismissed(
@@ -1078,10 +1067,8 @@
     JNIEnv* env,
     const JavaParamRef<jobject>& obj,
     jint unique_id) {
-  auto* android_node =
-      static_cast<BrowserAccessibilityAndroid*>(g_autofill_popup_proxy_node);
-
-  return g_autofill_popup_proxy_node && android_node->unique_id() == unique_id;
+  return g_autofill_popup_proxy_node &&
+         g_autofill_popup_proxy_node->unique_id() == unique_id;
 }
 
 bool WebContentsAccessibilityAndroid::Scroll(JNIEnv* env,
@@ -1098,7 +1085,7 @@
 BrowserAccessibilityAndroid* WebContentsAccessibilityAndroid::GetAXFromUniqueID(
     int32_t unique_id) {
   return static_cast<BrowserAccessibilityAndroid*>(
-      BrowserAccessibilityAndroid::GetFromUniqueId(unique_id));
+      BrowserAccessibility::GetFromUniqueID(unique_id));
 }
 
 void WebContentsAccessibilityAndroid::UpdateFrameInfo() {
diff --git a/content/browser/image_capture/image_capture_impl.cc b/content/browser/image_capture/image_capture_impl.cc
index 752ecd1a..c3f8651 100644
--- a/content/browser/image_capture/image_capture_impl.cc
+++ b/content/browser/image_capture/image_capture_impl.cc
@@ -15,6 +15,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/content_features.h"
 #include "media/base/bind_to_current_loop.h"
+#include "media/base/scoped_callback_runner.h"
 #include "media/capture/video/video_capture_device.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 
@@ -22,9 +23,7 @@
 
 namespace {
 
-void RunFailedGetPhotoStateCallback(
-    ImageCaptureImpl::GetPhotoStateCallback cb) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+media::mojom::PhotoStatePtr MakeEmptyCapabilities() {
   media::mojom::PhotoStatePtr empty_capabilities =
       media::mojom::PhotoState::New();
   empty_capabilities->iso = media::mojom::Range::New();
@@ -37,24 +36,12 @@
   empty_capabilities->contrast = media::mojom::Range::New();
   empty_capabilities->saturation = media::mojom::Range::New();
   empty_capabilities->sharpness = media::mojom::Range::New();
-  std::move(cb).Run(std::move(empty_capabilities));
+  return empty_capabilities;
 }
 
-void RunFailedSetOptionsCallback(ImageCaptureImpl::SetOptionsCallback cb) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  std::move(cb).Run(false);
-}
-
-void RunFailedTakePhotoCallback(ImageCaptureImpl::TakePhotoCallback cb) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  std::move(cb).Run(media::mojom::Blob::New());
-}
-
-void GetPhotoStateOnIOThread(
-    const std::string& source_id,
-    MediaStreamManager* media_stream_manager,
-    media::ScopedResultCallback<ImageCaptureImpl::GetPhotoStateCallback>
-        callback) {
+void GetPhotoStateOnIOThread(const std::string& source_id,
+                             MediaStreamManager* media_stream_manager,
+                             ImageCaptureImpl::GetPhotoStateCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
 // TODO(mcasas): Enable PhotoState collection in Windows when understood why it
@@ -70,12 +57,10 @@
 #endif
 }
 
-void SetOptionsOnIOThread(
-    const std::string& source_id,
-    MediaStreamManager* media_stream_manager,
-    media::mojom::PhotoSettingsPtr settings,
-    media::ScopedResultCallback<ImageCaptureImpl::SetOptionsCallback>
-        callback) {
+void SetOptionsOnIOThread(const std::string& source_id,
+                          MediaStreamManager* media_stream_manager,
+                          media::mojom::PhotoSettingsPtr settings,
+                          ImageCaptureImpl::SetOptionsCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   const int session_id =
@@ -87,10 +72,9 @@
       session_id, std::move(settings), std::move(callback));
 }
 
-void TakePhotoOnIOThread(
-    const std::string& source_id,
-    MediaStreamManager* media_stream_manager,
-    media::ScopedResultCallback<ImageCaptureImpl::TakePhotoCallback> callback) {
+void TakePhotoOnIOThread(const std::string& source_id,
+                         MediaStreamManager* media_stream_manager,
+                         ImageCaptureImpl::TakePhotoCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   const int session_id =
@@ -122,16 +106,13 @@
                                      GetPhotoStateCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  media::ScopedResultCallback<GetPhotoStateCallback> scoped_callback(
-      media::BindToCurrentLoop(std::move(callback)),
-      media::BindToCurrentLoop(
-          base::BindOnce(&RunFailedGetPhotoStateCallback)));
-
+  GetPhotoStateCallback scoped_callback = media::ScopedCallbackRunner(
+      media::BindToCurrentLoop(std::move(callback)), MakeEmptyCapabilities());
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&GetPhotoStateOnIOThread, source_id,
-                 BrowserMainLoop::GetInstance()->media_stream_manager(),
-                 base::Passed(&scoped_callback)));
+      base::BindOnce(&GetPhotoStateOnIOThread, source_id,
+                     BrowserMainLoop::GetInstance()->media_stream_manager(),
+                     std::move(scoped_callback)));
 }
 
 void ImageCaptureImpl::SetOptions(const std::string& source_id,
@@ -139,30 +120,26 @@
                                   SetOptionsCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  media::ScopedResultCallback<SetOptionsCallback> scoped_callback(
-      media::BindToCurrentLoop(std::move(callback)),
-      media::BindToCurrentLoop(base::Bind(&RunFailedSetOptionsCallback)));
-
+  SetOptionsCallback scoped_callback = media::ScopedCallbackRunner(
+      media::BindToCurrentLoop(std::move(callback)), false);
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&SetOptionsOnIOThread, source_id,
-                 BrowserMainLoop::GetInstance()->media_stream_manager(),
-                 base::Passed(&settings), base::Passed(&scoped_callback)));
+      base::BindOnce(&SetOptionsOnIOThread, source_id,
+                     BrowserMainLoop::GetInstance()->media_stream_manager(),
+                     std::move(settings), std::move(scoped_callback)));
 }
 
 void ImageCaptureImpl::TakePhoto(const std::string& source_id,
                                  TakePhotoCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  media::ScopedResultCallback<TakePhotoCallback> scoped_callback(
-      media::BindToCurrentLoop(std::move(callback)),
-      media::BindToCurrentLoop(base::BindOnce(&RunFailedTakePhotoCallback)));
-
+  TakePhotoCallback scoped_callback = media::ScopedCallbackRunner(
+      media::BindToCurrentLoop(std::move(callback)), media::mojom::Blob::New());
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&TakePhotoOnIOThread, source_id,
-                 BrowserMainLoop::GetInstance()->media_stream_manager(),
-                 base::Passed(&scoped_callback)));
+      base::BindOnce(&TakePhotoOnIOThread, source_id,
+                     BrowserMainLoop::GetInstance()->media_stream_manager(),
+                     std::move(scoped_callback)));
 }
 
 }  // namespace content
diff --git a/content/browser/media/encrypted_media_browsertest.cc b/content/browser/media/encrypted_media_browsertest.cc
index 4c28592..434cee39 100644
--- a/content/browser/media/encrypted_media_browsertest.cc
+++ b/content/browser/media/encrypted_media_browsertest.cc
@@ -108,10 +108,10 @@
     }
 
     base::StringPairs query_params;
-    query_params.push_back(std::make_pair("keySystem", CurrentKeySystem()));
-    query_params.push_back(std::make_pair(
+    query_params.emplace_back("keySystem", CurrentKeySystem());
+    query_params.emplace_back(
         "configChangeType",
-        base::IntToString(static_cast<int>(config_change_type))));
+        base::IntToString(static_cast<int>(config_change_type)));
     RunMediaTestPage("mse_config_change.html", query_params, kEnded, true);
   }
 
@@ -122,11 +122,11 @@
                              SrcType src_type,
                              const std::string& expectation) {
     base::StringPairs query_params;
-    query_params.push_back(std::make_pair("mediaFile", media_file));
-    query_params.push_back(std::make_pair("mediaType", media_type));
-    query_params.push_back(std::make_pair("keySystem", key_system));
+    query_params.emplace_back("mediaFile", media_file);
+    query_params.emplace_back("mediaType", media_type);
+    query_params.emplace_back("keySystem", key_system);
     if (src_type == SrcType::MSE)
-      query_params.push_back(std::make_pair("useMSE", "1"));
+      query_params.emplace_back("useMSE", "1");
     RunMediaTestPage(html_page, query_params, expectation, true);
   }
 
diff --git a/content/browser/media/media_browsertest.cc b/content/browser/media/media_browsertest.cc
index 5035245a..239bfb2 100644
--- a/content/browser/media/media_browsertest.cc
+++ b/content/browser/media/media_browsertest.cc
@@ -123,7 +123,7 @@
                  const std::string& media_file,
                  bool http) {
     base::StringPairs query_params;
-    query_params.push_back(std::make_pair(tag, media_file));
+    query_params.emplace_back(tag, media_file);
     RunMediaTestPage("player.html", query_params, kEnded, http);
   }
 
@@ -132,9 +132,9 @@
                            const std::string& expected_error_substring,
                            bool http) {
     base::StringPairs query_params;
-    query_params.push_back(std::make_pair(tag, media_file));
-    query_params.push_back(std::make_pair(
-        "error_substr", EncodeErrorMessage(expected_error_substring)));
+    query_params.emplace_back(tag, media_file);
+    query_params.emplace_back("error_substr",
+                              EncodeErrorMessage(expected_error_substring));
     RunMediaTestPage("player.html", query_params, kErrorEvent, http);
   }
 
@@ -144,7 +144,7 @@
     expected += " ";
     expected += base::IntToString(height);
     base::StringPairs query_params;
-    query_params.push_back(std::make_pair("video", media_file));
+    query_params.emplace_back("video", media_file);
     RunMediaTestPage("player.html", query_params, expected, false);
   }
 };
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index ef79cd0..831df78 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -687,21 +687,24 @@
     return;
 #endif
 
+  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kDisableTimeoutsForProfiling)) {
 #if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) || \
     defined(SYZYASAN) || defined(CYGPROFILE_INSTRUMENTATION)
-  const int64_t kGpuChannelTimeoutInSeconds = 40;
+    const int64_t kGpuChannelTimeoutInSeconds = 40;
 #else
-  // The GPU watchdog timeout is 15 seconds (1.5x the kGpuTimeout value due to
-  // logic in GpuWatchdogThread). Make this slightly longer to give the GPU a
-  // chance to crash itself before crashing the browser.
-  const int64_t kGpuChannelTimeoutInSeconds = 20;
+    // The GPU watchdog timeout is 15 seconds (1.5x the kGpuTimeout value due to
+    // logic in GpuWatchdogThread). Make this slightly longer to give the GPU a
+    // chance to crash itself before crashing the browser.
+    const int64_t kGpuChannelTimeoutInSeconds = 20;
 #endif
 
-  // Start the timer first, if the result comes synchronously, we want it to
-  // stop in the callback.
-  establish_gpu_channel_timeout_.Start(
-      FROM_HERE, base::TimeDelta::FromSeconds(kGpuChannelTimeoutInSeconds),
-      this, &CompositorImpl::OnGpuChannelTimeout);
+    // Start the timer first, if the result comes synchronously, we want it to
+    // stop in the callback.
+    establish_gpu_channel_timeout_.Start(
+        FROM_HERE, base::TimeDelta::FromSeconds(kGpuChannelTimeoutInSeconds),
+        this, &CompositorImpl::OnGpuChannelTimeout);
+  }
 
   DCHECK(surface_handle_ != gpu::kNullSurfaceHandle);
   BrowserMainLoop::GetInstance()
diff --git a/content/browser/renderer_host/media/service_launched_video_capture_device.cc b/content/browser/renderer_host/media/service_launched_video_capture_device.cc
index 43b0e49..a4ca945 100644
--- a/content/browser/renderer_host/media/service_launched_video_capture_device.cc
+++ b/content/browser/renderer_host/media/service_launched_video_capture_device.cc
@@ -88,7 +88,7 @@
     media::mojom::PhotoStatePtr capabilities) const {
   if (!capabilities)
     return;
-  callback.Run(std::move(capabilities));
+  std::move(callback).Run(std::move(capabilities));
 }
 
 void ServiceLaunchedVideoCaptureDevice::OnSetPhotoOptionsResponse(
@@ -96,7 +96,7 @@
     bool success) {
   if (!success)
     return;
-  callback.Run(true);
+  std::move(callback).Run(true);
 }
 
 void ServiceLaunchedVideoCaptureDevice::OnTakePhotoResponse(
@@ -104,7 +104,7 @@
     media::mojom::BlobPtr blob) {
   if (!blob)
     return;
-  callback.Run(std::move(blob));
+  std::move(callback).Run(std::move(blob));
 }
 
 }  // namespace content
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index d7101f4..729fa611 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -960,6 +960,10 @@
 // Disable the locking feature of the screen orientation API.
 const char kDisableScreenOrientationLock[]  = "disable-screen-orientation-lock";
 
+// Disable timeouts that may cause the browser to die when running slowly. This
+// is useful if running with profiling (such as debug malloc).
+const char kDisableTimeoutsForProfiling[] = "disable-timeouts-for-profiling";
+
 // Enable inverting of selection handles so that they are not clipped by the
 // viewport boundaries.
 const char kEnableAdaptiveSelectionHandleOrientation[] =
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index 0227769..57f68a8 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -272,6 +272,7 @@
 CONTENT_EXPORT extern const char kDisableOverscrollEdgeEffect[];
 CONTENT_EXPORT extern const char kDisablePullToRefreshEffect[];
 CONTENT_EXPORT extern const char kDisableScreenOrientationLock[];
+CONTENT_EXPORT extern const char kDisableTimeoutsForProfiling[];
 CONTENT_EXPORT extern const char kEnableAdaptiveSelectionHandleOrientation[];
 CONTENT_EXPORT extern const char kEnableLongpressDragSelection[];
 extern const char kNetworkCountryIso[];
diff --git a/device/serial/buffer.cc b/device/serial/buffer.cc
index c6eeea2..4c4a26a 100644
--- a/device/serial/buffer.cc
+++ b/device/serial/buffer.cc
@@ -16,7 +16,7 @@
 
 SendBuffer::SendBuffer(
     const std::vector<char>& data,
-    const base::Callback<void(int, device::serial::SendError)>& callback)
+    const base::Callback<void(int, device::mojom::SerialSendError)>& callback)
     : data_(data), callback_(callback) {}
 
 SendBuffer::~SendBuffer() {}
@@ -30,17 +30,18 @@
 }
 
 void SendBuffer::Done(uint32_t bytes_read) {
-  callback_.Run(bytes_read, device::serial::SendError::NONE);
+  callback_.Run(bytes_read, device::mojom::SerialSendError::NONE);
 }
 
 void SendBuffer::DoneWithError(uint32_t bytes_read, int32_t error) {
-  callback_.Run(bytes_read, static_cast<device::serial::SendError>(error));
+  callback_.Run(bytes_read, static_cast<device::mojom::SerialSendError>(error));
 }
 
 ReceiveBuffer::ReceiveBuffer(
     scoped_refptr<net::IOBuffer> buffer,
     uint32_t size,
-    const base::Callback<void(int, device::serial::ReceiveError)>& callback)
+    const base::Callback<void(int, device::mojom::SerialReceiveError)>&
+        callback)
     : buffer_(buffer), size_(size), callback_(callback) {}
 
 ReceiveBuffer::~ReceiveBuffer() {}
@@ -54,12 +55,12 @@
 }
 
 void ReceiveBuffer::Done(uint32_t bytes_written) {
-  callback_.Run(bytes_written, device::serial::ReceiveError::NONE);
+  callback_.Run(bytes_written, device::mojom::SerialReceiveError::NONE);
 }
 
 void ReceiveBuffer::DoneWithError(uint32_t bytes_written, int32_t error) {
   callback_.Run(bytes_written,
-                static_cast<device::serial::ReceiveError>(error));
+                static_cast<device::mojom::SerialReceiveError>(error));
 }
 
 }  // namespace device
diff --git a/device/serial/buffer.h b/device/serial/buffer.h
index 53ef909..ebecb92 100644
--- a/device/serial/buffer.h
+++ b/device/serial/buffer.h
@@ -43,9 +43,9 @@
 // initialized via a character vector.
 class SendBuffer : public device::ReadOnlyBuffer {
  public:
-  SendBuffer(
-      const std::vector<char>& data,
-      const base::Callback<void(int, device::serial::SendError)>& callback);
+  SendBuffer(const std::vector<char>& data,
+             const base::Callback<void(int, device::mojom::SerialSendError)>&
+                 callback);
   ~SendBuffer() override;
 
   const char* GetData() override;
@@ -55,7 +55,7 @@
 
  private:
   const std::vector<char> data_;
-  const base::Callback<void(int, device::serial::SendError)> callback_;
+  const base::Callback<void(int, device::mojom::SerialSendError)> callback_;
 };
 
 // A useful basic implementation of a WritableBuffer in which the data is
@@ -65,7 +65,8 @@
   ReceiveBuffer(
       scoped_refptr<net::IOBuffer> buffer,
       uint32_t size,
-      const base::Callback<void(int, device::serial::ReceiveError)>& callback);
+      const base::Callback<void(int, device::mojom::SerialReceiveError)>&
+          callback);
   ~ReceiveBuffer() override;
 
   char* GetData() override;
@@ -76,7 +77,7 @@
  private:
   scoped_refptr<net::IOBuffer> buffer_;
   const uint32_t size_;
-  const base::Callback<void(int, device::serial::ReceiveError)> callback_;
+  const base::Callback<void(int, device::mojom::SerialReceiveError)> callback_;
 };
 
 }  // namespace device
diff --git a/device/serial/serial.mojom b/device/serial/serial.mojom
index 72ba3a2..ea90494 100644
--- a/device/serial/serial.mojom
+++ b/device/serial/serial.mojom
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-module device.serial;
+module device.mojom;
 
-struct DeviceInfo {
+struct SerialDeviceInfo {
   string path;
   uint16 vendor_id;
   bool has_vendor_id = false;
@@ -13,7 +13,7 @@
   string? display_name;
 };
 
-enum SendError {
+enum SerialSendError {
   NONE,
   DISCONNECTED,
   PENDING,
@@ -21,7 +21,7 @@
   SYSTEM_ERROR,
 };
 
-enum ReceiveError {
+enum SerialReceiveError {
   NONE,
   DISCONNECTED,
   TIMEOUT,
@@ -34,50 +34,50 @@
   SYSTEM_ERROR,
 };
 
-enum DataBits {
+enum SerialDataBits {
   NONE,
   SEVEN,
   EIGHT,
 };
 
-enum ParityBit {
+enum SerialParityBit {
   NONE,
   NO_PARITY,
   ODD,
   EVEN,
 };
 
-enum StopBits {
+enum SerialStopBits {
   NONE,
   ONE,
   TWO,
 };
 
-struct ConnectionOptions {
+struct SerialConnectionOptions {
   uint32 bitrate = 0;
-  DataBits data_bits = NONE;
-  ParityBit parity_bit = NONE;
-  StopBits stop_bits = NONE;
+  SerialDataBits data_bits = NONE;
+  SerialParityBit parity_bit = NONE;
+  SerialStopBits stop_bits = NONE;
   bool cts_flow_control;
   bool has_cts_flow_control = false;
 };
 
-struct ConnectionInfo {
+struct SerialConnectionInfo {
   uint32 bitrate = 0;
-  DataBits data_bits = NONE;
-  ParityBit parity_bit = NONE;
-  StopBits stop_bits = NONE;
+  SerialDataBits data_bits = NONE;
+  SerialParityBit parity_bit = NONE;
+  SerialStopBits stop_bits = NONE;
   bool cts_flow_control;
 };
 
-struct HostControlSignals {
+struct SerialHostControlSignals {
   bool dtr;
   bool has_dtr = false;
   bool rts;
   bool has_rts = false;
 };
 
-struct DeviceControlSignals {
+struct SerialDeviceControlSignals {
   bool dcd;
   bool cts;
   bool ri;
diff --git a/device/serial/serial_device_enumerator.h b/device/serial/serial_device_enumerator.h
index 82fece2b..a1ee5b4b 100644
--- a/device/serial/serial_device_enumerator.h
+++ b/device/serial/serial_device_enumerator.h
@@ -19,7 +19,7 @@
   SerialDeviceEnumerator();
   virtual ~SerialDeviceEnumerator();
 
-  virtual std::vector<serial::DeviceInfoPtr> GetDevices() = 0;
+  virtual std::vector<mojom::SerialDeviceInfoPtr> GetDevices() = 0;
 };
 
 }  // namespace device
diff --git a/device/serial/serial_device_enumerator_linux.cc b/device/serial/serial_device_enumerator_linux.cc
index f716e56..010cf78 100644
--- a/device/serial/serial_device_enumerator_linux.cc
+++ b/device/serial/serial_device_enumerator_linux.cc
@@ -38,8 +38,9 @@
 
 SerialDeviceEnumeratorLinux::~SerialDeviceEnumeratorLinux() {}
 
-std::vector<serial::DeviceInfoPtr> SerialDeviceEnumeratorLinux::GetDevices() {
-  std::vector<serial::DeviceInfoPtr> devices;
+std::vector<mojom::SerialDeviceInfoPtr>
+SerialDeviceEnumeratorLinux::GetDevices() {
+  std::vector<mojom::SerialDeviceInfoPtr> devices;
   ScopedUdevEnumeratePtr enumerate(udev_enumerate_new(udev_.get()));
   if (!enumerate) {
     LOG(ERROR) << "Serial device enumeration failed.";
@@ -67,7 +68,7 @@
         udev_device_get_property_value(device.get(), kHostPathKey);
     const char* bus = udev_device_get_property_value(device.get(), kHostBusKey);
     if (path != NULL && bus != NULL) {
-      serial::DeviceInfoPtr info(serial::DeviceInfo::New());
+      mojom::SerialDeviceInfoPtr info(mojom::SerialDeviceInfo::New());
       info->path = path;
 
       const char* vendor_id =
diff --git a/device/serial/serial_device_enumerator_linux.h b/device/serial/serial_device_enumerator_linux.h
index 1acc8e46..92f47ae 100644
--- a/device/serial/serial_device_enumerator_linux.h
+++ b/device/serial/serial_device_enumerator_linux.h
@@ -18,7 +18,7 @@
   ~SerialDeviceEnumeratorLinux() override;
 
   // Implementation for SerialDeviceEnumerator.
-  std::vector<serial::DeviceInfoPtr> GetDevices() override;
+  std::vector<mojom::SerialDeviceInfoPtr> GetDevices() override;
 
  private:
   ScopedUdevPtr udev_;
diff --git a/device/serial/serial_device_enumerator_mac.cc b/device/serial/serial_device_enumerator_mac.cc
index 954ab7d..3d1b4fa 100644
--- a/device/serial/serial_device_enumerator_mac.cc
+++ b/device/serial/serial_device_enumerator_mac.cc
@@ -101,8 +101,8 @@
 // Returns an array of devices as retrieved through the new method of
 // enumerating serial devices (IOKit).  This new method gives more information
 // about the devices than the old method.
-std::vector<serial::DeviceInfoPtr> GetDevicesNew() {
-  std::vector<serial::DeviceInfoPtr> devices;
+std::vector<mojom::SerialDeviceInfoPtr> GetDevicesNew() {
+  std::vector<mojom::SerialDeviceInfoPtr> devices;
 
   // Make a service query to find all serial devices.
   CFMutableDictionaryRef matchingDict =
@@ -119,7 +119,7 @@
   base::mac::ScopedIOObject<io_iterator_t> scoped_it(it);
   base::mac::ScopedIOObject<io_service_t> scoped_device;
   while (scoped_device.reset(IOIteratorNext(scoped_it.get())), scoped_device) {
-    serial::DeviceInfoPtr callout_info(serial::DeviceInfo::New());
+    mojom::SerialDeviceInfoPtr callout_info(mojom::SerialDeviceInfo::New());
 
     uint16_t vendorId;
     if (GetUInt16Property(scoped_device.get(), CFSTR(kUSBVendorID),
@@ -148,7 +148,7 @@
     std::string dialinDevice;
     if (GetStringProperty(scoped_device.get(), CFSTR(kIODialinDeviceKey),
                           &dialinDevice)) {
-      serial::DeviceInfoPtr dialin_info = callout_info.Clone();
+      mojom::SerialDeviceInfoPtr dialin_info = callout_info.Clone();
       dialin_info->path = dialinDevice;
       devices.push_back(std::move(dialin_info));
     }
@@ -167,7 +167,7 @@
 // Returns an array of devices as retrieved through the old method of
 // enumerating serial devices (pattern matching in /dev/). This old method gives
 // less information about the devices than the new method.
-std::vector<serial::DeviceInfoPtr> GetDevicesOld() {
+std::vector<mojom::SerialDeviceInfoPtr> GetDevicesOld() {
   const base::FilePath kDevRoot("/dev");
   const int kFilesAndSymLinks =
       base::FileEnumerator::FILES | base::FileEnumerator::SHOW_SYM_LINKS;
@@ -181,7 +181,7 @@
   valid_patterns.insert("/dev/tty.*");
   valid_patterns.insert("/dev/cu.*");
 
-  std::vector<serial::DeviceInfoPtr> devices;
+  std::vector<mojom::SerialDeviceInfoPtr> devices;
   base::FileEnumerator enumerator(kDevRoot, false, kFilesAndSymLinks);
   do {
     const base::FilePath next_device_path(enumerator.Next());
@@ -192,7 +192,7 @@
     std::set<std::string>::const_iterator i = valid_patterns.begin();
     for (; i != valid_patterns.end(); ++i) {
       if (base::MatchPattern(next_device, *i)) {
-        serial::DeviceInfoPtr info(serial::DeviceInfo::New());
+        mojom::SerialDeviceInfoPtr info(mojom::SerialDeviceInfo::New());
         info->path = next_device;
         devices.push_back(std::move(info));
         break;
@@ -214,9 +214,10 @@
 
 SerialDeviceEnumeratorMac::~SerialDeviceEnumeratorMac() {}
 
-std::vector<serial::DeviceInfoPtr> SerialDeviceEnumeratorMac::GetDevices() {
-  std::vector<serial::DeviceInfoPtr> devices = GetDevicesNew();
-  std::vector<serial::DeviceInfoPtr> old_devices = GetDevicesOld();
+std::vector<mojom::SerialDeviceInfoPtr>
+SerialDeviceEnumeratorMac::GetDevices() {
+  std::vector<mojom::SerialDeviceInfoPtr> devices = GetDevicesNew();
+  std::vector<mojom::SerialDeviceInfoPtr> old_devices = GetDevicesOld();
 
   UMA_HISTOGRAM_SPARSE_SLOWLY(
       "Hardware.Serial.NewMinusOldDeviceListSize",
diff --git a/device/serial/serial_device_enumerator_mac.h b/device/serial/serial_device_enumerator_mac.h
index 433d0682..04c504f7 100644
--- a/device/serial/serial_device_enumerator_mac.h
+++ b/device/serial/serial_device_enumerator_mac.h
@@ -17,7 +17,7 @@
   ~SerialDeviceEnumeratorMac() override;
 
   // Implementation for SerialDeviceEnumerator.
-  std::vector<serial::DeviceInfoPtr> GetDevices() override;
+  std::vector<mojom::SerialDeviceInfoPtr> GetDevices() override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(SerialDeviceEnumeratorMac);
diff --git a/device/serial/serial_device_enumerator_win.cc b/device/serial/serial_device_enumerator_win.cc
index 6864ba2..b8aa470 100644
--- a/device/serial/serial_device_enumerator_win.cc
+++ b/device/serial/serial_device_enumerator_win.cc
@@ -88,8 +88,8 @@
 // Returns an array of devices as retrieved through the new method of
 // enumerating serial devices (SetupDi).  This new method gives more information
 // about the devices than the old method.
-std::vector<serial::DeviceInfoPtr> GetDevicesNew() {
-  std::vector<serial::DeviceInfoPtr> devices;
+std::vector<mojom::SerialDeviceInfoPtr> GetDevicesNew() {
+  std::vector<mojom::SerialDeviceInfoPtr> devices;
 
   // Make a device interface query to find all serial devices.
   HDEVINFO dev_info =
@@ -109,7 +109,7 @@
       // serial device. If the COM can't be found, ignore the device.
       continue;
 
-    serial::DeviceInfoPtr info(serial::DeviceInfo::New());
+    mojom::SerialDeviceInfoPtr info(mojom::SerialDeviceInfo::New());
     info->path = com_port;
 
     std::string display_name;
@@ -140,12 +140,12 @@
 // Returns an array of devices as retrieved through the old method of
 // enumerating serial devices (searching the registry). This old method gives
 // less information about the devices than the new method.
-std::vector<serial::DeviceInfoPtr> GetDevicesOld() {
+std::vector<mojom::SerialDeviceInfoPtr> GetDevicesOld() {
   base::win::RegistryValueIterator iter_key(
       HKEY_LOCAL_MACHINE, L"HARDWARE\\DEVICEMAP\\SERIALCOMM\\");
-  std::vector<serial::DeviceInfoPtr> devices;
+  std::vector<mojom::SerialDeviceInfoPtr> devices;
   for (; iter_key.Valid(); ++iter_key) {
-    serial::DeviceInfoPtr info(serial::DeviceInfo::New());
+    mojom::SerialDeviceInfoPtr info(mojom::SerialDeviceInfo::New());
     info->path = base::UTF16ToASCII(iter_key.Value());
     devices.push_back(std::move(info));
   }
@@ -164,9 +164,10 @@
 
 SerialDeviceEnumeratorWin::~SerialDeviceEnumeratorWin() {}
 
-std::vector<serial::DeviceInfoPtr> SerialDeviceEnumeratorWin::GetDevices() {
-  std::vector<serial::DeviceInfoPtr> devices = GetDevicesNew();
-  std::vector<serial::DeviceInfoPtr> old_devices = GetDevicesOld();
+std::vector<mojom::SerialDeviceInfoPtr>
+SerialDeviceEnumeratorWin::GetDevices() {
+  std::vector<mojom::SerialDeviceInfoPtr> devices = GetDevicesNew();
+  std::vector<mojom::SerialDeviceInfoPtr> old_devices = GetDevicesOld();
 
   UMA_HISTOGRAM_SPARSE_SLOWLY(
       "Hardware.Serial.NewMinusOldDeviceListSize",
diff --git a/device/serial/serial_device_enumerator_win.h b/device/serial/serial_device_enumerator_win.h
index b6652505..1eea2df0 100644
--- a/device/serial/serial_device_enumerator_win.h
+++ b/device/serial/serial_device_enumerator_win.h
@@ -17,7 +17,7 @@
   ~SerialDeviceEnumeratorWin() override;
 
   // Implementation for SerialDeviceEnumerator.
-  std::vector<serial::DeviceInfoPtr> GetDevices() override;
+  std::vector<mojom::SerialDeviceInfoPtr> GetDevices() override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(SerialDeviceEnumeratorWin);
diff --git a/device/serial/serial_io_handler.cc b/device/serial/serial_io_handler.cc
index 70f90a6..fab3d2c 100644
--- a/device/serial/serial_io_handler.cc
+++ b/device/serial/serial_io_handler.cc
@@ -26,9 +26,9 @@
     scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner)
     : ui_thread_task_runner_(ui_thread_task_runner) {
   options_.bitrate = 9600;
-  options_.data_bits = serial::DataBits::EIGHT;
-  options_.parity_bit = serial::ParityBit::NO_PARITY;
-  options_.stop_bits = serial::StopBits::ONE;
+  options_.data_bits = mojom::SerialDataBits::EIGHT;
+  options_.parity_bit = mojom::SerialParityBit::NO_PARITY;
+  options_.stop_bits = mojom::SerialStopBits::ONE;
   options_.cts_flow_control = false;
   options_.has_cts_flow_control = true;
 }
@@ -39,7 +39,7 @@
 }
 
 void SerialIoHandler::Open(const std::string& port,
-                           const serial::ConnectionOptions& options,
+                           const mojom::SerialConnectionOptions& options,
                            const OpenCompleteCallback& callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(open_complete_.is_null());
@@ -104,17 +104,17 @@
 #endif
 
 void SerialIoHandler::MergeConnectionOptions(
-    const serial::ConnectionOptions& options) {
+    const mojom::SerialConnectionOptions& options) {
   if (options.bitrate) {
     options_.bitrate = options.bitrate;
   }
-  if (options.data_bits != serial::DataBits::NONE) {
+  if (options.data_bits != mojom::SerialDataBits::NONE) {
     options_.data_bits = options.data_bits;
   }
-  if (options.parity_bit != serial::ParityBit::NONE) {
+  if (options.parity_bit != mojom::SerialParityBit::NONE) {
     options_.parity_bit = options.parity_bit;
   }
-  if (options.stop_bits != serial::StopBits::NONE) {
+  if (options.stop_bits != mojom::SerialStopBits::NONE) {
     options_.stop_bits = options.stop_bits;
   }
   if (options.has_cts_flow_control) {
@@ -201,12 +201,12 @@
 }
 
 void SerialIoHandler::ReadCompleted(int bytes_read,
-                                    serial::ReceiveError error) {
+                                    mojom::SerialReceiveError error) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(IsReadPending());
   std::unique_ptr<WritableBuffer> pending_read_buffer =
       std::move(pending_read_buffer_);
-  if (error == serial::ReceiveError::NONE) {
+  if (error == mojom::SerialReceiveError::NONE) {
     pending_read_buffer->Done(bytes_read);
   } else {
     pending_read_buffer->DoneWithError(bytes_read, static_cast<int32_t>(error));
@@ -215,12 +215,12 @@
 }
 
 void SerialIoHandler::WriteCompleted(int bytes_written,
-                                     serial::SendError error) {
+                                     mojom::SerialSendError error) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(IsWritePending());
   std::unique_ptr<ReadOnlyBuffer> pending_write_buffer =
       std::move(pending_write_buffer_);
-  if (error == serial::SendError::NONE) {
+  if (error == mojom::SerialSendError::NONE) {
     pending_write_buffer->Done(bytes_written);
   } else {
     pending_write_buffer->DoneWithError(bytes_written,
@@ -239,7 +239,7 @@
   return pending_write_buffer_ != NULL;
 }
 
-void SerialIoHandler::CancelRead(serial::ReceiveError reason) {
+void SerialIoHandler::CancelRead(mojom::SerialReceiveError reason) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (IsReadPending() && !read_canceled_) {
     read_canceled_ = true;
@@ -248,7 +248,7 @@
   }
 }
 
-void SerialIoHandler::CancelWrite(serial::SendError reason) {
+void SerialIoHandler::CancelWrite(mojom::SerialSendError reason) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (IsWritePending() && !write_canceled_) {
     write_canceled_ = true;
@@ -257,20 +257,21 @@
   }
 }
 
-bool SerialIoHandler::ConfigurePort(const serial::ConnectionOptions& options) {
+bool SerialIoHandler::ConfigurePort(
+    const mojom::SerialConnectionOptions& options) {
   MergeConnectionOptions(options);
   return ConfigurePortImpl();
 }
 
 void SerialIoHandler::QueueReadCompleted(int bytes_read,
-                                         serial::ReceiveError error) {
+                                         mojom::SerialReceiveError error) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
       base::Bind(&SerialIoHandler::ReadCompleted, this, bytes_read, error));
 }
 
 void SerialIoHandler::QueueWriteCompleted(int bytes_written,
-                                          serial::SendError error) {
+                                          mojom::SerialSendError error) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
       base::Bind(&SerialIoHandler::WriteCompleted, this, bytes_written, error));
diff --git a/device/serial/serial_io_handler.h b/device/serial/serial_io_handler.h
index c0adb5e..3a4991b1 100644
--- a/device/serial/serial_io_handler.h
+++ b/device/serial/serial_io_handler.h
@@ -36,7 +36,7 @@
 
   // Initiates an asynchronous Open of the device.
   virtual void Open(const std::string& port,
-                    const serial::ConnectionOptions& options,
+                    const mojom::SerialConnectionOptions& options,
                     const OpenCompleteCallback& callback);
 
 #if defined(OS_CHROMEOS)
@@ -73,10 +73,10 @@
   bool IsWritePending() const;
 
   // Attempts to cancel a pending read operation.
-  void CancelRead(serial::ReceiveError reason);
+  void CancelRead(mojom::SerialReceiveError reason);
 
   // Attempts to cancel a pending write operation.
-  void CancelWrite(serial::SendError reason);
+  void CancelWrite(mojom::SerialSendError reason);
 
   // Flushes input and output buffers.
   virtual bool Flush() const = 0;
@@ -84,22 +84,22 @@
   // Reads current control signals (DCD, CTS, etc.) into an existing
   // DeviceControlSignals structure. Returns |true| iff the signals were
   // successfully read.
-  virtual serial::DeviceControlSignalsPtr GetControlSignals() const = 0;
+  virtual mojom::SerialDeviceControlSignalsPtr GetControlSignals() const = 0;
 
   // Sets one or more control signals (DTR and/or RTS). Returns |true| iff
   // the signals were successfully set. Unininitialized flags in the
   // HostControlSignals structure are left unchanged.
   virtual bool SetControlSignals(
-      const serial::HostControlSignals& control_signals) = 0;
+      const mojom::SerialHostControlSignals& control_signals) = 0;
 
   // Performs platform-specific port configuration. Returns |true| iff
   // configuration was successful.
-  bool ConfigurePort(const serial::ConnectionOptions& options);
+  bool ConfigurePort(const mojom::SerialConnectionOptions& options);
 
   // Performs a platform-specific port configuration query. Fills values in an
   // existing ConnectionInfo. Returns |true| iff port configuration was
   // successfully retrieved.
-  virtual serial::ConnectionInfoPtr GetPortInfo() const = 0;
+  virtual mojom::SerialConnectionInfoPtr GetPortInfo() const = 0;
 
   // Initiates a BREAK signal. Places the transmission line in a break state
   // until the |ClearBreak| is called.
@@ -143,22 +143,22 @@
   // Called by the implementation to signal that the active read has completed.
   // WARNING: Calling this method can destroy the SerialIoHandler instance
   // if the associated I/O operation was the only thing keeping it alive.
-  void ReadCompleted(int bytes_read, serial::ReceiveError error);
+  void ReadCompleted(int bytes_read, mojom::SerialReceiveError error);
 
   // Called by the implementation to signal that the active write has completed.
   // WARNING: Calling this method may destroy the SerialIoHandler instance
   // if the associated I/O operation was the only thing keeping it alive.
-  void WriteCompleted(int bytes_written, serial::SendError error);
+  void WriteCompleted(int bytes_written, mojom::SerialSendError error);
 
   // Queues a ReadCompleted call on the current thread. This is used to allow
   // ReadImpl to immediately signal completion with 0 bytes and an error,
   // without being reentrant.
-  void QueueReadCompleted(int bytes_read, serial::ReceiveError error);
+  void QueueReadCompleted(int bytes_read, mojom::SerialReceiveError error);
 
   // Queues a WriteCompleted call on the current thread. This is used to allow
   // WriteImpl to immediately signal completion with 0 bytes and an error,
   // without being reentrant.
-  void QueueWriteCompleted(int bytes_written, serial::SendError error);
+  void QueueWriteCompleted(int bytes_written, mojom::SerialSendError error);
 
   const base::File& file() const { return file_; }
 
@@ -170,7 +170,7 @@
     return pending_read_buffer_ ? pending_read_buffer_->GetSize() : 0;
   }
 
-  serial::ReceiveError read_cancel_reason() const {
+  mojom::SerialReceiveError read_cancel_reason() const {
     return read_cancel_reason_;
   }
 
@@ -184,11 +184,13 @@
     return pending_write_buffer_ ? pending_write_buffer_->GetSize() : 0;
   }
 
-  serial::SendError write_cancel_reason() const { return write_cancel_reason_; }
+  mojom::SerialSendError write_cancel_reason() const {
+    return write_cancel_reason_;
+  }
 
   bool write_canceled() const { return write_canceled_; }
 
-  const serial::ConnectionOptions& options() const { return options_; }
+  const mojom::SerialConnectionOptions& options() const { return options_; }
 
   // Possibly fixes up a serial port path name in a platform-specific manner.
   static std::string MaybeFixUpPortName(const std::string& port_name);
@@ -204,7 +206,7 @@
  private:
   friend class base::RefCountedThreadSafe<SerialIoHandler>;
 
-  void MergeConnectionOptions(const serial::ConnectionOptions& options);
+  void MergeConnectionOptions(const mojom::SerialConnectionOptions& options);
 
   // Continues an Open operation on the FILE thread.
   void StartOpen(const std::string& port,
@@ -223,14 +225,14 @@
   base::File file_;
 
   // Currently applied connection options.
-  serial::ConnectionOptions options_;
+  mojom::SerialConnectionOptions options_;
 
   std::unique_ptr<WritableBuffer> pending_read_buffer_;
-  serial::ReceiveError read_cancel_reason_;
+  mojom::SerialReceiveError read_cancel_reason_;
   bool read_canceled_;
 
   std::unique_ptr<ReadOnlyBuffer> pending_write_buffer_;
-  serial::SendError write_cancel_reason_;
+  mojom::SerialSendError write_cancel_reason_;
   bool write_canceled_;
 
   // Callback to handle the completion of a pending Open() request.
diff --git a/device/serial/serial_io_handler_posix.cc b/device/serial/serial_io_handler_posix.cc
index 8ffba121..a7d77de 100644
--- a/device/serial/serial_io_handler_posix.cc
+++ b/device/serial/serial_io_handler_posix.cc
@@ -200,28 +200,28 @@
 #endif
   }
 
-  DCHECK(options().data_bits != serial::DataBits::NONE);
+  DCHECK(options().data_bits != mojom::SerialDataBits::NONE);
   config.c_cflag &= ~CSIZE;
   switch (options().data_bits) {
-    case serial::DataBits::SEVEN:
+    case mojom::SerialDataBits::SEVEN:
       config.c_cflag |= CS7;
       break;
-    case serial::DataBits::EIGHT:
+    case mojom::SerialDataBits::EIGHT:
     default:
       config.c_cflag |= CS8;
       break;
   }
 
-  DCHECK(options().parity_bit != serial::ParityBit::NONE);
+  DCHECK(options().parity_bit != mojom::SerialParityBit::NONE);
   switch (options().parity_bit) {
-    case serial::ParityBit::EVEN:
+    case mojom::SerialParityBit::EVEN:
       config.c_cflag |= PARENB;
       config.c_cflag &= ~PARODD;
       break;
-    case serial::ParityBit::ODD:
+    case mojom::SerialParityBit::ODD:
       config.c_cflag |= (PARODD | PARENB);
       break;
-    case serial::ParityBit::NO_PARITY:
+    case mojom::SerialParityBit::NO_PARITY:
     default:
       config.c_cflag &= ~(PARODD | PARENB);
       break;
@@ -240,12 +240,12 @@
     parity_check_enabled_ = false;
   }
 
-  DCHECK(options().stop_bits != serial::StopBits::NONE);
+  DCHECK(options().stop_bits != mojom::SerialStopBits::NONE);
   switch (options().stop_bits) {
-    case serial::StopBits::TWO:
+    case mojom::SerialStopBits::TWO:
       config.c_cflag |= CSTOPB;
       break;
-    case serial::StopBits::ONE:
+    case mojom::SerialStopBits::ONE:
     default:
       config.c_cflag &= ~CSTOPB;
       break;
@@ -308,12 +308,14 @@
         // The fd does not have data to read yet so continue waiting.
         EnsureWatchingReads();
       } else if (errno == ENXIO) {
-        RunReadCompleted(within_read, 0, serial::ReceiveError::DEVICE_LOST);
+        RunReadCompleted(within_read, 0,
+                         mojom::SerialReceiveError::DEVICE_LOST);
       } else {
-        RunReadCompleted(within_read, 0, serial::ReceiveError::SYSTEM_ERROR);
+        RunReadCompleted(within_read, 0,
+                         mojom::SerialReceiveError::SYSTEM_ERROR);
       }
     } else if (bytes_read == 0) {
-      RunReadCompleted(within_read, 0, serial::ReceiveError::DEVICE_LOST);
+      RunReadCompleted(within_read, 0, mojom::SerialReceiveError::DEVICE_LOST);
     } else {
       bool break_detected = false;
       bool parity_error_detected = false;
@@ -323,13 +325,13 @@
 
       if (break_detected) {
         RunReadCompleted(within_read, new_bytes_read,
-                         serial::ReceiveError::BREAK);
+                         mojom::SerialReceiveError::BREAK);
       } else if (parity_error_detected) {
         RunReadCompleted(within_read, new_bytes_read,
-                         serial::ReceiveError::PARITY_ERROR);
+                         mojom::SerialReceiveError::PARITY_ERROR);
       } else {
         RunReadCompleted(within_read, new_bytes_read,
-                         serial::ReceiveError::NONE);
+                         mojom::SerialReceiveError::NONE);
       }
     }
   } else {
@@ -341,7 +343,7 @@
 
 void SerialIoHandlerPosix::RunReadCompleted(bool within_read,
                                             int bytes_read,
-                                            serial::ReceiveError error) {
+                                            mojom::SerialReceiveError error) {
   if (within_read) {
     // Stop watching the fd to avoid more reads until the queued ReadCompleted()
     // completes and releases the pending_read_buffer.
@@ -361,9 +363,9 @@
                                            pending_write_buffer(),
                                            pending_write_buffer_len()));
     if (bytes_written < 0) {
-      WriteCompleted(0, serial::SendError::SYSTEM_ERROR);
+      WriteCompleted(0, mojom::SerialSendError::SYSTEM_ERROR);
     } else {
-      WriteCompleted(bytes_written, serial::SendError::NONE);
+      WriteCompleted(bytes_written, mojom::SerialSendError::NONE);
     }
   } else {
     // Stop watching the fd if we get notifications with no pending
@@ -401,15 +403,16 @@
   return true;
 }
 
-serial::DeviceControlSignalsPtr SerialIoHandlerPosix::GetControlSignals()
+mojom::SerialDeviceControlSignalsPtr SerialIoHandlerPosix::GetControlSignals()
     const {
   int status;
   if (ioctl(file().GetPlatformFile(), TIOCMGET, &status) == -1) {
     VPLOG(1) << "Failed to get port control signals";
-    return serial::DeviceControlSignalsPtr();
+    return mojom::SerialDeviceControlSignalsPtr();
   }
 
-  serial::DeviceControlSignalsPtr signals(serial::DeviceControlSignals::New());
+  mojom::SerialDeviceControlSignalsPtr signals(
+      mojom::SerialDeviceControlSignals::New());
   signals->dcd = (status & TIOCM_CAR) != 0;
   signals->cts = (status & TIOCM_CTS) != 0;
   signals->dsr = (status & TIOCM_DSR) != 0;
@@ -418,7 +421,7 @@
 }
 
 bool SerialIoHandlerPosix::SetControlSignals(
-    const serial::HostControlSignals& signals) {
+    const mojom::SerialHostControlSignals& signals) {
   int status;
 
   if (ioctl(file().GetPlatformFile(), TIOCMGET, &status) == -1) {
@@ -449,7 +452,7 @@
   return true;
 }
 
-serial::ConnectionInfoPtr SerialIoHandlerPosix::GetPortInfo() const {
+mojom::SerialConnectionInfoPtr SerialIoHandlerPosix::GetPortInfo() const {
 #if defined(OS_LINUX)
   struct termios2 config;
   if (ioctl(file().GetPlatformFile(), TCGETS2, &config) < 0) {
@@ -458,10 +461,10 @@
   if (tcgetattr(file().GetPlatformFile(), &config) == -1) {
 #endif
     VPLOG(1) << "Failed to get port info";
-    return serial::ConnectionInfoPtr();
+    return mojom::SerialConnectionInfoPtr();
   }
 
-  serial::ConnectionInfoPtr info(serial::ConnectionInfo::New());
+  mojom::SerialConnectionInfoPtr info(mojom::SerialConnectionInfo::New());
 #if defined(OS_LINUX)
   // Linux forces c_ospeed to contain the correct value, which is nice.
   info->bitrate = config.c_ospeed;
@@ -479,20 +482,20 @@
 #endif
 
   if ((config.c_cflag & CSIZE) == CS7) {
-    info->data_bits = serial::DataBits::SEVEN;
+    info->data_bits = mojom::SerialDataBits::SEVEN;
   } else if ((config.c_cflag & CSIZE) == CS8) {
-    info->data_bits = serial::DataBits::EIGHT;
+    info->data_bits = mojom::SerialDataBits::EIGHT;
   } else {
-    info->data_bits = serial::DataBits::NONE;
+    info->data_bits = mojom::SerialDataBits::NONE;
   }
   if (config.c_cflag & PARENB) {
-    info->parity_bit = (config.c_cflag & PARODD) ? serial::ParityBit::ODD
-                                                 : serial::ParityBit::EVEN;
+    info->parity_bit = (config.c_cflag & PARODD) ? mojom::SerialParityBit::ODD
+                                                 : mojom::SerialParityBit::EVEN;
   } else {
-    info->parity_bit = serial::ParityBit::NO_PARITY;
+    info->parity_bit = mojom::SerialParityBit::NO_PARITY;
   }
-  info->stop_bits =
-      (config.c_cflag & CSTOPB) ? serial::StopBits::TWO : serial::StopBits::ONE;
+  info->stop_bits = (config.c_cflag & CSTOPB) ? mojom::SerialStopBits::TWO
+                                              : mojom::SerialStopBits::ONE;
   info->cts_flow_control = (config.c_cflag & CRTSCTS) != 0;
   return info;
 }
diff --git a/device/serial/serial_io_handler_posix.h b/device/serial/serial_io_handler_posix.h
index ee5d129..7b8abd0 100644
--- a/device/serial/serial_io_handler_posix.h
+++ b/device/serial/serial_io_handler_posix.h
@@ -30,10 +30,10 @@
   bool ConfigurePortImpl() override;
   bool PostOpen() override;
   bool Flush() const override;
-  serial::DeviceControlSignalsPtr GetControlSignals() const override;
+  mojom::SerialDeviceControlSignalsPtr GetControlSignals() const override;
   bool SetControlSignals(
-      const serial::HostControlSignals& control_signals) override;
-  serial::ConnectionInfoPtr GetPortInfo() const override;
+      const mojom::SerialHostControlSignals& control_signals) override;
+  mojom::SerialConnectionInfoPtr GetPortInfo() const override;
   bool SetBreak() override;
   bool ClearBreak() override;
   int CheckReceiveError(char* buffer,
@@ -53,7 +53,7 @@
   void AttemptRead(bool within_read);
   void RunReadCompleted(bool within_read,
                         int bytes_read,
-                        serial::ReceiveError error);
+                        mojom::SerialReceiveError error);
 
   // Called when file() is writable without blocking.
   void OnFileCanWriteWithoutBlocking();
diff --git a/device/serial/serial_io_handler_win.cc b/device/serial/serial_io_handler_win.cc
index 9a25e9a..359ffc3 100644
--- a/device/serial/serial_io_handler_win.cc
+++ b/device/serial/serial_io_handler_win.cc
@@ -49,33 +49,33 @@
 #undef BITRATE_TO_SPEED_CASE
 }
 
-int DataBitsEnumToConstant(serial::DataBits data_bits) {
+int DataBitsEnumToConstant(mojom::SerialDataBits data_bits) {
   switch (data_bits) {
-    case serial::DataBits::SEVEN:
+    case mojom::SerialDataBits::SEVEN:
       return 7;
-    case serial::DataBits::EIGHT:
+    case mojom::SerialDataBits::EIGHT:
     default:
       return 8;
   }
 }
 
-int ParityBitEnumToConstant(serial::ParityBit parity_bit) {
+int ParityBitEnumToConstant(mojom::SerialParityBit parity_bit) {
   switch (parity_bit) {
-    case serial::ParityBit::EVEN:
+    case mojom::SerialParityBit::EVEN:
       return EVENPARITY;
-    case serial::ParityBit::ODD:
+    case mojom::SerialParityBit::ODD:
       return ODDPARITY;
-    case serial::ParityBit::NO_PARITY:
+    case mojom::SerialParityBit::NO_PARITY:
     default:
       return NOPARITY;
   }
 }
 
-int StopBitsEnumToConstant(serial::StopBits stop_bits) {
+int StopBitsEnumToConstant(mojom::SerialStopBits stop_bits) {
   switch (stop_bits) {
-    case serial::StopBits::TWO:
+    case mojom::SerialStopBits::TWO:
       return TWOSTOPBITS;
-    case serial::StopBits::ONE:
+    case mojom::SerialStopBits::ONE:
     default:
       return ONESTOPBIT;
   }
@@ -109,35 +109,35 @@
 #undef SPEED_TO_BITRATE_CASE
 }
 
-serial::DataBits DataBitsConstantToEnum(int data_bits) {
+mojom::SerialDataBits DataBitsConstantToEnum(int data_bits) {
   switch (data_bits) {
     case 7:
-      return serial::DataBits::SEVEN;
+      return mojom::SerialDataBits::SEVEN;
     case 8:
     default:
-      return serial::DataBits::EIGHT;
+      return mojom::SerialDataBits::EIGHT;
   }
 }
 
-serial::ParityBit ParityBitConstantToEnum(int parity_bit) {
+mojom::SerialParityBit ParityBitConstantToEnum(int parity_bit) {
   switch (parity_bit) {
     case EVENPARITY:
-      return serial::ParityBit::EVEN;
+      return mojom::SerialParityBit::EVEN;
     case ODDPARITY:
-      return serial::ParityBit::ODD;
+      return mojom::SerialParityBit::ODD;
     case NOPARITY:
     default:
-      return serial::ParityBit::NO_PARITY;
+      return mojom::SerialParityBit::NO_PARITY;
   }
 }
 
-serial::StopBits StopBitsConstantToEnum(int stop_bits) {
+mojom::SerialStopBits StopBitsConstantToEnum(int stop_bits) {
   switch (stop_bits) {
     case TWOSTOPBITS:
-      return serial::StopBits::TWO;
+      return mojom::SerialStopBits::TWO;
     case ONESTOPBIT:
     default:
-      return serial::StopBits::ONE;
+      return mojom::SerialStopBits::ONE;
   }
 }
 
@@ -228,7 +228,7 @@
   }
 
   if (port() == com_port)
-    CancelRead(serial::ReceiveError::DEVICE_LOST);
+    CancelRead(mojom::SerialReceiveError::DEVICE_LOST);
 }
 
 bool SerialIoHandlerWin::PostOpen() {
@@ -278,7 +278,7 @@
       file().GetPlatformFile(), &event_mask_, &comm_context_->overlapped);
   if (!ok && GetLastError() != ERROR_IO_PENDING) {
     VPLOG(1) << "Failed to receive serial event";
-    QueueReadCompleted(0, serial::ReceiveError::SYSTEM_ERROR);
+    QueueReadCompleted(0, mojom::SerialReceiveError::SYSTEM_ERROR);
   }
   is_comm_pending_ = true;
 }
@@ -295,7 +295,7 @@
                         &write_context_->overlapped);
   if (!ok && GetLastError() != ERROR_IO_PENDING) {
     VPLOG(1) << "Write failed";
-    QueueWriteCompleted(0, serial::SendError::SYSTEM_ERROR);
+    QueueWriteCompleted(0, mojom::SerialSendError::SYSTEM_ERROR);
   }
 }
 
@@ -332,13 +332,13 @@
   DCHECK(options().bitrate);
   config.BaudRate = BitrateToSpeedConstant(options().bitrate);
 
-  DCHECK(options().data_bits != serial::DataBits::NONE);
+  DCHECK(options().data_bits != mojom::SerialDataBits::NONE);
   config.ByteSize = DataBitsEnumToConstant(options().data_bits);
 
-  DCHECK(options().parity_bit != serial::ParityBit::NONE);
+  DCHECK(options().parity_bit != mojom::SerialParityBit::NONE);
   config.Parity = ParityBitEnumToConstant(options().parity_bit);
 
-  DCHECK(options().stop_bits != serial::StopBits::NONE);
+  DCHECK(options().stop_bits != mojom::SerialStopBits::NONE);
   config.StopBits = StopBitsEnumToConstant(options().stop_bits);
 
   DCHECK(options().has_cts_flow_control);
@@ -380,17 +380,17 @@
     if (!ClearCommError(file().GetPlatformFile(), &errors, &status) ||
         errors != 0) {
       if (errors & CE_BREAK) {
-        ReadCompleted(0, serial::ReceiveError::BREAK);
+        ReadCompleted(0, mojom::SerialReceiveError::BREAK);
       } else if (errors & CE_FRAME) {
-        ReadCompleted(0, serial::ReceiveError::FRAME_ERROR);
+        ReadCompleted(0, mojom::SerialReceiveError::FRAME_ERROR);
       } else if (errors & CE_OVERRUN) {
-        ReadCompleted(0, serial::ReceiveError::OVERRUN);
+        ReadCompleted(0, mojom::SerialReceiveError::OVERRUN);
       } else if (errors & CE_RXOVER) {
-        ReadCompleted(0, serial::ReceiveError::BUFFER_OVERFLOW);
+        ReadCompleted(0, mojom::SerialReceiveError::BUFFER_OVERFLOW);
       } else if (errors & CE_RXPARITY) {
-        ReadCompleted(0, serial::ReceiveError::PARITY_ERROR);
+        ReadCompleted(0, mojom::SerialReceiveError::PARITY_ERROR);
       } else {
-        ReadCompleted(0, serial::ReceiveError::SYSTEM_ERROR);
+        ReadCompleted(0, mojom::SerialReceiveError::SYSTEM_ERROR);
       }
       return;
     }
@@ -398,7 +398,7 @@
     if (read_canceled()) {
       ReadCompleted(bytes_transferred, read_cancel_reason());
     } else if (error != ERROR_SUCCESS && error != ERROR_OPERATION_ABORTED) {
-      ReadCompleted(0, serial::ReceiveError::SYSTEM_ERROR);
+      ReadCompleted(0, mojom::SerialReceiveError::SYSTEM_ERROR);
     } else if (pending_read_buffer()) {
       BOOL ok = ::ReadFile(file().GetPlatformFile(),
                            pending_read_buffer(),
@@ -407,26 +407,26 @@
                            &read_context_->overlapped);
       if (!ok && GetLastError() != ERROR_IO_PENDING) {
         VPLOG(1) << "Read failed";
-        ReadCompleted(0, serial::ReceiveError::SYSTEM_ERROR);
+        ReadCompleted(0, mojom::SerialReceiveError::SYSTEM_ERROR);
       }
     }
   } else if (context == read_context_.get()) {
     if (read_canceled()) {
       ReadCompleted(bytes_transferred, read_cancel_reason());
     } else if (error != ERROR_SUCCESS && error != ERROR_OPERATION_ABORTED) {
-      ReadCompleted(0, serial::ReceiveError::SYSTEM_ERROR);
+      ReadCompleted(0, mojom::SerialReceiveError::SYSTEM_ERROR);
     } else {
       ReadCompleted(bytes_transferred,
                     error == ERROR_SUCCESS
-                        ? serial::ReceiveError::NONE
-                        : serial::ReceiveError::SYSTEM_ERROR);
+                        ? mojom::SerialReceiveError::NONE
+                        : mojom::SerialReceiveError::SYSTEM_ERROR);
     }
   } else if (context == write_context_.get()) {
     DCHECK(pending_write_buffer());
     if (write_canceled()) {
       WriteCompleted(0, write_cancel_reason());
     } else if (error != ERROR_SUCCESS && error != ERROR_OPERATION_ABORTED) {
-      WriteCompleted(0, serial::SendError::SYSTEM_ERROR);
+      WriteCompleted(0, mojom::SerialSendError::SYSTEM_ERROR);
       if (error == ERROR_GEN_FAILURE && IsReadPending()) {
         // For devices using drivers such as FTDI, CP2xxx, when device is
         // disconnected, the context is comm_context_ and the error is
@@ -435,14 +435,15 @@
         // disconnected, the context is write_context_ and the error is
         // ERROR_GEN_FAILURE. In this situation, in addition to a write error
         // signal, also need to generate a read error signal
-        // serial::OnReceiveError which will notify the app about the
+        // mojom::SerialOnReceiveError which will notify the app about the
         // disconnection.
-        CancelRead(serial::ReceiveError::SYSTEM_ERROR);
+        CancelRead(mojom::SerialReceiveError::SYSTEM_ERROR);
       }
     } else {
-      WriteCompleted(bytes_transferred, error == ERROR_SUCCESS
-                                            ? serial::SendError::NONE
-                                            : serial::SendError::SYSTEM_ERROR);
+      WriteCompleted(bytes_transferred,
+                     error == ERROR_SUCCESS
+                         ? mojom::SerialSendError::NONE
+                         : mojom::SerialSendError::SYSTEM_ERROR);
     }
   } else {
     NOTREACHED() << "Invalid IOContext";
@@ -457,14 +458,16 @@
   return true;
 }
 
-serial::DeviceControlSignalsPtr SerialIoHandlerWin::GetControlSignals() const {
+mojom::SerialDeviceControlSignalsPtr SerialIoHandlerWin::GetControlSignals()
+    const {
   DWORD status;
   if (!GetCommModemStatus(file().GetPlatformFile(), &status)) {
     VPLOG(1) << "Failed to get port control signals";
-    return serial::DeviceControlSignalsPtr();
+    return mojom::SerialDeviceControlSignalsPtr();
   }
 
-  serial::DeviceControlSignalsPtr signals(serial::DeviceControlSignals::New());
+  mojom::SerialDeviceControlSignalsPtr signals(
+      mojom::SerialDeviceControlSignals::New());
   signals->dcd = (status & MS_RLSD_ON) != 0;
   signals->cts = (status & MS_CTS_ON) != 0;
   signals->dsr = (status & MS_DSR_ON) != 0;
@@ -473,7 +476,7 @@
 }
 
 bool SerialIoHandlerWin::SetControlSignals(
-    const serial::HostControlSignals& signals) {
+    const mojom::SerialHostControlSignals& signals) {
   if (signals.has_dtr) {
     if (!EscapeCommFunction(file().GetPlatformFile(),
                             signals.dtr ? SETDTR : CLRDTR)) {
@@ -491,14 +494,14 @@
   return true;
 }
 
-serial::ConnectionInfoPtr SerialIoHandlerWin::GetPortInfo() const {
+mojom::SerialConnectionInfoPtr SerialIoHandlerWin::GetPortInfo() const {
   DCB config = {0};
   config.DCBlength = sizeof(config);
   if (!GetCommState(file().GetPlatformFile(), &config)) {
     VPLOG(1) << "Failed to get serial port info";
-    return serial::ConnectionInfoPtr();
+    return mojom::SerialConnectionInfoPtr();
   }
-  serial::ConnectionInfoPtr info(serial::ConnectionInfo::New());
+  mojom::SerialConnectionInfoPtr info(mojom::SerialConnectionInfo::New());
   info->bitrate = SpeedConstantToBitrate(config.BaudRate);
   info->data_bits = DataBitsConstantToEnum(config.ByteSize);
   info->parity_bit = ParityBitConstantToEnum(config.Parity);
diff --git a/device/serial/serial_io_handler_win.h b/device/serial/serial_io_handler_win.h
index bb31bea..96b495d 100644
--- a/device/serial/serial_io_handler_win.h
+++ b/device/serial/serial_io_handler_win.h
@@ -25,10 +25,10 @@
   void CancelWriteImpl() override;
   bool ConfigurePortImpl() override;
   bool Flush() const override;
-  serial::DeviceControlSignalsPtr GetControlSignals() const override;
+  mojom::SerialDeviceControlSignalsPtr GetControlSignals() const override;
   bool SetControlSignals(
-      const serial::HostControlSignals& control_signals) override;
-  serial::ConnectionInfoPtr GetPortInfo() const override;
+      const mojom::SerialHostControlSignals& control_signals) override;
+  mojom::SerialConnectionInfoPtr GetPortInfo() const override;
   bool SetBreak() override;
   bool ClearBreak() override;
   bool PostOpen() override;
diff --git a/device/serial/test_serial_io_handler.cc b/device/serial/test_serial_io_handler.cc
index 50c38db..3007b46a 100644
--- a/device/serial/test_serial_io_handler.cc
+++ b/device/serial/test_serial_io_handler.cc
@@ -26,7 +26,7 @@
 }
 
 void TestSerialIoHandler::Open(const std::string& port,
-                               const serial::ConnectionOptions& options,
+                               const mojom::SerialConnectionOptions& options,
                                const OpenCompleteCallback& callback) {
   DCHECK(!opened_);
   opened_ = true;
@@ -44,7 +44,8 @@
       std::min(buffer_.size(), static_cast<size_t>(pending_read_buffer_len()));
   memcpy(pending_read_buffer(), buffer_.c_str(), num_bytes);
   buffer_ = buffer_.substr(num_bytes);
-  ReadCompleted(static_cast<uint32_t>(num_bytes), serial::ReceiveError::NONE);
+  ReadCompleted(static_cast<uint32_t>(num_bytes),
+                mojom::SerialReceiveError::NONE);
 }
 
 void TestSerialIoHandler::CancelReadImpl() {
@@ -59,7 +60,7 @@
     return;
   }
   buffer_ += std::string(pending_write_buffer(), pending_write_buffer_len());
-  WriteCompleted(pending_write_buffer_len(), serial::SendError::NONE);
+  WriteCompleted(pending_write_buffer_len(), mojom::SerialSendError::NONE);
   if (pending_read_buffer())
     ReadImpl();
 }
@@ -77,14 +78,16 @@
   return true;
 }
 
-serial::DeviceControlSignalsPtr TestSerialIoHandler::GetControlSignals() const {
-  serial::DeviceControlSignalsPtr signals(serial::DeviceControlSignals::New());
+mojom::SerialDeviceControlSignalsPtr TestSerialIoHandler::GetControlSignals()
+    const {
+  mojom::SerialDeviceControlSignalsPtr signals(
+      mojom::SerialDeviceControlSignals::New());
   *signals = device_control_signals_;
   return signals;
 }
 
-serial::ConnectionInfoPtr TestSerialIoHandler::GetPortInfo() const {
-  serial::ConnectionInfoPtr info(serial::ConnectionInfo::New());
+mojom::SerialConnectionInfoPtr TestSerialIoHandler::GetPortInfo() const {
+  mojom::SerialConnectionInfoPtr info(mojom::SerialConnectionInfo::New());
   *info = info_;
   return info;
 }
@@ -95,7 +98,7 @@
 }
 
 bool TestSerialIoHandler::SetControlSignals(
-    const serial::HostControlSignals& signals) {
+    const mojom::SerialHostControlSignals& signals) {
   if (signals.has_dtr)
     dtr_ = signals.dtr;
   if (signals.has_rts)
diff --git a/device/serial/test_serial_io_handler.h b/device/serial/test_serial_io_handler.h
index 50891784..a49af11 100644
--- a/device/serial/test_serial_io_handler.h
+++ b/device/serial/test_serial_io_handler.h
@@ -22,22 +22,23 @@
 
   // SerialIoHandler overrides.
   void Open(const std::string& port,
-            const serial::ConnectionOptions& options,
+            const mojom::SerialConnectionOptions& options,
             const OpenCompleteCallback& callback) override;
   void ReadImpl() override;
   void CancelReadImpl() override;
   void WriteImpl() override;
   void CancelWriteImpl() override;
   bool ConfigurePortImpl() override;
-  serial::DeviceControlSignalsPtr GetControlSignals() const override;
-  serial::ConnectionInfoPtr GetPortInfo() const override;
+  mojom::SerialDeviceControlSignalsPtr GetControlSignals() const override;
+  mojom::SerialConnectionInfoPtr GetPortInfo() const override;
   bool Flush() const override;
-  bool SetControlSignals(const serial::HostControlSignals& signals) override;
+  bool SetControlSignals(
+      const mojom::SerialHostControlSignals& signals) override;
   bool SetBreak() override;
   bool ClearBreak() override;
 
-  serial::ConnectionInfo* connection_info() { return &info_; }
-  serial::DeviceControlSignals* device_control_signals() {
+  mojom::SerialConnectionInfo* connection_info() { return &info_; }
+  mojom::SerialDeviceControlSignals* device_control_signals() {
     return &device_control_signals_;
   }
   bool dtr() { return dtr_; }
@@ -54,8 +55,8 @@
 
  private:
   bool opened_;
-  serial::ConnectionInfo info_;
-  serial::DeviceControlSignals device_control_signals_;
+  mojom::SerialConnectionInfo info_;
+  mojom::SerialDeviceControlSignals device_control_signals_;
   bool dtr_;
   bool rts_;
   mutable int flushes_;
diff --git a/docs/testing/layout_test_expectations.md b/docs/testing/layout_test_expectations.md
index 2023fbd0..c283864 100644
--- a/docs/testing/layout_test_expectations.md
+++ b/docs/testing/layout_test_expectations.md
@@ -94,8 +94,6 @@
 `third_party/WebKit/Tools/Scripts/webkit-patch rebaseline-cl`:
 
 1. First, upload a CL.
-   There is no need to add `[ NeedsRebaseline ]` lines in TestExpectations for
-   tests that are rebaselined by this method.
 2. Trigger try jobs by running `webkit-patch rebaseline-cl`. This should
    trigger jobs on
    [tryserver.blink](https://build.chromium.org/p/tryserver.blink/builders).
@@ -112,6 +110,8 @@
 
 #### Options
 
+### Rebaselining with try jobs
+
 The tests which `webkit-patch rebaseline-cl` tries to download new baselines for
 depends on its arguments.
 
@@ -125,19 +125,6 @@
   assuming that there are no platform-specific results for those platforms,
   you can add the flag `--fill-missing`.
 
-### Rebaselining with rebaseline-o-matic
-
-If the test is not already listed in
-[TestExpectations](../../third_party/WebKit/LayoutTests/TestExpectations), you
-can mark it as `[ NeedsRebaseline ]`. The
-[rebaseline-o-matic bot](https://build.chromium.org/p/chromium.infra.cron/builders/rebaseline-o-matic)
-will automatically detect when the bots have cycled (by looking at the blame on
-the file) and do the rebaseline for you. As long as the test doesn't timeout or
-crash, it won't turn the bots red if it has a `NeedsRebaseline` expectation.
-When  all of the continuous builders on the waterfall have cycled, the
-rebaseline-o-matic bot will commit a patch which includes the new baselines and
-removes the `[ NeedsRebaseline ]` entry from TestExpectations.
-
 ### Rebaselining manually
 
 1. If the tests is already listed in TestExpectations as flaky, mark the test
@@ -150,8 +137,8 @@
 ## Kinds of expectations files
 
 * [TestExpectations](../../third_party/WebKit/LayoutTests/TestExpectations): The
-  main test failure suppression file. In theory, this should be used for flaky
-  lines and `NeedsRebaseline`/`NeedsManualRebaseline` lines.
+  main test failure suppression file. In theory, this should be used for
+  temporarily marking tests as flaky.
 * [ASANExpectations](../../third_party/WebKit/LayoutTests/ASANExpectations):
   Tests that fail under ASAN.
 * [LeakExpectations](../../third_party/WebKit/LayoutTests/LeakExpectations):
@@ -219,9 +206,9 @@
   [third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py](../../third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py)
   for the meta keywords and which modifiers they represent.
 * Expectations can be one or more of `Crash`, `Failure`, `Pass`, `Rebaseline`,
-  `Slow`, `Skip`, `Timeout`, `WontFix`, `Missing`, `NeedsRebaseline`,
-  `NeedsManualRebaseline`. If multiple expectations are listed, the test is
-  considered "flaky" and any of those results will be considered as expected.
+  `Slow`, `Skip`, `Timeout`, `WontFix`, `Missing`, `NeedsManualRebaseline`.
+  If multiple expectations are listed, the test is considered "flaky" and any
+  of those results will be considered as expected.
 
 For example:
 
diff --git a/extensions/browser/api/serial/serial_api.cc b/extensions/browser/api/serial/serial_api.cc
index 734b6b3f..a493ae9 100644
--- a/extensions/browser/api/serial/serial_api.cc
+++ b/extensions/browser/api/serial/serial_api.cc
@@ -87,7 +87,8 @@
 
   std::unique_ptr<device::SerialDeviceEnumerator> enumerator =
       device::SerialDeviceEnumerator::Create();
-  std::vector<device::serial::DeviceInfoPtr> devices = enumerator->GetDevices();
+  std::vector<device::mojom::SerialDeviceInfoPtr> devices =
+      enumerator->GetDevices();
   results_ = serial::GetDevices::Results::Create(
       mojo::ConvertTo<std::vector<serial::DeviceInfo>>(devices));
 }
@@ -450,10 +451,10 @@
 namespace mojo {
 
 // static
-extensions::api::serial::DeviceInfo TypeConverter<
-    extensions::api::serial::DeviceInfo,
-    device::serial::DeviceInfoPtr>::Convert(const device::serial::DeviceInfoPtr&
-                                                device) {
+extensions::api::serial::DeviceInfo
+TypeConverter<extensions::api::serial::DeviceInfo,
+              device::mojom::SerialDeviceInfoPtr>::
+    Convert(const device::mojom::SerialDeviceInfoPtr& device) {
   extensions::api::serial::DeviceInfo info;
   info.path = device->path;
   if (device->has_vendor_id)
diff --git a/extensions/browser/api/serial/serial_api.h b/extensions/browser/api/serial/serial_api.h
index d22808f..c2bd5c3 100644
--- a/extensions/browser/api/serial/serial_api.h
+++ b/extensions/browser/api/serial/serial_api.h
@@ -279,9 +279,9 @@
 
 template <>
 struct TypeConverter<extensions::api::serial::DeviceInfo,
-                     device::serial::DeviceInfoPtr> {
+                     device::mojom::SerialDeviceInfoPtr> {
   static extensions::api::serial::DeviceInfo Convert(
-      const device::serial::DeviceInfoPtr& input);
+      const device::mojom::SerialDeviceInfoPtr& input);
 };
 
 }  // namespace mojo
diff --git a/extensions/browser/api/serial/serial_apitest.cc b/extensions/browser/api/serial/serial_apitest.cc
index 37567658e..fe37900 100644
--- a/extensions/browser/api/serial/serial_apitest.cc
+++ b/extensions/browser/api/serial/serial_apitest.cc
@@ -49,11 +49,13 @@
  public:
   ~FakeSerialDeviceEnumerator() override {}
 
-  std::vector<device::serial::DeviceInfoPtr> GetDevices() override {
-    std::vector<device::serial::DeviceInfoPtr> devices;
-    device::serial::DeviceInfoPtr device0(device::serial::DeviceInfo::New());
+  std::vector<device::mojom::SerialDeviceInfoPtr> GetDevices() override {
+    std::vector<device::mojom::SerialDeviceInfoPtr> devices;
+    device::mojom::SerialDeviceInfoPtr device0(
+        device::mojom::SerialDeviceInfo::New());
     device0->path = "/dev/fakeserialmojo";
-    device::serial::DeviceInfoPtr device1(device::serial::DeviceInfo::New());
+    device::mojom::SerialDeviceInfoPtr device1(
+        device::mojom::SerialDeviceInfo::New());
     device1->path = "\\\\COM800\\";
     devices.push_back(std::move(device0));
     devices.push_back(std::move(device1));
@@ -76,7 +78,7 @@
   }
 
   MOCK_METHOD1(SetControlSignals,
-               bool(const device::serial::HostControlSignals&));
+               bool(const device::mojom::SerialHostControlSignals&));
 
  protected:
   ~FakeEchoSerialIoHandler() override {}
diff --git a/extensions/browser/api/serial/serial_connection.cc b/extensions/browser/api/serial/serial_connection.cc
index 488669b..b9e7b96 100644
--- a/extensions/browser/api/serial/serial_connection.cc
+++ b/extensions/browser/api/serial/serial_connection.cc
@@ -24,124 +24,129 @@
 const int kDefaultBufferSize = 4096;
 
 api::serial::SendError ConvertSendErrorFromMojo(
-    device::serial::SendError input) {
+    device::mojom::SerialSendError input) {
   switch (input) {
-    case device::serial::SendError::NONE:
+    case device::mojom::SerialSendError::NONE:
       return api::serial::SEND_ERROR_NONE;
-    case device::serial::SendError::DISCONNECTED:
+    case device::mojom::SerialSendError::DISCONNECTED:
       return api::serial::SEND_ERROR_DISCONNECTED;
-    case device::serial::SendError::PENDING:
+    case device::mojom::SerialSendError::PENDING:
       return api::serial::SEND_ERROR_PENDING;
-    case device::serial::SendError::TIMEOUT:
+    case device::mojom::SerialSendError::TIMEOUT:
       return api::serial::SEND_ERROR_TIMEOUT;
-    case device::serial::SendError::SYSTEM_ERROR:
+    case device::mojom::SerialSendError::SYSTEM_ERROR:
       return api::serial::SEND_ERROR_SYSTEM_ERROR;
   }
   return api::serial::SEND_ERROR_NONE;
 }
 
 api::serial::ReceiveError ConvertReceiveErrorFromMojo(
-    device::serial::ReceiveError input) {
+    device::mojom::SerialReceiveError input) {
   switch (input) {
-    case device::serial::ReceiveError::NONE:
+    case device::mojom::SerialReceiveError::NONE:
       return api::serial::RECEIVE_ERROR_NONE;
-    case device::serial::ReceiveError::DISCONNECTED:
+    case device::mojom::SerialReceiveError::DISCONNECTED:
       return api::serial::RECEIVE_ERROR_DISCONNECTED;
-    case device::serial::ReceiveError::TIMEOUT:
+    case device::mojom::SerialReceiveError::TIMEOUT:
       return api::serial::RECEIVE_ERROR_TIMEOUT;
-    case device::serial::ReceiveError::DEVICE_LOST:
+    case device::mojom::SerialReceiveError::DEVICE_LOST:
       return api::serial::RECEIVE_ERROR_DEVICE_LOST;
-    case device::serial::ReceiveError::BREAK:
+    case device::mojom::SerialReceiveError::BREAK:
       return api::serial::RECEIVE_ERROR_BREAK;
-    case device::serial::ReceiveError::FRAME_ERROR:
+    case device::mojom::SerialReceiveError::FRAME_ERROR:
       return api::serial::RECEIVE_ERROR_FRAME_ERROR;
-    case device::serial::ReceiveError::OVERRUN:
+    case device::mojom::SerialReceiveError::OVERRUN:
       return api::serial::RECEIVE_ERROR_OVERRUN;
-    case device::serial::ReceiveError::BUFFER_OVERFLOW:
+    case device::mojom::SerialReceiveError::BUFFER_OVERFLOW:
       return api::serial::RECEIVE_ERROR_BUFFER_OVERFLOW;
-    case device::serial::ReceiveError::PARITY_ERROR:
+    case device::mojom::SerialReceiveError::PARITY_ERROR:
       return api::serial::RECEIVE_ERROR_PARITY_ERROR;
-    case device::serial::ReceiveError::SYSTEM_ERROR:
+    case device::mojom::SerialReceiveError::SYSTEM_ERROR:
       return api::serial::RECEIVE_ERROR_SYSTEM_ERROR;
   }
   return api::serial::RECEIVE_ERROR_NONE;
 }
 
-api::serial::DataBits ConvertDataBitsFromMojo(device::serial::DataBits input) {
+api::serial::DataBits ConvertDataBitsFromMojo(
+    device::mojom::SerialDataBits input) {
   switch (input) {
-    case device::serial::DataBits::NONE:
+    case device::mojom::SerialDataBits::NONE:
       return api::serial::DATA_BITS_NONE;
-    case device::serial::DataBits::SEVEN:
+    case device::mojom::SerialDataBits::SEVEN:
       return api::serial::DATA_BITS_SEVEN;
-    case device::serial::DataBits::EIGHT:
+    case device::mojom::SerialDataBits::EIGHT:
       return api::serial::DATA_BITS_EIGHT;
   }
   return api::serial::DATA_BITS_NONE;
 }
 
-device::serial::DataBits ConvertDataBitsToMojo(api::serial::DataBits input) {
+device::mojom::SerialDataBits ConvertDataBitsToMojo(
+    api::serial::DataBits input) {
   switch (input) {
     case api::serial::DATA_BITS_NONE:
-      return device::serial::DataBits::NONE;
+      return device::mojom::SerialDataBits::NONE;
     case api::serial::DATA_BITS_SEVEN:
-      return device::serial::DataBits::SEVEN;
+      return device::mojom::SerialDataBits::SEVEN;
     case api::serial::DATA_BITS_EIGHT:
-      return device::serial::DataBits::EIGHT;
+      return device::mojom::SerialDataBits::EIGHT;
   }
-  return device::serial::DataBits::NONE;
+  return device::mojom::SerialDataBits::NONE;
 }
 
 api::serial::ParityBit ConvertParityBitFromMojo(
-    device::serial::ParityBit input) {
+    device::mojom::SerialParityBit input) {
   switch (input) {
-    case device::serial::ParityBit::NONE:
+    case device::mojom::SerialParityBit::NONE:
       return api::serial::PARITY_BIT_NONE;
-    case device::serial::ParityBit::ODD:
+    case device::mojom::SerialParityBit::ODD:
       return api::serial::PARITY_BIT_ODD;
-    case device::serial::ParityBit::NO_PARITY:
+    case device::mojom::SerialParityBit::NO_PARITY:
       return api::serial::PARITY_BIT_NO;
-    case device::serial::ParityBit::EVEN:
+    case device::mojom::SerialParityBit::EVEN:
       return api::serial::PARITY_BIT_EVEN;
   }
   return api::serial::PARITY_BIT_NONE;
 }
 
-device::serial::ParityBit ConvertParityBitToMojo(api::serial::ParityBit input) {
+device::mojom::SerialParityBit ConvertParityBitToMojo(
+    api::serial::ParityBit input) {
   switch (input) {
     case api::serial::PARITY_BIT_NONE:
-      return device::serial::ParityBit::NONE;
+      return device::mojom::SerialParityBit::NONE;
     case api::serial::PARITY_BIT_NO:
-      return device::serial::ParityBit::NO_PARITY;
+      return device::mojom::SerialParityBit::NO_PARITY;
     case api::serial::PARITY_BIT_ODD:
-      return device::serial::ParityBit::ODD;
+      return device::mojom::SerialParityBit::ODD;
     case api::serial::PARITY_BIT_EVEN:
-      return device::serial::ParityBit::EVEN;
+      return device::mojom::SerialParityBit::EVEN;
   }
-  return device::serial::ParityBit::NONE;
+  return device::mojom::SerialParityBit::NONE;
 }
 
-api::serial::StopBits ConvertStopBitsFromMojo(device::serial::StopBits input) {
+api::serial::StopBits ConvertStopBitsFromMojo(
+    device::mojom::SerialStopBits input) {
   switch (input) {
-    case device::serial::StopBits::NONE:
+    case device::mojom::SerialStopBits::NONE:
       return api::serial::STOP_BITS_NONE;
-    case device::serial::StopBits::ONE:
+    case device::mojom::SerialStopBits::ONE:
       return api::serial::STOP_BITS_ONE;
-    case device::serial::StopBits::TWO:
+    case device::mojom::SerialStopBits::TWO:
       return api::serial::STOP_BITS_TWO;
   }
   return api::serial::STOP_BITS_NONE;
 }
 
-device::serial::StopBits ConvertStopBitsToMojo(api::serial::StopBits input) {
+device::mojom::SerialStopBits ConvertStopBitsToMojo(
+    api::serial::StopBits input) {
   switch (input) {
     case api::serial::STOP_BITS_NONE:
-      return device::serial::StopBits::NONE;
+      return device::mojom::SerialStopBits::NONE;
     case api::serial::STOP_BITS_ONE:
-      return device::serial::StopBits::ONE;
+      return device::mojom::SerialStopBits::ONE;
     case api::serial::STOP_BITS_TWO:
-      return device::serial::StopBits::TWO;
+      return device::mojom::SerialStopBits::TWO;
   }
-  return device::serial::StopBits::NONE;
+  return device::mojom::SerialStopBits::NONE;
 }
 
 }  // namespace
@@ -173,8 +178,8 @@
 }
 
 SerialConnection::~SerialConnection() {
-  io_handler_->CancelRead(device::serial::ReceiveError::DISCONNECTED);
-  io_handler_->CancelWrite(device::serial::SendError::DISCONNECTED);
+  io_handler_->CancelRead(device::mojom::SerialReceiveError::DISCONNECTED);
+  io_handler_->CancelWrite(device::mojom::SerialSendError::DISCONNECTED);
 }
 
 bool SerialConnection::IsPersistent() const {
@@ -196,7 +201,7 @@
 void SerialConnection::set_paused(bool paused) {
   paused_ = paused;
   if (paused) {
-    io_handler_->CancelRead(device::serial::ReceiveError::NONE);
+    io_handler_->CancelRead(device::mojom::SerialReceiveError::NONE);
   }
 }
 
@@ -213,8 +218,8 @@
     set_receive_timeout(*options.receive_timeout);
   if (options.send_timeout.get())
     set_send_timeout(*options.send_timeout);
-  io_handler_->Open(port_, *device::serial::ConnectionOptions::From(options),
-                    callback);
+  io_handler_->Open(
+      port_, *device::mojom::SerialConnectionOptions::From(options), callback);
 }
 
 bool SerialConnection::Receive(const ReceiveCompleteCallback& callback) {
@@ -266,8 +271,8 @@
   if (options.send_timeout.get())
     set_send_timeout(*options.send_timeout);
   bool success = io_handler_->ConfigurePort(
-      *device::serial::ConnectionOptions::From(options));
-  io_handler_->CancelRead(device::serial::ReceiveError::NONE);
+      *device::mojom::SerialConnectionOptions::From(options));
+  io_handler_->CancelRead(device::mojom::SerialReceiveError::NONE);
   return success;
 }
 
@@ -284,7 +289,7 @@
   info->buffer_size = buffer_size_;
   info->receive_timeout = receive_timeout_;
   info->send_timeout = send_timeout_;
-  device::serial::ConnectionInfoPtr port_info = io_handler_->GetPortInfo();
+  device::mojom::SerialConnectionInfoPtr port_info = io_handler_->GetPortInfo();
   if (!port_info)
     return false;
 
@@ -302,7 +307,7 @@
 
 bool SerialConnection::GetControlSignals(
     api::serial::DeviceControlSignals* control_signals) const {
-  device::serial::DeviceControlSignalsPtr signals =
+  device::mojom::SerialDeviceControlSignalsPtr signals =
       io_handler_->GetControlSignals();
   if (!signals)
     return false;
@@ -317,7 +322,7 @@
 bool SerialConnection::SetControlSignals(
     const api::serial::HostControlSignals& control_signals) {
   return io_handler_->SetControlSignals(
-      *device::serial::HostControlSignals::From(control_signals));
+      *device::mojom::SerialHostControlSignals::From(control_signals));
 }
 
 bool SerialConnection::SetBreak() {
@@ -330,16 +335,17 @@
 
 void SerialConnection::OnReceiveTimeout() {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  io_handler_->CancelRead(device::serial::ReceiveError::TIMEOUT);
+  io_handler_->CancelRead(device::mojom::SerialReceiveError::TIMEOUT);
 }
 
 void SerialConnection::OnSendTimeout() {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  io_handler_->CancelWrite(device::serial::SendError::TIMEOUT);
+  io_handler_->CancelWrite(device::mojom::SerialSendError::TIMEOUT);
 }
 
-void SerialConnection::OnAsyncReadComplete(int bytes_read,
-                                           device::serial::ReceiveError error) {
+void SerialConnection::OnAsyncReadComplete(
+    int bytes_read,
+    device::mojom::SerialReceiveError error) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(!receive_complete_.is_null());
   ReceiveCompleteCallback callback = receive_complete_;
@@ -351,8 +357,9 @@
   receive_buffer_ = NULL;
 }
 
-void SerialConnection::OnAsyncWriteComplete(int bytes_sent,
-                                            device::serial::SendError error) {
+void SerialConnection::OnAsyncWriteComplete(
+    int bytes_sent,
+    device::mojom::SerialSendError error) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(!send_complete_.is_null());
   SendCompleteCallback callback = send_complete_;
@@ -381,12 +388,12 @@
 namespace mojo {
 
 // static
-device::serial::HostControlSignalsPtr
-TypeConverter<device::serial::HostControlSignalsPtr,
+device::mojom::SerialHostControlSignalsPtr
+TypeConverter<device::mojom::SerialHostControlSignalsPtr,
               extensions::api::serial::HostControlSignals>::
     Convert(const extensions::api::serial::HostControlSignals& input) {
-  device::serial::HostControlSignalsPtr output(
-      device::serial::HostControlSignals::New());
+  device::mojom::SerialHostControlSignalsPtr output(
+      device::mojom::SerialHostControlSignals::New());
   if (input.dtr.get()) {
     output->has_dtr = true;
     output->dtr = *input.dtr;
@@ -399,12 +406,12 @@
 }
 
 // static
-device::serial::ConnectionOptionsPtr
-TypeConverter<device::serial::ConnectionOptionsPtr,
+device::mojom::SerialConnectionOptionsPtr
+TypeConverter<device::mojom::SerialConnectionOptionsPtr,
               extensions::api::serial::ConnectionOptions>::
     Convert(const extensions::api::serial::ConnectionOptions& input) {
-  device::serial::ConnectionOptionsPtr output(
-      device::serial::ConnectionOptions::New());
+  device::mojom::SerialConnectionOptionsPtr output(
+      device::mojom::SerialConnectionOptions::New());
   if (input.bitrate.get() && *input.bitrate > 0)
     output->bitrate = *input.bitrate;
   output->data_bits = extensions::ConvertDataBitsToMojo(input.data_bits);
diff --git a/extensions/browser/api/serial/serial_connection.h b/extensions/browser/api/serial/serial_connection.h
index d9ab5d7..1e3288af 100644
--- a/extensions/browser/api/serial/serial_connection.h
+++ b/extensions/browser/api/serial/serial_connection.h
@@ -149,10 +149,12 @@
   void OnSendTimeout();
 
   // Receives read completion notification from the |io_handler_|.
-  void OnAsyncReadComplete(int bytes_read, device::serial::ReceiveError error);
+  void OnAsyncReadComplete(int bytes_read,
+                           device::mojom::SerialReceiveError error);
 
   // Receives write completion notification from the |io_handler_|.
-  void OnAsyncWriteComplete(int bytes_sent, device::serial::SendError error);
+  void OnAsyncWriteComplete(int bytes_sent,
+                            device::mojom::SerialSendError error);
 
   // The pathname of the serial device.
   std::string port_;
@@ -204,16 +206,16 @@
 namespace mojo {
 
 template <>
-struct TypeConverter<device::serial::HostControlSignalsPtr,
+struct TypeConverter<device::mojom::SerialHostControlSignalsPtr,
                      extensions::api::serial::HostControlSignals> {
-  static device::serial::HostControlSignalsPtr Convert(
+  static device::mojom::SerialHostControlSignalsPtr Convert(
       const extensions::api::serial::HostControlSignals& input);
 };
 
 template <>
-struct TypeConverter<device::serial::ConnectionOptionsPtr,
+struct TypeConverter<device::mojom::SerialConnectionOptionsPtr,
                      extensions::api::serial::ConnectionOptions> {
-  static device::serial::ConnectionOptionsPtr Convert(
+  static device::mojom::SerialConnectionOptionsPtr Convert(
       const extensions::api::serial::ConnectionOptions& input);
 };
 
diff --git a/extensions/browser/sandboxed_unpacker.cc b/extensions/browser/sandboxed_unpacker.cc
index a88157396..f49e9292 100644
--- a/extensions/browser/sandboxed_unpacker.cc
+++ b/extensions/browser/sandboxed_unpacker.cc
@@ -377,13 +377,17 @@
 
   utility_process_mojo_client_.reset();
 
-  ReportFailure(
-      UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL,
-      l10n_util::GetStringFUTF16(
-          IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-          ASCIIToUTF16("UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL")) +
-          ASCIIToUTF16(". ") +
-          l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_PROCESS_CRASHED));
+  unpacker_io_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(
+          &SandboxedUnpacker::ReportFailure, this,
+          UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL,
+          l10n_util::GetStringFUTF16(
+              IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+              ASCIIToUTF16("UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL")) +
+              ASCIIToUTF16(". ") +
+              l10n_util::GetStringUTF16(
+                  IDS_EXTENSION_INSTALL_PROCESS_CRASHED)));
 }
 
 void SandboxedUnpacker::Unzip(const base::FilePath& crx_path) {
@@ -406,8 +410,11 @@
 
   if (!success) {
     utility_process_mojo_client_.reset();
-    ReportFailure(UNZIP_FAILED,
-                  l10n_util::GetStringUTF16(IDS_EXTENSION_PACKAGE_UNZIP_ERROR));
+    unpacker_io_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(
+            &SandboxedUnpacker::ReportFailure, this, UNZIP_FAILED,
+            l10n_util::GetStringUTF16(IDS_EXTENSION_PACKAGE_UNZIP_ERROR)));
     return;
   }
 
@@ -663,6 +670,8 @@
 
 void SandboxedUnpacker::ReportFailure(FailureReason reason,
                                       const base::string16& error) {
+  DCHECK(unpacker_io_task_runner_->RunsTasksInCurrentSequence());
+
   UMA_HISTOGRAM_ENUMERATION("Extensions.SandboxUnpackFailureReason", reason,
                             NUM_FAILURE_REASONS);
   if (!crx_unpack_start_time_.is_null())
diff --git a/extensions/browser/sandboxed_unpacker_unittest.cc b/extensions/browser/sandboxed_unpacker_unittest.cc
index 8975af2..ce9190e 100644
--- a/extensions/browser/sandboxed_unpacker_unittest.cc
+++ b/extensions/browser/sandboxed_unpacker_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "components/crx_file/id_util.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_utils.h"
 #include "extensions/browser/extensions_test.h"
@@ -65,8 +66,11 @@
 class SandboxedUnpackerTest : public ExtensionsTest {
  public:
   SandboxedUnpackerTest()
-      : ExtensionsTest(base::MakeUnique<content::TestBrowserThreadBundle>(
-            content::TestBrowserThreadBundle::IO_MAINLOOP)) {}
+      : SandboxedUnpackerTest(content::TestBrowserThreadBundle::IO_MAINLOOP) {}
+
+  SandboxedUnpackerTest(content::TestBrowserThreadBundle::Options options)
+      : ExtensionsTest(
+            base::MakeUnique<content::TestBrowserThreadBundle>(options)) {}
 
   void SetUp() override {
     ExtensionsTest::SetUp();
@@ -125,6 +129,20 @@
     client_->WaitForUnpack();
   }
 
+  void SimulateUtilityProcessCrash() {
+    sandboxed_unpacker_->CreateTempDirectory();
+
+    content::BrowserThread::PostTask(
+        content::BrowserThread::IO, FROM_HERE,
+        base::Bind(&SandboxedUnpacker::StartUtilityProcessIfNeeded,
+                   sandboxed_unpacker_));
+
+    content::BrowserThread::PostTask(
+        content::BrowserThread::IO, FROM_HERE,
+        base::Bind(&SandboxedUnpacker::UtilityProcessCrashed,
+                   sandboxed_unpacker_));
+  }
+
   base::FilePath GetInstallPath() {
     return client_->temp_dir().AppendASCII(kTempExtensionName);
   }
@@ -191,4 +209,18 @@
   EXPECT_EQ(base::string16(), GetInstallError());
 }
 
+class SandboxedUnpackerTestWithRealIOThread : public SandboxedUnpackerTest {
+ public:
+  SandboxedUnpackerTestWithRealIOThread()
+      : SandboxedUnpackerTest(
+            content::TestBrowserThreadBundle::REAL_IO_THREAD) {}
+};
+
+TEST_F(SandboxedUnpackerTestWithRealIOThread, UtilityProcessCrash) {
+  SimulateUtilityProcessCrash();
+  client_->WaitForUnpack();
+  // Check that there is an error message.
+  EXPECT_NE(base::string16(), GetInstallError());
+}
+
 }  // namespace extensions
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 0b07c67..c0b793c 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -684,7 +684,6 @@
 
   // Initialize or re-initialize the shader translator.
   bool InitializeShaderTranslator();
-  void DestroyShaderTranslator();
 
   void UpdateCapabilities();
 
@@ -1751,7 +1750,7 @@
       GLuint renderbuffer, GLenum format);
 
   // Wrapper for glReleaseShaderCompiler.
-  void DoReleaseShaderCompiler();
+  void DoReleaseShaderCompiler() { }
 
   // Wrappers for glSamplerParameter functions.
   void DoSamplerParameterf(GLuint client_id, GLenum pname, GLfloat param);
@@ -2372,7 +2371,6 @@
   // if not returning an error.
   error::Error current_decoder_error_;
 
-  bool has_fragment_precision_high_ = false;
   scoped_refptr<ShaderTranslatorInterface> vertex_translator_;
   scoped_refptr<ShaderTranslatorInterface> fragment_translator_;
 
@@ -3538,12 +3536,9 @@
                               features().khr_robustness ||
                               features().ext_robustness;
 
-  GLint range[2] = {0, 0};
-  GLint precision = 0;
-  QueryShaderPrecisionFormat(gl_version_info(), GL_FRAGMENT_SHADER,
-                             GL_HIGH_FLOAT, range, &precision);
-  has_fragment_precision_high_ =
-      PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
+  if (!InitializeShaderTranslator()) {
+    return false;
+  }
 
   GLint viewport_params[4] = { 0 };
   glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params);
@@ -3904,10 +3899,6 @@
   if (feature_info_->disable_shader_translator()) {
     return true;
   }
-  if (vertex_translator_ || fragment_translator_) {
-    DCHECK(vertex_translator_ && fragment_translator_);
-    return true;
-  }
   ShBuiltInResources resources;
   sh::InitBuiltInResources(&resources);
   resources.MaxVertexAttribs = group_->max_vertex_attribs();
@@ -3934,7 +3925,12 @@
     resources.MinProgramTexelOffset = group_->min_program_texel_offset();
   }
 
-  resources.FragmentPrecisionHigh = has_fragment_precision_high_;
+  GLint range[2] = { 0, 0 };
+  GLint precision = 0;
+  QueryShaderPrecisionFormat(gl_version_info(), GL_FRAGMENT_SHADER,
+                             GL_HIGH_FLOAT, range, &precision);
+  resources.FragmentPrecisionHigh =
+      PrecisionMeetsSpecForHighpFloat(range[0], range[1], precision);
 
   ShShaderSpec shader_spec;
   switch (feature_info_->context_type()) {
@@ -4053,11 +4049,6 @@
   return true;
 }
 
-void GLES2DecoderImpl::DestroyShaderTranslator() {
-  vertex_translator_ = nullptr;
-  fragment_translator_ = nullptr;
-}
-
 bool GLES2DecoderImpl::GenBuffersHelper(GLsizei n, const GLuint* client_ids) {
   for (GLsizei ii = 0; ii < n; ++ii) {
     if (GetBuffer(client_ids[ii])) {
@@ -4919,7 +4910,8 @@
 
   // Need to release these before releasing |group_| which may own the
   // ShaderTranslatorCache.
-  DestroyShaderTranslator();
+  fragment_translator_ = NULL;
+  vertex_translator_ = NULL;
 
   // Destroy the GPU Tracer which may own some in process GPU Timings.
   if (gpu_tracer_) {
@@ -8736,10 +8728,6 @@
       pixel[2] == 0xFF);
 }
 
-void GLES2DecoderImpl::DoReleaseShaderCompiler() {
-  DestroyShaderTranslator();
-}
-
 void GLES2DecoderImpl::DoRenderbufferStorage(
   GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
   Renderbuffer* renderbuffer =
@@ -10569,9 +10557,6 @@
 
 scoped_refptr<ShaderTranslatorInterface> GLES2DecoderImpl::GetTranslator(
     GLenum type) {
-  if (!InitializeShaderTranslator()) {
-    return nullptr;
-  }
   return type == GL_VERTEX_SHADER ? vertex_translator_ : fragment_translator_;
 }
 
@@ -15845,7 +15830,7 @@
     frag_depth_explicitly_enabled_ |= desire_frag_depth;
     draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
     shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
-    DestroyShaderTranslator();
+    InitializeShaderTranslator();
   }
 
   if (feature_str.find("GL_CHROMIUM_color_buffer_float_rgba ") !=
diff --git a/gpu/command_buffer/service/shader_manager.cc b/gpu/command_buffer/service/shader_manager.cc
index 01596d37..8a77b519 100644
--- a/gpu/command_buffer/service/shader_manager.cc
+++ b/gpu/command_buffer/service/shader_manager.cc
@@ -121,8 +121,6 @@
         << "\n--translated-shader--\n" << source_for_driver
         << "\n--info-log--\n" << log_info_;
   }
-
-  translator_ = nullptr;
 }
 
 void Shader::RefreshTranslatedShaderSource() {
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json
index 9e0b0d9..4a6ec35c 100644
--- a/gpu/config/gpu_driver_bug_list.json
+++ b/gpu/config/gpu_driver_bug_list.json
@@ -2530,14 +2530,14 @@
     },
     {
       "id": 234,
-      "description": "Disable EGL_EXT_image_flush_external on NVIDIA",
+      "description": "Avoid using EGL_IMAGE_EXTERNAL_FLUSH_EXT with eglCreateImageKHR on NVIDIA",
       "cr_bugs": [727462],
       "os": {
         "type": "chromeos"
       },
       "gl_vendor": "NVIDIA.*",
-      "disabled_extensions": [
-        "EGL_EXT_image_flush_external"
+      "features": [
+        "avoid_using_image_flush_external_with_egl_create_image"
       ]
     },
     {
diff --git a/gpu/config/gpu_driver_bug_workaround_type.h b/gpu/config/gpu_driver_bug_workaround_type.h
index 67c224a..20e3472 100644
--- a/gpu/config/gpu_driver_bug_workaround_type.h
+++ b/gpu/config/gpu_driver_bug_workaround_type.h
@@ -229,6 +229,8 @@
          wake_up_gpu_before_drawing)                         \
   GPU_OP(RELY_ON_IMPLICIT_SYNC_FOR_SWAP_BUFFERS,             \
          rely_on_implicit_sync_for_swap_buffers)             \
+  GPU_OP(AVOID_USING_IMAGE_FLUSH_EXTERNAL_WITH_EGL_CREATE_IMAGE, \
+         avoid_using_image_flush_external_with_egl_create_image) \
 // clang-format on
 
 namespace gpu {
diff --git a/gpu/ipc/service/direct_composition_child_surface_win.cc b/gpu/ipc/service/direct_composition_child_surface_win.cc
index e93aae9..7bbfeea3 100644
--- a/gpu/ipc/service/direct_composition_child_surface_win.cc
+++ b/gpu/ipc/service/direct_composition_child_surface_win.cc
@@ -158,7 +158,7 @@
       }
     }
   }
-  if (dcomp_surface_ == g_current_surface)
+  if (dcomp_surface_.Get() == g_current_surface)
     g_current_surface = nullptr;
 }
 
@@ -177,7 +177,7 @@
     }
     real_surface_ = nullptr;
   }
-  if (dcomp_surface_ && (dcomp_surface_ == g_current_surface)) {
+  if (dcomp_surface_ && (dcomp_surface_.Get() == g_current_surface)) {
     HRESULT hr = dcomp_surface_->EndDraw();
     CHECK(SUCCEEDED(hr));
     g_current_surface = nullptr;
@@ -212,7 +212,7 @@
 }
 
 bool DirectCompositionChildSurfaceWin::OnMakeCurrent(gl::GLContext* context) {
-  if (g_current_surface != dcomp_surface_) {
+  if (g_current_surface != dcomp_surface_.Get()) {
     if (g_current_surface) {
       HRESULT hr = g_current_surface->SuspendDraw();
       CHECK(SUCCEEDED(hr));
diff --git a/gpu/ipc/service/direct_composition_surface_win_unittest.cc b/gpu/ipc/service/direct_composition_surface_win_unittest.cc
index 264c44b..a546429b 100644
--- a/gpu/ipc/service/direct_composition_surface_win_unittest.cc
+++ b/gpu/ipc/service/direct_composition_surface_win_unittest.cc
@@ -356,7 +356,7 @@
 
   base::win::ScopedComPtr<IDXGISwapChain1> swap_chain2 =
       surface->GetLayerSwapChainForTesting(1);
-  EXPECT_EQ(swap_chain2, swap_chain);
+  EXPECT_EQ(swap_chain2.Get(), swap_chain.Get());
 
   // It's the same image, so it should have the same swapchain.
   EXPECT_TRUE(SUCCEEDED(swap_chain->GetLastPresentCount(&last_present_count)));
@@ -374,7 +374,7 @@
 
   base::win::ScopedComPtr<IDXGISwapChain1> swap_chain3 =
       surface->GetLayerSwapChainForTesting(1);
-  EXPECT_NE(swap_chain2, swap_chain3);
+  EXPECT_NE(swap_chain2.Get(), swap_chain3.Get());
 
   context = nullptr;
   DestroySurface(std::move(surface));
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm
index 12c3656..d70099e 100644
--- a/ios/chrome/app/main_controller.mm
+++ b/ios/chrome/app/main_controller.mm
@@ -1240,6 +1240,7 @@
   if (firstRun || [self shouldOpenNTPTabOnActivationOfTabModel:tabModel]) {
     OpenNewTabCommand* command = [OpenNewTabCommand
         commandWithIncognito:(self.currentBVC == self.otrBVC)];
+    command.userInitiated = NO;
     [self.currentBVC.dispatcher openNewTab:command];
   }
 
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index 9428362..99722d9 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -529,10 +529,7 @@
         Save Image
       </message>
       <message name="IDS_IOS_CONTENT_SUGGESTIONS_ACCESSIBILITY_LABEL_SUGGESTION" desc="The accessibility label of a suggestion. Summarizes fields in the reading list entry (title, publisher informations, status and informations). Read by Text-to-Speech.">
-        <ph name="TITLE"><ex>Learn about the new Chromium Projects</ex>$1</ph>, <ph name="PUBLISHER_INFORMATION"><ex>The Chromium organization</ex>$2</ph>, <ph name="PUBLICATION_DATE"><ex>January 1 2017</ex>$3</ph>, <ph name="STATE"><ex>Available offline</ex>$4</ph>
-      </message>
-      <message name="IDS_IOS_CONTENT_SUGGESTIONS_ACCESSIBILITY_AVAILABLE_OFFLINE" desc="Accessibility label to indicate that the suggestion is available offline. Read by Text-to-Speech.">
-        Available offline
+        <ph name="TITLE"><ex>Learn about the new Chromium Projects</ex>$1</ph>, <ph name="PUBLISHER_INFORMATION"><ex>The Chromium organization</ex>$2</ph>, <ph name="PUBLICATION_DATE"><ex>January 1 2017</ex>$3</ph>
       </message>
       <message name="IDS_IOS_CONTENT_SUGGESTIONS_FOOTER_TITLE" desc="The title of the footer of the sections of Content Suggestions">
         More
diff --git a/ios/chrome/browser/content_suggestions/mediator_util.mm b/ios/chrome/browser/content_suggestions/mediator_util.mm
index 2042984..4dd5855 100644
--- a/ios/chrome/browser/content_suggestions/mediator_util.mm
+++ b/ios/chrome/browser/content_suggestions/mediator_util.mm
@@ -59,8 +59,6 @@
   suggestion.suggestionIdentifier.sectionInfo = sectionInfo;
 
   if (category.IsKnownCategory(ntp_snippets::KnownCategories::READING_LIST)) {
-    suggestion.availableOffline =
-        contentSuggestion.reading_list_suggestion_extra()->distilled;
     suggestion.faviconURL =
         contentSuggestion.reading_list_suggestion_extra()->favicon_page_url;
   }
diff --git a/ios/chrome/browser/experimental_flags.mm b/ios/chrome/browser/experimental_flags.mm
index bacb43a..81a010b 100644
--- a/ios/chrome/browser/experimental_flags.mm
+++ b/ios/chrome/browser/experimental_flags.mm
@@ -208,13 +208,16 @@
   return !command_line->HasSwitch(switches::kDisableTabStripAutoScrollNewTabs);
 }
 
+// This feature is on by default. Finch and experimental settings can be used to
+// disable it.
+// TODO(crbug.com/739404): Remove this method and the experimental flag once the
+// feature spends a couple of releases in stable.
 bool IsViewCopyPasswordsEnabled() {
+  if (!base::FeatureList::IsEnabled(password_manager::features::kViewPasswords))
+    return false;
   NSString* viewCopyPasswordFlag = [[NSUserDefaults standardUserDefaults]
       objectForKey:kEnableViewCopyPasswords];
-  if ([viewCopyPasswordFlag isEqualToString:@"Enabled"])
-    return true;
-  return base::FeatureList::IsEnabled(
-      password_manager::features::kViewPasswords);
+  return ![viewCopyPasswordFlag isEqualToString:@"Disabled"];
 }
 
 bool UseOnlyLocalHeuristicsForPasswordGeneration() {
diff --git a/ios/chrome/browser/feature_engagement_tracker/BUILD.gn b/ios/chrome/browser/feature_engagement_tracker/BUILD.gn
index 480b628c..b90bbd0 100644
--- a/ios/chrome/browser/feature_engagement_tracker/BUILD.gn
+++ b/ios/chrome/browser/feature_engagement_tracker/BUILD.gn
@@ -6,6 +6,8 @@
   sources = [
     "feature_engagement_tracker_factory.h",
     "feature_engagement_tracker_factory.mm",
+    "feature_engagement_tracker_util.h",
+    "feature_engagement_tracker_util.mm",
   ]
 
   configs += [ "//build/config/compiler:enable_arc" ]
@@ -16,5 +18,6 @@
     "//components/keyed_service/ios",
     "//ios/chrome/browser",
     "//ios/chrome/browser/browser_state",
+    "//ios/chrome/browser/ui/commands",
   ]
 }
diff --git a/ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_util.h b/ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_util.h
new file mode 100644
index 0000000..52189b7
--- /dev/null
+++ b/ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_util.h
@@ -0,0 +1,24 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace ios {
+class ChromeBrowserState;
+}  // namespace ios
+@class OpenNewTabCommand;
+
+namespace feature_engagement_tracker {
+// Sends a new tab event to the FeatureEngagementTracker based on |isIncognito|.
+// If |isIncognito| is |true|, then the "Incognito Tab Opened" is fired. If
+// |isIncognito| is |false|, then the "New Tab Event" is fired.
+void NotifyNewTabEvent(ios::ChromeBrowserState* browserState, bool isIncognito);
+
+// Sends a new tab event to the FeatureEngagementTracker based on
+// |command.incognito| and |command.userInitiated|. If |command.userInitiated|
+// is |false|, then no event is fired. If |command.userInitiated| is |true|,
+// then one of the new tab events is fired. If |command.incognito| is |true|,
+// then the "Incognito Tab Opened" event is fired, and if |command.incognito| is
+// |false|, then the "New Tab Opened" event is fired.
+void NotifyNewTabEventForCommand(ios::ChromeBrowserState* browserState,
+                                 OpenNewTabCommand* command);
+}  // namespace feature_engagement_tracker
diff --git a/ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_util.mm b/ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_util.mm
new file mode 100644
index 0000000..e9b358a
--- /dev/null
+++ b/ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_util.mm
@@ -0,0 +1,30 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_util.h"
+
+#include "components/feature_engagement_tracker/public/event_constants.h"
+#include "components/feature_engagement_tracker/public/feature_engagement_tracker.h"
+#include "ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h"
+#import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
+
+namespace feature_engagement_tracker {
+
+void NotifyNewTabEvent(ios::ChromeBrowserState* browserState,
+                       bool isIncognito) {
+  const char* const event =
+      isIncognito ? feature_engagement_tracker::events::kIncognitoTabOpened
+                  : feature_engagement_tracker::events::kNewTabOpened;
+  FeatureEngagementTrackerFactory::GetForBrowserState(browserState)
+      ->NotifyEvent(std::string(event));
+}
+
+void NotifyNewTabEventForCommand(ios::ChromeBrowserState* browserState,
+                                 OpenNewTabCommand* command) {
+  if (command.isUserInitiated) {
+    NotifyNewTabEvent(browserState, command.incognito);
+  }
+}
+
+}  // namespace feature_engagement_tracker
diff --git a/ios/chrome/browser/ui/BUILD.gn b/ios/chrome/browser/ui/BUILD.gn
index 5db31d0..3407dcb 100644
--- a/ios/chrome/browser/ui/BUILD.gn
+++ b/ios/chrome/browser/ui/BUILD.gn
@@ -340,6 +340,7 @@
     "//base",
     "//base:i18n",
     "//components/bookmarks/browser",
+    "//components/feature_engagement_tracker",
     "//components/image_fetcher/ios",
     "//components/infobars/core",
     "//components/payments/core",
@@ -357,6 +358,7 @@
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/content_suggestions",
     "//ios/chrome/browser/favicon",
+    "//ios/chrome/browser/feature_engagement_tracker",
     "//ios/chrome/browser/find_in_page",
     "//ios/chrome/browser/first_run",
     "//ios/chrome/browser/geolocation:geolocation_internal",
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_handset_view_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_home_handset_view_controller.mm
index ced41cc..0b050dc 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_home_handset_view_controller.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_handset_view_controller.mm
@@ -193,6 +193,7 @@
   self.folderView.frame = self.panelView.contentView.bounds;
   [self.panelView.contentView addSubview:self.folderView];
   [self.panelView.menuView addSubview:self.menuView];
+  [self.menuView setFrame:self.panelView.menuView.bounds];
 
   // Load the last primary menu item which the user had active.
   BookmarkMenuItem* item = nil;
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index dd8679f..6bd8571e 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -38,6 +38,8 @@
 #include "base/threading/thread_restrictions.h"
 #include "components/bookmarks/browser/base_bookmark_model_observer.h"
 #include "components/bookmarks/browser/bookmark_model.h"
+#include "components/feature_engagement_tracker/public/event_constants.h"
+#include "components/feature_engagement_tracker/public/feature_engagement_tracker.h"
 #include "components/image_fetcher/ios/ios_image_data_fetcher_wrapper.h"
 #include "components/infobars/core/infobar_manager.h"
 #include "components/payments/core/features.h"
@@ -56,6 +58,8 @@
 #include "ios/chrome/browser/experimental_flags.h"
 #import "ios/chrome/browser/favicon/favicon_loader.h"
 #include "ios/chrome/browser/favicon/ios_chrome_favicon_loader_factory.h"
+#include "ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h"
+#include "ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_util.h"
 #import "ios/chrome/browser/find_in_page/find_in_page_controller.h"
 #import "ios/chrome/browser/find_in_page/find_in_page_model.h"
 #import "ios/chrome/browser/find_in_page/find_tab_helper.h"
@@ -2573,8 +2577,12 @@
           IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB);
       action = ^{
         Record(ACTION_OPEN_IN_NEW_TAB, isImage, isLink);
+        // The "New Tab" item in the context menu opens a new tab in the current
+        // browser state. |isOffTheRecord| indicates whether or not the current
+        // browser state is incognito.
         [weakSelf webPageOrderedOpen:link
                             referrer:referrer
+                         inIncognito:weakSelf.isOffTheRecord
                         inBackground:YES
                             appendTo:kCurrentTab];
       };
@@ -3780,6 +3788,11 @@
                inIncognito:(BOOL)inIncognito
               inBackground:(BOOL)inBackground
                   appendTo:(OpenPosition)appendTo {
+  // Send either the "New Tab Opened" or "New Incognito Tab" opened to the
+  // FeatureEngagementTracker based on |inIncognito|.
+  feature_engagement_tracker::NotifyNewTabEvent(_model.browserState,
+                                                inIncognito);
+
   if (inIncognito == _isOffTheRecord) {
     [self webPageOrderedOpen:url
                     referrer:referrer
@@ -4022,6 +4035,12 @@
     return;
   }
 
+  // Either send or don't send the "New Tab Opened" or "Incognito Tab Opened"
+  // events to the FeatureEngagementTracker based on |command.userInitiated| and
+  // |command.incognito|.
+  feature_engagement_tracker::NotifyNewTabEventForCommand(_browserState,
+                                                          command);
+
   NSTimeInterval startTime = [NSDate timeIntervalSinceReferenceDate];
   BOOL offTheRecord = self.isOffTheRecord;
   ProceduralBlock oldForegroundTabWasAddedCompletionBlock =
diff --git a/ios/chrome/browser/ui/commands/open_new_tab_command.h b/ios/chrome/browser/ui/commands/open_new_tab_command.h
index 9e3af58..baf2008b 100644
--- a/ios/chrome/browser/ui/commands/open_new_tab_command.h
+++ b/ios/chrome/browser/ui/commands/open_new_tab_command.h
@@ -38,6 +38,12 @@
 
 @property(nonatomic, readonly) CGPoint originPoint;
 
+// Whether the new tab command was initiated by the user (e.g. by tapping the
+// new tab button in the tools menu) or not (e.g. opening a new tab via a
+// Javascript action). Defaults to |YES|.
+@property(nonatomic, readwrite, assign, getter=isUserInitiated)
+    BOOL userInitiated;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_COMMANDS_OPEN_NEW_TAB_COMMAND_H_
diff --git a/ios/chrome/browser/ui/commands/open_new_tab_command.mm b/ios/chrome/browser/ui/commands/open_new_tab_command.mm
index e261e41..18d9748 100644
--- a/ios/chrome/browser/ui/commands/open_new_tab_command.mm
+++ b/ios/chrome/browser/ui/commands/open_new_tab_command.mm
@@ -12,12 +12,14 @@
 
 @synthesize incognito = _incognito;
 @synthesize originPoint = _originPoint;
+@synthesize userInitiated = _userInitiated;
 
 - (instancetype)initWithIncognito:(BOOL)incognito
                       originPoint:(CGPoint)originPoint {
   if ((self = [super initWithTag:0])) {
     _incognito = incognito;
     _originPoint = originPoint;
+    _userInitiated = YES;
   }
   return self;
 }
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_cell.h b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_cell.h
index 82a15f05b..390305c 100644
--- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_cell.h
+++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_cell.h
@@ -24,8 +24,7 @@
 // Sets the publisher |name| and |date| and add an icon to signal the offline
 // availability if |availableOffline| is YES.
 - (void)setAdditionalInformationWithPublisherName:(NSString*)publisherName
-                                             date:(NSString*)publishDate
-                              offlineAvailability:(BOOL)availableOffline;
+                                             date:(NSString*)publishDate;
 
 // Returns the height needed by a cell contained in |width| and containing the
 // listed informations.
@@ -33,8 +32,7 @@
                 withImage:(BOOL)hasImage
                     title:(NSString*)title
             publisherName:(NSString*)publisherName
-          publicationDate:(NSString*)publicationDate
-         availableOffline:(BOOL)availableOffline;
+          publicationDate:(NSString*)publicationDate;
 
 @end
 
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_cell.mm b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_cell.mm
index a27cc80..9a11e2f 100644
--- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_cell.mm
+++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_cell.mm
@@ -20,11 +20,6 @@
 const CGFloat kStandardSpacing = 16;
 const CGFloat kSmallSpacing = 8;
 
-// Name of the icon displayed when a suggestion is available offline.
-NSString* const kOfflineIconName = @"content_suggestions_offline";
-// Size of the icon displayed when a suggestion is available offline.
-const CGFloat kOfflineIconSize = 16;
-
 // Size of the favicon view.
 const CGFloat kFaviconSize = 16;
 // Size of the icon displayed when there is not image but one should be
@@ -143,12 +138,9 @@
 }
 
 - (void)setAdditionalInformationWithPublisherName:(NSString*)publisherName
-                                             date:(NSString*)date
-                              offlineAvailability:(BOOL)availableOffline {
-  self.additionalInformationLabel.attributedText =
-      [[self class] attributedStringForPublisher:publisherName
-                                            date:date
-                                availableOffline:availableOffline];
+                                             date:(NSString*)date {
+  self.additionalInformationLabel.text =
+      [[self class] stringForPublisher:publisherName date:date];
 }
 
 - (void)setDisplayImage:(BOOL)displayImage {
@@ -168,18 +160,15 @@
                 withImage:(BOOL)hasImage
                     title:(NSString*)title
             publisherName:(NSString*)publisherName
-          publicationDate:(NSString*)publicationDate
-         availableOffline:(BOOL)availableOffline {
+          publicationDate:(NSString*)publicationDate {
   UILabel* titleLabel = [[UILabel alloc] init];
   [self configureTitleLabel:titleLabel];
   titleLabel.text = title;
 
   UILabel* additionalInfoLabel = [[UILabel alloc] init];
   additionalInfoLabel.font = [self additionalInformationFont];
-  additionalInfoLabel.attributedText =
-      [self attributedStringForPublisher:publisherName
-                                    date:publicationDate
-                        availableOffline:availableOffline];
+  additionalInfoLabel.text =
+      [self stringForPublisher:publisherName date:publicationDate];
 
   CGSize sizeForLabels =
       CGSizeMake(width - [self labelMarginWithImage:hasImage], 500);
@@ -317,29 +306,9 @@
 }
 
 // Returns the attributed string to be displayed.
-+ (NSAttributedString*)attributedStringForPublisher:(NSString*)publisherName
-                                               date:(NSString*)date
-                                   availableOffline:(BOOL)availableOffline {
-  NSString* publisherString = AdjustStringForLocaleDirection(
++ (NSString*)stringForPublisher:(NSString*)publisherName date:(NSString*)date {
+  return AdjustStringForLocaleDirection(
       [NSString stringWithFormat:@"%@ - %@ ", publisherName, date]);
-
-  NSMutableAttributedString* additionInformation =
-      [[NSMutableAttributedString alloc] initWithString:publisherString
-                                             attributes:nil];
-
-  if (availableOffline) {
-    NSTextAttachment* offlineIcon = [[NSTextAttachment alloc] init];
-    offlineIcon.image = [[UIImage imageNamed:kOfflineIconName]
-        imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
-    offlineIcon.bounds = CGRectMake(
-        0, ([self additionalInformationFont].xHeight - kOfflineIconSize) / 2,
-        kOfflineIconSize, kOfflineIconSize);
-
-    [additionInformation
-        appendAttributedString:[NSAttributedString
-                                   attributedStringWithAttachment:offlineIcon]];
-  }
-  return additionInformation;
 }
 
 @end
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.h b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.h
index dd52179..f7db2f4f 100644
--- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.h
+++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.h
@@ -44,8 +44,6 @@
 @property(nonatomic, strong) UIImage* image;
 // Whether the suggestion has an image associated.
 @property(nonatomic, assign) BOOL hasImage;
-// Whether the suggestion is available offline. If YES, an icon is displayed.
-@property(nonatomic, assign) BOOL availableOffline;
 // Attributes for favicon.
 @property(nonatomic, strong) FaviconAttributes* attributes;
 // URL for the favicon, if different of |URL|.
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.mm b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.mm
index d297b327..201092e 100644
--- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.mm
+++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.mm
@@ -45,7 +45,6 @@
 @synthesize attributes = _attributes;
 @synthesize faviconURL = _faviconURL;
 @synthesize hasImage = _hasImage;
-@synthesize availableOffline = _availableOffline;
 @synthesize firstTimeWithImage = _firstTimeWithImage;
 
 - (instancetype)initWithType:(NSInteger)type
@@ -73,8 +72,7 @@
   [cell setContentImage:self.image animated:self.firstTimeWithImage];
   self.firstTimeWithImage = NO;
   [cell setAdditionalInformationWithPublisherName:self.publisher
-                                             date:[self relativeDate]
-                              offlineAvailability:self.availableOffline];
+                                             date:[self relativeDate]];
   cell.isAccessibilityElement = YES;
   cell.accessibilityLabel = [self accessibilityLabel];
 }
@@ -90,8 +88,7 @@
                               withImage:self.hasImage
                                   title:self.title
                           publisherName:self.publisher
-                        publicationDate:[self relativeDate]
-                       availableOffline:self.availableOffline];
+                        publicationDate:[self relativeDate]];
 }
 
 #pragma mark - Private
@@ -117,18 +114,11 @@
 
 // Returns the accessibility label.
 - (NSString*)accessibilityLabel {
-  NSString* offlineAvailability = @"";
-  if (self.availableOffline) {
-    offlineAvailability = l10n_util::GetNSString(
-        IDS_IOS_CONTENT_SUGGESTIONS_ACCESSIBILITY_AVAILABLE_OFFLINE);
-  }
-
   return l10n_util::GetNSStringF(
       IDS_IOS_CONTENT_SUGGESTIONS_ACCESSIBILITY_LABEL_SUGGESTION,
       base::SysNSStringToUTF16(self.title),
       base::SysNSStringToUTF16(self.publisher),
-      base::SysNSStringToUTF16([self relativeDate]),
-      base::SysNSStringToUTF16(offlineAvailability));
+      base::SysNSStringToUTF16([self relativeDate]));
 }
 
 @end
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item_unittest.mm b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item_unittest.mm
index 3302d738..56d3175b 100644
--- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item_unittest.mm
+++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item_unittest.mm
@@ -37,7 +37,6 @@
   item.hasImage = YES;
   item.publisher = publisher;
   item.publishDate = publishTime;
-  item.availableOffline = YES;
   OCMExpect([delegateMock loadImageForSuggestedItem:item]);
   ContentSuggestionsCell* cell = [[[item cellClass] alloc] init];
   ASSERT_EQ([ContentSuggestionsCell class], [cell class]);
@@ -45,9 +44,8 @@
   ASSERT_EQ(nil, item.image);
   id cellMock = OCMPartialMock(cell);
   OCMExpect([cellMock setContentImage:item.image animated:NO]);
-  OCMExpect([cellMock setAdditionalInformationWithPublisherName:publisher
-                                                           date:date
-                                            offlineAvailability:YES]);
+  OCMExpect(
+      [cellMock setAdditionalInformationWithPublisherName:publisher date:date]);
 
   // Action.
   [item configureCell:cell];
diff --git a/ios/chrome/browser/ui/ntp/google_landing_view_controller.mm b/ios/chrome/browser/ui/ntp/google_landing_view_controller.mm
index f94466a..cd09a0c 100644
--- a/ios/chrome/browser/ui/ntp/google_landing_view_controller.mm
+++ b/ios/chrome/browser/ui/ntp/google_landing_view_controller.mm
@@ -941,8 +941,13 @@
       MostVisitedCell* cell = (MostVisitedCell*)sender.view;
       [[strongSelf dataSource] logMostVisitedClick:index
                                           tileType:cell.tileType];
+      // GoogleLandingViewController is only displayed in non-incognito tabs,
+      // so |inIncognito| can be assumed to be NO. If it were displayed in an
+      // incognito state, then passing NO to |inIncognito| would open a tab in
+      // the wrong browser state.
       [[strongSelf dispatcher] webPageOrderedOpen:url
                                          referrer:web::Referrer()
+                                      inIncognito:NO
                                      inBackground:YES
                                          appendTo:kCurrentTab];
     };
diff --git a/ios/chrome/browser/ui/settings/autofill_settings_egtest.mm b/ios/chrome/browser/ui/settings/autofill_settings_egtest.mm
index 0a8a9520..2760f045 100644
--- a/ios/chrome/browser/ui/settings/autofill_settings_egtest.mm
+++ b/ios/chrome/browser/ui/settings/autofill_settings_egtest.mm
@@ -4,6 +4,7 @@
 
 #import <XCTest/XCTest.h>
 
+#include "base/ios/ios_util.h"
 #import "base/mac/bind_objc_block.h"
 #include "ios/chrome/browser/ui/tools_menu/tools_menu_constants.h"
 #include "ios/chrome/grit/ios_strings.h"
@@ -178,6 +179,11 @@
 // Test that editing country names is followed by validating the value and
 // replacing it with a canonical one.
 - (void)testAutofillProfileEditing {
+  // TODO(crbug.com/747431): re-enable this test on iOS 11.
+  if (base::ios::IsRunningOnIOS11OrLater()) {
+    EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.");
+  }
+
   [self loadAndSubmitTheForm];
   [self openEditAddress:@"George Washington, 1600 Pennsylvania Ave NW"];
 
diff --git a/ios/chrome/browser/ui/settings/passwords_settings_egtest.mm b/ios/chrome/browser/ui/settings/passwords_settings_egtest.mm
index f86db19..8652bef 100644
--- a/ios/chrome/browser/ui/settings/passwords_settings_egtest.mm
+++ b/ios/chrome/browser/ui/settings/passwords_settings_egtest.mm
@@ -229,11 +229,12 @@
 scoped_refptr<password_manager::PasswordStore> GetPasswordStore() {
   // ServiceAccessType governs behaviour in Incognito: only modifications with
   // EXPLICIT_ACCESS, which correspond to user's explicit gesture, succeed.
-  // This test does not deal with Incognito, so the value of the argument is
-  // irrelevant.
+  // This test does not deal with Incognito, and should not run in Incognito
+  // context. Therefore IMPLICIT_ACCESS is used to let the test fail if in
+  // Incognito context.
   return IOSChromePasswordStoreFactory::GetForBrowserState(
       chrome_test_util::GetOriginalBrowserState(),
-      ServiceAccessType::EXPLICIT_ACCESS);
+      ServiceAccessType::IMPLICIT_ACCESS);
 }
 
 // This class is used to obtain results from the PasswordStore and hence both
@@ -408,10 +409,6 @@
 }
 
 // Verifies the UI elements are accessible on the Passwords page.
-// TODO(crbug.com/159166): This differs from testAccessibilityOnPasswords in
-// settings_egtest.mm in that here this tests the new UI (for viewing
-// passwords), where in settings_egtest.mm the default (old) UI is tested.
-// Once the new is the default, just remove the test in settings_egtest.mm.
 - (void)testAccessibilityOnPasswords {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndEnableFeature(
diff --git a/ios/chrome/browser/ui/settings/settings_egtest.mm b/ios/chrome/browser/ui/settings/settings_egtest.mm
index a2474ab..b8d9fc49 100644
--- a/ios/chrome/browser/ui/settings/settings_egtest.mm
+++ b/ios/chrome/browser/ui/settings/settings_egtest.mm
@@ -14,7 +14,6 @@
 #include "base/strings/sys_string_conversions.h"
 #include "components/browsing_data/core/pref_names.h"
 #include "components/metrics/metrics_pref_names.h"
-#include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/prefs/pref_member.h"
 #include "components/prefs/pref_service.h"
 #include "components/strings/grit/components_strings.h"
@@ -107,10 +106,6 @@
 id<GREYMatcher> ConfirmClearBrowsingDataButton() {
   return ButtonWithAccessibilityLabelId(IDS_IOS_CONFIRM_CLEAR_BUTTON);
 }
-// Matcher for the Save Passwords cell on the main Settings screen.
-id<GREYMatcher> PasswordsButton() {
-  return ButtonWithAccessibilityLabelId(IDS_IOS_SAVE_PASSWORDS);
-}
 // Matcher for the Send Usage Data cell on the Privacy screen.
 id<GREYMatcher> SendUsageDataButton() {
   return ButtonWithAccessibilityLabelId(IDS_IOS_OPTIONS_SEND_USAGE_DATA);
@@ -153,10 +148,6 @@
 id<GREYMatcher> TranslateSettingsButton() {
   return ButtonWithAccessibilityLabelId(IDS_IOS_TRANSLATE_SETTING);
 }
-// Matcher for the save button in the save password bar.
-id<GREYMatcher> SavePasswordButton() {
-  return ButtonWithAccessibilityLabelId(IDS_IOS_PASSWORD_MANAGER_SAVE_BUTTON);
-}
 // Matcher for the Bandwidth Settings button on the main Settings screen.
 id<GREYMatcher> BandwidthSettingsButton() {
   return ButtonWithAccessibilityLabelId(IDS_IOS_BANDWIDTH_MANAGEMENT_SETTINGS);
@@ -345,34 +336,6 @@
       performAction:grey_tap()];
 }
 
-// Enable password management.
-- (void)enablePasswordManagement {
-  ios::ChromeBrowserState* browserState =
-      chrome_test_util::GetOriginalBrowserState();
-  PrefService* preferences = browserState->GetPrefs();
-  preferences->SetBoolean(
-      password_manager::prefs::kPasswordManagerSavingEnabled, true);
-}
-
-// Return pref for password management back to default and restore the Clear
-// Browsing Data checkmarks prefs to their default state.
-- (void)passwordsTearDown:(BOOL)defaultPasswordManagementSetting {
-  ios::ChromeBrowserState* browserState =
-      chrome_test_util::GetOriginalBrowserState();
-  PrefService* preferences = browserState->GetPrefs();
-  preferences->SetBoolean(
-      password_manager::prefs::kPasswordManagerSavingEnabled, true);
-  [self clearPasswords];
-
-  // Restore the password management pref state.
-  preferences->SetBoolean(
-      password_manager::prefs::kPasswordManagerSavingEnabled,
-      defaultPasswordManagementSetting);
-
-  // Restore the Clear Browsing Data checkmarks prefs to their default state.
-  [self restoreClearBrowsingDataCheckmarksToDefault];
-}
-
 // Restore the Clear Browsing Data checkmarks prefs to their default state.
 - (void)restoreClearBrowsingDataCheckmarksToDefault {
   ios::ChromeBrowserState* browserState =
@@ -385,70 +348,6 @@
   preferences->SetBoolean(browsing_data::prefs::kDeleteFormData, false);
 }
 
-// Checks the presence (or absence) of saved passwords.
-// If |saved| is YES, it checks that there is a Saved Passwords section.
-// If |saved| is NO, it checks that there is no Saved Passwords section.
-- (void)checkIfPasswordsSaved:(BOOL)saved {
-  [ChromeEarlGreyUI openSettingsMenu];
-  [ChromeEarlGreyUI tapSettingsMenuButton:PasswordsButton()];
-
-  id<GREYMatcher> visibilityMatcher =
-      saved ? grey_sufficientlyVisible() : grey_notVisible();
-  [[EarlGrey
-      selectElementWithMatcher:grey_text(l10n_util::GetNSString(
-                                   IDS_IOS_SETTINGS_PASSWORDS_SAVED_HEADING))]
-      assertWithMatcher:visibilityMatcher];
-
-  // Close the Settings.
-  [self closeSubSettingsMenu];
-}
-
-// Loads a page with a login and submits it.
-- (void)loadFormAndLogin {
-  std::map<GURL, std::string> responses;
-  const GURL URL = web::test::HttpServer::MakeUrl("http://testClearPasswords");
-
-  // TODO(crbug.com/432596): There looks to be a bug where the save password
-  // infobar is not displayed if the action is about:blank.
-  responses[URL] =
-      "<form method=\"POST\" action=\"dest\">"
-      "Username:<input type=\"text\" name=\"username\" value=\"name\" /><br />"
-      "Password:<input type=\"password\""
-      "name=\"password\" value=\"pass\"/><br />"
-      "<input type=\"submit\" value=\"Login\" id=\"Login\"/>"
-      "</form>";
-  const GURL destinationURL =
-      web::test::HttpServer::MakeUrl("http://testClearPasswords/dest");
-  responses[destinationURL] = "Logged in!";
-  web::test::SetUpSimpleHttpServer(responses);
-
-  // Login to page and click to save password and check that its saved.
-  [ChromeEarlGrey loadURL:URL];
-  chrome_test_util::TapWebViewElementWithId("Login");
-
-  GREYCondition* condition = [GREYCondition
-      conditionWithName:@"Wait for save button"
-                  block:^BOOL {
-                    NSError* error = nil;
-                    [[EarlGrey selectElementWithMatcher:SavePasswordButton()]
-                        assertWithMatcher:grey_notNil()
-                                    error:&error];
-                    return !error;
-                  }];
-  GREYAssert([condition waitWithTimeout:testing::kWaitForUIElementTimeout],
-             @"Failed waiting for save button");
-  [[EarlGrey selectElementWithMatcher:SavePasswordButton()]
-      performAction:grey_tap()];
-}
-
-// Opens the passwords page from the NTP. It requires no menus to be open.
-- (void)openPasswordSettings {
-  // Open settings and verify data in the view controller.
-  [ChromeEarlGreyUI openSettingsMenu];
-  [[EarlGrey selectElementWithMatcher:PasswordsButton()]
-      performAction:grey_tap()];
-}
-
 - (void)setMetricsReportingEnabled:(BOOL)reportingEnabled
                           wifiOnly:(BOOL)wifiOnly {
   chrome_test_util::SetBooleanLocalStatePref(
@@ -673,30 +572,6 @@
   chrome_test_util::CloseAllTabs();
 }
 
-// Verifies that logging into a form on a web page allows the user to save and
-// then clear a password.
-- (void)testClearPasswords {
-  ios::ChromeBrowserState* browserState =
-      chrome_test_util::GetOriginalBrowserState();
-  PrefService* preferences = browserState->GetPrefs();
-  bool defaultPasswordManagerSavingPref = preferences->GetBoolean(
-      password_manager::prefs::kPasswordManagerSavingEnabled);
-
-  [self enablePasswordManagement];
-  __weak SettingsTestCase* weakSelf = self;
-  [self setTearDownHandler:^{
-    [weakSelf passwordsTearDown:defaultPasswordManagerSavingPref];
-  }];
-
-  // Clear passwords and check that none are saved.
-  [self clearPasswords];
-  [self checkIfPasswordsSaved:NO];
-
-  // Login to page and click to save password and check that its saved.
-  [self loadFormAndLogin];
-  [self checkIfPasswordsSaved:YES];
-}
-
 // Verifies that metrics reporting works properly under possible settings of the
 // preferences kMetricsReportingEnabled and kMetricsReportingWifiOnly.
 - (void)testMetricsReporting {
@@ -851,15 +726,6 @@
   [self closeSubSettingsMenu];
 }
 
-// Verifies the UI elements are accessible on the Save Passwords page.
-- (void)testAccessibilityOnSavePasswords {
-  [ChromeEarlGreyUI openSettingsMenu];
-  [[EarlGrey selectElementWithMatcher:PasswordsButton()]
-      performAction:grey_tap()];
-  chrome_test_util::VerifyAccessibilityForCurrentScreen();
-  [self closeSubSettingsMenu];
-}
-
 // Verifies the UI elements are accessible on the Search engine page.
 - (void)testAccessibilityOnSearchEngine {
   [ChromeEarlGreyUI openSettingsMenu];
@@ -893,42 +759,6 @@
   [self closeSubSettingsMenu];
 }
 
-// Verifies the UI elements are accessible on the Passwords page.
-- (void)testAccessibilityOnPasswords {
-  [self openPasswordSettings];
-  chrome_test_util::VerifyAccessibilityForCurrentScreen();
-  [self closeSubSettingsMenu];
-}
-
-// Verifies that saved passwords are accessible in Passwords page.
-- (void)testAccessibilityOnPasswordEditing {
-  [self clearPasswords];
-  [self checkIfPasswordsSaved:NO];
-
-  ios::ChromeBrowserState* browserState =
-      chrome_test_util::GetOriginalBrowserState();
-  PrefService* preferences = browserState->GetPrefs();
-  bool defaultPasswordManagerSavingPref = preferences->GetBoolean(
-      password_manager::prefs::kPasswordManagerSavingEnabled);
-
-  [self enablePasswordManagement];
-  __weak SettingsTestCase* weakSelf = self;
-  [self setTearDownHandler:^{
-    [weakSelf passwordsTearDown:defaultPasswordManagerSavingPref];
-  }];
-
-  [self loadFormAndLogin];
-  [self openPasswordSettings];
-
-  // Switch on edit mode.
-  [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabelId(
-                                          IDS_IOS_NAVIGATION_BAR_EDIT_BUTTON)]
-      performAction:grey_tap()];
-  chrome_test_util::VerifyAccessibilityForCurrentScreen();
-
-  [self closeSubSettingsMenu];
-}
-
 // Verifies that the Settings UI registers keyboard commands when presented, but
 // not when it itslef presents something.
 - (void)testSettingsKeyboardCommands {
diff --git a/ios/chrome/browser/ui/stack_view/BUILD.gn b/ios/chrome/browser/ui/stack_view/BUILD.gn
index 0d12d0a3e..a9f5828 100644
--- a/ios/chrome/browser/ui/stack_view/BUILD.gn
+++ b/ios/chrome/browser/ui/stack_view/BUILD.gn
@@ -42,9 +42,11 @@
     "resources:card_frame_shadow",
     "resources:stack_view_background_noise",
     "//base",
+    "//components/feature_engagement_tracker",
     "//components/strings",
     "//ios/chrome/app/strings",
     "//ios/chrome/browser",
+    "//ios/chrome/browser/feature_engagement_tracker",
     "//ios/chrome/browser/tabs",
     "//ios/chrome/browser/ui",
     "//ios/chrome/browser/ui/commands",
diff --git a/ios/chrome/browser/ui/stack_view/stack_view_controller.mm b/ios/chrome/browser/ui/stack_view/stack_view_controller.mm
index 0bc5627e..d822fe75 100644
--- a/ios/chrome/browser/ui/stack_view/stack_view_controller.mm
+++ b/ios/chrome/browser/ui/stack_view/stack_view_controller.mm
@@ -21,8 +21,12 @@
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
 #include "base/strings/sys_string_conversions.h"
+#include "components/feature_engagement_tracker/public/event_constants.h"
+#include "components/feature_engagement_tracker/public/feature_engagement_tracker.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
 #include "ios/chrome/browser/experimental_flags.h"
+#include "ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h"
+#include "ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_util.h"
 #import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
 #import "ios/chrome/browser/tabs/tab_model_observer.h"
@@ -2713,6 +2717,13 @@
   // Ensure that the right mode is showing.
   if ([self isCurrentSetIncognito] != command.incognito)
     [self setActiveCardSet:[self inactiveCardSet]];
+
+  // Either send or don't send the "New Tab Opened" or "Incognito Tab Opened" to
+  // the FeatureEngagementTracker based on |command.userInitiated| and
+  // |command.incognito|.
+  feature_engagement_tracker::NotifyNewTabEventForCommand(
+      _activeCardSet.tabModel.browserState, command);
+
   [self setLastTapPoint:command];
   [self dismissWithNewTabAnimation:GURL(kChromeUINewTabURL)
                            atIndex:NSNotFound
diff --git a/ios/chrome/browser/ui/static_content/static_html_native_content.mm b/ios/chrome/browser/ui/static_content/static_html_native_content.mm
index c7255d4..cb12633 100644
--- a/ios/chrome/browser/ui/static_content/static_html_native_content.mm
+++ b/ios/chrome/browser/ui/static_content/static_html_native_content.mm
@@ -156,6 +156,8 @@
   }
   _webUsageEnabled = webUsageEnabled;
   if (!_webUsageEnabled) {
+    [_overscrollActionsController invalidate];
+    [[self scrollView] setDelegate:nil];
     _staticHTMLViewController = nil;
   }
 }
diff --git a/ios/chrome/browser/ui/tab_switcher/BUILD.gn b/ios/chrome/browser/ui/tab_switcher/BUILD.gn
index 026f8ee..ed258676 100644
--- a/ios/chrome/browser/ui/tab_switcher/BUILD.gn
+++ b/ios/chrome/browser/ui/tab_switcher/BUILD.gn
@@ -68,6 +68,7 @@
     "//ios/chrome/browser",
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/favicon",
+    "//ios/chrome/browser/feature_engagement_tracker",
     "//ios/chrome/browser/metrics:metrics_internal",
     "//ios/chrome/browser/sessions",
     "//ios/chrome/browser/signin",
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller.mm
index ef8ded5..0c27a434 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller.mm
@@ -14,6 +14,7 @@
 #include "components/sync_sessions/open_tabs_ui_delegate.h"
 #import "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
+#include "ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_util.h"
 #import "ios/chrome/browser/metrics/tab_usage_recorder.h"
 #include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h"
 #include "ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.h"
@@ -411,6 +412,13 @@
                           : TabSwitcherSessionType::REGULAR_SESSION;
 
   TabModel* model = [self tabModelForSessionType:panelSessionType];
+
+  // Either send or don't send the "New Tab Opened" or "Incognito Tab Opened" to
+  // the FeatureEngagementTracker based on |command.userInitiated| and
+  // |command.incognito|.
+  feature_engagement_tracker::NotifyNewTabEventForCommand(model.browserState,
+                                                          command);
+
   [self dismissWithNewTabAnimation:GURL(kChromeUINewTabURL)
                            atIndex:NSNotFound
                         transition:ui::PAGE_TRANSITION_TYPED
diff --git a/ios/chrome/browser/ui/toolbar/BUILD.gn b/ios/chrome/browser/ui/toolbar/BUILD.gn
index 456e57e..11086436 100644
--- a/ios/chrome/browser/ui/toolbar/BUILD.gn
+++ b/ios/chrome/browser/ui/toolbar/BUILD.gn
@@ -5,11 +5,6 @@
 source_set("toolbar") {
   configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
-    "keyboard_accessory_view_delegate.h",
-    "keyboard_assist/toolbar_assistive_keyboard_views.h",
-    "keyboard_assist/toolbar_assistive_keyboard_views.mm",
-    "new_keyboard_accessory_view.h",
-    "new_keyboard_accessory_view.mm",
     "new_tab_button.h",
     "new_tab_button.mm",
     "toolbar_button_tints.h",
@@ -38,8 +33,6 @@
     "resources:collapse_pressed",
     "resources:collapse_pressed_incognito",
     "resources:incognito_marker_typing",
-    "resources:keyboard_accessory_qr_scanner",
-    "resources:keyboard_accessory_voice_search",
     "resources:toolbar_dark_newtab",
     "resources:toolbar_dark_newtab_active",
     "resources:toolbar_dark_newtab_incognito",
@@ -73,6 +66,7 @@
     "//ios/chrome/browser/ui/keyboard",
     "//ios/chrome/browser/ui/popup_menu",
     "//ios/chrome/browser/ui/qr_scanner",
+    "//ios/chrome/browser/ui/toolbar/keyboard_assist",
     "//ios/chrome/browser/ui/tools_menu",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/browser/ui/voice",
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/BUILD.gn b/ios/chrome/browser/ui/toolbar/keyboard_assist/BUILD.gn
new file mode 100644
index 0000000..b01742b1
--- /dev/null
+++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/BUILD.gn
@@ -0,0 +1,27 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("keyboard_assist") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  sources = [
+    "toolbar_assistive_keyboard_delegate.h",
+    "toolbar_assistive_keyboard_views.h",
+    "toolbar_assistive_keyboard_views.mm",
+    "toolbar_keyboard_accessory_view.h",
+    "toolbar_keyboard_accessory_view.mm",
+  ]
+  deps = [
+    "resources:keyboard_accessory_qr_scanner",
+    "resources:keyboard_accessory_voice_search",
+    "//base",
+    "//base:i18n",
+    "//ios/chrome/app/strings:ios_strings_grit",
+    "//ios/chrome/browser",
+    "//ios/chrome/browser/ui",
+    "//ios/chrome/browser/ui/commands",
+    "//ui/base",
+    "//ui/gfx",
+  ]
+  libs = [ "UIKit.framework" ]
+}
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/resources/BUILD.gn b/ios/chrome/browser/ui/toolbar/keyboard_assist/resources/BUILD.gn
new file mode 100644
index 0000000..b1e9715
--- /dev/null
+++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/resources/BUILD.gn
@@ -0,0 +1,23 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/ios/imageset.gni")
+
+imageset("keyboard_accessory_voice_search") {
+  sources = [
+    "keyboard_accessory_voice_search.imageset/Contents.json",
+    "keyboard_accessory_voice_search.imageset/keyboard_accessory_voice_search.png",
+    "keyboard_accessory_voice_search.imageset/keyboard_accessory_voice_search@2x.png",
+    "keyboard_accessory_voice_search.imageset/keyboard_accessory_voice_search@3x.png",
+  ]
+}
+
+imageset("keyboard_accessory_qr_scanner") {
+  sources = [
+    "keyboard_accessory_qr_scanner.imageset/Contents.json",
+    "keyboard_accessory_qr_scanner.imageset/keyboard_accessory_qr_scanner.png",
+    "keyboard_accessory_qr_scanner.imageset/keyboard_accessory_qr_scanner@2x.png",
+    "keyboard_accessory_qr_scanner.imageset/keyboard_accessory_qr_scanner@3x.png",
+  ]
+}
diff --git a/ios/chrome/browser/ui/toolbar/resources/keyboard_accessory_qr_scanner.imageset/Contents.json b/ios/chrome/browser/ui/toolbar/keyboard_assist/resources/keyboard_accessory_qr_scanner.imageset/Contents.json
similarity index 100%
rename from ios/chrome/browser/ui/toolbar/resources/keyboard_accessory_qr_scanner.imageset/Contents.json
rename to ios/chrome/browser/ui/toolbar/keyboard_assist/resources/keyboard_accessory_qr_scanner.imageset/Contents.json
diff --git a/ios/chrome/browser/ui/toolbar/resources/keyboard_accessory_qr_scanner.imageset/keyboard_accessory_qr_scanner.png b/ios/chrome/browser/ui/toolbar/keyboard_assist/resources/keyboard_accessory_qr_scanner.imageset/keyboard_accessory_qr_scanner.png
similarity index 100%
rename from ios/chrome/browser/ui/toolbar/resources/keyboard_accessory_qr_scanner.imageset/keyboard_accessory_qr_scanner.png
rename to ios/chrome/browser/ui/toolbar/keyboard_assist/resources/keyboard_accessory_qr_scanner.imageset/keyboard_accessory_qr_scanner.png
Binary files differ
diff --git a/ios/chrome/browser/ui/toolbar/resources/keyboard_accessory_qr_scanner.imageset/keyboard_accessory_qr_scanner@2x.png b/ios/chrome/browser/ui/toolbar/keyboard_assist/resources/keyboard_accessory_qr_scanner.imageset/keyboard_accessory_qr_scanner@2x.png
similarity index 100%
rename from ios/chrome/browser/ui/toolbar/resources/keyboard_accessory_qr_scanner.imageset/keyboard_accessory_qr_scanner@2x.png
rename to ios/chrome/browser/ui/toolbar/keyboard_assist/resources/keyboard_accessory_qr_scanner.imageset/keyboard_accessory_qr_scanner@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/toolbar/resources/keyboard_accessory_qr_scanner.imageset/keyboard_accessory_qr_scanner@3x.png b/ios/chrome/browser/ui/toolbar/keyboard_assist/resources/keyboard_accessory_qr_scanner.imageset/keyboard_accessory_qr_scanner@3x.png
similarity index 100%
rename from ios/chrome/browser/ui/toolbar/resources/keyboard_accessory_qr_scanner.imageset/keyboard_accessory_qr_scanner@3x.png
rename to ios/chrome/browser/ui/toolbar/keyboard_assist/resources/keyboard_accessory_qr_scanner.imageset/keyboard_accessory_qr_scanner@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/toolbar/resources/keyboard_accessory_voice_search.imageset/Contents.json b/ios/chrome/browser/ui/toolbar/keyboard_assist/resources/keyboard_accessory_voice_search.imageset/Contents.json
similarity index 100%
rename from ios/chrome/browser/ui/toolbar/resources/keyboard_accessory_voice_search.imageset/Contents.json
rename to ios/chrome/browser/ui/toolbar/keyboard_assist/resources/keyboard_accessory_voice_search.imageset/Contents.json
diff --git a/ios/chrome/browser/ui/toolbar/resources/keyboard_accessory_voice_search.imageset/keyboard_accessory_voice_search.png b/ios/chrome/browser/ui/toolbar/keyboard_assist/resources/keyboard_accessory_voice_search.imageset/keyboard_accessory_voice_search.png
similarity index 100%
rename from ios/chrome/browser/ui/toolbar/resources/keyboard_accessory_voice_search.imageset/keyboard_accessory_voice_search.png
rename to ios/chrome/browser/ui/toolbar/keyboard_assist/resources/keyboard_accessory_voice_search.imageset/keyboard_accessory_voice_search.png
Binary files differ
diff --git a/ios/chrome/browser/ui/toolbar/resources/keyboard_accessory_voice_search.imageset/keyboard_accessory_voice_search@2x.png b/ios/chrome/browser/ui/toolbar/keyboard_assist/resources/keyboard_accessory_voice_search.imageset/keyboard_accessory_voice_search@2x.png
similarity index 100%
rename from ios/chrome/browser/ui/toolbar/resources/keyboard_accessory_voice_search.imageset/keyboard_accessory_voice_search@2x.png
rename to ios/chrome/browser/ui/toolbar/keyboard_assist/resources/keyboard_accessory_voice_search.imageset/keyboard_accessory_voice_search@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/toolbar/resources/keyboard_accessory_voice_search.imageset/keyboard_accessory_voice_search@3x.png b/ios/chrome/browser/ui/toolbar/keyboard_assist/resources/keyboard_accessory_voice_search.imageset/keyboard_accessory_voice_search@3x.png
similarity index 100%
rename from ios/chrome/browser/ui/toolbar/resources/keyboard_accessory_voice_search.imageset/keyboard_accessory_voice_search@3x.png
rename to ios/chrome/browser/ui/toolbar/keyboard_assist/resources/keyboard_accessory_voice_search.imageset/keyboard_accessory_voice_search@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_accessory_view_delegate.h b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.h
similarity index 70%
rename from ios/chrome/browser/ui/toolbar/keyboard_accessory_view_delegate.h
rename to ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.h
index 426be79..8467f7a 100644
--- a/ios/chrome/browser/ui/toolbar/keyboard_accessory_view_delegate.h
+++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ACCESSORY_VIEW_DELEGATE_H_
-#define IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ACCESSORY_VIEW_DELEGATE_H_
+#ifndef IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_TOOLBAR_ASSISTIVE_KEYBOARD_DELEGATE_H_
+#define IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_TOOLBAR_ASSISTIVE_KEYBOARD_DELEGATE_H_
 
 #import <UIKit/UIKIt.h>
 
 // Delegate protocol for the KeyboardAccessoryView.
-@protocol KeyboardAccessoryViewDelegate
+@protocol ToolbarAssistiveKeyboardDelegate
 
 // Notifies the delegate that the Voice Search button was pressed.
 - (void)keyboardAccessoryVoiceSearchTouchDown:(UIView*)view;
@@ -25,4 +25,4 @@
 
 @end
 
-#endif  // IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ACCESSORY_VIEW_DELEGATE_H_
+#endif  // IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_TOOLBAR_ASSISTIVE_KEYBOARD_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views.h b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views.h
index 6a3a2bb..01429e8 100644
--- a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views.h
+++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views.h
@@ -2,14 +2,24 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_ASSISTIVE_KEYBOARD_VIEWS_H_
-#define IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_ASSISTIVE_KEYBOARD_VIEWS_H_
+#ifndef IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_TOOLBAR_ASSISTIVE_KEYBOARD_VIEWS_H_
+#define IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_TOOLBAR_ASSISTIVE_KEYBOARD_VIEWS_H_
 
 #import <UIKit/UIKIt.h>
 
-@protocol KeyboardAccessoryViewDelegate;
+@protocol ToolbarAssistiveKeyboardDelegate;
 
+// Returns the leading buttons of the assistive view.
 NSArray<UIButton*>* ToolbarAssistiveKeyboardLeadingButtons(
-    id<KeyboardAccessoryViewDelegate> delegate);
+    id<ToolbarAssistiveKeyboardDelegate> delegate);
 
-#endif  // IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_ASSISTIVE_KEYBOARD_VIEWS_H_
+// Adds a keyboard assistive view to |textField|. The assistive view shows a
+// button to quickly enter |dotComTLD|, and the callbacks are handled via
+// |delegate|.
+// |dotComTLD| must not be nil.
+void ConfigureAssistiveKeyboardViews(
+    UITextField* textField,
+    NSString* dotComTLD,
+    id<ToolbarAssistiveKeyboardDelegate> delegate);
+
+#endif  // IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_TOOLBAR_ASSISTIVE_KEYBOARD_VIEWS_H_
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views.mm b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views.mm
index c19b100..2f44a861 100644
--- a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views.mm
+++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views.mm
@@ -4,7 +4,9 @@
 
 #import "ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views.h"
 
-#import "ios/chrome/browser/ui/toolbar/keyboard_accessory_view_delegate.h"
+#include "base/logging.h"
+#import "ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.h"
+#import "ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_keyboard_accessory_view.h"
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
 #include "ios/chrome/grit/ios_strings.h"
 
@@ -33,7 +35,7 @@
 }  // namespace
 
 NSArray<UIButton*>* ToolbarAssistiveKeyboardLeadingButtons(
-    id<KeyboardAccessoryViewDelegate> delegate) {
+    id<ToolbarAssistiveKeyboardDelegate> delegate) {
   UIButton* voiceSearchButton =
       ButtonWitIcon(@"keyboard_accessory_voice_search");
   [voiceSearchButton addTarget:delegate
@@ -57,3 +59,20 @@
 
   return @[ voiceSearchButton, cameraButton ];
 }
+
+void ConfigureAssistiveKeyboardViews(
+    UITextField* textField,
+    NSString* dotComTLD,
+    id<ToolbarAssistiveKeyboardDelegate> delegate) {
+  DCHECK(dotComTLD);
+  textField.inputAssistantItem.leadingBarButtonGroups = @[];
+  textField.inputAssistantItem.trailingBarButtonGroups = @[];
+
+  NSArray<NSString*>* buttonTitles = @[ @":", @"-", @"/", dotComTLD ];
+  UIView* keyboardAccessoryView =
+      [[ToolbarKeyboardAccessoryView alloc] initWithButtons:buttonTitles
+                                                   delegate:delegate];
+  [keyboardAccessoryView setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
+
+  [textField setInputAccessoryView:keyboardAccessoryView];
+}
diff --git a/ios/chrome/browser/ui/toolbar/new_keyboard_accessory_view.h b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_keyboard_accessory_view.h
similarity index 80%
rename from ios/chrome/browser/ui/toolbar/new_keyboard_accessory_view.h
rename to ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_keyboard_accessory_view.h
index 242b6ff..71b1029 100644
--- a/ios/chrome/browser/ui/toolbar/new_keyboard_accessory_view.h
+++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_keyboard_accessory_view.h
@@ -7,18 +7,18 @@
 
 #import <UIKit/UIKIt.h>
 
-#import "ios/chrome/browser/ui/toolbar/keyboard_accessory_view_delegate.h"
+#import "ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.h"
 
 // Accessory View above the keyboard.
 // Shows keys that are shortcuts to commonly used characters or strings,
 // and buttons to start Voice Search or a Camera Search.
-@interface NewKeyboardAccessoryView : UIInputView<UIInputViewAudioFeedback>
+@interface ToolbarKeyboardAccessoryView : UIInputView<UIInputViewAudioFeedback>
 
 // Designated initializer. |buttonTitles| lists the titles of the shortcut
 // buttons. |delegate| receives the various events triggered in the view. Not
 // retained, and can be nil.
 - (instancetype)initWithButtons:(NSArray<NSString*>*)buttonTitles
-                       delegate:(id<KeyboardAccessoryViewDelegate>)delegate
+                       delegate:(id<ToolbarAssistiveKeyboardDelegate>)delegate
     NS_DESIGNATED_INITIALIZER;
 
 - (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
diff --git a/ios/chrome/browser/ui/toolbar/new_keyboard_accessory_view.mm b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_keyboard_accessory_view.mm
similarity index 92%
rename from ios/chrome/browser/ui/toolbar/new_keyboard_accessory_view.mm
rename to ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_keyboard_accessory_view.mm
index f614460..db1f24c 100644
--- a/ios/chrome/browser/ui/toolbar/new_keyboard_accessory_view.mm
+++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_keyboard_accessory_view.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/chrome/browser/ui/toolbar/new_keyboard_accessory_view.h"
+#import "ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_keyboard_accessory_view.h"
 
 #import <NotificationCenter/NotificationCenter.h>
 
@@ -18,10 +18,10 @@
 #error "This file requires ARC support."
 #endif
 
-@interface NewKeyboardAccessoryView ()
+@interface ToolbarKeyboardAccessoryView ()
 
 @property(nonatomic, retain) NSArray<NSString*>* buttonTitles;
-@property(nonatomic, weak) id<KeyboardAccessoryViewDelegate> delegate;
+@property(nonatomic, weak) id<ToolbarAssistiveKeyboardDelegate> delegate;
 
 // Called when a keyboard shortcut button is pressed.
 - (void)keyboardButtonPressed:(NSString*)title;
@@ -30,16 +30,16 @@
 
 @end
 
-@implementation NewKeyboardAccessoryView
+@implementation ToolbarKeyboardAccessoryView
 
 @synthesize buttonTitles = _buttonTitles;
 @synthesize delegate = _delegate;
 
 - (instancetype)initWithButtons:(NSArray<NSString*>*)buttonTitles
-                       delegate:(id<KeyboardAccessoryViewDelegate>)delegate {
+                       delegate:(id<ToolbarAssistiveKeyboardDelegate>)delegate {
   const CGFloat kViewHeight = 44.0;
   CGFloat width = [[UIScreen mainScreen] bounds].size.width;
-  // TODO(734512): Have the creator of the view define the size.
+  // TODO(crbug.com/734512): Have the creator of the view define the size.
   CGRect frame = CGRectMake(0.0, 0.0, width, kViewHeight);
 
   self = [super initWithFrame:frame inputViewStyle:UIInputViewStyleKeyboard];
diff --git a/ios/chrome/browser/ui/toolbar/resources/BUILD.gn b/ios/chrome/browser/ui/toolbar/resources/BUILD.gn
index 33479f4..dceb086 100644
--- a/ios/chrome/browser/ui/toolbar/resources/BUILD.gn
+++ b/ios/chrome/browser/ui/toolbar/resources/BUILD.gn
@@ -22,15 +22,6 @@
   ]
 }
 
-imageset("keyboard_accessory_voice_search") {
-  sources = [
-    "keyboard_accessory_voice_search.imageset/Contents.json",
-    "keyboard_accessory_voice_search.imageset/keyboard_accessory_voice_search.png",
-    "keyboard_accessory_voice_search.imageset/keyboard_accessory_voice_search@2x.png",
-    "keyboard_accessory_voice_search.imageset/keyboard_accessory_voice_search@3x.png",
-  ]
-}
-
 imageset("toolbar_dark_newtab") {
   sources = [
     "toolbar_dark_newtab.imageset/Contents.json",
@@ -85,15 +76,6 @@
   ]
 }
 
-imageset("keyboard_accessory_qr_scanner") {
-  sources = [
-    "keyboard_accessory_qr_scanner.imageset/Contents.json",
-    "keyboard_accessory_qr_scanner.imageset/keyboard_accessory_qr_scanner.png",
-    "keyboard_accessory_qr_scanner.imageset/keyboard_accessory_qr_scanner@2x.png",
-    "keyboard_accessory_qr_scanner.imageset/keyboard_accessory_qr_scanner@3x.png",
-  ]
-}
-
 imageset("collapse") {
   sources = [
     "collapse.imageset/Contents.json",
diff --git a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
index 28765ba..272502b 100644
--- a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
+++ b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
@@ -48,8 +48,8 @@
 #import "ios/chrome/browser/ui/popup_menu/popup_menu_view.h"
 #import "ios/chrome/browser/ui/reversed_animation.h"
 #include "ios/chrome/browser/ui/rtl_geometry.h"
-#import "ios/chrome/browser/ui/toolbar/keyboard_accessory_view_delegate.h"
-#import "ios/chrome/browser/ui/toolbar/new_keyboard_accessory_view.h"
+#import "ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.h"
+#import "ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views.h"
 #import "ios/chrome/browser/ui/toolbar/toolbar_controller+protected.h"
 #import "ios/chrome/browser/ui/toolbar/toolbar_controller.h"
 #import "ios/chrome/browser/ui/toolbar/toolbar_model_ios.h"
@@ -228,7 +228,7 @@
 // switch the main bots to Xcode 8.
 #if defined(__IPHONE_10_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0)
 @interface WebToolbarController ()<CAAnimationDelegate,
-                                   KeyboardAccessoryViewDelegate>
+                                   ToolbarAssistiveKeyboardDelegate>
 @end
 #endif
 
@@ -328,11 +328,6 @@
 - (void)updateToolbarAlphaForFrame:(CGRect)frame;
 // Navigate to |query| from omnibox.
 - (void)loadURLForQuery:(NSString*)query;
-// Lazily instantiate the keyboard accessory view.
-- (UIView*)keyboardAccessoryView;
-// Configures the KeyboardAccessoryView and InputAssistantItem associated with
-// the omnibox.
-- (void)configureAssistiveKeyboardViews;
 - (void)preloadVoiceSearch:(id)sender;
 // Calculates the CGRect to use for the omnibox's frame. Also sets the frames
 // of some buttons and |_webToolbar|.
@@ -644,7 +639,7 @@
     [self.view addSubview:_determinateProgressView];
   }
 
-  [self configureAssistiveKeyboardViews];
+  ConfigureAssistiveKeyboardViews(_omniBox, kDotComTLD, self);
 
   // Add the handler to preload voice search when the voice search button is
   // tapped, but only if voice search is enabled.
@@ -1467,7 +1462,7 @@
 }
 
 #pragma mark -
-#pragma mark KeyboardAccessoryViewDelegate
+#pragma mark ToolbarAssistiveKeyboardDelegate
 
 - (void)keyboardAccessoryVoiceSearchTouchDown:(UIView*)view {
   if (ios::GetChromeBrowserProvider()
@@ -1854,23 +1849,6 @@
   }
 }
 
-- (UIView*)keyboardAccessoryView {
-  NSArray<NSString*>* buttonTitles = @[ @":", @"-", @"/", kDotComTLD ];
-  UIView* keyboardAccessoryView =
-      [[NewKeyboardAccessoryView alloc] initWithButtons:buttonTitles
-                                               delegate:self];
-  [keyboardAccessoryView setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
-  return keyboardAccessoryView;
-}
-
-- (void)configureAssistiveKeyboardViews {
-  // The InputAssistantItems are disabled when the new Keyboard Accessory View
-  // is enabled.
-  _omniBox.inputAssistantItem.leadingBarButtonGroups = @[];
-  _omniBox.inputAssistantItem.trailingBarButtonGroups = @[];
-  [_omniBox setInputAccessoryView:[self keyboardAccessoryView]];
-}
-
 - (void)preloadVoiceSearch:(id)sender {
   DCHECK(ios::GetChromeBrowserProvider()
              ->GetVoiceSearchProvider()
diff --git a/ios/showcase/content_suggestions/sc_content_suggestions_item.mm b/ios/showcase/content_suggestions/sc_content_suggestions_item.mm
index 0bfb6649..ab193be7 100644
--- a/ios/showcase/content_suggestions/sc_content_suggestions_item.mm
+++ b/ios/showcase/content_suggestions/sc_content_suggestions_item.mm
@@ -37,8 +37,7 @@
   cell.displayImage = self.hasImage;
   [cell setContentImage:self.image animated:NO];
   [cell setAdditionalInformationWithPublisherName:self.publisher
-                                             date:self.publicationDate
-                              offlineAvailability:self.availableOffline];
+                                             date:self.publicationDate];
   cell.isAccessibilityElement = YES;
   cell.accessibilityLabel = self.title;
   cell.accessibilityIdentifier = self.title;
@@ -53,8 +52,7 @@
                               withImage:self.hasImage
                                   title:self.title
                           publisherName:self.publisher
-                        publicationDate:self.publicationDate
-                       availableOffline:self.availableOffline];
+                        publicationDate:self.publicationDate];
 }
 
 @end
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn
index 8ba44e0..7ad30a83 100644
--- a/ios/web/BUILD.gn
+++ b/ios/web/BUILD.gn
@@ -254,6 +254,16 @@
     "web_state/ui/wk_web_view_configuration_provider.mm",
     "web_state/web_controller_observer_bridge.h",
     "web_state/web_controller_observer_bridge.mm",
+    "web_state/web_state.mm",
+    "web_state/web_state_delegate.mm",
+    "web_state/web_state_delegate_bridge.mm",
+    "web_state/web_state_impl.h",
+    "web_state/web_state_impl.mm",
+    "web_state/web_state_observer.mm",
+    "web_state/web_state_observer_bridge.mm",
+    "web_state/web_state_policy_decider.mm",
+    "web_state/web_state_weak_ptr_factory.h",
+    "web_state/web_state_weak_ptr_factory.mm",
     "web_state/web_view_internal_creation_util.h",
     "web_state/web_view_internal_creation_util.mm",
     "web_state/wk_web_view_security_util.h",
@@ -328,16 +338,6 @@
     "web_state/ui/crw_web_controller.mm",
     "web_state/ui/crw_web_controller_container_view.h",
     "web_state/ui/crw_web_controller_container_view.mm",
-    "web_state/web_state.mm",
-    "web_state/web_state_delegate.mm",
-    "web_state/web_state_delegate_bridge.mm",
-    "web_state/web_state_impl.h",
-    "web_state/web_state_impl.mm",
-    "web_state/web_state_observer.mm",
-    "web_state/web_state_observer_bridge.mm",
-    "web_state/web_state_policy_decider.mm",
-    "web_state/web_state_weak_ptr_factory.h",
-    "web_state/web_state_weak_ptr_factory.mm",
   ]
 
   libs = [
diff --git a/ios/web/public/web_state/web_state_observer_bridge.h b/ios/web/public/web_state/web_state_observer_bridge.h
index e1d7782..f0099db 100644
--- a/ios/web/public/web_state/web_state_observer_bridge.h
+++ b/ios/web/public/web_state/web_state_observer_bridge.h
@@ -129,7 +129,7 @@
   void DidStopLoading() override;
 
  private:
-  base::WeakNSProtocol<id<CRWWebStateObserver>> observer_;
+  __unsafe_unretained id<CRWWebStateObserver> observer_;
   DISALLOW_COPY_AND_ASSIGN(WebStateObserverBridge);
 };
 
diff --git a/ios/web/web_state/web_state.mm b/ios/web/web_state/web_state.mm
index ad5791d..55ece67 100644
--- a/ios/web/web_state/web_state.mm
+++ b/ios/web/web_state/web_state.mm
@@ -4,6 +4,10 @@
 
 #import "ios/web/public/web_state/web_state.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace web {
 
 WebState::CreateParams::CreateParams(web::BrowserState* browser_state)
diff --git a/ios/web/web_state/web_state_delegate.mm b/ios/web/web_state/web_state_delegate.mm
index c6a2def0..2c58355 100644
--- a/ios/web/web_state/web_state_delegate.mm
+++ b/ios/web/web_state/web_state_delegate.mm
@@ -6,6 +6,10 @@
 
 #import "ios/web/public/web_state/web_state.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace web {
 
 WebStateDelegate::WebStateDelegate() {}
diff --git a/ios/web/web_state/web_state_delegate_bridge.mm b/ios/web/web_state/web_state_delegate_bridge.mm
index 797e9f46..b4c1255 100644
--- a/ios/web/web_state/web_state_delegate_bridge.mm
+++ b/ios/web/web_state/web_state_delegate_bridge.mm
@@ -7,6 +7,10 @@
 #include "base/logging.h"
 #import "ios/web/public/web_state/context_menu_params.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace web {
 
 WebStateDelegateBridge::WebStateDelegateBridge(id<CRWWebStateDelegate> delegate)
diff --git a/ios/web/web_state/web_state_impl.mm b/ios/web/web_state/web_state_impl.mm
index 238e235..92896ade 100644
--- a/ios/web/web_state/web_state_impl.mm
+++ b/ios/web/web_state/web_state_impl.mm
@@ -44,6 +44,10 @@
 #include "net/http/http_response_headers.h"
 #include "ui/gfx/image/image.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace web {
 
 /* static */
@@ -173,7 +177,7 @@
 
 void WebStateImpl::SetWebController(CRWWebController* web_controller) {
   [web_controller_ close];
-  web_controller_.reset([web_controller retain]);
+  web_controller_.reset(web_controller);
 }
 
 void WebStateImpl::OnTitleChanged() {
diff --git a/ios/web/web_state/web_state_observer.mm b/ios/web/web_state/web_state_observer.mm
index 1408a6e8..4c24630 100644
--- a/ios/web/web_state/web_state_observer.mm
+++ b/ios/web/web_state/web_state_observer.mm
@@ -7,6 +7,10 @@
 #include "ios/web/public/load_committed_details.h"
 #import "ios/web/public/web_state/web_state.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace web {
 
 WebStateObserver::WebStateObserver(WebState* web_state) : web_state_(nullptr) {
diff --git a/ios/web/web_state/web_state_observer_bridge.mm b/ios/web/web_state/web_state_observer_bridge.mm
index 73982ff..12de262 100644
--- a/ios/web/web_state/web_state_observer_bridge.mm
+++ b/ios/web/web_state/web_state_observer_bridge.mm
@@ -4,6 +4,10 @@
 
 #import "ios/web/public/web_state/web_state_observer_bridge.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace web {
 
 WebStateObserverBridge::WebStateObserverBridge(web::WebState* webState,
diff --git a/ios/web/web_state/web_state_policy_decider.mm b/ios/web/web_state/web_state_policy_decider.mm
index f061dfa12..5f3e69d 100644
--- a/ios/web/web_state/web_state_policy_decider.mm
+++ b/ios/web/web_state/web_state_policy_decider.mm
@@ -7,6 +7,10 @@
 #import "ios/web/public/web_state/web_state.h"
 #import "ios/web/web_state/web_state_impl.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace web {
 
 WebStatePolicyDecider::WebStatePolicyDecider(WebState* web_state)
diff --git a/ios/web/web_state/web_state_weak_ptr_factory.mm b/ios/web/web_state/web_state_weak_ptr_factory.mm
index 3b93e4b..2b94ef4 100644
--- a/ios/web/web_state/web_state_weak_ptr_factory.mm
+++ b/ios/web/web_state/web_state_weak_ptr_factory.mm
@@ -6,6 +6,10 @@
 
 #import "ios/web/public/web_state/web_state.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace web {
 
 // static
diff --git a/ios/web/webui/web_ui_mojo_inttest.mm b/ios/web/webui/web_ui_mojo_inttest.mm
index bfc779a..3028111 100644
--- a/ios/web/webui/web_ui_mojo_inttest.mm
+++ b/ios/web/webui/web_ui_mojo_inttest.mm
@@ -144,6 +144,23 @@
         new TestWebUIControllerFactory(ui_handler_.get()));
   }
 
+  void TearDown() override {
+    @autoreleasepool {
+      // WebState owns CRWWebUIManager. When WebState is destroyed,
+      // CRWWebUIManager is autoreleased and will be destroyed upon autorelease
+      // pool purge. However in this test, WebTest destructor is called before
+      // PlatformTest, thus CRWWebUIManager outlives the WebThreadBundle.
+      // However, CRWWebUIManager owns a URLFetcherImpl, which DCHECKs that its
+      // destructor is called on UI web thread. Hence, URLFetcherImpl has to
+      // outlive the WebThreadBundle, since [NSThread mainThread] will not be
+      // WebThread::UI once WebThreadBundle is destroyed.
+      web_state_.reset();
+      ui_handler_.reset();
+    }
+
+    WebIntTest::TearDown();
+  }
+
   // Returns WebState which loads test WebUI page.
   WebStateImpl* web_state() { return web_state_.get(); }
   // Returns UI handler which communicates with WebUI page.
@@ -164,31 +181,33 @@
 #endif
 // TODO(crbug.com/720098): Enable this test on device.
 TEST_F(WebUIMojoTest, MAYBE_MessageExchange) {
-  web_state()->SetWebUsageEnabled(true);
-  web_state()->GetView();  // WebState won't load URL without view.
-  GURL url(
-      url::SchemeHostPort(kTestWebUIScheme, kTestWebUIURLHost, 0).Serialize());
-  NavigationManager::WebLoadParams load_params(url);
-  web_state()->GetNavigationManager()->LoadURLWithParams(load_params);
+  @autoreleasepool {
+    web_state()->SetWebUsageEnabled(true);
+    web_state()->GetView();  // WebState won't load URL without view.
+    GURL url(url::SchemeHostPort(kTestWebUIScheme, kTestWebUIURLHost, 0)
+                 .Serialize());
+    NavigationManager::WebLoadParams load_params(url);
+    web_state()->GetNavigationManager()->LoadURLWithParams(load_params);
 
-  // Wait until |TestUIHandler| receives "fin" message from WebUI page.
-  bool fin_received = testing::WaitUntilConditionOrTimeout(kMessageTimeout, ^{
-    // Flush any pending tasks. Don't RunUntilIdle() because
-    // RunUntilIdle() is incompatible with mojo::SimpleWatcher's
-    // automatic arming behavior, which Mojo JS still depends upon.
-    //
-    // TODO(crbug.com/701875): Introduce the full watcher API to JS and get rid
-    // of this hack.
-    base::RunLoop loop;
-    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
-                                                  loop.QuitClosure());
-    loop.Run();
-    return test_ui_handler()->IsFinReceived();
-  });
+    // Wait until |TestUIHandler| receives "fin" message from WebUI page.
+    bool fin_received = testing::WaitUntilConditionOrTimeout(kMessageTimeout, ^{
+      // Flush any pending tasks. Don't RunUntilIdle() because
+      // RunUntilIdle() is incompatible with mojo::SimpleWatcher's
+      // automatic arming behavior, which Mojo JS still depends upon.
+      //
+      // TODO(crbug.com/701875): Introduce the full watcher API to JS and get
+      // rid of this hack.
+      base::RunLoop loop;
+      base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                    loop.QuitClosure());
+      loop.Run();
+      return test_ui_handler()->IsFinReceived();
+    });
 
-  ASSERT_TRUE(fin_received);
-  EXPECT_FALSE(web_state()->IsLoading());
-  EXPECT_EQ(url, web_state()->GetLastCommittedURL());
+    ASSERT_TRUE(fin_received);
+    EXPECT_FALSE(web_state()->IsLoading());
+    EXPECT_EQ(url, web_state()->GetLastCommittedURL());
+  }
 }
 
 }  // namespace web
diff --git a/media/capture/BUILD.gn b/media/capture/BUILD.gn
index 79e561da..d217a5f3 100644
--- a/media/capture/BUILD.gn
+++ b/media/capture/BUILD.gn
@@ -75,7 +75,6 @@
     "video/mac/video_capture_device_factory_mac.mm",
     "video/mac/video_capture_device_mac.h",
     "video/mac/video_capture_device_mac.mm",
-    "video/scoped_result_callback.h",
     "video/shared_memory_buffer_handle.cc",
     "video/shared_memory_buffer_handle.h",
     "video/shared_memory_buffer_tracker.cc",
diff --git a/media/capture/video/android/video_capture_device_android.cc b/media/capture/video/android/video_capture_device_android.cc
index 826f8c5b..6efae0d 100644
--- a/media/capture/video/android/video_capture_device_android.cc
+++ b/media/capture/video/android/video_capture_device_android.cc
@@ -415,7 +415,7 @@
   mojom::BlobPtr blob = mojom::Blob::New();
   base::android::JavaByteArrayToByteVector(env, data.obj(), &blob->data);
   blob->mime_type = blob->data.empty() ? "" : "image/jpeg";
-  cb->Run(std::move(blob));
+  std::move(*cb).Run(std::move(blob));
 
   photo_callbacks_.erase(reference_it);
 }
@@ -580,7 +580,7 @@
     modes.push_back(ToMojomFillLightMode(fill_light_mode));
   photo_capabilities->fill_light_mode = modes;
 
-  callback.Run(std::move(photo_capabilities));
+  std::move(callback).Run(std::move(photo_capabilities));
 }
 
 void VideoCaptureDeviceAndroid::DoSetPhotoOptions(
@@ -647,7 +647,7 @@
       static_cast<int>(fill_light_mode), settings->has_torch, settings->torch,
       color_temperature);
 
-  callback.Run(true);
+  std::move(callback).Run(true);
 }
 
 }  // namespace media
diff --git a/media/capture/video/fake_video_capture_device.cc b/media/capture/video/fake_video_capture_device.cc
index 178614ea..800cdd03 100644
--- a/media/capture/video/fake_video_capture_device.cc
+++ b/media/capture/video/fake_video_capture_device.cc
@@ -398,7 +398,7 @@
   DCHECK(result);
 
   blob->mime_type = "image/png";
-  callback.Run(std::move(blob));
+  std::move(callback).Run(std::move(blob));
 }
 
 FakeVideoCaptureDevice::FakeVideoCaptureDevice(
@@ -493,7 +493,7 @@
   photo_state->width->min = 96.0;
   photo_state->width->step = 1.0;
 
-  callback.Run(std::move(photo_state));
+  std::move(callback).Run(std::move(photo_state));
 }
 
 void FakeVideoCaptureDevice::SetPhotoOptions(mojom::PhotoSettingsPtr settings,
@@ -515,7 +515,7 @@
         std::max(kMinZoom, std::min(settings->zoom, kMaxZoom));
   }
 
-  callback.Run(true);
+  std::move(callback).Run(true);
 }
 
 void FakeVideoCaptureDevice::TakePhoto(TakePhotoCallback callback) {
diff --git a/media/capture/video/fake_video_capture_device_unittest.cc b/media/capture/video/fake_video_capture_device_unittest.cc
index f636d225..7bfbb67 100644
--- a/media/capture/video/fake_video_capture_device_unittest.cc
+++ b/media/capture/video/fake_video_capture_device_unittest.cc
@@ -164,24 +164,10 @@
   }
   MOCK_METHOD0(OnCorrectGetPhotoState, void(void));
 
-  void OnGetPhotoStateFailure(
-      mojom::ImageCapture::GetPhotoStateCallback callback) {
-    OnGetPhotoStateFailureInternal(callback);
-  }
-  MOCK_METHOD1(OnGetPhotoStateFailureInternal,
-               void(mojom::ImageCapture::GetPhotoStateCallback&));
-
   const mojom::PhotoState* state() { return state_.get(); }
 
   MOCK_METHOD1(OnCorrectSetPhotoOptions, void(bool));
 
-  void OnSetPhotoOptionsFailure(
-      mojom::ImageCapture::SetOptionsCallback callback) {
-    OnSetPhotoOptionsFailureInternal(callback);
-  }
-  MOCK_METHOD1(OnSetPhotoOptionsFailureInternal,
-               void(mojom::ImageCapture::SetOptionsCallback&));
-
   // GMock doesn't support move-only arguments, so we use this forward method.
   void DoOnPhotoTaken(mojom::BlobPtr blob) {
     // Only PNG images are supported right now.
@@ -196,12 +182,6 @@
   }
   MOCK_METHOD0(OnCorrectPhotoTaken, void(void));
 
-  void OnTakePhotoFailure(mojom::ImageCapture::TakePhotoCallback callback) {
-    OnTakePhotoFailureInternal(callback);
-  }
-  MOCK_METHOD1(OnTakePhotoFailureInternal,
-               void(mojom::ImageCapture::TakePhotoCallback&));
-
  private:
   friend class base::RefCounted<ImageCaptureClient>;
   virtual ~ImageCaptureClient() {}
@@ -391,11 +371,9 @@
   EXPECT_CALL(*client_, OnStarted());
   device->AllocateAndStart(capture_params, std::move(client_));
 
-  VideoCaptureDevice::GetPhotoStateCallback scoped_get_callback(
+  VideoCaptureDevice::GetPhotoStateCallback scoped_get_callback =
       base::BindOnce(&ImageCaptureClient::DoOnGetPhotoState,
-                     image_capture_client_),
-      base::BindOnce(&ImageCaptureClient::OnGetPhotoStateFailure,
-                     image_capture_client_));
+                     image_capture_client_);
 
   EXPECT_CALL(*image_capture_client_.get(), OnCorrectGetPhotoState()).Times(1);
   device->GetPhotoState(std::move(scoped_get_callback));
@@ -461,11 +439,9 @@
 
   // Set options: zoom to the maximum value.
   const int max_zoom_value = state->zoom->max;
-  VideoCaptureDevice::SetPhotoOptionsCallback scoped_set_callback(
+  VideoCaptureDevice::SetPhotoOptionsCallback scoped_set_callback =
       base::BindOnce(&ImageCaptureClient::OnCorrectSetPhotoOptions,
-                     image_capture_client_),
-      base::BindOnce(&ImageCaptureClient::OnSetPhotoOptionsFailure,
-                     image_capture_client_));
+                     image_capture_client_);
 
   mojom::PhotoSettingsPtr settings = mojom::PhotoSettings::New();
   settings->zoom = max_zoom_value;
@@ -478,10 +454,9 @@
   run_loop_->Run();
 
   // Retrieve Capabilities again and check against the set values.
-  VideoCaptureDevice::GetPhotoStateCallback scoped_get_callback2(
-      base::Bind(&ImageCaptureClient::DoOnGetPhotoState, image_capture_client_),
-      base::Bind(&ImageCaptureClient::OnGetPhotoStateFailure,
-                 image_capture_client_));
+  VideoCaptureDevice::GetPhotoStateCallback scoped_get_callback2 =
+      base::BindOnce(&ImageCaptureClient::DoOnGetPhotoState,
+                     image_capture_client_);
 
   EXPECT_CALL(*image_capture_client_.get(), OnCorrectGetPhotoState()).Times(1);
   device->GetPhotoState(std::move(scoped_get_callback2));
@@ -506,11 +481,8 @@
   EXPECT_CALL(*client_, OnStarted());
   device->AllocateAndStart(capture_params, std::move(client_));
 
-  VideoCaptureDevice::TakePhotoCallback scoped_callback(
-      base::BindOnce(&ImageCaptureClient::DoOnPhotoTaken,
-                     image_capture_client_),
-      base::BindOnce(&ImageCaptureClient::OnTakePhotoFailure,
-                     image_capture_client_));
+  VideoCaptureDevice::TakePhotoCallback scoped_callback = base::BindOnce(
+      &ImageCaptureClient::DoOnPhotoTaken, image_capture_client_);
 
   EXPECT_CALL(*image_capture_client_.get(), OnCorrectPhotoTaken()).Times(1);
   device->TakePhoto(std::move(scoped_callback));
diff --git a/media/capture/video/linux/v4l2_capture_delegate.cc b/media/capture/video/linux/v4l2_capture_delegate.cc
index 542f745..f776dfb 100644
--- a/media/capture/video/linux/v4l2_capture_delegate.cc
+++ b/media/capture/video/linux/v4l2_capture_delegate.cc
@@ -643,7 +643,7 @@
   photo_capabilities->sharpness =
       RetrieveUserControlRange(device_fd_.get(), V4L2_CID_SHARPNESS);
 
-  callback.Run(std::move(photo_capabilities));
+  std::move(callback).Run(std::move(photo_capabilities));
 }
 
 void V4L2CaptureDelegate::SetPhotoOptions(
@@ -740,7 +740,7 @@
       DPLOG(ERROR) << "setting sharpness to " << settings->sharpness;
   }
 
-  callback.Run(true);
+  std::move(callback).Run(true);
 }
 
 void V4L2CaptureDelegate::SetRotation(int rotation) {
@@ -849,7 +849,7 @@
       mojom::BlobPtr blob =
           Blobify(buffer_tracker->start(), buffer.bytesused, capture_format_);
       if (blob)
-        cb.Run(std::move(blob));
+        std::move(cb).Run(std::move(blob));
     }
 
     if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) < 0) {
diff --git a/media/capture/video/mac/video_capture_device_mac.h b/media/capture/video/mac/video_capture_device_mac.h
index 2a3defe5..3e21a5d 100644
--- a/media/capture/video/mac/video_capture_device_mac.h
+++ b/media/capture/video/mac/video_capture_device_mac.h
@@ -117,7 +117,7 @@
   base::scoped_nsobject<VideoCaptureDeviceAVFoundation> capture_device_;
 
   // To hold on to the TakePhotoCallback while the picture is being taken.
-  std::unique_ptr<TakePhotoCallback> photo_callback_;
+  TakePhotoCallback photo_callback_;
 
   // Used with Bind and PostTask to ensure that methods aren't called after the
   // VideoCaptureDeviceMac is destroyed.
diff --git a/media/capture/video/mac/video_capture_device_mac.mm b/media/capture/video/mac/video_capture_device_mac.mm
index 5cbbcb6..5589405 100644
--- a/media/capture/video/mac/video_capture_device_mac.mm
+++ b/media/capture/video/mac/video_capture_device_mac.mm
@@ -385,7 +385,7 @@
   if (photo_callback_)  // Only one picture can be in flight at a time.
     return;
 
-  photo_callback_.reset(new TakePhotoCallback(std::move(callback)));
+  photo_callback_ = std::move(callback);
   [capture_device_ takePhoto];
 }
 
@@ -414,7 +414,7 @@
       capture_format_.frame_size.width(), 0 /* step */);
   photo_state->torch = false;
 
-  callback.Run(std::move(photo_state));
+  std::move(callback).Run(std::move(photo_state));
 }
 
 void VideoCaptureDeviceMac::SetPhotoOptions(mojom::PhotoSettingsPtr settings,
@@ -429,7 +429,7 @@
       settings->has_fill_light_mode || settings->has_red_eye_reduction) {
     return;
   }
-  callback.Run(true);
+  std::move(callback).Run(true);
 }
 
 bool VideoCaptureDeviceMac::Init(VideoCaptureApi capture_api_type) {
@@ -478,13 +478,12 @@
   mojom::BlobPtr blob = mojom::Blob::New();
   blob->data.assign(image_data, image_data + image_length);
   blob->mime_type = mime_type;
-  photo_callback_->Run(std::move(blob));
-  photo_callback_.reset();
+  std::move(photo_callback_).Run(std::move(blob));
 }
 
 void VideoCaptureDeviceMac::OnPhotoError() {
   DLOG(ERROR) << __func__ << " error taking picture";
-  photo_callback_.reset();
+  photo_callback_.Reset();
 }
 
 void VideoCaptureDeviceMac::ReceiveError(
diff --git a/media/capture/video/scoped_result_callback.h b/media/capture/video/scoped_result_callback.h
deleted file mode 100644
index 2c40b54..0000000
--- a/media/capture/video/scoped_result_callback.h
+++ /dev/null
@@ -1,47 +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 MEDIA_CAPTURE_VIDEO_SCOPED_RESULT_CALLBACK_H_
-#define MEDIA_CAPTURE_VIDEO_SCOPED_RESULT_CALLBACK_H_
-
-#include "base/callback.h"
-#include "base/callback_helpers.h"
-#include "base/macros.h"
-
-namespace media {
-
-// This class guarantees that |callback_| has either been called or will pass it
-// to |on_error_callback_| on destruction. Inspired by ScopedWebCallbacks<>.
-template <typename CallbackType>
-class ScopedResultCallback {
- public:
-  using OnErrorCallback = base::OnceCallback<void(CallbackType)>;
-  ScopedResultCallback(CallbackType callback, OnErrorCallback on_error_callback)
-      : callback_(std::move(callback)),
-        on_error_callback_(std::move(on_error_callback)) {}
-
-  ~ScopedResultCallback() {
-    if (!callback_.is_null())
-      std::move(on_error_callback_).Run(std::move(callback_));
-  }
-
-  ScopedResultCallback(ScopedResultCallback&& other) = default;
-  ScopedResultCallback& operator=(ScopedResultCallback&& other) = default;
-
-  template <typename... Args>
-  void Run(Args&&... args) {
-    on_error_callback_.Reset();
-    std::move(callback_).Run(std::forward<Args>(args)...);
-  }
-
- private:
-  CallbackType callback_;
-  OnErrorCallback on_error_callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedResultCallback);
-};
-
-}  // namespace media
-
-#endif  // MEDIA_CAPTURE_VIDEO_SCOPED_RESULT_CALLBACK_H_
diff --git a/media/capture/video/video_capture_device.h b/media/capture/video/video_capture_device.h
index 6cff3ae9..fc66c3f 100644
--- a/media/capture/video/video_capture_device.h
+++ b/media/capture/video/video_capture_device.h
@@ -29,7 +29,6 @@
 #include "media/base/video_frame.h"
 #include "media/capture/capture_export.h"
 #include "media/capture/mojo/image_capture.mojom.h"
-#include "media/capture/video/scoped_result_callback.h"
 #include "media/capture/video/video_capture_buffer_handle.h"
 #include "media/capture/video/video_capture_device_descriptor.h"
 #include "media/capture/video_capture_types.h"
@@ -274,14 +273,12 @@
   // Retrieve the photo capabilities and settings of the device (e.g. zoom
   // levels etc). On success, invokes |callback|. On failure, drops callback
   // without invoking it.
-  using GetPhotoStateCallback =
-      ScopedResultCallback<base::OnceCallback<void(mojom::PhotoStatePtr)>>;
+  using GetPhotoStateCallback = base::OnceCallback<void(mojom::PhotoStatePtr)>;
   virtual void GetPhotoState(GetPhotoStateCallback callback);
 
   // On success, invokes |callback| with value |true|. On failure, drops
   // callback without invoking it.
-  using SetPhotoOptionsCallback =
-      ScopedResultCallback<base::OnceCallback<void(bool)>>;
+  using SetPhotoOptionsCallback = base::OnceCallback<void(bool)>;
   virtual void SetPhotoOptions(mojom::PhotoSettingsPtr settings,
                                SetPhotoOptionsCallback callback);
 
@@ -289,8 +286,7 @@
   // and/or interrupting the capture flow. Runs |callback| on the thread
   // where TakePhoto() is called, if the photo was successfully taken. On
   // failure, drops callback without invoking it.
-  using TakePhotoCallback =
-      ScopedResultCallback<base::OnceCallback<void(mojom::BlobPtr blob)>>;
+  using TakePhotoCallback = base::OnceCallback<void(mojom::BlobPtr blob)>;
   virtual void TakePhoto(TakePhotoCallback callback);
 
   // Gets the power line frequency, either from the params if specified by the
diff --git a/media/capture/video/video_capture_device_unittest.cc b/media/capture/video/video_capture_device_unittest.cc
index 3e6bc39..fc10dbb 100644
--- a/media/capture/video/video_capture_device_unittest.cc
+++ b/media/capture/video/video_capture_device_unittest.cc
@@ -206,13 +206,6 @@
   }
   MOCK_METHOD0(OnCorrectPhotoTaken, void(void));
 
-  void OnTakePhotoFailure(mojom::ImageCapture::TakePhotoCallback callback) {
-    OnTakePhotoFailureInternal(callback);
-  }
-
-  MOCK_METHOD1(OnTakePhotoFailureInternal,
-               void(mojom::ImageCapture::TakePhotoCallback&));
-
   // GMock doesn't support move-only arguments, so we use this forward method.
   void DoOnGetPhotoState(mojom::PhotoStatePtr state) {
     state_ = std::move(state);
@@ -220,13 +213,6 @@
   }
   MOCK_METHOD0(OnCorrectGetPhotoState, void(void));
 
-  void OnGetPhotoStateFailure(
-      mojom::ImageCapture::GetPhotoStateCallback callback) {
-    OnGetPhotoStateFailureInternal(callback);
-  }
-  MOCK_METHOD1(OnGetPhotoStateFailureInternal,
-               void(mojom::ImageCapture::GetPhotoStateCallback&));
-
   const mojom::PhotoState* capabilities() { return state_.get(); }
 
  private:
@@ -627,11 +613,8 @@
   capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420;
   device->AllocateAndStart(capture_params, std::move(video_capture_client_));
 
-  VideoCaptureDevice::TakePhotoCallback scoped_callback(
-      base::BindOnce(&MockImageCaptureClient::DoOnPhotoTaken,
-                     image_capture_client_),
-      media::BindToCurrentLoop(base::Bind(
-          &MockImageCaptureClient::OnTakePhotoFailure, image_capture_client_)));
+  VideoCaptureDevice::TakePhotoCallback scoped_callback = base::BindOnce(
+      &MockImageCaptureClient::DoOnPhotoTaken, image_capture_client_);
 
   base::RunLoop run_loop;
   base::Closure quit_closure = media::BindToCurrentLoop(run_loop.QuitClosure());
@@ -679,12 +662,9 @@
   capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420;
   device->AllocateAndStart(capture_params, std::move(video_capture_client_));
 
-  VideoCaptureDevice::GetPhotoStateCallback scoped_get_callback(
+  VideoCaptureDevice::GetPhotoStateCallback scoped_get_callback =
       base::BindOnce(&MockImageCaptureClient::DoOnGetPhotoState,
-                     image_capture_client_),
-      media::BindToCurrentLoop(
-          base::BindOnce(&MockImageCaptureClient::OnGetPhotoStateFailure,
-                         image_capture_client_)));
+                     image_capture_client_);
 
   base::RunLoop run_loop;
   base::Closure quit_closure = media::BindToCurrentLoop(run_loop.QuitClosure());
diff --git a/media/capture/video/win/video_capture_device_win.cc b/media/capture/video/win/video_capture_device_win.cc
index c6fb6f0..b1c90bc 100644
--- a/media/capture/video/win/video_capture_device_win.cc
+++ b/media/capture/video/win/video_capture_device_win.cc
@@ -583,7 +583,7 @@
       capture_format_.frame_size.width(), 0 /* step */);
   photo_capabilities->torch = false;
 
-  callback.Run(std::move(photo_capabilities));
+  std::move(callback).Run(std::move(photo_capabilities));
 }
 
 void VideoCaptureDeviceWin::SetPhotoOptions(
@@ -674,7 +674,7 @@
       return;
   }
 
-  callback.Run(true);
+  std::move(callback).Run(true);
 }
 
 bool VideoCaptureDeviceWin::InitializeVideoAndCameraControls() {
@@ -740,7 +740,7 @@
 
     mojom::BlobPtr blob = Blobify(buffer, length, format);
     if (blob)
-      cb.Run(std::move(blob));
+      std::move(cb).Run(std::move(blob));
   }
 }
 
diff --git a/mojo/public/cpp/bindings/array_traits.h b/mojo/public/cpp/bindings/array_traits.h
index 67fe4931..3bf2328 100644
--- a/mojo/public/cpp/bindings/array_traits.h
+++ b/mojo/public/cpp/bindings/array_traits.h
@@ -26,6 +26,8 @@
 //     // using ConstIterator = T::const_iterator;
 //
 //     // These two methods are optional. Please see comments in struct_traits.h
+//     // Note that unlike with StructTraits, IsNull() is called *twice* during
+//     // serialization for ArrayTraits.
 //     static bool IsNull(const Container<T>& input);
 //     static void SetToNull(Container<T>* output);
 //
diff --git a/mojo/public/cpp/bindings/lib/array_internal.h b/mojo/public/cpp/bindings/lib/array_internal.h
index eecfcfbc..5da63d6 100644
--- a/mojo/public/cpp/bindings/lib/array_internal.h
+++ b/mojo/public/cpp/bindings/lib/array_internal.h
@@ -12,6 +12,7 @@
 #include <new>
 
 #include "base/logging.h"
+#include "base/macros.h"
 #include "mojo/public/c/system/macros.h"
 #include "mojo/public/cpp/bindings/bindings_export.h"
 #include "mojo/public/cpp/bindings/lib/bindings_internal.h"
@@ -268,17 +269,35 @@
           std::is_same<T, Handle_Data>::value>;
   using Element = T;
 
-  // Returns null if |num_elements| or the corresponding storage size cannot be
-  // stored in uint32_t.
-  static Array_Data<T>* New(size_t num_elements, Buffer* buf) {
-    if (num_elements > Traits::kMaxNumElements)
-      return nullptr;
+  class BufferWriter {
+   public:
+    BufferWriter() = default;
 
-    uint32_t num_bytes =
-        Traits::GetStorageSize(static_cast<uint32_t>(num_elements));
-    return new (buf->Allocate(num_bytes))
-        Array_Data<T>(num_bytes, static_cast<uint32_t>(num_elements));
-  }
+    void Allocate(size_t num_elements, Buffer* buffer) {
+      if (num_elements > Traits::kMaxNumElements)
+        return;
+
+      uint32_t num_bytes =
+          Traits::GetStorageSize(static_cast<uint32_t>(num_elements));
+      buffer_ = buffer;
+      index_ = buffer_->Allocate(num_bytes);
+      new (data())
+          Array_Data<T>(num_bytes, static_cast<uint32_t>(num_elements));
+    }
+
+    bool is_null() const { return !buffer_; }
+    Array_Data<T>* data() {
+      DCHECK(!is_null());
+      return buffer_->Get<Array_Data<T>>(index_);
+    }
+    Array_Data<T>* operator->() { return data(); }
+
+   private:
+    Buffer* buffer_ = nullptr;
+    size_t index_ = 0;
+
+    DISALLOW_COPY_AND_ASSIGN(BufferWriter);
+  };
 
   static bool Validate(const void* data,
                        ValidationContext* validation_context,
diff --git a/mojo/public/cpp/bindings/lib/array_serialization.h b/mojo/public/cpp/bindings/lib/array_serialization.h
index 9396237..4d465b0e 100644
--- a/mojo/public/cpp/bindings/lib/array_serialization.h
+++ b/mojo/public/cpp/bindings/lib/array_serialization.h
@@ -112,20 +112,19 @@
   using DataElement = typename Data::Element;
   using Element = typename MojomType::Element;
   using Traits = ArrayTraits<UserType>;
+  using BufferWriter = typename Data::BufferWriter;
 
   static_assert(std::is_same<Element, DataElement>::value,
                 "Incorrect array serializer");
   static_assert(std::is_same<Element, typename Traits::Element>::value,
                 "Incorrect array serializer");
 
-  static size_t GetSerializedSize(UserTypeIterator* input,
-                                  SerializationContext* context) {
-    return sizeof(Data) + Align(input->GetSize() * sizeof(DataElement));
-  }
+  static void PrepareToSerialize(UserTypeIterator* input,
+                                 SerializationContext* context) {}
 
   static void SerializeElements(UserTypeIterator* input,
                                 Buffer* buf,
-                                Data* output,
+                                BufferWriter* writer,
                                 const ContainerValidateParams* validate_params,
                                 SerializationContext* context) {
     DCHECK(!validate_params->element_is_nullable)
@@ -138,6 +137,7 @@
       return;
 
     auto data = input->GetDataIfExists();
+    Data* output = writer->data();
     if (data) {
       memcpy(output->storage(), data, size * sizeof(DataElement));
     } else {
@@ -180,18 +180,17 @@
   using DataElement = typename Data::Element;
   using Element = typename MojomType::Element;
   using Traits = ArrayTraits<UserType>;
+  using BufferWriter = typename Data::BufferWriter;
 
   static_assert(sizeof(Element) == sizeof(DataElement),
                 "Incorrect array serializer");
 
-  static size_t GetSerializedSize(UserTypeIterator* input,
-                                  SerializationContext* context) {
-    return sizeof(Data) + Align(input->GetSize() * sizeof(DataElement));
-  }
+  static void PrepareToSerialize(UserTypeIterator* input,
+                                 SerializationContext* context) {}
 
   static void SerializeElements(UserTypeIterator* input,
                                 Buffer* buf,
-                                Data* output,
+                                BufferWriter* writer,
                                 const ContainerValidateParams* validate_params,
                                 SerializationContext* context) {
     DCHECK(!validate_params->element_is_nullable)
@@ -199,6 +198,7 @@
     DCHECK(!validate_params->element_validate_params)
         << "Primitive type should not have array validate params";
 
+    Data* output = writer->data();
     size_t size = input->GetSize();
     for (size_t i = 0; i < size; ++i)
       Serialize<Element>(input->GetNext(), output->storage() + i);
@@ -231,18 +231,17 @@
   using UserType = typename std::remove_const<MaybeConstUserType>::type;
   using Traits = ArrayTraits<UserType>;
   using Data = typename MojomTypeTraits<MojomType>::Data;
+  using BufferWriter = typename Data::BufferWriter;
 
   static_assert(std::is_same<bool, typename Traits::Element>::value,
                 "Incorrect array serializer");
 
-  static size_t GetSerializedSize(UserTypeIterator* input,
-                                  SerializationContext* context) {
-    return sizeof(Data) + Align((input->GetSize() + 7) / 8);
-  }
+  static void PrepareToSerialize(UserTypeIterator* input,
+                                 SerializationContext* context) {}
 
   static void SerializeElements(UserTypeIterator* input,
                                 Buffer* buf,
-                                Data* output,
+                                BufferWriter* writer,
                                 const ContainerValidateParams* validate_params,
                                 SerializationContext* context) {
     DCHECK(!validate_params->element_is_nullable)
@@ -250,6 +249,7 @@
     DCHECK(!validate_params->element_validate_params)
         << "Primitive type should not have array validate params";
 
+    Data* output = writer->data();
     size_t size = input->GetSize();
     for (size_t i = 0; i < size; ++i)
       output->at(i) = input->GetNext();
@@ -284,26 +284,26 @@
   using Data = typename MojomTypeTraits<MojomType>::Data;
   using Element = typename MojomType::Element;
   using Traits = ArrayTraits<UserType>;
+  using BufferWriter = typename Data::BufferWriter;
 
-  static size_t GetSerializedSize(UserTypeIterator* input,
-                                  SerializationContext* context) {
+  static void PrepareToSerialize(UserTypeIterator* input,
+                                 SerializationContext* context) {
     size_t element_count = input->GetSize();
     for (size_t i = 0; i < element_count; ++i) {
       typename UserTypeIterator::GetNextResult next = input->GetNext();
-      size_t size = PrepareToSerialize<Element>(next, context);
-      DCHECK_EQ(size, 0u);
+      ::mojo::internal::PrepareToSerialize<Element>(next, context);
     }
-    return sizeof(Data) + Align(element_count * sizeof(typename Data::Element));
   }
 
   static void SerializeElements(UserTypeIterator* input,
                                 Buffer* buf,
-                                Data* output,
+                                BufferWriter* writer,
                                 const ContainerValidateParams* validate_params,
                                 SerializationContext* context) {
     DCHECK(!validate_params->element_validate_params)
         << "Handle or interface type should not have array validate params";
 
+    Data* output = writer->data();
     size_t size = input->GetSize();
     for (size_t i = 0; i < size; ++i) {
       typename UserTypeIterator::GetNextResult next = input->GetNext();
@@ -355,35 +355,36 @@
   using UserType = typename std::remove_const<MaybeConstUserType>::type;
   using Data = typename MojomTypeTraits<MojomType>::Data;
   using Element = typename MojomType::Element;
-  using DataElementPtr = typename MojomTypeTraits<Element>::Data*;
+  using DataElementWriter =
+      typename MojomTypeTraits<Element>::Data::BufferWriter;
   using Traits = ArrayTraits<UserType>;
+  using BufferWriter = typename Data::BufferWriter;
 
-  static size_t GetSerializedSize(UserTypeIterator* input,
-                                  SerializationContext* context) {
+  static void PrepareToSerialize(UserTypeIterator* input,
+                                 SerializationContext* context) {
     size_t element_count = input->GetSize();
-    size_t size = sizeof(Data) + element_count * sizeof(typename Data::Element);
     for (size_t i = 0; i < element_count; ++i) {
       typename UserTypeIterator::GetNextResult next = input->GetNext();
-      size += PrepareToSerialize<Element>(next, context);
+      ::mojo::internal::PrepareToSerialize<Element>(next, context);
     }
-    return size;
   }
 
   static void SerializeElements(UserTypeIterator* input,
                                 Buffer* buf,
-                                Data* output,
+                                BufferWriter* writer,
                                 const ContainerValidateParams* validate_params,
                                 SerializationContext* context) {
     size_t size = input->GetSize();
     for (size_t i = 0; i < size; ++i) {
-      DataElementPtr data_ptr;
+      DataElementWriter data_writer;
       typename UserTypeIterator::GetNextResult next = input->GetNext();
-      SerializeCaller<Element>::Run(next, buf, &data_ptr,
+      SerializeCaller<Element>::Run(next, buf, &data_writer,
                                     validate_params->element_validate_params,
                                     context);
-      output->at(i).Set(data_ptr);
+      writer->data()->at(i).Set(data_writer.is_null() ? nullptr
+                                                      : data_writer.data());
       MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
-          !validate_params->element_is_nullable && !data_ptr,
+          !validate_params->element_is_nullable && data_writer.is_null(),
           VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
           MakeMessageWithArrayIndex("null in array expecting valid pointers",
                                     size, i));
@@ -412,10 +413,10 @@
     template <typename InputElementType>
     static void Run(InputElementType&& input,
                     Buffer* buf,
-                    DataElementPtr* output,
+                    DataElementWriter* writer,
                     const ContainerValidateParams* validate_params,
                     SerializationContext* context) {
-      Serialize<T>(std::forward<InputElementType>(input), buf, output, context);
+      Serialize<T>(std::forward<InputElementType>(input), buf, writer, context);
     }
   };
 
@@ -424,10 +425,10 @@
     template <typename InputElementType>
     static void Run(InputElementType&& input,
                     Buffer* buf,
-                    DataElementPtr* output,
+                    DataElementWriter* writer,
                     const ContainerValidateParams* validate_params,
                     SerializationContext* context) {
-      Serialize<T>(std::forward<InputElementType>(input), buf, output,
+      Serialize<T>(std::forward<InputElementType>(input), buf, writer,
                    validate_params, context);
     }
   };
@@ -446,33 +447,35 @@
   using UserType = typename std::remove_const<MaybeConstUserType>::type;
   using Data = typename MojomTypeTraits<MojomType>::Data;
   using Element = typename MojomType::Element;
+  using ElementWriter = typename Data::Element::BufferWriter;
   using Traits = ArrayTraits<UserType>;
+  using BufferWriter = typename Data::BufferWriter;
 
-  static size_t GetSerializedSize(UserTypeIterator* input,
-                                  SerializationContext* context) {
+  static void PrepareToSerialize(UserTypeIterator* input,
+                                 SerializationContext* context) {
     size_t element_count = input->GetSize();
-    size_t size = sizeof(Data);
     for (size_t i = 0; i < element_count; ++i) {
       // Call with |inlined| set to false, so that it will account for both the
       // data in the union and the space in the array used to hold the union.
       typename UserTypeIterator::GetNextResult next = input->GetNext();
-      size += PrepareToSerialize<Element>(next, false, context);
+      ::mojo::internal::PrepareToSerialize<Element>(next, false, context);
     }
-    return size;
   }
 
   static void SerializeElements(UserTypeIterator* input,
                                 Buffer* buf,
-                                Data* output,
+                                BufferWriter* writer,
                                 const ContainerValidateParams* validate_params,
                                 SerializationContext* context) {
     size_t size = input->GetSize();
     for (size_t i = 0; i < size; ++i) {
-      typename Data::Element* result = output->storage() + i;
+      ElementWriter result;
+      result.AllocateInline(buf, writer->data()->storage() + i);
       typename UserTypeIterator::GetNextResult next = input->GetNext();
       Serialize<Element>(next, buf, &result, true, context);
       MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
-          !validate_params->element_is_nullable && output->at(i).is_null(),
+          !validate_params->element_is_nullable &&
+              writer->data()->at(i).is_null(),
           VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
           MakeMessageWithArrayIndex("null in array expecting valid unions",
                                     size, i));
@@ -501,40 +504,36 @@
                                MaybeConstUserType,
                                ArrayIterator<Traits, MaybeConstUserType>>;
   using Data = typename MojomTypeTraits<ArrayDataView<Element>>::Data;
+  using BufferWriter = typename Data::BufferWriter;
 
-  static size_t PrepareToSerialize(MaybeConstUserType& input,
-                                   SerializationContext* context) {
-    const bool is_null = CallIsNullIfExists<Traits>(input);
-    context->PushNextNullState(is_null);
-    if (is_null)
-      return 0;
+  static void PrepareToSerialize(MaybeConstUserType& input,
+                                 SerializationContext* context) {
+    if (CallIsNullIfExists<Traits>(input))
+      return;
+
     ArrayIterator<Traits, MaybeConstUserType> iterator(input);
-    return Impl::GetSerializedSize(&iterator, context);
+    Impl::PrepareToSerialize(&iterator, context);
   }
 
   static void Serialize(MaybeConstUserType& input,
                         Buffer* buf,
-                        Data** output,
+                        BufferWriter* writer,
                         const ContainerValidateParams* validate_params,
                         SerializationContext* context) {
-    if (!context->IsNextFieldNull()) {
-      MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
-          validate_params->expected_num_elements != 0 &&
-              Traits::GetSize(input) != validate_params->expected_num_elements,
-          internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER,
-          internal::MakeMessageWithExpectedArraySize(
-              "fixed-size array has wrong number of elements",
-              Traits::GetSize(input), validate_params->expected_num_elements));
-      Data* result = Data::New(Traits::GetSize(input), buf);
-      if (result) {
-        ArrayIterator<Traits, MaybeConstUserType> iterator(input);
-        Impl::SerializeElements(&iterator, buf, result, validate_params,
-                                context);
-      }
-      *output = result;
-    } else {
-      *output = nullptr;
-    }
+    if (CallIsNullIfExists<Traits>(input))
+      return;
+
+    const size_t size = Traits::GetSize(input);
+    MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
+        validate_params->expected_num_elements != 0 &&
+            size != validate_params->expected_num_elements,
+        internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER,
+        internal::MakeMessageWithExpectedArraySize(
+            "fixed-size array has wrong number of elements", size,
+            validate_params->expected_num_elements));
+    writer->Allocate(size, buf);
+    ArrayIterator<Traits, MaybeConstUserType> iterator(input);
+    Impl::SerializeElements(&iterator, buf, writer, validate_params, context);
   }
 
   static bool Deserialize(Data* input,
diff --git a/mojo/public/cpp/bindings/lib/buffer.cc b/mojo/public/cpp/bindings/lib/buffer.cc
index 308156ad..7ae856a4a 100644
--- a/mojo/public/cpp/bindings/lib/buffer.cc
+++ b/mojo/public/cpp/bindings/lib/buffer.cc
@@ -5,6 +5,8 @@
 #include "mojo/public/cpp/bindings/lib/buffer.h"
 
 #include "base/logging.h"
+#include "base/numerics/safe_math.h"
+#include "mojo/public/c/system/message_pipe.h"
 #include "mojo/public/cpp/bindings/lib/bindings_internal.h"
 
 namespace mojo {
@@ -12,7 +14,13 @@
 
 Buffer::Buffer() = default;
 
-Buffer::Buffer(void* data, size_t size) : data_(data), size_(size), cursor_(0) {
+Buffer::Buffer(void* data, size_t size, size_t cursor)
+    : data_(data), size_(size), cursor_(cursor) {
+  DCHECK(IsAligned(data_));
+}
+
+Buffer::Buffer(MessageHandle message, void* data, size_t size)
+    : message_(message), data_(data), size_(size), cursor_(0) {
   DCHECK(IsAligned(data_));
 }
 
@@ -23,6 +31,7 @@
 Buffer::~Buffer() = default;
 
 Buffer& Buffer::operator=(Buffer&& other) {
+  message_ = other.message_;
   data_ = other.data_;
   size_ = other.size_;
   cursor_ = other.cursor_;
@@ -30,19 +39,59 @@
   return *this;
 }
 
-void* Buffer::Allocate(size_t num_bytes) {
-  const size_t block_start = cursor_;
-  cursor_ += Align(num_bytes);
-  if (cursor_ > size_ || cursor_ < block_start) {
+size_t Buffer::Allocate(size_t num_bytes) {
+  const size_t aligned_num_bytes = Align(num_bytes);
+  const size_t new_cursor = cursor_ + aligned_num_bytes;
+  if (new_cursor < cursor_ || (new_cursor > size_ && !message_.is_valid())) {
+    // Either we've overflowed or exceeded a fixed capacity.
     NOTREACHED();
-    cursor_ = block_start;
-    return nullptr;
+    return 0;
   }
-  DCHECK_LE(cursor_, size_);
-  return reinterpret_cast<char*>(data_) + block_start;
+
+  if (new_cursor > size_) {
+    // If we have an underlying message object we can extend its payload to
+    // obtain more storage capacity.
+    DCHECK(base::IsValueInRangeForNumericType<uint32_t>(new_cursor));
+    uint32_t new_size;
+    MojoResult rv = MojoExtendSerializedMessagePayload(
+        message_.value(), static_cast<uint32_t>(new_cursor), &data_, &new_size);
+    DCHECK_EQ(MOJO_RESULT_OK, rv);
+    size_ = new_size;
+  }
+
+  DCHECK_LE(new_cursor, size_);
+  size_t block_start = cursor_;
+  cursor_ = new_cursor;
+
+  // Clear any padding reserved for this allocation. Non-padding bytes are the
+  // caller's responsibility to fill in.
+  memset(static_cast<uint8_t*>(data_) + block_start + num_bytes, 0,
+         aligned_num_bytes - num_bytes);
+
+  return block_start;
+}
+
+void Buffer::Seal() {
+  if (!message_.is_valid())
+    return;
+
+  // Ensure that the backing message has the final accumulated payload size.
+  DCHECK(base::IsValueInRangeForNumericType<uint32_t>(cursor_));
+  void* data;
+  uint32_t size;
+  MojoResult rv = MojoExtendSerializedMessagePayload(
+      message_.value(), static_cast<uint32_t>(cursor_), &data, &size);
+  DCHECK_EQ(MOJO_RESULT_OK, rv);
+
+  // The buffer size should remain the same, as the final cursor position was
+  // necessarily within the previous allocated payload range.
+  DCHECK_EQ(size, size_);
+  DCHECK_EQ(data, data_);
+  message_ = MessageHandle();
 }
 
 void Buffer::Reset() {
+  message_ = MessageHandle();
   data_ = nullptr;
   size_ = 0;
   cursor_ = 0;
diff --git a/mojo/public/cpp/bindings/lib/buffer.h b/mojo/public/cpp/bindings/lib/buffer.h
index 2b6cbcc..7218352 100644
--- a/mojo/public/cpp/bindings/lib/buffer.h
+++ b/mojo/public/cpp/bindings/lib/buffer.h
@@ -10,6 +10,7 @@
 
 #include "base/macros.h"
 #include "mojo/public/cpp/bindings/bindings_export.h"
+#include "mojo/public/cpp/system/message.h"
 
 namespace mojo {
 namespace internal {
@@ -25,9 +26,21 @@
   // Constructs an invalid Buffer. May not call Allocate().
   Buffer();
 
-  // Constructs a Buffer which can Allocate() blocks starting at |data|, up to
-  // a total of |size| bytes. |data| is not owned.
-  Buffer(void* data, size_t size);
+  // Constructs a Buffer which can Allocate() blocks from a buffer of fixed size
+  // |size| at |data|. Allocations start at |cursor|, so if |cursor| == |size|
+  // then no allocations are allowed.
+  //
+  // |data| is not owned.
+  Buffer(void* data, size_t size, size_t cursor);
+
+  // Like above, but gives the Buffer an underlying message object which can
+  // have its payload extended to acquire more storage capacity on Allocate().
+  //
+  // |data| and |size| must correspond to |message|'s serialized buffer contents
+  // at the time of construction.
+  //
+  // |message| is NOT owned and must outlive this Buffer.
+  Buffer(MessageHandle message, void* data, size_t size);
 
   Buffer(Buffer&& other);
   ~Buffer();
@@ -38,16 +51,47 @@
   size_t size() const { return size_; }
   size_t cursor() const { return cursor_; }
 
-  bool is_valid() const { return data_ != nullptr; }
+  bool is_valid() const {
+    return data_ != nullptr || (size_ == 0 && !message_.is_valid());
+  }
 
-  // Allocates |num_bytes| from the buffer and returns a pointer to the start of
-  // the allocated block. The resulting address is 8-byte aligned.
-  void* Allocate(size_t num_bytes);
+  // Allocates |num_bytes| from the buffer and returns an index to the start of
+  // the allocated block. The resulting index is 8-byte aligned and can be
+  // resolved to an address using Get<T>() below.
+  size_t Allocate(size_t num_bytes);
+
+  // Returns a typed address within the Buffer corresponding to |index|. Note
+  // that this address is NOT stable across calls to |Allocate()| and thus must
+  // not be cached accordingly.
+  template <typename T>
+  T* Get(size_t index) {
+    DCHECK_LT(index, cursor_);
+    return reinterpret_cast<T*>(static_cast<uint8_t*>(data_) + index);
+  }
+
+  // A template helper combining Allocate() and Get<T>() above to allocate and
+  // return a block of size |sizeof(T)|.
+  template <typename T>
+  T* AllocateAndGet() {
+    return Get<T>(Allocate(sizeof(T)));
+  }
+
+  // A helper which combines Allocate() and Get<void>() for a specified number
+  // of bytes.
+  void* AllocateAndGet(size_t num_bytes) {
+    return Get<void>(Allocate(num_bytes));
+  }
+
+  // Seals this Buffer so it can no longer be used for allocation, and ensures
+  // the backing message object has a complete accounting of the size of the
+  // meaningful payload bytes.
+  void Seal();
 
   // Resets the buffer to an invalid state. Can no longer be used to Allocate().
   void Reset();
 
  private:
+  MessageHandle message_;
   void* data_ = nullptr;
   size_t size_ = 0;
   size_t cursor_ = 0;
diff --git a/mojo/public/cpp/bindings/lib/control_message_handler.cc b/mojo/public/cpp/bindings/lib/control_message_handler.cc
index 2160a78..b87c11c8 100644
--- a/mojo/public/cpp/bindings/lib/control_message_handler.cc
+++ b/mojo/public/cpp/bindings/lib/control_message_handler.cc
@@ -115,14 +115,11 @@
 
   auto response_params_ptr = interface_control::RunResponseMessageParams::New();
   response_params_ptr->output = std::move(output);
-  size_t size =
-      PrepareToSerialize<interface_control::RunResponseMessageParamsDataView>(
-          response_params_ptr, &context_);
   Message response_message(interface_control::kRunMessageId,
-                           Message::kFlagIsResponse, size, 0);
+                           Message::kFlagIsResponse, 0, 0, nullptr);
   response_message.set_request_id(message->request_id());
-  interface_control::internal::RunResponseMessageParams_Data* response_params =
-      nullptr;
+  interface_control::internal::RunResponseMessageParams_Data::BufferWriter
+      response_params;
   Serialize<interface_control::RunResponseMessageParamsDataView>(
       response_params_ptr, response_message.payload_buffer(), &response_params,
       &context_);
diff --git a/mojo/public/cpp/bindings/lib/control_message_proxy.cc b/mojo/public/cpp/bindings/lib/control_message_proxy.cc
index 672d620..2509081 100644
--- a/mojo/public/cpp/bindings/lib/control_message_proxy.cc
+++ b/mojo/public/cpp/bindings/lib/control_message_proxy.cc
@@ -72,15 +72,12 @@
 void SendRunMessage(MessageReceiverWithResponder* receiver,
                     interface_control::RunInputPtr input_ptr,
                     const RunCallback& callback) {
-  SerializationContext context;
   auto params_ptr = interface_control::RunMessageParams::New();
   params_ptr->input = std::move(input_ptr);
-  const size_t size =
-      PrepareToSerialize<interface_control::RunMessageParamsDataView>(
-          params_ptr, &context);
   Message message(interface_control::kRunMessageId,
-                  Message::kFlagExpectsResponse, size, 0);
-  interface_control::internal::RunMessageParams_Data* params = nullptr;
+                  Message::kFlagExpectsResponse, 0, 0, nullptr);
+  SerializationContext context;
+  interface_control::internal::RunMessageParams_Data::BufferWriter params;
   Serialize<interface_control::RunMessageParamsDataView>(
       params_ptr, message.payload_buffer(), &params, &context);
   std::unique_ptr<MessageReceiver> responder =
@@ -90,15 +87,13 @@
 
 Message ConstructRunOrClosePipeMessage(
     interface_control::RunOrClosePipeInputPtr input_ptr) {
-  SerializationContext context;
   auto params_ptr = interface_control::RunOrClosePipeMessageParams::New();
   params_ptr->input = std::move(input_ptr);
-  const size_t size = PrepareToSerialize<
-      interface_control::RunOrClosePipeMessageParamsDataView>(params_ptr,
-                                                              &context);
-  Message message(interface_control::kRunOrClosePipeMessageId, 0, size, 0);
-  interface_control::internal::RunOrClosePipeMessageParams_Data* params =
-      nullptr;
+  Message message(interface_control::kRunOrClosePipeMessageId, 0, 0, 0,
+                  nullptr);
+  SerializationContext context;
+  interface_control::internal::RunOrClosePipeMessageParams_Data::BufferWriter
+      params;
   Serialize<interface_control::RunOrClosePipeMessageParamsDataView>(
       params_ptr, message.payload_buffer(), &params, &context);
   return message;
diff --git a/mojo/public/cpp/bindings/lib/fixed_buffer.cc b/mojo/public/cpp/bindings/lib/fixed_buffer.cc
index 3a540268..3d595cc0 100644
--- a/mojo/public/cpp/bindings/lib/fixed_buffer.cc
+++ b/mojo/public/cpp/bindings/lib/fixed_buffer.cc
@@ -12,21 +12,11 @@
 namespace internal {
 
 FixedBufferForTesting::FixedBufferForTesting(size_t size)
-    : FixedBufferForTesting(nullptr, Align(size)) {}
+    : Buffer(calloc(Align(size), 1), Align(size), 0) {}
 
 FixedBufferForTesting::~FixedBufferForTesting() {
   free(data());
 }
 
-void* FixedBufferForTesting::Leak() {
-  void* ptr = data();
-  Reset();
-  return ptr;
-}
-
-FixedBufferForTesting::FixedBufferForTesting(std::nullptr_t,
-                                             size_t aligned_size)
-    : Buffer(calloc(aligned_size, 1), aligned_size) {}
-
 }  // namespace internal
 }  // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/fixed_buffer.h b/mojo/public/cpp/bindings/lib/fixed_buffer.h
index 8fa3ff5d..0df600f 100644
--- a/mojo/public/cpp/bindings/lib/fixed_buffer.h
+++ b/mojo/public/cpp/bindings/lib/fixed_buffer.h
@@ -21,15 +21,7 @@
   explicit FixedBufferForTesting(size_t size);
   ~FixedBufferForTesting();
 
-  // Returns the internal memory owned by the Buffer to the caller. The Buffer
-  // relinquishes its pointer, effectively resetting the state of the Buffer
-  // and leaving the caller responsible for freeing the returned memory address
-  // when no longer needed.
-  void* Leak();
-
  private:
-  FixedBufferForTesting(std::nullptr_t, size_t aligned_size);
-
   DISALLOW_COPY_AND_ASSIGN(FixedBufferForTesting);
 };
 
diff --git a/mojo/public/cpp/bindings/lib/handle_interface_serialization.h b/mojo/public/cpp/bindings/lib/handle_interface_serialization.h
index 661519b4..701c4da 100644
--- a/mojo/public/cpp/bindings/lib/handle_interface_serialization.h
+++ b/mojo/public/cpp/bindings/lib/handle_interface_serialization.h
@@ -26,11 +26,10 @@
                   AssociatedInterfacePtrInfo<T>> {
   static_assert(std::is_base_of<Base, T>::value, "Interface type mismatch.");
 
-  static size_t PrepareToSerialize(AssociatedInterfacePtrInfo<T>& input,
-                                   SerializationContext* context) {
+  static void PrepareToSerialize(AssociatedInterfacePtrInfo<T>& input,
+                                 SerializationContext* context) {
     DCHECK(!input.handle().is_valid() || input.handle().pending_association());
     context->AddAssociatedInterfaceInfo(input.PassHandle(), input.version());
-    return 0;
   }
 
   static void Serialize(const AssociatedInterfacePtrInfo<T>& input,
@@ -59,11 +58,10 @@
                   AssociatedInterfaceRequest<T>> {
   static_assert(std::is_base_of<Base, T>::value, "Interface type mismatch.");
 
-  static size_t PrepareToSerialize(AssociatedInterfaceRequest<T>& input,
-                                   SerializationContext* context) {
+  static void PrepareToSerialize(AssociatedInterfaceRequest<T>& input,
+                                 SerializationContext* context) {
     DCHECK(!input.handle().is_valid() || input.handle().pending_association());
     context->AddAssociatedEndpoint(input.PassHandle());
-    return 0;
   }
 
   static void Serialize(const AssociatedInterfaceRequest<T>& input,
@@ -89,11 +87,10 @@
 struct Serializer<InterfacePtrDataView<Base>, InterfacePtr<T>> {
   static_assert(std::is_base_of<Base, T>::value, "Interface type mismatch.");
 
-  static size_t PrepareToSerialize(InterfacePtr<T>& input,
-                                   SerializationContext* context) {
+  static void PrepareToSerialize(InterfacePtr<T>& input,
+                                 SerializationContext* context) {
     InterfacePtrInfo<T> info = input.PassInterface();
     context->AddInterfaceInfo(info.PassHandle(), info.version());
-    return 0;
   }
 
   static void Serialize(const InterfacePtr<T>& input,
@@ -117,10 +114,9 @@
 struct Serializer<InterfaceRequestDataView<Base>, InterfaceRequest<T>> {
   static_assert(std::is_base_of<Base, T>::value, "Interface type mismatch.");
 
-  static size_t PrepareToSerialize(InterfaceRequest<T>& input,
-                                   SerializationContext* context) {
+  static void PrepareToSerialize(InterfaceRequest<T>& input,
+                                 SerializationContext* context) {
     context->AddHandle(ScopedHandle::From(input.PassMessagePipe()));
-    return 0;
   }
 
   static void Serialize(const InterfaceRequest<T>& input,
@@ -141,10 +137,9 @@
 
 template <typename T>
 struct Serializer<ScopedHandleBase<T>, ScopedHandleBase<T>> {
-  static size_t PrepareToSerialize(ScopedHandleBase<T>& input,
-                                   SerializationContext* context) {
+  static void PrepareToSerialize(ScopedHandleBase<T>& input,
+                                 SerializationContext* context) {
     context->AddHandle(ScopedHandle::From(std::move(input)));
-    return 0;
   }
 
   static void Serialize(const ScopedHandleBase<T>& input,
diff --git a/mojo/public/cpp/bindings/lib/map_data_internal.h b/mojo/public/cpp/bindings/lib/map_data_internal.h
index f8e3d29..4809d08b 100644
--- a/mojo/public/cpp/bindings/lib/map_data_internal.h
+++ b/mojo/public/cpp/bindings/lib/map_data_internal.h
@@ -5,6 +5,7 @@
 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_DATA_INTERNAL_H_
 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_MAP_DATA_INTERNAL_H_
 
+#include "base/macros.h"
 #include "mojo/public/cpp/bindings/lib/array_internal.h"
 #include "mojo/public/cpp/bindings/lib/validate_params.h"
 #include "mojo/public/cpp/bindings/lib/validation_errors.h"
@@ -18,9 +19,29 @@
 template <typename Key, typename Value>
 class Map_Data {
  public:
-  static Map_Data* New(Buffer* buf) {
-    return new (buf->Allocate(sizeof(Map_Data))) Map_Data();
-  }
+  class BufferWriter {
+   public:
+    BufferWriter() = default;
+
+    void Allocate(Buffer* buffer) {
+      buffer_ = buffer;
+      index_ = buffer_->Allocate(sizeof(Map_Data));
+      new (data()) Map_Data();
+    }
+
+    bool is_null() const { return !buffer_; }
+    Map_Data* data() {
+      DCHECK(!is_null());
+      return buffer_->Get<Map_Data>(index_);
+    }
+    Map_Data* operator->() { return data(); }
+
+   private:
+    Buffer* buffer_ = nullptr;
+    size_t index_ = 0;
+
+    DISALLOW_COPY_AND_ASSIGN(BufferWriter);
+  };
 
   // |validate_params| must have non-null |key_validate_params| and
   // |element_validate_params| members.
diff --git a/mojo/public/cpp/bindings/lib/map_serialization.h b/mojo/public/cpp/bindings/lib/map_serialization.h
index 23b0a12..13d780a 100644
--- a/mojo/public/cpp/bindings/lib/map_serialization.h
+++ b/mojo/public/cpp/bindings/lib/map_serialization.h
@@ -95,59 +95,45 @@
                       std::vector<UserValue>,
                       MapValueReader<MaybeConstUserType>>;
 
-  static size_t PrepareToSerialize(MaybeConstUserType& input,
-                                   SerializationContext* context) {
-    const bool is_null = CallIsNullIfExists<Traits>(input);
-    context->PushNextNullState(is_null);
-    if (is_null)
-      return 0;
+  static void PrepareToSerialize(MaybeConstUserType& input,
+                                 SerializationContext* context) {
+    if (CallIsNullIfExists<Traits>(input))
+      return;
 
-    size_t struct_overhead = sizeof(Data);
     MapKeyReader<MaybeConstUserType> key_reader(input);
-    size_t keys_size =
-        KeyArraySerializer::GetSerializedSize(&key_reader, context);
+    KeyArraySerializer::PrepareToSerialize(&key_reader, context);
     MapValueReader<MaybeConstUserType> value_reader(input);
-    size_t values_size =
-        ValueArraySerializer::GetSerializedSize(&value_reader, context);
-
-    return struct_overhead + keys_size + values_size;
+    ValueArraySerializer::PrepareToSerialize(&value_reader, context);
   }
 
   static void Serialize(MaybeConstUserType& input,
                         Buffer* buf,
-                        Data** output,
+                        typename Data::BufferWriter* writer,
                         const ContainerValidateParams* validate_params,
                         SerializationContext* context) {
     DCHECK(validate_params->key_validate_params);
     DCHECK(validate_params->element_validate_params);
-    if (context->IsNextFieldNull()) {
-      *output = nullptr;
+    if (CallIsNullIfExists<Traits>(input))
       return;
-    }
 
-    auto result = Data::New(buf);
-    if (result) {
-      auto keys_ptr = MojomTypeTraits<ArrayDataView<Key>>::Data::New(
-          Traits::GetSize(input), buf);
-      if (keys_ptr) {
-        MapKeyReader<MaybeConstUserType> key_reader(input);
-        KeyArraySerializer::SerializeElements(
-            &key_reader, buf, keys_ptr, validate_params->key_validate_params,
-            context);
-        result->keys.Set(keys_ptr);
-      }
+    writer->Allocate(buf);
+    typename MojomTypeTraits<ArrayDataView<Key>>::Data::BufferWriter
+        keys_writer;
+    keys_writer.Allocate(Traits::GetSize(input), buf);
+    MapKeyReader<MaybeConstUserType> key_reader(input);
+    KeyArraySerializer::SerializeElements(&key_reader, buf, &keys_writer,
+                                          validate_params->key_validate_params,
+                                          context);
+    (*writer)->keys.Set(keys_writer.data());
 
-      auto values_ptr = MojomTypeTraits<ArrayDataView<Value>>::Data::New(
-          Traits::GetSize(input), buf);
-      if (values_ptr) {
-        MapValueReader<MaybeConstUserType> value_reader(input);
-        ValueArraySerializer::SerializeElements(
-            &value_reader, buf, values_ptr,
-            validate_params->element_validate_params, context);
-        result->values.Set(values_ptr);
-      }
-    }
-    *output = result;
+    typename MojomTypeTraits<ArrayDataView<Value>>::Data::BufferWriter
+        values_writer;
+    values_writer.Allocate(Traits::GetSize(input), buf);
+    MapValueReader<MaybeConstUserType> value_reader(input);
+    ValueArraySerializer::SerializeElements(
+        &value_reader, buf, &values_writer,
+        validate_params->element_validate_params, context);
+    (*writer)->values.Set(values_writer.data());
   }
 
   static bool Deserialize(Data* input,
diff --git a/mojo/public/cpp/bindings/lib/message.cc b/mojo/public/cpp/bindings/lib/message.cc
index 11b02d9fb..9dbebed 100644
--- a/mojo/public/cpp/bindings/lib/message.cc
+++ b/mojo/public/cpp/bindings/lib/message.cc
@@ -37,7 +37,7 @@
 
 template <typename HeaderType>
 void AllocateHeaderFromBuffer(internal::Buffer* buffer, HeaderType** header) {
-  *header = static_cast<HeaderType*>(buffer->Allocate(sizeof(HeaderType)));
+  *header = buffer->AllocateAndGet<HeaderType>();
   (*header)->num_bytes = sizeof(HeaderType);
 }
 
@@ -102,7 +102,7 @@
       ignore_result(handles->at(i).release());
   }
 
-  internal::Buffer payload_buffer(buffer, buffer_size);
+  internal::Buffer payload_buffer(handle.get(), buffer, buffer_size);
 
   // Make sure we zero the memory first!
   memset(payload_buffer.data(), 0, total_size);
@@ -136,7 +136,7 @@
   if (rv != MOJO_RESULT_OK)
     return;
 
-  internal::Buffer payload_buffer(buffer, num_bytes);
+  internal::Buffer payload_buffer(MessageHandle(message), buffer, buffer_size);
   WriteMessageHeader(context->message_name(), context->message_flags(),
                      0 /* payload_interface_id_count */, &payload_buffer);
 
@@ -153,6 +153,7 @@
   }
 
   context->SerializePayload(&payload_buffer);
+  payload_buffer.Seal();
 }
 
 void DestroyUnserializedContext(uintptr_t context) {
@@ -190,8 +191,6 @@
   CreateSerializedMessageObject(name, flags, payload_size,
                                 payload_interface_id_count, handles, &handle_,
                                 &payload_buffer_);
-  data_ = payload_buffer_.data();
-  data_size_ = payload_buffer_.size();
   transferable_ = true;
   serialized_ = true;
 }
@@ -227,8 +226,7 @@
       return;
     }
 
-    data_ = buffer;
-    data_size_ = num_bytes;
+    payload_buffer_ = internal::Buffer(buffer, num_bytes, num_bytes);
     serialized_ = true;
   } else {
     DCHECK_EQ(MOJO_RESULT_OK, get_context_result);
@@ -238,8 +236,9 @@
     // choice is V1 reflects unserialized message capabilities: we may or may
     // not need to support request IDs (which require at least V1), but we never
     // (for now, anyway) need to support associated interface handles (V2).
-    data_ = context->header();
-    data_size_ = sizeof(internal::MessageHeaderV1);
+    payload_buffer_ =
+        internal::Buffer(context->header(), sizeof(internal::MessageHeaderV1),
+                         sizeof(internal::MessageHeaderV1));
     transferable_ = true;
     serialized_ = false;
   }
@@ -253,10 +252,9 @@
 
 void Message::Reset() {
   handle_.reset();
+  payload_buffer_.Reset();
   handles_.clear();
   associated_endpoint_handles_.clear();
-  data_ = nullptr;
-  data_size_ = 0;
   transferable_ = false;
   serialized_ = false;
 }
@@ -284,7 +282,7 @@
     DCHECK_GE(payload_end, payload_begin);
     num_bytes = payload_end - payload_begin;
   }
-  DCHECK_LE(num_bytes, std::numeric_limits<uint32_t>::max());
+  DCHECK(base::IsValueInRangeForNumericType<uint32_t>(num_bytes));
   return static_cast<uint32_t>(num_bytes);
 }
 
@@ -305,6 +303,7 @@
   // SerializeAssociatedEndpointHandles() must be called before this method.
   DCHECK(associated_endpoint_handles_.empty());
   DCHECK(transferable_);
+  payload_buffer_.Seal();
   auto handle = std::move(handle_);
   Reset();
   return handle;
@@ -323,16 +322,19 @@
   DCHECK_GE(version(), 2u);
   DCHECK(header_v2()->payload_interface_ids.is_null());
   DCHECK(payload_buffer_.is_valid());
+  DCHECK(handle_.is_valid());
 
   size_t size = associated_endpoint_handles_.size();
-  auto* data = internal::Array_Data<uint32_t>::New(size, &payload_buffer_);
-  header_v2()->payload_interface_ids.Set(data);
+
+  internal::Array_Data<uint32_t>::BufferWriter handle_writer;
+  handle_writer.Allocate(size, &payload_buffer_);
+  header_v2()->payload_interface_ids.Set(handle_writer.data());
 
   for (size_t i = 0; i < size; ++i) {
     ScopedInterfaceEndpointHandle& handle = associated_endpoint_handles_[i];
 
     DCHECK(handle.pending_association());
-    data->storage()[i] =
+    handle_writer->storage()[i] =
         group_controller->AssociateInterface(std::move(handle));
   }
   associated_endpoint_handles_.clear();
diff --git a/mojo/public/cpp/bindings/lib/native_struct_data.h b/mojo/public/cpp/bindings/lib/native_struct_data.h
index 1c7cd81..bf3e8906 100644
--- a/mojo/public/cpp/bindings/lib/native_struct_data.h
+++ b/mojo/public/cpp/bindings/lib/native_struct_data.h
@@ -7,6 +7,7 @@
 
 #include <vector>
 
+#include "base/macros.h"
 #include "mojo/public/cpp/bindings/bindings_export.h"
 #include "mojo/public/cpp/bindings/lib/array_internal.h"
 #include "mojo/public/cpp/system/handle.h"
@@ -18,6 +19,28 @@
 
 class MOJO_CPP_BINDINGS_EXPORT NativeStruct_Data {
  public:
+  class BufferWriter {
+   public:
+    BufferWriter() = default;
+
+    void Allocate(size_t num_bytes, Buffer* buffer) {
+      array_writer_.Allocate(num_bytes, buffer);
+    }
+
+    Array_Data<uint8_t>::BufferWriter& array_writer() { return array_writer_; }
+
+    bool is_null() const { return array_writer_.is_null(); }
+    NativeStruct_Data* data() {
+      return reinterpret_cast<NativeStruct_Data*>(array_writer_.data());
+    }
+    NativeStruct_Data* operator->() { return data(); }
+
+   private:
+    Array_Data<uint8_t>::BufferWriter array_writer_;
+
+    DISALLOW_COPY_AND_ASSIGN(BufferWriter);
+  };
+
   static bool Validate(const void* data, ValidationContext* validation_context);
 
   // Unlike normal structs, the memory layout is exactly the same as an array
diff --git a/mojo/public/cpp/bindings/lib/native_struct_serialization.cc b/mojo/public/cpp/bindings/lib/native_struct_serialization.cc
index fa0dbf3..49715c9 100644
--- a/mojo/public/cpp/bindings/lib/native_struct_serialization.cc
+++ b/mojo/public/cpp/bindings/lib/native_struct_serialization.cc
@@ -10,31 +10,22 @@
 namespace internal {
 
 // static
-size_t UnmappedNativeStructSerializerImpl::PrepareToSerialize(
+void UnmappedNativeStructSerializerImpl::PrepareToSerialize(
     const NativeStructPtr& input,
-    SerializationContext* context) {
-  if (!input)
-    return 0;
-  return internal::PrepareToSerialize<ArrayDataView<uint8_t>>(input->data,
-                                                              context);
-}
+    SerializationContext* context) {}
 
 // static
 void UnmappedNativeStructSerializerImpl::Serialize(
     const NativeStructPtr& input,
     Buffer* buffer,
-    NativeStruct_Data** output,
+    NativeStruct_Data::BufferWriter* writer,
     SerializationContext* context) {
-  if (!input) {
-    *output = nullptr;
+  if (!input)
     return;
-  }
 
-  Array_Data<uint8_t>* data = nullptr;
   const ContainerValidateParams params(0, false, nullptr);
-  internal::Serialize<ArrayDataView<uint8_t>>(input->data, buffer, &data,
-                                              &params, context);
-  *output = reinterpret_cast<NativeStruct_Data*>(data);
+  internal::Serialize<ArrayDataView<uint8_t>>(
+      input->data, buffer, &writer->array_writer(), &params, context);
 }
 
 // static
diff --git a/mojo/public/cpp/bindings/lib/native_struct_serialization.h b/mojo/public/cpp/bindings/lib/native_struct_serialization.h
index 457435b..ead1ce8 100644
--- a/mojo/public/cpp/bindings/lib/native_struct_serialization.h
+++ b/mojo/public/cpp/bindings/lib/native_struct_serialization.h
@@ -30,16 +30,12 @@
   using UserType = typename std::remove_const<MaybeConstUserType>::type;
   using Traits = IPC::ParamTraits<UserType>;
 
-  static size_t PrepareToSerialize(MaybeConstUserType& value,
-                                   SerializationContext* context) {
-    base::PickleSizer sizer;
-    Traits::GetSize(&sizer, value);
-    return Align(sizer.payload_size() + sizeof(ArrayHeader));
-  }
+  static void PrepareToSerialize(MaybeConstUserType& value,
+                                 SerializationContext* context) {}
 
   static void Serialize(MaybeConstUserType& value,
                         Buffer* buffer,
-                        NativeStruct_Data** out,
+                        NativeStruct_Data::BufferWriter* writer,
                         SerializationContext* context) {
     base::Pickle pickle;
     Traits::Write(&pickle, value);
@@ -50,18 +46,10 @@
     DCHECK_EQ(sizer.payload_size(), pickle.payload_size());
 #endif
 
-    size_t total_size = pickle.payload_size() + sizeof(ArrayHeader);
-    DCHECK_LT(total_size, std::numeric_limits<uint32_t>::max());
-
     // Allocate a uint8 array, initialize its header, and copy the Pickle in.
-    ArrayHeader* header =
-        reinterpret_cast<ArrayHeader*>(buffer->Allocate(total_size));
-    header->num_bytes = static_cast<uint32_t>(total_size);
-    header->num_elements = static_cast<uint32_t>(pickle.payload_size());
-    memcpy(reinterpret_cast<char*>(header) + sizeof(ArrayHeader),
-           pickle.payload(), pickle.payload_size());
-
-    *out = reinterpret_cast<NativeStruct_Data*>(header);
+    writer->Allocate(pickle.payload_size(), buffer);
+    memcpy(writer->array_writer()->storage(), pickle.payload(),
+           pickle.payload_size());
   }
 
   static bool Deserialize(NativeStruct_Data* data,
@@ -105,11 +93,11 @@
 };
 
 struct MOJO_CPP_BINDINGS_EXPORT UnmappedNativeStructSerializerImpl {
-  static size_t PrepareToSerialize(const NativeStructPtr& input,
-                                   SerializationContext* context);
+  static void PrepareToSerialize(const NativeStructPtr& input,
+                                 SerializationContext* context);
   static void Serialize(const NativeStructPtr& input,
                         Buffer* buffer,
-                        NativeStruct_Data** output,
+                        NativeStruct_Data::BufferWriter* writer,
                         SerializationContext* context);
   static bool Deserialize(NativeStruct_Data* input,
                           NativeStructPtr* output,
diff --git a/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc b/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc
index 50db139..f218892 100644
--- a/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc
+++ b/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc
@@ -18,15 +18,12 @@
 
 Message ConstructRunOrClosePipeMessage(
     pipe_control::RunOrClosePipeInputPtr input_ptr) {
-  internal::SerializationContext context;
-
   auto params_ptr = pipe_control::RunOrClosePipeMessageParams::New();
   params_ptr->input = std::move(input_ptr);
 
-  size_t size = internal::PrepareToSerialize<
-      pipe_control::RunOrClosePipeMessageParamsDataView>(params_ptr, &context);
-  Message message(pipe_control::kRunOrClosePipeMessageId, 0, size, 0);
-  pipe_control::internal::RunOrClosePipeMessageParams_Data* params = nullptr;
+  Message message(pipe_control::kRunOrClosePipeMessageId, 0, 0, 0, nullptr);
+  internal::SerializationContext context;
+  pipe_control::internal::RunOrClosePipeMessageParams_Data::BufferWriter params;
   internal::Serialize<pipe_control::RunOrClosePipeMessageParamsDataView>(
       params_ptr, message.payload_buffer(), &params, &context);
   message.set_interface_id(kInvalidInterfaceId);
diff --git a/mojo/public/cpp/bindings/lib/serialization.h b/mojo/public/cpp/bindings/lib/serialization.h
index f479e9ed..aa839b8 100644
--- a/mojo/public/cpp/bindings/lib/serialization.h
+++ b/mojo/public/cpp/bindings/lib/serialization.h
@@ -18,6 +18,7 @@
 #include "mojo/public/cpp/bindings/lib/string_serialization.h"
 #include "mojo/public/cpp/bindings/lib/template_util.h"
 #include "mojo/public/cpp/bindings/map_traits_stl.h"
+#include "mojo/public/cpp/bindings/message.h"
 #include "mojo/public/cpp/bindings/string_traits_stl.h"
 #include "mojo/public/cpp/bindings/string_traits_string16.h"
 #include "mojo/public/cpp/bindings/string_traits_string_piece.h"
@@ -31,34 +32,16 @@
                 "Unexpected type.");
 
   SerializationContext context;
-  size_t size = PrepareToSerialize<MojomType>(*input, &context);
-  DCHECK_EQ(size, Align(size));
+  PrepareToSerialize<MojomType>(*input, &context);
 
+  Message message;
+  typename MojomTypeTraits<MojomType>::Data::BufferWriter writer;
+  context.PrepareMessage(0, 0, &message);
+  Serialize<MojomType>(*input, message.payload_buffer(), &writer, &context);
+  uint32_t size = message.payload_num_bytes();
   DataArrayType result(size);
-  if (size == 0)
-    return result;
-
-  void* result_buffer = &result.front();
-  // The serialization logic requires that the buffer is 8-byte aligned. If the
-  // result buffer is not properly aligned, we have to do an extra copy. In
-  // practice, this should never happen for std::vector.
-  bool need_copy = !IsAligned(result_buffer);
-
-  if (need_copy) {
-    // calloc sets the memory to all zero.
-    result_buffer = calloc(size, 1);
-    DCHECK(IsAligned(result_buffer));
-  }
-
-  Buffer buffer(result_buffer, size);
-  typename MojomTypeTraits<MojomType>::Data* data = nullptr;
-  Serialize<MojomType>(*input, &buffer, &data, &context);
-
-  if (need_copy) {
-    memcpy(&result.front(), result_buffer, size);
-    free(result_buffer);
-  }
-
+  if (size)
+    memcpy(&result.front(), message.payload(), size);
   return result;
 }
 
diff --git a/mojo/public/cpp/bindings/lib/serialization_context.cc b/mojo/public/cpp/bindings/lib/serialization_context.cc
index 8921a0e..ef8621641 100644
--- a/mojo/public/cpp/bindings/lib/serialization_context.cc
+++ b/mojo/public/cpp/bindings/lib/serialization_context.cc
@@ -111,9 +111,8 @@
 
 void SerializationContext::PrepareMessage(uint32_t message_name,
                                           uint32_t flags,
-                                          size_t payload_size,
                                           Message* message) {
-  *message = Message(message_name, flags, payload_size,
+  *message = Message(message_name, flags, 0,
                      associated_endpoint_handles_.size(), &handles_);
   associated_endpoint_handles_.swap(
       *message->mutable_associated_endpoint_handles());
diff --git a/mojo/public/cpp/bindings/lib/serialization_context.h b/mojo/public/cpp/bindings/lib/serialization_context.h
index d1e0da88..4e7dc0b 100644
--- a/mojo/public/cpp/bindings/lib/serialization_context.h
+++ b/mojo/public/cpp/bindings/lib/serialization_context.h
@@ -87,10 +87,7 @@
 
   // Prepares a new serialized message based on the state accumulated by this
   // SerializationContext so far.
-  void PrepareMessage(uint32_t message_name,
-                      uint32_t flags,
-                      size_t payload_size,
-                      Message* message);
+  void PrepareMessage(uint32_t message_name, uint32_t flags, Message* message);
 
   const std::vector<mojo::ScopedHandle>* handles() { return &handles_; }
   std::vector<mojo::ScopedHandle>* mutable_handles() { return &handles_; }
diff --git a/mojo/public/cpp/bindings/lib/serialization_forward.h b/mojo/public/cpp/bindings/lib/serialization_forward.h
index 55c9982..78f32ae 100644
--- a/mojo/public/cpp/bindings/lib/serialization_forward.h
+++ b/mojo/public/cpp/bindings/lib/serialization_forward.h
@@ -42,9 +42,8 @@
           typename... Args,
           typename std::enable_if<
               !IsOptionalWrapper<InputUserType>::value>::type* = nullptr>
-size_t PrepareToSerialize(InputUserType&& input, Args&&... args) {
-  return Serializer<MojomType,
-                    typename std::remove_reference<InputUserType>::type>::
+void PrepareToSerialize(InputUserType&& input, Args&&... args) {
+  Serializer<MojomType, typename std::remove_reference<InputUserType>::type>::
       PrepareToSerialize(std::forward<InputUserType>(input),
                          std::forward<Args>(args)...);
 }
@@ -77,27 +76,24 @@
           typename... Args,
           typename std::enable_if<
               IsOptionalWrapper<InputUserType>::value>::type* = nullptr>
-size_t PrepareToSerialize(InputUserType&& input, Args&&... args) {
-  if (!input)
-    return 0;
-  return PrepareToSerialize<MojomType>(*input, std::forward<Args>(args)...);
+void PrepareToSerialize(InputUserType&& input, Args&&... args) {
+  if (input)
+    PrepareToSerialize<MojomType>(*input, std::forward<Args>(args)...);
 }
 
 template <typename MojomType,
           typename InputUserType,
-          typename DataType,
+          typename BufferWriterType,
           typename... Args,
           typename std::enable_if<
               IsOptionalWrapper<InputUserType>::value>::type* = nullptr>
 void Serialize(InputUserType&& input,
                Buffer* buffer,
-               DataType** output,
+               BufferWriterType* writer,
                Args&&... args) {
-  if (!input) {
-    *output = nullptr;
+  if (!input)
     return;
-  }
-  Serialize<MojomType>(*input, buffer, output, std::forward<Args>(args)...);
+  Serialize<MojomType>(*input, buffer, writer, std::forward<Args>(args)...);
 }
 
 template <typename MojomType,
diff --git a/mojo/public/cpp/bindings/lib/serialization_util.h b/mojo/public/cpp/bindings/lib/serialization_util.h
index 22e0948..b2e502f 100644
--- a/mojo/public/cpp/bindings/lib/serialization_util.h
+++ b/mojo/public/cpp/bindings/lib/serialization_util.h
@@ -96,12 +96,18 @@
 template <typename Traits>
 struct CustomContextHelper<Traits, true> {
   template <typename MaybeConstUserType>
-  static void* SetUp(MaybeConstUserType& input, SerializationContext* context) {
-    void* custom_context = Traits::SetUpContext(input);
+  static void* SetUpAndPush(MaybeConstUserType& input,
+                            SerializationContext* context) {
+    void* custom_context = SetUp(input, context);
     context->PushCustomContext(custom_context);
     return custom_context;
   }
 
+  template <typename MaybeConstUserType>
+  static void* SetUp(MaybeConstUserType& input, SerializationContext* context) {
+    return Traits::SetUpContext(input);
+  }
+
   static void* GetNext(SerializationContext* context) {
     return context->ConsumeNextCustomContext();
   }
@@ -115,6 +121,12 @@
 template <typename Traits>
 struct CustomContextHelper<Traits, false> {
   template <typename MaybeConstUserType>
+  static void* SetUpAndPush(MaybeConstUserType& input,
+                            SerializationContext* context) {
+    return nullptr;
+  }
+
+  template <typename MaybeConstUserType>
   static void* SetUp(MaybeConstUserType& input, SerializationContext* context) {
     return nullptr;
   }
diff --git a/mojo/public/cpp/bindings/lib/string_serialization.h b/mojo/public/cpp/bindings/lib/string_serialization.h
index 54d9dd9..058842e 100644
--- a/mojo/public/cpp/bindings/lib/string_serialization.h
+++ b/mojo/public/cpp/bindings/lib/string_serialization.h
@@ -22,38 +22,21 @@
   using UserType = typename std::remove_const<MaybeConstUserType>::type;
   using Traits = StringTraits<UserType>;
 
-  static size_t PrepareToSerialize(MaybeConstUserType& input,
-                                   SerializationContext* context) {
-    const bool is_null = CallIsNullIfExists<Traits>(input);
-    context->PushNextNullState(is_null);
-    if (is_null)
-      return 0;
-
-    void* custom_context = CustomContextHelper<Traits>::SetUp(input, context);
-    return Align(sizeof(String_Data) +
-                 CallWithContext(Traits::GetSize, input, custom_context));
-  }
+  static void PrepareToSerialize(MaybeConstUserType& input,
+                                 SerializationContext* context) {}
 
   static void Serialize(MaybeConstUserType& input,
                         Buffer* buffer,
-                        String_Data** output,
+                        String_Data::BufferWriter* writer,
                         SerializationContext* context) {
-    if (context->IsNextFieldNull()) {
-      *output = nullptr;
+    if (CallIsNullIfExists<Traits>(input))
       return;
-    }
 
-    void* custom_context = CustomContextHelper<Traits>::GetNext(context);
-
-    String_Data* result = String_Data::New(
-        CallWithContext(Traits::GetSize, input, custom_context), buffer);
-    if (result) {
-      memcpy(result->storage(),
-             CallWithContext(Traits::GetData, input, custom_context),
-             CallWithContext(Traits::GetSize, input, custom_context));
-    }
-    *output = result;
-
+    void* custom_context = CustomContextHelper<Traits>::SetUp(input, context);
+    const size_t size = CallWithContext(Traits::GetSize, input, custom_context);
+    writer->Allocate(size, buffer);
+    memcpy((*writer)->storage(),
+           CallWithContext(Traits::GetData, input, custom_context), size);
     CustomContextHelper<Traits>::TearDown(input, custom_context);
   }
 
diff --git a/mojo/public/cpp/bindings/lib/unserialized_message_context.cc b/mojo/public/cpp/bindings/lib/unserialized_message_context.cc
index 48a0d68..f09655a 100644
--- a/mojo/public/cpp/bindings/lib/unserialized_message_context.cc
+++ b/mojo/public/cpp/bindings/lib/unserialized_message_context.cc
@@ -24,9 +24,9 @@
   DCHECK(!serialization_context_.has_value());
   serialization_context_.emplace();
 
-  size_t payload_size = PrepareToSerialize(&serialization_context_.value());
+  PrepareToSerialize(&serialization_context_.value());
   total_serialized_size_ = ComputeSerializedMessageSize(
-      header_.flags, payload_size, 0 /* payload_interface_id_count */);
+      header_.flags, 0, 0 /* payload_interface_id_count */);
   *num_bytes = total_serialized_size_;
   *num_handles = serialization_context_->handles()->size();
 }
diff --git a/mojo/public/cpp/bindings/lib/unserialized_message_context.h b/mojo/public/cpp/bindings/lib/unserialized_message_context.h
index 7a83f988..e3db5803 100644
--- a/mojo/public/cpp/bindings/lib/unserialized_message_context.h
+++ b/mojo/public/cpp/bindings/lib/unserialized_message_context.h
@@ -50,7 +50,7 @@
   void SerializeHandles(MojoHandle* handles);
   void SerializePayload(Buffer* buffer);
 
-  virtual size_t PrepareToSerialize(
+  virtual void PrepareToSerialize(
       SerializationContext* serialization_context) = 0;
   virtual void Serialize(SerializationContext* serialization_context,
                          Buffer* buffer) = 0;
diff --git a/mojo/public/cpp/bindings/map_traits.h b/mojo/public/cpp/bindings/map_traits.h
index c8f979d..60bcb59 100644
--- a/mojo/public/cpp/bindings/map_traits.h
+++ b/mojo/public/cpp/bindings/map_traits.h
@@ -21,6 +21,8 @@
 //     using Value = V;
 //
 //     // These two methods are optional. Please see comments in struct_traits.h
+//     // Note that unlike with StructTraits, IsNull() is called *twice* during
+//     // serialization for MapTraits.
 //     static bool IsNull(const CustomMap<K, V>& input);
 //     static void SetToNull(CustomMap<K, V>* output);
 //
diff --git a/mojo/public/cpp/bindings/message.h b/mojo/public/cpp/bindings/message.h
index 2b6fd0b..765f02c 100644
--- a/mojo/public/cpp/bindings/message.h
+++ b/mojo/public/cpp/bindings/message.h
@@ -56,11 +56,15 @@
   //
   // If |handles| is non-null, any handles in |*handles| are attached to the
   // newly constructed message.
+  //
+  // Note that |payload_size| is only the initially known size of the message
+  // payload, if any. The payload can be expanded after construction using the
+  // interface returned by |payload_buffer()|.
   Message(uint32_t name,
           uint32_t flags,
           size_t payload_size,
           size_t payload_interface_id_count,
-          std::vector<ScopedHandle>* handles = nullptr);
+          std::vector<ScopedHandle>* handles);
 
   // Constructs a new serialized Message object from an existing
   // ScopedMessageHandle; e.g., one read from a message pipe.
@@ -87,36 +91,42 @@
   // Indicates whether this Message is serialized.
   bool is_serialized() const { return serialized_; }
 
-  uint32_t data_num_bytes() const { return static_cast<uint32_t>(data_size_); }
-
   // Access the raw bytes of the message.
-  const uint8_t* data() const { return static_cast<const uint8_t*>(data_); }
-  uint8_t* mutable_data() { return static_cast<uint8_t*>(data_); }
+  const uint8_t* data() const {
+    DCHECK(payload_buffer_.is_valid());
+    return static_cast<const uint8_t*>(payload_buffer_.data());
+  }
+  uint8_t* mutable_data() { return const_cast<uint8_t*>(data()); }
+
+  size_t data_num_bytes() const {
+    DCHECK(payload_buffer_.is_valid());
+    return payload_buffer_.cursor();
+  }
 
   // Access the header.
   const internal::MessageHeader* header() const {
-    return static_cast<const internal::MessageHeader*>(data_);
+    return reinterpret_cast<const internal::MessageHeader*>(data());
   }
   internal::MessageHeader* header() {
-    return static_cast<internal::MessageHeader*>(data_);
+    return reinterpret_cast<internal::MessageHeader*>(mutable_data());
   }
 
   const internal::MessageHeaderV1* header_v1() const {
     DCHECK_GE(version(), 1u);
-    return static_cast<const internal::MessageHeaderV1*>(data_);
+    return reinterpret_cast<const internal::MessageHeaderV1*>(data());
   }
   internal::MessageHeaderV1* header_v1() {
     DCHECK_GE(version(), 1u);
-    return static_cast<internal::MessageHeaderV1*>(data_);
+    return reinterpret_cast<internal::MessageHeaderV1*>(mutable_data());
   }
 
   const internal::MessageHeaderV2* header_v2() const {
     DCHECK_GE(version(), 2u);
-    return static_cast<const internal::MessageHeaderV2*>(data_);
+    return reinterpret_cast<const internal::MessageHeaderV2*>(data());
   }
   internal::MessageHeaderV2* header_v2() {
     DCHECK_GE(version(), 2u);
-    return static_cast<internal::MessageHeaderV2*>(data_);
+    return reinterpret_cast<internal::MessageHeaderV2*>(mutable_data());
   }
 
   uint32_t version() const { return header()->version; }
@@ -197,10 +207,9 @@
  private:
   ScopedMessageHandle handle_;
 
-  // Pointer to raw serialized message data, including header. This is only
-  // valid when |handle_| is a valid handle to a serialized message object.
-  void* data_ = nullptr;
-  size_t data_size_ = 0;
+  // A Buffer which may be used to allocate blocks of data within the message
+  // payload for reading or writing.
+  internal::Buffer payload_buffer_;
 
   std::vector<ScopedHandle> handles_;
   std::vector<ScopedInterfaceEndpointHandle> associated_endpoint_handles_;
@@ -214,10 +223,6 @@
   // Indicates whether this Message object is serialized.
   bool serialized_ = false;
 
-  // A Buffer which may be used to allocated blocks of data within the message
-  // payload. May be invalid if there is no capacity remaining in the payload.
-  internal::Buffer payload_buffer_;
-
   DISALLOW_COPY_AND_ASSIGN(Message);
 };
 
diff --git a/mojo/public/cpp/bindings/struct_traits.h b/mojo/public/cpp/bindings/struct_traits.h
index e27e0cd..09b493c 100644
--- a/mojo/public/cpp/bindings/struct_traits.h
+++ b/mojo/public/cpp/bindings/struct_traits.h
@@ -52,13 +52,10 @@
 //      return value or reference of base::Optional<T>/WTF::Optional<T>, if T
 //      has the right *Traits defined.
 //
-//      During serialization, getters for string/struct/array/map/union fields
-//      are called twice (one for size calculation and one for actual
-//      serialization). If you want to return a value (as opposed to a
-//      reference) from these getters, you have to be sure that constructing and
-//      copying the returned object is really cheap.
-//
-//      Getters for fields of other types are called once.
+//      During serialization, getters for all fields are called exactly once. It
+//      is therefore reasonably effecient for a getter to construct and return
+//      temporary value in the event that it cannot return a readily
+//      serializable reference to some existing object.
 //
 //   2. A static Read() method to set the contents of a |T| instance from a
 //      DataViewType.
@@ -78,9 +75,10 @@
 //
 //        static bool IsNull(const T& input);
 //
-//      If this method returns true, it is guaranteed that none of the getters
-//      (described in section 1) will be called for the same |input|. So you
-//      don't have to check whether |input| is null in those getters.
+//      This method is called exactly once during serialization, and if it
+//      returns |true|, it is guaranteed that none of the getters (described in
+//      section 1) will be called for the same |input|. So you don't have to
+//      check whether |input| is null in those getters.
 //
 //      If it is not defined, |T| instances are always considered non-null.
 //
diff --git a/mojo/public/cpp/bindings/tests/bindings_perftest.cc b/mojo/public/cpp/bindings/tests/bindings_perftest.cc
index aee51ef2..c54d7ca 100644
--- a/mojo/public/cpp/bindings/tests/bindings_perftest.cc
+++ b/mojo/public/cpp/bindings/tests/bindings_perftest.cc
@@ -153,7 +153,7 @@
       }
     }
 
-    Message reply(count, 0, 8, 0);
+    Message reply(count, 0, 0, 0, nullptr);
     bool result = sender_->Accept(&reply);
     DCHECK(result);
     return true;
@@ -173,7 +173,7 @@
     quit_closure_ = run_loop.QuitClosure();
 
     start_time_ = base::TimeTicks::Now();
-    Message message(0, 0, 8, 0);
+    Message message(0, 0, 0, 0, nullptr);
     bool result = sender_->Accept(&message);
     DCHECK(result);
 
@@ -263,7 +263,7 @@
     receiver.Reset();
     base::TimeTicks start_time = base::TimeTicks::Now();
     for (size_t j = 0; j < kIterations[i]; ++j) {
-      Message message(0, 0, 8, 0);
+      Message message(0, 0, 8, 0, nullptr);
       bool result = router->SimulateReceivingMessageForTesting(&message);
       DCHECK(result);
     }
diff --git a/mojo/public/cpp/bindings/tests/buffer_unittest.cc b/mojo/public/cpp/bindings/tests/buffer_unittest.cc
index d75bdd0..2370454b 100644
--- a/mojo/public/cpp/bindings/tests/buffer_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/buffer_unittest.cc
@@ -14,80 +14,20 @@
 namespace test {
 namespace {
 
-bool IsZero(void* p_buf, size_t size) {
-  char* buf = reinterpret_cast<char*>(p_buf);
-  for (size_t i = 0; i < size; ++i) {
-    if (buf[i] != 0)
-      return false;
-  }
-  return true;
-}
-
 // Tests that FixedBuffer allocates memory aligned to 8 byte boundaries.
 TEST(FixedBufferTest, Alignment) {
   internal::FixedBufferForTesting buf(internal::Align(10) * 2);
   ASSERT_EQ(buf.size(), 16u * 2);
 
-  void* a = buf.Allocate(10);
-  ASSERT_TRUE(a);
-  EXPECT_TRUE(IsZero(a, 10));
-  EXPECT_EQ(0, reinterpret_cast<ptrdiff_t>(a) % 8);
+  size_t a = buf.Allocate(10);
+  EXPECT_EQ(0u, a);
 
-  void* b = buf.Allocate(10);
-  ASSERT_TRUE(b);
-  EXPECT_TRUE(IsZero(b, 10));
-  EXPECT_EQ(0, reinterpret_cast<ptrdiff_t>(b) % 8);
+  size_t b = buf.Allocate(10);
+  ASSERT_EQ(16u, b);
 
   // Any more allocations would result in an assert, but we can't test that.
 }
 
-// Tests that FixedBufferForTesting::Leak passes ownership to the caller.
-TEST(FixedBufferTest, Leak) {
-  void* ptr = nullptr;
-  void* buf_ptr = nullptr;
-  {
-    internal::FixedBufferForTesting buf(8);
-    ASSERT_EQ(8u, buf.size());
-
-    ptr = buf.Allocate(8);
-    ASSERT_TRUE(ptr);
-    buf_ptr = buf.Leak();
-
-    // The buffer should point to the first element allocated.
-    // TODO(mpcomplete): Is this a reasonable expectation?
-    EXPECT_EQ(ptr, buf_ptr);
-
-    // The FixedBufferForTesting should be empty now.
-    EXPECT_EQ(0u, buf.size());
-    EXPECT_FALSE(buf.Leak());
-  }
-
-  // Since we called Leak, ptr is still writable after FixedBufferForTesting
-  // went out of scope.
-  memset(ptr, 1, 8);
-  free(buf_ptr);
-}
-
-#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
-TEST(FixedBufferTest, TooBig) {
-  internal::FixedBufferForTesting buf(24);
-
-  // A little bit too large.
-  EXPECT_EQ(reinterpret_cast<void*>(0), buf.Allocate(32));
-
-  // Move the cursor forward.
-  EXPECT_NE(reinterpret_cast<void*>(0), buf.Allocate(16));
-
-  // A lot too large.
-  EXPECT_EQ(reinterpret_cast<void*>(0),
-            buf.Allocate(std::numeric_limits<size_t>::max() - 1024u));
-
-  // A lot too large, leading to possible integer overflow.
-  EXPECT_EQ(reinterpret_cast<void*>(0),
-            buf.Allocate(std::numeric_limits<size_t>::max() - 8u));
-}
-#endif
-
 }  // namespace
 }  // namespace test
 }  // namespace mojo
diff --git a/mojo/public/cpp/bindings/tests/connector_unittest.cc b/mojo/public/cpp/bindings/tests/connector_unittest.cc
index a163458d..8266b910 100644
--- a/mojo/public/cpp/bindings/tests/connector_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/connector_unittest.cc
@@ -100,7 +100,7 @@
       std::vector<ScopedHandle> handles = std::vector<ScopedHandle>()) {
     const size_t size = strlen(text) + 1;  // Plus null terminator.
     Message message(1, 0, size, 0, &handles);
-    memcpy(message.payload_buffer()->Allocate(size), text, size);
+    memcpy(message.payload_buffer()->AllocateAndGet(size), text, size);
     return message;
   }
 
diff --git a/mojo/public/cpp/bindings/tests/data_view_unittest.cc b/mojo/public/cpp/bindings/tests/data_view_unittest.cc
index 0ebfda5..e333a13 100644
--- a/mojo/public/cpp/bindings/tests/data_view_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/data_view_unittest.cc
@@ -26,22 +26,20 @@
 
 struct DataViewHolder {
   std::unique_ptr<TestStructDataView> data_view;
-  std::unique_ptr<mojo::internal::FixedBufferForTesting> buf;
+  mojo::Message message;
   mojo::internal::SerializationContext context;
 };
 
 std::unique_ptr<DataViewHolder> SerializeTestStruct(TestStructPtr input) {
-  std::unique_ptr<DataViewHolder> result(new DataViewHolder);
-
-  size_t size = mojo::internal::PrepareToSerialize<TestStructDataView>(
-      input, &result->context);
-
-  result->buf.reset(new mojo::internal::FixedBufferForTesting(size));
-  internal::TestStruct_Data* data = nullptr;
-  mojo::internal::Serialize<TestStructDataView>(input, result->buf.get(), &data,
-                                                &result->context);
-
-  result->data_view.reset(new TestStructDataView(data, &result->context));
+  auto result = base::MakeUnique<DataViewHolder>();
+  mojo::internal::PrepareToSerialize<TestStructDataView>(input,
+                                                         &result->context);
+  result->message = Message(0, 0, 0, 0, nullptr);
+  internal::TestStruct_Data::BufferWriter writer;
+  mojo::internal::Serialize<TestStructDataView>(
+      input, result->message.payload_buffer(), &writer, &result->context);
+  result->data_view =
+      base::MakeUnique<TestStructDataView>(writer.data(), &result->context);
   return result;
 }
 
diff --git a/mojo/public/cpp/bindings/tests/router_test_util.cc b/mojo/public/cpp/bindings/tests/router_test_util.cc
index 4a0b4cd..b509fe6 100644
--- a/mojo/public/cpp/bindings/tests/router_test_util.cc
+++ b/mojo/public/cpp/bindings/tests/router_test_util.cc
@@ -17,8 +17,10 @@
 
 void AllocRequestMessage(uint32_t name, const char* text, Message* message) {
   size_t payload_size = strlen(text) + 1;  // Plus null terminator.
-  *message = Message(name, Message::kFlagExpectsResponse, payload_size, 0);
-  memcpy(message->payload_buffer()->Allocate(payload_size), text, payload_size);
+  *message =
+      Message(name, Message::kFlagExpectsResponse, payload_size, 0, nullptr);
+  memcpy(message->payload_buffer()->AllocateAndGet(payload_size), text,
+         payload_size);
 }
 
 void AllocResponseMessage(uint32_t name,
@@ -26,9 +28,10 @@
                           uint64_t request_id,
                           Message* message) {
   size_t payload_size = strlen(text) + 1;  // Plus null terminator.
-  *message = Message(name, Message::kFlagIsResponse, payload_size, 0);
+  *message = Message(name, Message::kFlagIsResponse, payload_size, 0, nullptr);
   message->set_request_id(request_id);
-  memcpy(message->payload_buffer()->Allocate(payload_size), text, payload_size);
+  memcpy(message->payload_buffer()->AllocateAndGet(payload_size), text,
+         payload_size);
 }
 
 MessageAccumulator::MessageAccumulator(MessageQueue* queue,
diff --git a/mojo/public/cpp/bindings/tests/sample_service_unittest.cc b/mojo/public/cpp/bindings/tests/sample_service_unittest.cc
index 10fd32d..6083ad7 100644
--- a/mojo/public/cpp/bindings/tests/sample_service_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/sample_service_unittest.cc
@@ -226,8 +226,8 @@
   }
 }
 
-void DumpHex(const uint8_t* bytes, uint32_t num_bytes) {
-  for (uint32_t i = 0; i < num_bytes; ++i) {
+void DumpHex(const uint8_t* bytes, size_t num_bytes) {
+  for (size_t i = 0; i < num_bytes; ++i) {
     std::cout << std::setw(2) << std::setfill('0') << std::hex
               << uint32_t(bytes[i]);
 
diff --git a/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc b/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc
index 275f10f..a61f6cd6 100644
--- a/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc
@@ -51,11 +51,12 @@
     warning_observer_.set_last_warning(mojo::internal::VALIDATION_ERROR_NONE);
 
     mojo::internal::SerializationContext context;
-    mojo::internal::FixedBufferForTesting buf(
-        mojo::internal::PrepareToSerialize<MojomType>(obj, &context));
-    typename mojo::internal::MojomTypeTraits<MojomType>::Data* data;
-    mojo::internal::Serialize<MojomType>(obj, &buf, &data, &context);
-
+    mojo::Message message(0, 0, 0, 0, nullptr);
+    typename mojo::internal::MojomTypeTraits<MojomType>::Data::BufferWriter
+        writer;
+    mojo::internal::PrepareToSerialize<MojomType>(obj, &context);
+    mojo::internal::Serialize<MojomType>(obj, message.payload_buffer(), &writer,
+                                         &context);
     EXPECT_EQ(expected_warning, warning_observer_.last_warning());
   }
 
@@ -66,12 +67,12 @@
     warning_observer_.set_last_warning(mojo::internal::VALIDATION_ERROR_NONE);
 
     mojo::internal::SerializationContext context;
-    mojo::internal::FixedBufferForTesting buf(
-        mojo::internal::PrepareToSerialize<MojomType>(obj, &context));
-    typename mojo::internal::MojomTypeTraits<MojomType>::Data* data;
-    mojo::internal::Serialize<MojomType>(obj, &buf, &data, validate_params,
-                                         &context);
-
+    mojo::Message message(0, 0, 0, 0, nullptr);
+    typename mojo::internal::MojomTypeTraits<MojomType>::Data::BufferWriter
+        writer;
+    mojo::internal::PrepareToSerialize<MojomType>(obj, &context);
+    mojo::internal::Serialize<MojomType>(obj, message.payload_buffer(), &writer,
+                                         validate_params, &context);
     EXPECT_EQ(expected_warning, warning_observer_.last_warning());
   }
 
@@ -83,10 +84,12 @@
     warning_observer_.set_last_warning(mojo::internal::VALIDATION_ERROR_NONE);
 
     mojo::internal::SerializationContext context;
-    mojo::internal::FixedBufferForTesting buf(
-        mojo::internal::PrepareToSerialize<MojomType>(obj, false, &context));
-    typename mojo::internal::MojomTypeTraits<MojomType>::Data* data;
-    mojo::internal::Serialize<MojomType>(obj, &buf, &data, false, &context);
+    mojo::Message message(0, 0, 0, 0, nullptr);
+    typename mojo::internal::MojomTypeTraits<MojomType>::Data::BufferWriter
+        writer;
+    mojo::internal::PrepareToSerialize<MojomType>(obj, false, &context);
+    mojo::internal::Serialize<MojomType>(obj, message.payload_buffer(), &writer,
+                                         false, &context);
 
     EXPECT_EQ(expected_warning, warning_observer_.last_warning());
   }
diff --git a/mojo/public/cpp/bindings/tests/struct_unittest.cc b/mojo/public/cpp/bindings/tests/struct_unittest.cc
index fa9b370..0a165ee9 100644
--- a/mojo/public/cpp/bindings/tests/struct_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/struct_unittest.cc
@@ -28,6 +28,34 @@
   EXPECT_EQ(20 * factor, rect.height);
 }
 
+template <typename StructType>
+struct SerializeStructHelperTraits {
+  using DataView = typename StructType::DataView;
+};
+
+template <>
+struct SerializeStructHelperTraits<NativeStruct> {
+  using DataView = NativeStructDataView;
+};
+
+template <typename InputType, typename DataType>
+size_t SerializeStruct(InputType& input,
+                       mojo::Message* message,
+                       mojo::internal::SerializationContext* context,
+                       DataType** out_data) {
+  using StructType = typename InputType::Struct;
+  using DataViewType =
+      typename SerializeStructHelperTraits<StructType>::DataView;
+  *message = mojo::Message(0, 0, 0, 0, nullptr);
+  const size_t payload_start = message->payload_buffer()->cursor();
+  typename DataType::BufferWriter writer;
+  mojo::internal::PrepareToSerialize<DataViewType>(input, context);
+  mojo::internal::Serialize<DataViewType>(input, message->payload_buffer(),
+                                          &writer, context);
+  *out_data = writer.is_null() ? nullptr : writer.data();
+  return message->payload_buffer()->cursor() - payload_start;
+}
+
 MultiVersionStructPtr MakeMultiVersionStruct() {
   MessagePipe pipe;
   return MultiVersionStruct::New(123, MakeRect(5), std::string("hello"),
@@ -45,16 +73,14 @@
   using OutputDataType =
       typename mojo::internal::MojomTypeTraits<OutputMojomType>::Data*;
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size =
-      mojo::internal::PrepareToSerialize<InputMojomType>(input, &context);
-  mojo::internal::FixedBufferForTesting buf(size + 32);
   InputDataType data;
-  mojo::internal::Serialize<InputMojomType>(input, &buf, &data, &context);
+  SerializeStruct(input, &message, &context, &data);
 
   // Set the subsequent area to a special value, so that we can find out if we
   // mistakenly access the area.
-  void* subsequent_area = buf.Allocate(32);
+  void* subsequent_area = message.payload_buffer()->AllocateAndGet(32);
   memset(subsequent_area, 0xAA, 32);
 
   OutputDataType output_data = reinterpret_cast<OutputDataType>(data);
@@ -124,14 +150,10 @@
 TEST_F(StructTest, Serialization_Basic) {
   RectPtr rect(MakeRect());
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size =
-      mojo::internal::PrepareToSerialize<RectDataView>(rect, &context);
-  EXPECT_EQ(8U + 16U, size);
-
-  mojo::internal::FixedBufferForTesting buf(size);
   internal::Rect_Data* data;
-  mojo::internal::Serialize<RectDataView>(rect, &buf, &data, &context);
+  EXPECT_EQ(8U + 16U, SerializeStruct(rect, &message, &context, &data));
 
   RectPtr rect2;
   mojo::internal::Deserialize<RectDataView>(data, &rect2, &context);
@@ -157,14 +179,11 @@
 TEST_F(StructTest, Serialization_StructPointers) {
   RectPairPtr pair(RectPair::New(MakeRect(), MakeRect()));
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size =
-      mojo::internal::PrepareToSerialize<RectPairDataView>(pair, &context);
-  EXPECT_EQ(8U + 16U + 2 * (8U + 16U), size);
-
-  mojo::internal::FixedBufferForTesting buf(size);
   internal::RectPair_Data* data;
-  mojo::internal::Serialize<RectPairDataView>(pair, &buf, &data, &context);
+  EXPECT_EQ(8U + 16U + 2 * (8U + 16U),
+            SerializeStruct(pair, &message, &context, &data));
 
   RectPairPtr pair2;
   mojo::internal::Deserialize<RectPairDataView>(data, &pair2, &context);
@@ -182,9 +201,9 @@
   NamedRegionPtr region(
       NamedRegion::New(std::string("region"), std::move(rects)));
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size =
-      mojo::internal::PrepareToSerialize<NamedRegionDataView>(region, &context);
+  internal::NamedRegion_Data* data;
   EXPECT_EQ(8U +            // header
                 8U +        // name pointer
                 8U +        // rects pointer
@@ -194,11 +213,7 @@
                 4 * 8U +    // rects payload (four pointers)
                 4 * (8U +   // rect header
                      16U),  // rect payload (four ints)
-            size);
-
-  mojo::internal::FixedBufferForTesting buf(size);
-  internal::NamedRegion_Data* data;
-  mojo::internal::Serialize<NamedRegionDataView>(region, &buf, &data, &context);
+            SerializeStruct(region, &message, &context, &data));
 
   NamedRegionPtr region2;
   mojo::internal::Deserialize<NamedRegionDataView>(data, &region2, &context);
@@ -216,17 +231,13 @@
   EXPECT_FALSE(region->name);
   EXPECT_FALSE(region->rects);
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size =
-      mojo::internal::PrepareToSerialize<NamedRegionDataView>(region, &context);
+  internal::NamedRegion_Data* data;
   EXPECT_EQ(8U +      // header
                 8U +  // name pointer
                 8U,   // rects pointer
-            size);
-
-  mojo::internal::FixedBufferForTesting buf(size);
-  internal::NamedRegion_Data* data;
-  mojo::internal::Serialize<NamedRegionDataView>(region, &buf, &data, &context);
+            SerializeStruct(region, &message, &context, &data));
 
   NamedRegionPtr region2;
   mojo::internal::Deserialize<NamedRegionDataView>(data, &region2, &context);
@@ -369,16 +380,11 @@
   {
     // Serialization of a null native struct.
     NativeStructPtr native;
+
+    mojo::Message message;
     mojo::internal::SerializationContext context;
-    size_t size = mojo::internal::PrepareToSerialize<NativeStructDataView>(
-        native, &context);
-    EXPECT_EQ(0u, size);
-    mojo::internal::FixedBufferForTesting buf(size);
-
     Data* data = nullptr;
-    mojo::internal::Serialize<NativeStructDataView>(std::move(native), &buf,
-                                                    &data, &context);
-
+    EXPECT_EQ(0u, SerializeStruct(native, &message, &context, &data));
     EXPECT_EQ(nullptr, data);
 
     NativeStructPtr output_native;
@@ -390,16 +396,11 @@
   {
     // Serialization of a native struct with null data.
     NativeStructPtr native(NativeStruct::New());
+
+    mojo::Message message;
     mojo::internal::SerializationContext context;
-    size_t size = mojo::internal::PrepareToSerialize<NativeStructDataView>(
-        native, &context);
-    EXPECT_EQ(0u, size);
-    mojo::internal::FixedBufferForTesting buf(size);
-
     Data* data = nullptr;
-    mojo::internal::Serialize<NativeStructDataView>(std::move(native), &buf,
-                                                    &data, &context);
-
+    EXPECT_EQ(0u, SerializeStruct(native, &message, &context, &data));
     EXPECT_EQ(nullptr, data);
 
     NativeStructPtr output_native;
@@ -412,16 +413,10 @@
     NativeStructPtr native(NativeStruct::New());
     native->data = std::vector<uint8_t>{'X', 'Y'};
 
+    mojo::Message message;
     mojo::internal::SerializationContext context;
-    size_t size = mojo::internal::PrepareToSerialize<NativeStructDataView>(
-        native, &context);
-    EXPECT_EQ(16u, size);
-    mojo::internal::FixedBufferForTesting buf(size);
-
     Data* data = nullptr;
-    mojo::internal::Serialize<NativeStructDataView>(std::move(native), &buf,
-                                                    &data, &context);
-
+    EXPECT_EQ(16u, SerializeStruct(native, &message, &context, &data));
     EXPECT_NE(nullptr, data);
 
     NativeStructPtr output_native;
diff --git a/mojo/public/cpp/bindings/tests/union_unittest.cc b/mojo/public/cpp/bindings/tests/union_unittest.cc
index 5439a95..2fc3d3a0 100644
--- a/mojo/public/cpp/bindings/tests/union_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/union_unittest.cc
@@ -15,6 +15,7 @@
 #include "mojo/public/cpp/bindings/lib/serialization.h"
 #include "mojo/public/cpp/bindings/lib/validation_context.h"
 #include "mojo/public/cpp/bindings/lib/validation_errors.h"
+#include "mojo/public/cpp/bindings/message.h"
 #include "mojo/public/cpp/test_support/test_utils.h"
 #include "mojo/public/interfaces/bindings/tests/test_structs.mojom.h"
 #include "mojo/public/interfaces/bindings/tests/test_unions.mojom.h"
@@ -23,6 +24,58 @@
 namespace mojo {
 namespace test {
 
+template <typename InputType, typename DataType>
+size_t SerializeStruct(InputType& input,
+                       mojo::Message* message,
+                       mojo::internal::SerializationContext* context,
+                       DataType** out_data) {
+  using StructType = typename InputType::Struct;
+  using DataViewType = typename StructType::DataView;
+  *message = mojo::Message(0, 0, 0, 0, nullptr);
+  const size_t payload_start = message->payload_buffer()->cursor();
+  typename DataType::BufferWriter writer;
+  mojo::internal::PrepareToSerialize<DataViewType>(input, context);
+  mojo::internal::Serialize<DataViewType>(input, message->payload_buffer(),
+                                          &writer, context);
+  *out_data = writer.is_null() ? nullptr : writer.data();
+  return message->payload_buffer()->cursor() - payload_start;
+}
+
+template <typename InputType, typename DataType>
+size_t SerializeUnion(InputType& input,
+                      mojo::Message* message,
+                      mojo::internal::SerializationContext* context,
+                      DataType** out_data = nullptr) {
+  using StructType = typename InputType::Struct;
+  using DataViewType = typename StructType::DataView;
+  *message = mojo::Message(0, 0, 0, 0, nullptr);
+  const size_t payload_start = message->payload_buffer()->cursor();
+  typename DataType::BufferWriter writer;
+  mojo::internal::PrepareToSerialize<DataViewType>(input, false, context);
+  mojo::internal::Serialize<DataViewType>(input, message->payload_buffer(),
+                                          &writer, false, context);
+  *out_data = writer.is_null() ? nullptr : writer.data();
+  return message->payload_buffer()->cursor() - payload_start;
+}
+
+template <typename DataViewType, typename InputType>
+size_t SerializeArray(InputType& input,
+                      bool nullable_elements,
+                      mojo::Message* message,
+                      mojo::internal::SerializationContext* context,
+                      typename DataViewType::Data_** out_data) {
+  *message = mojo::Message(0, 0, 0, 0, nullptr);
+  const size_t payload_start = message->payload_buffer()->cursor();
+  typename DataViewType::Data_::BufferWriter writer;
+  mojo::internal::PrepareToSerialize<DataViewType>(input, context);
+  mojo::internal::ContainerValidateParams validate_params(0, nullable_elements,
+                                                          nullptr);
+  mojo::internal::Serialize<DataViewType>(input, message->payload_buffer(),
+                                          &writer, &validate_params, context);
+  *out_data = writer.is_null() ? nullptr : writer.data();
+  return message->payload_buffer()->cursor() - payload_start;
+}
+
 TEST(UnionTest, PlainOldDataGetterSetter) {
   PodUnionPtr pod(PodUnion::New());
 
@@ -184,15 +237,10 @@
   PodUnionPtr pod1(PodUnion::New());
   pod1->set_f_int8(10);
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<PodUnionDataView>(
-      pod1, false, &context);
-  EXPECT_EQ(16U, size);
-
-  mojo::internal::FixedBufferForTesting buf(size);
   internal::PodUnion_Data* data = nullptr;
-  mojo::internal::Serialize<PodUnionDataView>(pod1, &buf, &data, false,
-                                              &context);
+  EXPECT_EQ(16U, SerializeUnion(pod1, &message, &context, &data));
 
   PodUnionPtr pod2;
   mojo::internal::Deserialize<PodUnionDataView>(data, &pod2, &context);
@@ -205,15 +253,10 @@
 TEST(UnionTest, EnumSerialization) {
   PodUnionPtr pod1(PodUnion::NewFEnum(AnEnum::SECOND));
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<PodUnionDataView>(
-      pod1, false, &context);
-  EXPECT_EQ(16U, size);
-
-  mojo::internal::FixedBufferForTesting buf(size);
   internal::PodUnion_Data* data = nullptr;
-  mojo::internal::Serialize<PodUnionDataView>(pod1, &buf, &data, false,
-                                              &context);
+  EXPECT_EQ(16U, SerializeUnion(pod1, &message, &context, &data));
 
   PodUnionPtr pod2;
   mojo::internal::Deserialize<PodUnionDataView>(data, &pod2, nullptr);
@@ -227,69 +270,53 @@
   PodUnionPtr pod(PodUnion::New());
   pod->set_f_int8(10);
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<PodUnionDataView>(pod, false,
-                                                                     &context);
+  internal::PodUnion_Data* data = nullptr;
+  const size_t size = SerializeUnion(pod, &message, &context, &data);
   EXPECT_EQ(16U, size);
 
-  mojo::internal::FixedBufferForTesting buf(size);
-  internal::PodUnion_Data* data = nullptr;
-  mojo::internal::Serialize<PodUnionDataView>(pod, &buf, &data, false,
-                                              &context);
-
-  void* raw_buf = buf.Leak();
   mojo::internal::ValidationContext validation_context(
       data, static_cast<uint32_t>(size), 0, 0);
   EXPECT_TRUE(
-      internal::PodUnion_Data::Validate(raw_buf, &validation_context, false));
-  free(raw_buf);
+      internal::PodUnion_Data::Validate(data, &validation_context, false));
 }
 
 TEST(UnionTest, SerializeNotNull) {
   PodUnionPtr pod(PodUnion::New());
   pod->set_f_int8(0);
+
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<PodUnionDataView>(pod, false,
-                                                                     &context);
-  mojo::internal::FixedBufferForTesting buf(size);
   internal::PodUnion_Data* data = nullptr;
-  mojo::internal::Serialize<PodUnionDataView>(pod, &buf, &data, false,
-                                              &context);
+  SerializeUnion(pod, &message, &context, &data);
   EXPECT_FALSE(data->is_null());
 }
 
 TEST(UnionTest, SerializeIsNullInlined) {
   PodUnionPtr pod;
+
+  mojo::internal::FixedBufferForTesting buffer(16);
+  internal::PodUnion_Data::BufferWriter writer;
+  writer.Allocate(&buffer);
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<PodUnionDataView>(pod, false,
-                                                                     &context);
-  EXPECT_EQ(16U, size);
-  mojo::internal::FixedBufferForTesting buf(size);
-  internal::PodUnion_Data* data = internal::PodUnion_Data::New(&buf);
-
-  // Check that dirty output buffers are handled correctly by serialization.
-  data->size = 16U;
-  data->tag = PodUnion::Tag::F_UINT16;
-  data->data.f_f_int16 = 20;
-
-  mojo::internal::Serialize<PodUnionDataView>(pod, &buf, &data, true, &context);
-  EXPECT_TRUE(data->is_null());
+  mojo::internal::PrepareToSerialize<PodUnionDataView>(pod, true, &context);
+  mojo::internal::Serialize<PodUnionDataView>(pod, &buffer, &writer, true,
+                                              &context);
+  EXPECT_TRUE(writer.data()->is_null());
+  EXPECT_EQ(16U, buffer.cursor());
 
   PodUnionPtr pod2;
-  mojo::internal::Deserialize<PodUnionDataView>(data, &pod2, nullptr);
+  mojo::internal::Deserialize<PodUnionDataView>(writer.data(), &pod2, nullptr);
   EXPECT_TRUE(pod2.is_null());
 }
 
 TEST(UnionTest, SerializeIsNullNotInlined) {
   PodUnionPtr pod;
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<PodUnionDataView>(pod, false,
-                                                                     &context);
-  EXPECT_EQ(16U, size);
-  mojo::internal::FixedBufferForTesting buf(size);
   internal::PodUnion_Data* data = nullptr;
-  mojo::internal::Serialize<PodUnionDataView>(pod, &buf, &data, false,
-                                              &context);
+  EXPECT_EQ(0u, SerializeUnion(pod, &message, &context, &data));
   EXPECT_EQ(nullptr, data);
 }
 
@@ -300,88 +327,58 @@
       buf, &validation_context, false));
 }
 
-TEST(UnionTest, OutOfAlignmentValidation) {
-  size_t size = sizeof(internal::PodUnion_Data);
-  // Get an aligned object and shift the alignment.
-  mojo::internal::FixedBufferForTesting aligned_buf(size + 1);
-  void* raw_buf = aligned_buf.Leak();
-  char* buf = reinterpret_cast<char*>(raw_buf) + 1;
-
-  internal::PodUnion_Data* data =
-      reinterpret_cast<internal::PodUnion_Data*>(buf);
-  mojo::internal::ValidationContext validation_context(
-      data, static_cast<uint32_t>(size), 0, 0);
-  EXPECT_FALSE(internal::PodUnion_Data::Validate(
-      buf, &validation_context, false));
-  free(raw_buf);
-}
-
 TEST(UnionTest, OOBValidation) {
-  size_t size = sizeof(internal::PodUnion_Data) - 1;
-  mojo::internal::FixedBufferForTesting buf(size);
-  internal::PodUnion_Data* data = internal::PodUnion_Data::New(&buf);
+  constexpr size_t size = sizeof(internal::PodUnion_Data) - 1;
+  mojo::Message message(0, 0, size, 0, nullptr);
+  internal::PodUnion_Data::BufferWriter writer;
+  writer.Allocate(message.payload_buffer());
   mojo::internal::ValidationContext validation_context(
-      data, static_cast<uint32_t>(size), 0, 0);
-  void* raw_buf = buf.Leak();
-  EXPECT_FALSE(
-      internal::PodUnion_Data::Validate(raw_buf, &validation_context, false));
-  free(raw_buf);
+      writer.data(), static_cast<uint32_t>(size), 0, 0);
+  EXPECT_FALSE(internal::PodUnion_Data::Validate(writer.data(),
+                                                 &validation_context, false));
 }
 
 TEST(UnionTest, UnknownTagValidation) {
-  size_t size = sizeof(internal::PodUnion_Data);
-  mojo::internal::FixedBufferForTesting buf(size);
-  internal::PodUnion_Data* data = internal::PodUnion_Data::New(&buf);
-  data->tag = static_cast<internal::PodUnion_Data::PodUnion_Tag>(0xFFFFFF);
+  constexpr size_t size = sizeof(internal::PodUnion_Data);
+  mojo::Message message(0, 0, size, 0, nullptr);
+  internal::PodUnion_Data::BufferWriter writer;
+  writer.Allocate(message.payload_buffer());
+  writer->tag = static_cast<internal::PodUnion_Data::PodUnion_Tag>(0xFFFFFF);
   mojo::internal::ValidationContext validation_context(
-      data, static_cast<uint32_t>(size), 0, 0);
-  void* raw_buf = buf.Leak();
-  EXPECT_FALSE(
-      internal::PodUnion_Data::Validate(raw_buf, &validation_context, false));
-  free(raw_buf);
+      writer.data(), static_cast<uint32_t>(size), 0, 0);
+  EXPECT_FALSE(internal::PodUnion_Data::Validate(writer.data(),
+                                                 &validation_context, false));
 }
 
 TEST(UnionTest, UnknownEnumValueValidation) {
   PodUnionPtr pod(PodUnion::NewFEnum(static_cast<AnEnum>(0xFFFF)));
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<PodUnionDataView>(pod, false,
-                                                                     &context);
+  internal::PodUnion_Data* data = nullptr;
+  const size_t size = SerializeUnion(pod, &message, &context, &data);
   EXPECT_EQ(16U, size);
 
-  mojo::internal::FixedBufferForTesting buf(size);
-  internal::PodUnion_Data* data = nullptr;
-  mojo::internal::Serialize<PodUnionDataView>(pod, &buf, &data, false,
-                                              &context);
-
-  void* raw_buf = buf.Leak();
   mojo::internal::ValidationContext validation_context(
       data, static_cast<uint32_t>(size), 0, 0);
   EXPECT_FALSE(
-      internal::PodUnion_Data::Validate(raw_buf, &validation_context, false));
-  free(raw_buf);
+      internal::PodUnion_Data::Validate(data, &validation_context, false));
 }
 
 TEST(UnionTest, UnknownExtensibleEnumValueValidation) {
   PodUnionPtr pod(
       PodUnion::NewFExtensibleEnum(static_cast<AnExtensibleEnum>(0xFFFF)));
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<PodUnionDataView>(pod, false,
-                                                                     &context);
+  internal::PodUnion_Data* data = nullptr;
+  const size_t size = SerializeUnion(pod, &message, &context, &data);
   EXPECT_EQ(16U, size);
 
-  mojo::internal::FixedBufferForTesting buf(size);
-  internal::PodUnion_Data* data = nullptr;
-  mojo::internal::Serialize<PodUnionDataView>(pod, &buf, &data, false,
-                                              &context);
-
-  void* raw_buf = buf.Leak();
   mojo::internal::ValidationContext validation_context(
       data, static_cast<uint32_t>(size), 0, 0);
   EXPECT_TRUE(
-      internal::PodUnion_Data::Validate(raw_buf, &validation_context, false));
-  free(raw_buf);
+      internal::PodUnion_Data::Validate(data, &validation_context, false));
 }
 
 TEST(UnionTest, StringGetterSetter) {
@@ -427,13 +424,10 @@
   std::string hello("hello world");
   ObjectUnionPtr pod1(ObjectUnion::NewFString(hello));
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>(
-      pod1, false, &context);
-  mojo::internal::FixedBufferForTesting buf(size);
   internal::ObjectUnion_Data* data = nullptr;
-  mojo::internal::Serialize<ObjectUnionDataView>(pod1, &buf, &data, false,
-                                                 &context);
+  SerializeUnion(pod1, &message, &context, &data);
 
   ObjectUnionPtr pod2;
   mojo::internal::Deserialize<ObjectUnionDataView>(data, &pod2, nullptr);
@@ -443,50 +437,47 @@
 }
 
 TEST(UnionTest, NullStringValidation) {
-  size_t size = sizeof(internal::ObjectUnion_Data);
-  mojo::internal::FixedBufferForTesting buf(size);
-  internal::ObjectUnion_Data* data = internal::ObjectUnion_Data::New(&buf);
-  data->tag = internal::ObjectUnion_Data::ObjectUnion_Tag::F_STRING;
-  data->data.unknown = 0x0;
+  constexpr size_t size = sizeof(internal::ObjectUnion_Data);
+  mojo::internal::FixedBufferForTesting buffer(size);
+  internal::ObjectUnion_Data::BufferWriter writer;
+  writer.Allocate(&buffer);
+  writer->tag = internal::ObjectUnion_Data::ObjectUnion_Tag::F_STRING;
+  writer->data.unknown = 0x0;
   mojo::internal::ValidationContext validation_context(
-      data, static_cast<uint32_t>(size), 0, 0);
-  void* raw_buf = buf.Leak();
+      writer.data(), static_cast<uint32_t>(size), 0, 0);
   EXPECT_FALSE(internal::ObjectUnion_Data::Validate(
-      raw_buf, &validation_context, false));
-  free(raw_buf);
+      buffer.data(), &validation_context, false));
 }
 
 TEST(UnionTest, StringPointerOverflowValidation) {
-  size_t size = sizeof(internal::ObjectUnion_Data);
-  mojo::internal::FixedBufferForTesting buf(size);
-  internal::ObjectUnion_Data* data = internal::ObjectUnion_Data::New(&buf);
-  data->tag = internal::ObjectUnion_Data::ObjectUnion_Tag::F_STRING;
-  data->data.unknown = 0xFFFFFFFFFFFFFFFF;
+  constexpr size_t size = sizeof(internal::ObjectUnion_Data);
+  mojo::internal::FixedBufferForTesting buffer(size);
+  internal::ObjectUnion_Data::BufferWriter writer;
+  writer.Allocate(&buffer);
+  writer->tag = internal::ObjectUnion_Data::ObjectUnion_Tag::F_STRING;
+  writer->data.unknown = 0xFFFFFFFFFFFFFFFF;
   mojo::internal::ValidationContext validation_context(
-      data, static_cast<uint32_t>(size), 0, 0);
-  void* raw_buf = buf.Leak();
+      writer.data(), static_cast<uint32_t>(size), 0, 0);
   EXPECT_FALSE(internal::ObjectUnion_Data::Validate(
-      raw_buf, &validation_context, false));
-  free(raw_buf);
+      buffer.data(), &validation_context, false));
 }
 
 TEST(UnionTest, StringValidateOOB) {
-  size_t size = 32;
-  mojo::internal::FixedBufferForTesting buf(size);
-  internal::ObjectUnion_Data* data = internal::ObjectUnion_Data::New(&buf);
-  data->tag = internal::ObjectUnion_Data::ObjectUnion_Tag::F_STRING;
+  constexpr size_t size = 32;
+  mojo::internal::FixedBufferForTesting buffer(size);
+  internal::ObjectUnion_Data::BufferWriter writer;
+  writer.Allocate(&buffer);
+  writer->tag = internal::ObjectUnion_Data::ObjectUnion_Tag::F_STRING;
 
-  data->data.f_f_string.offset = 8;
-  char* ptr = reinterpret_cast<char*>(&data->data.f_f_string);
+  writer->data.f_f_string.offset = 8;
+  char* ptr = reinterpret_cast<char*>(&writer->data.f_f_string);
   mojo::internal::ArrayHeader* array_header =
       reinterpret_cast<mojo::internal::ArrayHeader*>(ptr + *ptr);
   array_header->num_bytes = 20;  // This should go out of bounds.
   array_header->num_elements = 20;
-  mojo::internal::ValidationContext validation_context(data, 32, 0, 0);
-  void* raw_buf = buf.Leak();
+  mojo::internal::ValidationContext validation_context(writer.data(), 32, 0, 0);
   EXPECT_FALSE(internal::ObjectUnion_Data::Validate(
-      raw_buf, &validation_context, false));
-  free(raw_buf);
+      buffer.data(), &validation_context, false));
 }
 
 // TODO(azani): Move back in array_unittest.cc when possible.
@@ -513,24 +504,16 @@
   array[1]->set_f_int16(12);
   EXPECT_EQ(2U, array.size());
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size =
-      mojo::internal::PrepareToSerialize<ArrayDataView<PodUnionDataView>>(
-          array, &context);
-  EXPECT_EQ(40U, size);
-
-  mojo::internal::FixedBufferForTesting buf(size);
   mojo::internal::Array_Data<internal::PodUnion_Data>* data;
-  mojo::internal::ContainerValidateParams validate_params(0, false, nullptr);
-  mojo::internal::Serialize<ArrayDataView<PodUnionDataView>>(
-      array, &buf, &data, &validate_params, &context);
+  EXPECT_EQ(40U, SerializeArray<ArrayDataView<PodUnionDataView>>(
+                     array, false, &message, &context, &data));
 
   std::vector<PodUnionPtr> array2;
   mojo::internal::Deserialize<ArrayDataView<PodUnionDataView>>(data, &array2,
                                                                nullptr);
-
   EXPECT_EQ(2U, array2.size());
-
   EXPECT_EQ(10, array2[0]->get_f_int8());
   EXPECT_EQ(12, array2[1]->get_f_int16());
 }
@@ -542,24 +525,16 @@
   array[0]->set_f_int8(10);
   EXPECT_EQ(2U, array.size());
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size =
-      mojo::internal::PrepareToSerialize<ArrayDataView<PodUnionDataView>>(
-          array, &context);
-  EXPECT_EQ(40U, size);
-
-  mojo::internal::FixedBufferForTesting buf(size);
   mojo::internal::Array_Data<internal::PodUnion_Data>* data;
-  mojo::internal::ContainerValidateParams validate_params(0, true, nullptr);
-  mojo::internal::Serialize<ArrayDataView<PodUnionDataView>>(
-      array, &buf, &data, &validate_params, &context);
+  EXPECT_EQ(40U, SerializeArray<ArrayDataView<PodUnionDataView>>(
+                     array, true, &message, &context, &data));
 
   std::vector<PodUnionPtr> array2;
   mojo::internal::Deserialize<ArrayDataView<PodUnionDataView>>(data, &array2,
                                                                nullptr);
-
   EXPECT_EQ(2U, array2.size());
-
   EXPECT_EQ(10, array2[0]->get_f_int8());
   EXPECT_TRUE(array2[1].is_null());
 }
@@ -573,31 +548,23 @@
   array[1]->set_f_string("world");
   EXPECT_EQ(2U, array.size());
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size =
-      mojo::internal::PrepareToSerialize<ArrayDataView<ObjectUnionDataView>>(
-          array, &context);
-  EXPECT_EQ(72U, size);
-
-  mojo::internal::FixedBufferForTesting buf(size);
-
   mojo::internal::Array_Data<internal::ObjectUnion_Data>* data;
-  mojo::internal::ContainerValidateParams validate_params(0, false, nullptr);
-  mojo::internal::Serialize<ArrayDataView<ObjectUnionDataView>>(
-      array, &buf, &data, &validate_params, &context);
+  const size_t size = SerializeArray<ArrayDataView<ObjectUnionDataView>>(
+      array, false, &message, &context, &data);
+  EXPECT_EQ(72U, size);
 
   std::vector<char> new_buf;
   new_buf.resize(size);
-
-  void* raw_buf = buf.Leak();
-  memcpy(new_buf.data(), raw_buf, size);
-  free(raw_buf);
+  memcpy(new_buf.data(), data, size);
 
   data =
       reinterpret_cast<mojo::internal::Array_Data<internal::ObjectUnion_Data>*>(
           new_buf.data());
   mojo::internal::ValidationContext validation_context(
       data, static_cast<uint32_t>(size), 0, 0);
+  mojo::internal::ContainerValidateParams validate_params(0, false, nullptr);
   ASSERT_TRUE(mojo::internal::Array_Data<internal::ObjectUnion_Data>::Validate(
       data, &validation_context, &validate_params));
 
@@ -628,14 +595,10 @@
   small_struct->pod_union = PodUnion::New();
   small_struct->pod_union->set_f_int32(10);
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<SmallStructDataView>(
-      small_struct, &context);
-
-  mojo::internal::FixedBufferForTesting buf(size);
   internal::SmallStruct_Data* data = nullptr;
-  mojo::internal::Serialize<SmallStructDataView>(small_struct, &buf, &data,
-                                                 &context);
+  SerializeStruct(small_struct, &message, &context, &data);
 
   SmallStructPtr deserialized;
   mojo::internal::Deserialize<SmallStructDataView>(data, &deserialized,
@@ -651,14 +614,10 @@
   std::string hello("hello world");
   obj_struct->obj_union->set_f_string(hello);
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<SmallObjStructDataView>(
-      obj_struct, &context);
-
-  mojo::internal::FixedBufferForTesting buf(size);
   internal::SmallObjStruct_Data* data = nullptr;
-  mojo::internal::Serialize<SmallObjStructDataView>(obj_struct, &buf, &data,
-                                                    &context);
+  SerializeStruct(obj_struct, &message, &context, &data);
 
   SmallObjStructPtr deserialized;
   mojo::internal::Deserialize<SmallObjStructDataView>(data, &deserialized,
@@ -673,21 +632,14 @@
   small_struct->pod_union = PodUnion::New();
   small_struct->pod_union->set_f_int32(10);
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<SmallStructDataView>(
-      small_struct, &context);
-
-  mojo::internal::FixedBufferForTesting buf(size);
   internal::SmallStruct_Data* data = nullptr;
-  mojo::internal::Serialize<SmallStructDataView>(small_struct, &buf, &data,
-                                                 &context);
+  const size_t size = SerializeStruct(small_struct, &message, &context, &data);
 
-  void* raw_buf = buf.Leak();
   mojo::internal::ValidationContext validation_context(
       data, static_cast<uint32_t>(size), 0, 0);
-  EXPECT_TRUE(internal::SmallStruct_Data::Validate(
-      raw_buf, &validation_context));
-  free(raw_buf);
+  EXPECT_TRUE(internal::SmallStruct_Data::Validate(data, &validation_context));
 }
 
 // Validation test of a struct union fails due to unknown union tag.
@@ -696,22 +648,15 @@
   small_struct->pod_union = PodUnion::New();
   small_struct->pod_union->set_f_int32(10);
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<SmallStructDataView>(
-      small_struct, &context);
-
-  mojo::internal::FixedBufferForTesting buf(size);
   internal::SmallStruct_Data* data = nullptr;
-  mojo::internal::Serialize<SmallStructDataView>(small_struct, &buf, &data,
-                                                 &context);
+  const size_t size = SerializeStruct(small_struct, &message, &context, &data);
   data->pod_union.tag = static_cast<internal::PodUnion_Data::PodUnion_Tag>(100);
 
-  void* raw_buf = buf.Leak();
   mojo::internal::ValidationContext validation_context(
       data, static_cast<uint32_t>(size), 0, 0);
-  EXPECT_FALSE(internal::SmallStruct_Data::Validate(
-      raw_buf, &validation_context));
-  free(raw_buf);
+  EXPECT_FALSE(internal::SmallStruct_Data::Validate(data, &validation_context));
 }
 
 // Validation fails due to non-nullable null union in struct.
@@ -719,42 +664,29 @@
   SmallStructNonNullableUnionPtr small_struct(
       SmallStructNonNullableUnion::New());
 
-  mojo::internal::SerializationContext context;
-  size_t size =
-      mojo::internal::PrepareToSerialize<SmallStructNonNullableUnionDataView>(
-          small_struct, &context);
-
-  mojo::internal::FixedBufferForTesting buf(size);
-  internal::SmallStructNonNullableUnion_Data* data =
-      internal::SmallStructNonNullableUnion_Data::New(&buf);
-
-  void* raw_buf = buf.Leak();
+  constexpr size_t size = sizeof(internal::SmallStructNonNullableUnion_Data);
+  mojo::internal::FixedBufferForTesting buffer(size);
+  mojo::Message message;
+  internal::SmallStructNonNullableUnion_Data::BufferWriter writer;
+  writer.Allocate(&buffer);
   mojo::internal::ValidationContext validation_context(
-      data, static_cast<uint32_t>(size), 0, 0);
+      writer.data(), static_cast<uint32_t>(size), 0, 0);
   EXPECT_FALSE(internal::SmallStructNonNullableUnion_Data::Validate(
-      raw_buf, &validation_context));
-  free(raw_buf);
+      writer.data(), &validation_context));
 }
 
 // Validation passes with nullable null union.
 TEST(UnionTest, Validation_NullableUnion) {
   SmallStructPtr small_struct(SmallStruct::New());
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<SmallStructDataView>(
-      small_struct, &context);
-
-  mojo::internal::FixedBufferForTesting buf(size);
   internal::SmallStruct_Data* data = nullptr;
-  mojo::internal::Serialize<SmallStructDataView>(small_struct, &buf, &data,
-                                                 &context);
+  const size_t size = SerializeStruct(small_struct, &message, &context, &data);
 
-  void* raw_buf = buf.Leak();
   mojo::internal::ValidationContext validation_context(
       data, static_cast<uint32_t>(size), 0, 0);
-  EXPECT_TRUE(internal::SmallStruct_Data::Validate(
-      raw_buf, &validation_context));
-  free(raw_buf);
+  EXPECT_TRUE(internal::SmallStruct_Data::Validate(data, &validation_context));
 }
 
 // TODO(azani): Move back in map_unittest.cc when possible.
@@ -782,21 +714,22 @@
   map["one"]->set_f_int8(8);
   map["two"]->set_f_int16(16);
 
+  mojo::Message message(0, 0, 0, 0, nullptr);
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<MojomType>(map, &context);
-  EXPECT_EQ(120U, size);
+  const size_t payload_start = message.payload_buffer()->cursor();
 
-  mojo::internal::FixedBufferForTesting buf(size);
-
-  typename mojo::internal::MojomTypeTraits<MojomType>::Data* data;
+  typename mojo::internal::MojomTypeTraits<MojomType>::Data::BufferWriter
+      writer;
   mojo::internal::ContainerValidateParams validate_params(
       new mojo::internal::ContainerValidateParams(0, false, nullptr),
       new mojo::internal::ContainerValidateParams(0, false, nullptr));
-  mojo::internal::Serialize<MojomType>(map, &buf, &data, &validate_params,
-                                       &context);
+  mojo::internal::PrepareToSerialize<MojomType>(map, &context);
+  mojo::internal::Serialize<MojomType>(map, message.payload_buffer(), &writer,
+                                       &validate_params, &context);
+  EXPECT_EQ(120U, message.payload_buffer()->cursor() - payload_start);
 
   std::unordered_map<std::string, PodUnionPtr> map2;
-  mojo::internal::Deserialize<MojomType>(data, &map2, &context);
+  mojo::internal::Deserialize<MojomType>(writer.data(), &map2, &context);
 
   EXPECT_EQ(8, map2["one"]->get_f_int8());
   EXPECT_EQ(16, map2["two"]->get_f_int16());
@@ -811,20 +744,22 @@
 
   map["one"]->set_f_int8(8);
 
+  mojo::Message message(0, 0, 0, 0, nullptr);
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<MojomType>(map, &context);
-  EXPECT_EQ(120U, size);
+  const size_t payload_start = message.payload_buffer()->cursor();
 
-  mojo::internal::FixedBufferForTesting buf(size);
-  typename mojo::internal::MojomTypeTraits<MojomType>::Data* data;
+  typename mojo::internal::MojomTypeTraits<MojomType>::Data::BufferWriter
+      writer;
   mojo::internal::ContainerValidateParams validate_params(
       new mojo::internal::ContainerValidateParams(0, false, nullptr),
       new mojo::internal::ContainerValidateParams(0, true, nullptr));
-  mojo::internal::Serialize<MojomType>(map, &buf, &data, &validate_params,
-                                       &context);
+  mojo::internal::PrepareToSerialize<MojomType>(map, &context);
+  mojo::internal::Serialize<MojomType>(map, message.payload_buffer(), &writer,
+                                       &validate_params, &context);
+  EXPECT_EQ(120U, message.payload_buffer()->cursor() - payload_start);
 
   std::unordered_map<std::string, PodUnionPtr> map2;
-  mojo::internal::Deserialize<MojomType>(data, &map2, &context);
+  mojo::internal::Deserialize<MojomType>(writer.data(), &map2, &context);
 
   EXPECT_EQ(8, map2["one"]->get_f_int8());
   EXPECT_TRUE(map2["two"].is_null());
@@ -847,15 +782,10 @@
   ObjectUnionPtr obj(ObjectUnion::New());
   obj->set_f_dummy(std::move(dummy));
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>(
-      obj, false, &context);
-  EXPECT_EQ(32U, size);
-
-  mojo::internal::FixedBufferForTesting buf(size);
   internal::ObjectUnion_Data* data = nullptr;
-  mojo::internal::Serialize<ObjectUnionDataView>(obj, &buf, &data, false,
-                                                 &context);
+  EXPECT_EQ(32U, SerializeUnion(obj, &message, &context, &data));
 
   ObjectUnionPtr obj2;
   mojo::internal::Deserialize<ObjectUnionDataView>(data, &obj2, nullptr);
@@ -869,21 +799,15 @@
   ObjectUnionPtr obj(ObjectUnion::New());
   obj->set_f_dummy(std::move(dummy));
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>(
-      obj, false, &context);
-
-  mojo::internal::FixedBufferForTesting buf(size);
   internal::ObjectUnion_Data* data = nullptr;
-  mojo::internal::Serialize<ObjectUnionDataView>(obj, &buf, &data, false,
-                                                 &context);
+  const size_t size = SerializeUnion(obj, &message, &context, &data);
 
-  void* raw_buf = buf.Leak();
   mojo::internal::ValidationContext validation_context(
       data, static_cast<uint32_t>(size), 0, 0);
-  EXPECT_TRUE(internal::ObjectUnion_Data::Validate(
-      raw_buf, &validation_context, false));
-  free(raw_buf);
+  EXPECT_TRUE(
+      internal::ObjectUnion_Data::Validate(data, &validation_context, false));
 }
 
 TEST(UnionTest, StructInUnionValidationNonNullable) {
@@ -894,21 +818,15 @@
   ObjectUnionPtr obj(ObjectUnion::New());
   obj->set_f_dummy(std::move(dummy));
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>(
-      obj, false, &context);
-
-  mojo::internal::FixedBufferForTesting buf(size);
   internal::ObjectUnion_Data* data = nullptr;
-  mojo::internal::Serialize<ObjectUnionDataView>(obj, &buf, &data, false,
-                                                 &context);
+  const size_t size = SerializeUnion(obj, &message, &context, &data);
 
-  void* raw_buf = buf.Leak();
   mojo::internal::ValidationContext validation_context(
       data, static_cast<uint32_t>(size), 0, 0);
-  EXPECT_FALSE(internal::ObjectUnion_Data::Validate(
-      raw_buf, &validation_context, false));
-  free(raw_buf);
+  EXPECT_FALSE(
+      internal::ObjectUnion_Data::Validate(data, &validation_context, false));
 }
 
 TEST(UnionTest, StructInUnionValidationNullable) {
@@ -917,21 +835,15 @@
   ObjectUnionPtr obj(ObjectUnion::New());
   obj->set_f_nullable(std::move(dummy));
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>(
-      obj, false, &context);
-
-  mojo::internal::FixedBufferForTesting buf(size);
   internal::ObjectUnion_Data* data = nullptr;
-  mojo::internal::Serialize<ObjectUnionDataView>(obj, &buf, &data, false,
-                                                 &context);
+  const size_t size = SerializeUnion(obj, &message, &context, &data);
 
-  void* raw_buf = buf.Leak();
   mojo::internal::ValidationContext validation_context(
       data, static_cast<uint32_t>(size), 0, 0);
-  EXPECT_TRUE(internal::ObjectUnion_Data::Validate(
-      raw_buf, &validation_context, false));
-  free(raw_buf);
+  EXPECT_TRUE(
+      internal::ObjectUnion_Data::Validate(data, &validation_context, false));
 }
 
 TEST(UnionTest, ArrayInUnionGetterSetter) {
@@ -954,15 +866,11 @@
   ObjectUnionPtr obj(ObjectUnion::New());
   obj->set_f_array_int8(std::move(array));
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>(
-      obj, false, &context);
-  EXPECT_EQ(32U, size);
-
-  mojo::internal::FixedBufferForTesting buf(size);
   internal::ObjectUnion_Data* data = nullptr;
-  mojo::internal::Serialize<ObjectUnionDataView>(obj, &buf, &data, false,
-                                                 &context);
+  const size_t size = SerializeUnion(obj, &message, &context, &data);
+  EXPECT_EQ(32U, size);
 
   ObjectUnionPtr obj2;
   mojo::internal::Deserialize<ObjectUnionDataView>(data, &obj2, nullptr);
@@ -979,21 +887,15 @@
   ObjectUnionPtr obj(ObjectUnion::New());
   obj->set_f_array_int8(std::move(array));
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>(
-      obj, false, &context);
-  mojo::internal::FixedBufferForTesting buf(size);
   internal::ObjectUnion_Data* data = nullptr;
-  mojo::internal::Serialize<ObjectUnionDataView>(obj, &buf, &data, false,
-                                                 &context);
+  const size_t size = SerializeUnion(obj, &message, &context, &data);
 
-  void* raw_buf = buf.Leak();
   mojo::internal::ValidationContext validation_context(
       data, static_cast<uint32_t>(size), 0, 0);
-
-  EXPECT_TRUE(internal::ObjectUnion_Data::Validate(
-      raw_buf, &validation_context, false));
-  free(raw_buf);
+  EXPECT_TRUE(
+      internal::ObjectUnion_Data::Validate(data, &validation_context, false));
 }
 
 TEST(UnionTest, MapInUnionGetterSetter) {
@@ -1016,15 +918,11 @@
   ObjectUnionPtr obj(ObjectUnion::New());
   obj->set_f_map_int8(std::move(map));
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>(
-      obj, false, &context);
-  EXPECT_EQ(112U, size);
-
-  mojo::internal::FixedBufferForTesting buf(size);
   internal::ObjectUnion_Data* data = nullptr;
-  mojo::internal::Serialize<ObjectUnionDataView>(obj, &buf, &data, false,
-                                                 &context);
+  const size_t size = SerializeUnion(obj, &message, &context, &data);
+  EXPECT_EQ(112U, size);
 
   ObjectUnionPtr obj2;
   mojo::internal::Deserialize<ObjectUnionDataView>(data, &obj2, &context);
@@ -1041,23 +939,16 @@
   ObjectUnionPtr obj(ObjectUnion::New());
   obj->set_f_map_int8(std::move(map));
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>(
-      obj, false, &context);
+  internal::ObjectUnion_Data* data = nullptr;
+  const size_t size = SerializeUnion(obj, &message, &context, &data);
   EXPECT_EQ(112U, size);
 
-  mojo::internal::FixedBufferForTesting buf(size);
-  internal::ObjectUnion_Data* data = nullptr;
-  mojo::internal::Serialize<ObjectUnionDataView>(obj, &buf, &data, false,
-                                                 &context);
-
-  void* raw_buf = buf.Leak();
   mojo::internal::ValidationContext validation_context(
       data, static_cast<uint32_t>(size), 0, 0);
-
-  EXPECT_TRUE(internal::ObjectUnion_Data::Validate(
-      raw_buf, &validation_context, false));
-  free(raw_buf);
+  EXPECT_TRUE(
+      internal::ObjectUnion_Data::Validate(data, &validation_context, false));
 }
 
 TEST(UnionTest, UnionInUnionGetterSetter) {
@@ -1086,15 +977,11 @@
   ObjectUnionPtr obj(ObjectUnion::New());
   obj->set_f_pod_union(std::move(pod));
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>(
-      obj, false, &context);
-  EXPECT_EQ(32U, size);
-
-  mojo::internal::FixedBufferForTesting buf(size);
   internal::ObjectUnion_Data* data = nullptr;
-  mojo::internal::Serialize<ObjectUnionDataView>(obj, &buf, &data, false,
-                                                 &context);
+  const size_t size = SerializeUnion(obj, &message, &context, &data);
+  EXPECT_EQ(32U, size);
 
   ObjectUnionPtr obj2;
   mojo::internal::Deserialize<ObjectUnionDataView>(data, &obj2, nullptr);
@@ -1108,22 +995,16 @@
   ObjectUnionPtr obj(ObjectUnion::New());
   obj->set_f_pod_union(std::move(pod));
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>(
-      obj, false, &context);
+  internal::ObjectUnion_Data* data = nullptr;
+  const size_t size = SerializeUnion(obj, &message, &context, &data);
   EXPECT_EQ(32U, size);
 
-  mojo::internal::FixedBufferForTesting buf(size);
-  internal::ObjectUnion_Data* data = nullptr;
-  mojo::internal::Serialize<ObjectUnionDataView>(obj, &buf, &data, false,
-                                                 &context);
-
-  void* raw_buf = buf.Leak();
   mojo::internal::ValidationContext validation_context(
       data, static_cast<uint32_t>(size), 0, 0);
-  EXPECT_TRUE(internal::ObjectUnion_Data::Validate(
-      raw_buf, &validation_context, false));
-  free(raw_buf);
+  EXPECT_TRUE(
+      internal::ObjectUnion_Data::Validate(data, &validation_context, false));
 }
 
 TEST(UnionTest, UnionInUnionValidationNonNullable) {
@@ -1134,21 +1015,15 @@
   ObjectUnionPtr obj(ObjectUnion::New());
   obj->set_f_pod_union(std::move(pod));
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<ObjectUnionDataView>(
-      obj, false, &context);
-
-  mojo::internal::FixedBufferForTesting buf(size);
   internal::ObjectUnion_Data* data = nullptr;
-  mojo::internal::Serialize<ObjectUnionDataView>(obj, &buf, &data, false,
-                                                 &context);
+  const size_t size = SerializeUnion(obj, &message, &context, &data);
 
-  void* raw_buf = buf.Leak();
   mojo::internal::ValidationContext validation_context(
       data, static_cast<uint32_t>(size), 0, 0);
-  EXPECT_FALSE(internal::ObjectUnion_Data::Validate(
-      raw_buf, &validation_context, false));
-  free(raw_buf);
+  EXPECT_FALSE(
+      internal::ObjectUnion_Data::Validate(data, &validation_context, false));
 }
 
 TEST(UnionTest, HandleInUnionGetterSetter) {
@@ -1195,15 +1070,11 @@
   HandleUnionPtr handle(HandleUnion::New());
   handle->set_f_message_pipe(std::move(pipe1));
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<HandleUnionDataView>(
-      handle, false, &context);
-  EXPECT_EQ(16U, size);
-
-  mojo::internal::FixedBufferForTesting buf(size);
   internal::HandleUnion_Data* data = nullptr;
-  mojo::internal::Serialize<HandleUnionDataView>(handle, &buf, &data, false,
-                                                 &context);
+  const size_t size = SerializeUnion(handle, &message, &context, &data);
+  EXPECT_EQ(16U, size);
   EXPECT_EQ(1U, context.handles()->size());
 
   HandleUnionPtr handle2(HandleUnion::New());
@@ -1227,22 +1098,16 @@
   HandleUnionPtr handle(HandleUnion::New());
   handle->set_f_message_pipe(std::move(pipe1));
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<HandleUnionDataView>(
-      handle, false, &context);
+  internal::HandleUnion_Data* data = nullptr;
+  const size_t size = SerializeUnion(handle, &message, &context, &data);
   EXPECT_EQ(16U, size);
 
-  mojo::internal::FixedBufferForTesting buf(size);
-  internal::HandleUnion_Data* data = nullptr;
-  mojo::internal::Serialize<HandleUnionDataView>(handle, &buf, &data, false,
-                                                 &context);
-
-  void* raw_buf = buf.Leak();
   mojo::internal::ValidationContext validation_context(
       data, static_cast<uint32_t>(size), 1, 0);
-  EXPECT_TRUE(internal::HandleUnion_Data::Validate(
-      raw_buf, &validation_context, false));
-  free(raw_buf);
+  EXPECT_TRUE(
+      internal::HandleUnion_Data::Validate(data, &validation_context, false));
 }
 
 TEST(UnionTest, HandleInUnionValidationNull) {
@@ -1252,22 +1117,16 @@
   HandleUnionPtr handle(HandleUnion::New());
   handle->set_f_message_pipe(std::move(pipe));
 
+  mojo::Message message;
   mojo::internal::SerializationContext context;
-  size_t size = mojo::internal::PrepareToSerialize<HandleUnionDataView>(
-      handle, false, &context);
+  internal::HandleUnion_Data* data = nullptr;
+  const size_t size = SerializeUnion(handle, &message, &context, &data);
   EXPECT_EQ(16U, size);
 
-  mojo::internal::FixedBufferForTesting buf(size);
-  internal::HandleUnion_Data* data = nullptr;
-  mojo::internal::Serialize<HandleUnionDataView>(handle, &buf, &data, false,
-                                                 &context);
-
-  void* raw_buf = buf.Leak();
   mojo::internal::ValidationContext validation_context(
       data, static_cast<uint32_t>(size), 1, 0);
-  EXPECT_FALSE(internal::HandleUnion_Data::Validate(
-      raw_buf, &validation_context, false));
-  free(raw_buf);
+  EXPECT_FALSE(
+      internal::HandleUnion_Data::Validate(data, &validation_context, false));
 }
 
 class SmallCacheImpl : public SmallCache {
@@ -1326,17 +1185,14 @@
   SmallCachePtr ptr;
   Binding<SmallCache> bindings(&impl, MakeRequest(&ptr));
 
-  mojo::internal::SerializationContext context;
   HandleUnionPtr handle(HandleUnion::New());
   handle->set_f_small_cache(std::move(ptr));
-  size_t size = mojo::internal::PrepareToSerialize<HandleUnionDataView>(
-      handle, false, &context);
-  EXPECT_EQ(16U, size);
 
-  mojo::internal::FixedBufferForTesting buf(size);
+  mojo::Message message;
+  mojo::internal::SerializationContext context;
   internal::HandleUnion_Data* data = nullptr;
-  mojo::internal::Serialize<HandleUnionDataView>(handle, &buf, &data, false,
-                                                 &context);
+  const size_t size = SerializeUnion(handle, &message, &context, &data);
+  EXPECT_EQ(16U, size);
   EXPECT_EQ(1U, context.handles()->size());
 
   HandleUnionPtr handle2(HandleUnion::New());
diff --git a/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc b/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc
index b0ce918..ba2f4fc 100644
--- a/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc
@@ -113,19 +113,18 @@
   WTF::Vector<WTF::String> strs = ConstructStringArray();
   auto cloned_strs = strs;
 
+  mojo::Message message(0, 0, 0, 0, nullptr);
   mojo::internal::SerializationContext context;
-  size_t size =
-      mojo::internal::PrepareToSerialize<MojomType>(cloned_strs, &context);
-
-  mojo::internal::FixedBufferForTesting buf(size);
-  typename mojo::internal::MojomTypeTraits<MojomType>::Data* data;
+  typename mojo::internal::MojomTypeTraits<MojomType>::Data::BufferWriter
+      writer;
+  mojo::internal::PrepareToSerialize<MojomType>(cloned_strs, &context);
   mojo::internal::ContainerValidateParams validate_params(
       0, true, new mojo::internal::ContainerValidateParams(0, false, nullptr));
-  mojo::internal::Serialize<MojomType>(cloned_strs, &buf, &data,
-                                       &validate_params, &context);
+  mojo::internal::Serialize<MojomType>(cloned_strs, message.payload_buffer(),
+                                       &writer, &validate_params, &context);
 
   WTF::Vector<WTF::String> strs2;
-  mojo::internal::Deserialize<MojomType>(data, &strs2, &context);
+  mojo::internal::Deserialize<MojomType>(writer.data(), &strs2, &context);
 
   EXPECT_EQ(strs, strs2);
 }
@@ -136,19 +135,18 @@
   WTF::Vector<WTF::String> strs = ConstructStringArray();
   auto cloned_strs = strs;
 
+  mojo::Message message(0, 0, 0, 0, nullptr);
   mojo::internal::SerializationContext context;
-  size_t size =
-      mojo::internal::PrepareToSerialize<MojomType>(cloned_strs, &context);
-
-  mojo::internal::FixedBufferForTesting buf(size);
-  typename mojo::internal::MojomTypeTraits<MojomType>::Data* data;
+  mojo::internal::PrepareToSerialize<MojomType>(cloned_strs, &context);
+  typename mojo::internal::MojomTypeTraits<MojomType>::Data::BufferWriter
+      writer;
   mojo::internal::ContainerValidateParams validate_params(
       0, true, new mojo::internal::ContainerValidateParams(0, false, nullptr));
-  mojo::internal::Serialize<MojomType>(cloned_strs, &buf, &data,
-                                       &validate_params, &context);
+  mojo::internal::Serialize<MojomType>(cloned_strs, message.payload_buffer(),
+                                       &writer, &validate_params, &context);
 
   std::vector<base::Optional<std::string>> strs2;
-  mojo::internal::Deserialize<MojomType>(data, &strs2, &context);
+  mojo::internal::Deserialize<MojomType>(writer.data(), &strs2, &context);
 
   ASSERT_EQ(4u, strs2.size());
   EXPECT_FALSE(strs2[0]);
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl
index 9e479b7b..86ab3f0 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl
@@ -59,12 +59,13 @@
                                    params_struct, params_description,
                                    flags_text, message_object) %}
   mojo::internal::SerializationContext serialization_context;
-  {{struct_macros.get_serialized_size(params_struct, param_name_prefix,
-                                      "&serialization_context")}}
+  {{struct_macros.prepare_to_serialize(params_struct, param_name_prefix,
+                                       "&serialization_context")}}
   serialization_context.PrepareMessage(
-      {{message_name}},
-      {{flags_text}}, size, {{message_object}});
+      {{message_name}}, {{flags_text}}, {{message_object}});
   auto* buffer = ({{message_object}})->payload_buffer();
+  {{params_struct|get_qualified_name_for_kind(internal=True)}}::BufferWriter
+      params;
   {{struct_macros.serialize(params_struct, params_description,
                             param_name_prefix, "params", "buffer",
                             "&serialization_context")}}
@@ -165,15 +166,16 @@
 
  private:
   // mojo::internal::UnserializedMessageContext:
-  size_t PrepareToSerialize(
+  void PrepareToSerialize(
       mojo::internal::SerializationContext* serialization_context) override {
-    {{struct_macros.get_serialized_size(params_struct, "param_%s_",
-                                        "serialization_context")}}
-    return size;
+    {{struct_macros.prepare_to_serialize(params_struct, "param_%s_",
+                                         "serialization_context")}}
   }
 
   void Serialize(mojo::internal::SerializationContext* serialization_context,
                  mojo::internal::Buffer* buffer) override {
+    {{params_struct|get_qualified_name_for_kind(internal=True)}}::BufferWriter
+        params;
     {{struct_macros.serialize(params_struct, params_description, "param_%s_",
                               "params", "buffer", "serialization_context")}}
   }
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl
index cc2dcb2..46563c3 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl
@@ -2,7 +2,29 @@
 
 class {{export_attribute}} {{class_name}} {
  public:
-  static {{class_name}}* New(mojo::internal::Buffer* buf);
+  class BufferWriter {
+   public:
+    BufferWriter() = default;
+
+    void Allocate(mojo::internal::Buffer* buffer) {
+      buffer_ = buffer;
+      index_ = buffer_->Allocate(sizeof({{class_name}}));
+      new (data()) {{class_name}}();
+    }
+
+    bool is_null() const { return !buffer_; }
+    {{class_name}}* data() {
+      DCHECK(!is_null());
+      return buffer_->Get<{{class_name}}>(index_);
+    }
+    {{class_name}}* operator->() { return data(); }
+
+   private:
+    mojo::internal::Buffer* buffer_ = nullptr;
+    size_t index_ = 0;
+
+    DISALLOW_COPY_AND_ASSIGN(BufferWriter);
+  };
 
   static bool Validate(const void* data,
                        mojo::internal::ValidationContext* validation_context);
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl
index ad816ab..9c1eae8 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/struct_definition.tmpl
@@ -2,11 +2,6 @@
 {%- set class_name = struct.name ~ "_Data" %}
 
 // static
-{{class_name}}* {{class_name}}::New(mojo::internal::Buffer* buf) {
-  return new (buf->Allocate(sizeof({{class_name}}))) {{class_name}}();
-}
-
-// static
 bool {{class_name}}::Validate(
     const void* data,
     mojo::internal::ValidationContext* validation_context) {
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl
index b61815f..26603ed 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/struct_macros.tmpl
@@ -1,6 +1,7 @@
 {#  TODO(yzshen): Make these templates more readable. #}
 
-{#  Computes the serialized size for the specified struct.
+{#  Prepares to serialize the specified struct, collecting handles and
+    associated handle info.
     |struct| is the struct definition.
     |input_field_pattern| should be a pattern that contains one string
     placeholder, for example, "input->%s", "p_%s". The placeholder will be
@@ -10,18 +11,15 @@
     We need to assign temporary objects to local variables before passing it to
     Serializer, because it is illegal to pass temporary objects as non-const
     references.
-    This macro is expanded to compute seriailized size for both:
+    This macro is expanded to collect handles from both:
     - user-defined structs: the input is an instance of the corresponding struct
       wrapper class.
     - method parameters/response parameters: the input is a list of
-      arguments.
-    It declares |size| of type size_t to store the resulting size. #}
-{%- macro get_serialized_size(struct, input_field_pattern, context,
-                              input_may_be_temp=False) -%}
-  size_t size = sizeof({{struct|get_qualified_name_for_kind(internal=True)}});
+      arguments. #}
+{%- macro prepare_to_serialize(struct, input_field_pattern, context,
+                               input_may_be_temp=False) -%}
 {%-   for pf in struct.packed.packed_fields_in_ordinal_order
-          if pf.field.kind|is_object_kind or
-              pf.field.kind|is_any_handle_or_interface_kind %}
+          if pf.field.kind|contains_handles_or_interfaces %}
 {%-     set name = pf.field.name -%}
 {%-     set kind = pf.field.kind -%}
 {%-     set original_input_field = input_field_pattern|format(name) %}
@@ -33,10 +31,10 @@
 
 {%-     set serializer_type = kind|unmapped_type_for_serializer %}
 {%-     if kind|is_union_kind %}
-  size += mojo::internal::PrepareToSerialize<{{serializer_type}}>(
+  mojo::internal::PrepareToSerialize<{{serializer_type}}>(
       {{input_field}}, true, {{context}});
 {%-     else %}
-  size += mojo::internal::PrepareToSerialize<{{serializer_type}}>(
+  mojo::internal::PrepareToSerialize<{{serializer_type}}>(
       {{input_field}}, {{context}});
 {%-     endif %}
 {%-   endfor %}
@@ -49,7 +47,7 @@
     |input_field_pattern| should be a pattern that contains one string
     placeholder, for example, "input->%s", "p_%s". The placeholder will be
     substituted with struct field names to refer to the input fields.
-    |output| is the name of the output struct instance.
+    |writer| is the name of the BufferWriter to use for allocation and writing.
     |buffer| is the name of the Buffer instance used.
     |context| is the name of the serialization context.
     |input_may_be_temp|: please see the comments of get_serialized_size.
@@ -58,11 +56,9 @@
       wrapper class.
     - method parameters/response parameters: the input is a list of
       arguments. #}
-{%- macro serialize(struct, struct_display_name, input_field_pattern, output,
+{%- macro serialize(struct, struct_display_name, input_field_pattern, writer,
                     buffer, context, input_may_be_temp=False) -%}
-  auto {{output}} =
-      {{struct|get_qualified_name_for_kind(internal=True)}}::New({{buffer}});
-  ALLOW_UNUSED_LOCAL({{output}});
+  {{writer}}.Allocate({{buffer}});
 {%- for pf in struct.packed.packed_fields_in_ordinal_order %}
 {%-   set input_field = input_field_pattern|format(pf.field.name) %}
 {%-   set name = pf.field.name %}
@@ -87,36 +83,41 @@
 
 {%-   if kind|is_object_kind %}
 {%-     if kind|is_array_kind or kind|is_map_kind %}
-  typename decltype({{output}}->{{name}})::BaseType* {{name}}_ptr;
+  typename decltype({{writer}}->{{name}})::BaseType::BufferWriter
+      {{name}}_writer;
   const mojo::internal::ContainerValidateParams {{name}}_validate_params(
       {{kind|get_container_validate_params_ctor_args|indent(10)}});
   mojo::internal::Serialize<{{serializer_type}}>(
-      {{input_field}}, {{buffer}}, &{{name}}_ptr, &{{name}}_validate_params,
+      {{input_field}}, {{buffer}}, &{{name}}_writer, &{{name}}_validate_params,
       {{context}});
-  {{output}}->{{name}}.Set({{name}}_ptr);
+  {{writer}}->{{name}}.Set(
+      {{name}}_writer.is_null() ? nullptr : {{name}}_writer.data());
 {%-     elif kind|is_union_kind %}
-  auto {{name}}_ptr = &{{output}}->{{name}};
+  typename decltype({{writer}}->{{name}})::BufferWriter {{name}}_writer;
+  {{name}}_writer.AllocateInline({{buffer}}, &{{writer}}->{{name}});
   mojo::internal::Serialize<{{serializer_type}}>(
-      {{input_field}}, {{buffer}}, &{{name}}_ptr, true, {{context}});
+      {{input_field}}, {{buffer}}, &{{name}}_writer, true, {{context}});
 {%-     else %}
-  typename decltype({{output}}->{{name}})::BaseType* {{name}}_ptr;
+  typename decltype({{writer}}->{{name}})::BaseType::BufferWriter
+      {{name}}_writer;
   mojo::internal::Serialize<{{serializer_type}}>(
-      {{input_field}}, {{buffer}}, &{{name}}_ptr, {{context}});
-  {{output}}->{{name}}.Set({{name}}_ptr);
+      {{input_field}}, {{buffer}}, &{{name}}_writer, {{context}});
+  {{writer}}->{{name}}.Set(
+      {{name}}_writer.is_null() ? nullptr : {{name}}_writer.data());
 {%-     endif %}
 {%-     if not kind|is_nullable_kind %}
   MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
-      {{output}}->{{name}}.is_null(),
+      {{writer}}->{{name}}.is_null(),
       mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
       "null {{name}} in {{struct_display_name}}");
 {%-     endif %}
 
 {%-   elif kind|is_any_handle_or_interface_kind %}
   mojo::internal::Serialize<{{serializer_type}}>(
-      {{input_field}}, &{{output}}->{{name}}, {{context}});
+      {{input_field}}, &{{writer}}->{{name}}, {{context}});
 {%-     if not kind|is_nullable_kind %}
   MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
-      !mojo::internal::IsHandleOrInterfaceValid({{output}}->{{name}}),
+      !mojo::internal::IsHandleOrInterfaceValid({{writer}}->{{name}}),
 {%-       if kind|is_associated_kind %}
       mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID,
 {%-       else %}
@@ -127,10 +128,10 @@
 
 {%-   elif kind|is_enum_kind %}
   mojo::internal::Serialize<{{serializer_type}}>(
-      {{input_field}}, &{{output}}->{{name}});
+      {{input_field}}, &{{writer}}->{{name}});
 
 {%-   else %}
-  {{output}}->{{name}} = {{input_field}};
+  {{writer}}->{{name}} = {{input_field}};
 {%-   endif %}
 {%- endfor %}
 {%- endmacro -%}
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl
index 9fcb6ac..e783e7b 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl
@@ -9,38 +9,45 @@
   using UserType = typename std::remove_const<MaybeConstUserType>::type;
   using Traits = StructTraits<{{data_view}}, UserType>;
 
-  static size_t PrepareToSerialize(MaybeConstUserType& input,
-                                   SerializationContext* context) {
+  static void PrepareToSerialize(MaybeConstUserType& input,
+                                 SerializationContext* context) {
+{# NOTE: Only types which may (recursively) contain handles or interface types
+   need to do any preparation for serialization. We don't bother in other cases,
+   and nullability testing and context setup can instead be done directly in
+   Serialize below. #}
+{%- if struct|contains_handles_or_interfaces %}
     const bool is_null = CallIsNullIfExists<Traits>(input);
     context->PushNextNullState(is_null);
     if (is_null)
-      return 0;
+      return;
 
-    void* custom_context = CustomContextHelper<Traits>::SetUp(input, context);
+    void* custom_context = CustomContextHelper<Traits>::SetUpAndPush(input,
+                                                                     context);
     ALLOW_UNUSED_LOCAL(custom_context);
 
-    {{struct_macros.get_serialized_size(
+    {{struct_macros.prepare_to_serialize(
           struct, "CallWithContext(Traits::%s, input, custom_context)",
           "context", True)|indent(2)}}
-    return size;
+{%- endif %}
   }
 
   static void Serialize(MaybeConstUserType& input,
                         Buffer* buffer,
-                        {{data_type}}** output,
+                        {{data_type}}::BufferWriter* output,
                         SerializationContext* context) {
-    if (context->IsNextFieldNull()) {
-      *output = nullptr;
+{%- if struct|contains_handles_or_interfaces %}
+    if (context->IsNextFieldNull())
       return;
-    }
-
     void* custom_context = CustomContextHelper<Traits>::GetNext(context);
-
+{%- else %}
+    if (CallIsNullIfExists<Traits>(input))
+      return;
+    void* custom_context = CustomContextHelper<Traits>::SetUp(input, context);
+{%- endif %}
     {{struct_macros.serialize(
           struct, struct.name ~ " struct",
-          "CallWithContext(Traits::%s, input, custom_context)", "result",
+          "CallWithContext(Traits::%s, input, custom_context)", "(*output)",
           "buffer", "context", True)|indent(2)}}
-    *output = result;
 
     CustomContextHelper<Traits>::TearDown(input, custom_context);
   }
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl
index a249eb6..c62ce2b 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl
@@ -12,9 +12,36 @@
   // non-inlined union.
   ~{{class_name}}() {}
 
-  static {{class_name}}* New(mojo::internal::Buffer* buf) {
-    return new (buf->Allocate(sizeof({{class_name}}))) {{class_name}}();
-  }
+  class BufferWriter {
+   public:
+    BufferWriter() = default;
+
+    void Allocate(mojo::internal::Buffer* buffer) {
+      buffer_ = buffer;
+      index_ = buffer_->Allocate(sizeof({{class_name}}));
+      new (data()) {{class_name}}();
+    }
+
+    void AllocateInline(mojo::internal::Buffer* buffer, void* ptr) {
+      const char* start = static_cast<const char*>(buffer->data());
+      const char* slot = static_cast<const char*>(ptr);
+      DCHECK_GT(slot, start);
+      buffer_ = buffer;
+      index_ = slot - start;
+      new (data()) {{class_name}}();
+    }
+
+    bool is_null() const { return !buffer_; }
+    {{class_name}}* data() {
+      DCHECK(!is_null());
+      return buffer_->Get<{{class_name}}>(index_);
+    }
+    {{class_name}}* operator->() { return data(); }
+
+   private:
+    mojo::internal::Buffer* buffer_ = nullptr;
+    size_t index_ = 0;
+  };
 
   static bool Validate(const void* data,
                        mojo::internal::ValidationContext* validation_context,
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl
index d16a07eb..1d7d1be 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl
@@ -8,63 +8,74 @@
   using UserType = typename std::remove_const<MaybeConstUserType>::type;
   using Traits = UnionTraits<{{data_view}}, UserType>;
 
-  static size_t PrepareToSerialize(MaybeConstUserType& input,
-                                   bool inlined,
-                                   SerializationContext* context) {
-    size_t size = inlined ? 0 : sizeof({{data_type}});
+  static void PrepareToSerialize(MaybeConstUserType& input,
+                                 bool inlined,
+                                 SerializationContext* context) {
+{# NOTE: Only types which may (recursively) contain handles or interface types
+   need to do any preparation for serialization. We don't bother in other cases,
+   and nullability testing and context setup can instead be done directly in
+   Serialize below. #}
+{%- if union|contains_handles_or_interfaces %}
     const bool is_null = CallIsNullIfExists<Traits>(input);
     context->PushNextNullState(is_null);
     if (is_null)
-      return size;
+      return;
 
-    void* custom_context = CustomContextHelper<Traits>::SetUp(input, context);
+    void* custom_context = CustomContextHelper<Traits>::SetUpAndPush(input,
+                                                                     context);
     ALLOW_UNUSED_LOCAL(custom_context);
 
     switch (CallWithContext(Traits::GetTag, input, custom_context)) {
-{%- for field in union.fields %}
-{%-   set name = field.name %}
+{%-   for field in union.fields %}
+{%-     set name = field.name %}
       case {{data_view}}::Tag::{{name|upper}}: {
-{%-   if field.kind|is_object_kind or
-          field.kind|is_any_handle_or_interface_kind %}
-{%-     set kind = field.kind %}
-{%-     set serializer_type = kind|unmapped_type_for_serializer %}
+{%-     if field.kind|contains_handles_or_interfaces %}
+{%-       set kind = field.kind %}
+{%-       set serializer_type = kind|unmapped_type_for_serializer %}
         decltype(CallWithContext(Traits::{{name}}, input, custom_context))
             in_{{name}} = CallWithContext(Traits::{{name}}, input,
                                           custom_context);
-{%-     if kind|is_union_kind %}
-        size += mojo::internal::PrepareToSerialize<{{serializer_type}}>(
+{%-       if kind|is_union_kind %}
+        mojo::internal::PrepareToSerialize<{{serializer_type}}>(
             in_{{name}}, false, context);
-{%-     else %}
-        size += mojo::internal::PrepareToSerialize<{{serializer_type}}>(
+{%-       else %}
+        mojo::internal::PrepareToSerialize<{{serializer_type}}>(
             in_{{name}}, context);
+{%-       endif %}
 {%-     endif %}
-{%-   endif %}
         break;
       }
-{%- endfor %}
+{%-   endfor %}
     }
-    return size;
+{%- endif %}
   }
 
   static void Serialize(MaybeConstUserType& input,
                         Buffer* buffer,
-                        {{data_type}}** output,
+                        {{data_type}}::BufferWriter* writer,
                         bool inlined,
                         SerializationContext* context) {
+{%- if union|contains_handles_or_interfaces %}
     if (context->IsNextFieldNull()) {
       if (inlined)
-        (*output)->set_null();
-      else
-        *output = nullptr;
+        writer->data()->set_null();
       return;
     }
 
     void* custom_context = CustomContextHelper<Traits>::GetNext(context);
+{%- else %}
+    if (CallIsNullIfExists<Traits>(input)) {
+       if (inlined)
+         writer->data()->set_null();
+      return;
+    }
+    void* custom_context = CustomContextHelper<Traits>::SetUp(input, context);
+{%- endif %}
 
     if (!inlined)
-      *output = {{data_type}}::New(buffer);
+      writer->Allocate(buffer);
 
-    {{data_type}}* result = *output;
+    {{data_type}}::BufferWriter& result = *writer;
     ALLOW_UNUSED_LOCAL(result);
     // TODO(azani): Handle unknown and objects.
     // Set the not-null flag.
@@ -80,25 +91,29 @@
             in_{{name}} = CallWithContext(Traits::{{name}}, input,
                                           custom_context);
 {%-   if kind|is_object_kind %}
-        typename decltype(result->data.f_{{name}})::BaseType* ptr;
+        typename decltype(result->data.f_{{name}})::BaseType::BufferWriter
+            value_writer;
 {%-     if kind|is_union_kind %}
         mojo::internal::Serialize<{{serializer_type}}>(
-            in_{{name}}, buffer, &ptr, false, context);
+            in_{{name}}, buffer, &value_writer, false, context);
 {%-     elif kind|is_array_kind or kind|is_map_kind %}
         const ContainerValidateParams {{name}}_validate_params(
             {{kind|get_container_validate_params_ctor_args|indent(16)}});
         mojo::internal::Serialize<{{serializer_type}}>(
-            in_{{name}}, buffer, &ptr, &{{name}}_validate_params, context);
-{%-     else %}
+            in_{{name}}, buffer, &value_writer, &{{name}}_validate_params,
+            context);
+ {%-     else %}
         mojo::internal::Serialize<{{serializer_type}}>(
-            in_{{name}}, buffer, &ptr, context);
+            in_{{name}}, buffer, &value_writer, context);
 {%-     endif %}
-        result->data.f_{{name}}.Set(ptr);
 {%-     if not kind|is_nullable_kind %}
         MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
-            !ptr, mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
+            value_writer.is_null(),
+            mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
             "null {{name}} in {{union.name}} union");
 {%-     endif %}
+        result->data.f_{{name}}.Set(
+            value_writer.is_null() ? nullptr : value_writer.data());
 
 {%-   elif kind|is_any_handle_or_interface_kind %}
         mojo::internal::Serialize<{{serializer_type}}>(
diff --git a/net/BUILD.gn b/net/BUILD.gn
index c49f4e71..4cd757c 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -1195,6 +1195,7 @@
       "quic/core/crypto/crypto_handshake.h",
       "quic/core/crypto/crypto_handshake_message.cc",
       "quic/core/crypto/crypto_handshake_message.h",
+      "quic/core/crypto/crypto_message_parser.h",
       "quic/core/crypto/crypto_protocol.h",
       "quic/core/crypto/crypto_secret_boxer.cc",
       "quic/core/crypto/crypto_secret_boxer.h",
@@ -1282,8 +1283,14 @@
       "quic/core/quic_connection_stats.h",
       "quic/core/quic_constants.cc",
       "quic/core/quic_constants.h",
+      "quic/core/quic_crypto_client_handshaker.cc",
+      "quic/core/quic_crypto_client_handshaker.h",
       "quic/core/quic_crypto_client_stream.cc",
       "quic/core/quic_crypto_client_stream.h",
+      "quic/core/quic_crypto_handshaker.cc",
+      "quic/core/quic_crypto_handshaker.h",
+      "quic/core/quic_crypto_server_handshaker.cc",
+      "quic/core/quic_crypto_server_handshaker.h",
       "quic/core/quic_crypto_server_stream.cc",
       "quic/core/quic_crypto_server_stream.h",
       "quic/core/quic_crypto_stream.cc",
diff --git a/net/base/fuzzer_test_support.cc b/net/base/fuzzer_test_support.cc
index 0b97dfb..78091baf 100644
--- a/net/base/fuzzer_test_support.cc
+++ b/net/base/fuzzer_test_support.cc
@@ -5,8 +5,8 @@
 #include "base/at_exit.h"
 #include "base/i18n/icu_util.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop.h"
 #include "base/metrics/statistics_recorder.h"
+#include "base/test/scoped_task_environment.h"
 
 namespace {
 
@@ -15,7 +15,9 @@
 // Note that in general static initializers are not allowed, however this is
 // just being used by test code.
 struct InitGlobals {
-  InitGlobals() {
+  InitGlobals()
+      : scoped_task_environment(
+            base::test::ScopedTaskEnvironment::MainThreadType::IO) {
     // Set up ICU. ICU is used internally by GURL, which is used throughout the
     // //net code. Initializing ICU is important to prevent fuzztests from
     // asserting when handling non-ASCII urls.
@@ -30,10 +32,10 @@
     logging::SetMinLogLevel(logging::LOG_FATAL);
   }
 
-  // A number of tests use async code which depends on there being a message
-  // loop.  Setting one up here allows tests to reuse the message loop between
-  // runs.
-  base::MessageLoopForIO message_loop;
+  // A number of tests use async code which depends on there being a
+  // ScopedTaskEnvironment.  Setting one up here allows tests to reuse the
+  // ScopedTaskEnvironment between runs.
+  base::test::ScopedTaskEnvironment scoped_task_environment;
 
   base::AtExitManager at_exit_manager;
 };
diff --git a/net/disk_cache/simple/simple_entry_impl.cc b/net/disk_cache/simple/simple_entry_impl.cc
index afc18852..f72ff2b 100644
--- a/net/disk_cache/simple/simple_entry_impl.cc
+++ b/net/disk_cache/simple/simple_entry_impl.cc
@@ -1511,8 +1511,8 @@
     uint32_t initial_crc =
         (offset != 0) ? crc32s_[stream_index] : crc32(0, Z_NULL, 0);
     if (length > 0) {
-      crc32s_[stream_index] = crc32(
-          initial_crc, reinterpret_cast<const Bytef*>(buffer->data()), length);
+      crc32s_[stream_index] =
+          simple_util::IncrementalCrc32(initial_crc, buffer->data(), length);
     }
     crc32s_end_offset_[stream_index] = offset + length;
   } else if (offset < crc32s_end_offset_[stream_index]) {
diff --git a/net/disk_cache/simple/simple_index_file.cc b/net/disk_cache/simple/simple_index_file.cc
index 05acd0b..ff26d4c 100644
--- a/net/disk_cache/simple/simple_index_file.cc
+++ b/net/disk_cache/simple/simple_index_file.cc
@@ -24,7 +24,6 @@
 #include "net/disk_cache/simple/simple_index.h"
 #include "net/disk_cache/simple/simple_synchronous_entry.h"
 #include "net/disk_cache/simple/simple_util.h"
-#include "third_party/zlib/zlib.h"
 
 using base::File;
 
@@ -43,9 +42,7 @@
     kMaxEntriesInIndex * (8 + EntryMetadata::kOnDiskSizeBytes);
 
 uint32_t CalculatePickleCRC(const base::Pickle& pickle) {
-  return crc32(crc32(0, Z_NULL, 0),
-               reinterpret_cast<const Bytef*>(pickle.payload()),
-               pickle.payload_size());
+  return simple_util::Crc32(pickle.payload(), pickle.payload_size());
 }
 
 // Used in histograms. Please only add new values at the end.
diff --git a/net/disk_cache/simple/simple_synchronous_entry.cc b/net/disk_cache/simple/simple_synchronous_entry.cc
index dc27812..cb97002 100644
--- a/net/disk_cache/simple/simple_synchronous_entry.cc
+++ b/net/disk_cache/simple/simple_synchronous_entry.cc
@@ -363,9 +363,8 @@
   if (bytes_read > 0) {
     entry_stat->set_last_used(Time::Now());
     if (crc_request != nullptr) {
-      crc_request->data_crc32 =
-          crc32(crc_request->data_crc32,
-                reinterpret_cast<const Bytef*>(out_buf->data()), bytes_read);
+      crc_request->data_crc32 = simple_util::IncrementalCrc32(
+          crc_request->data_crc32, out_buf->data(), bytes_read);
       // Verify checksum after last read, if we've been asked to.
       if (crc_request->request_verify &&
           in_entry_op.offset + bytes_read ==
@@ -1262,11 +1261,7 @@
 
   // Check the CRC32.
   uint32_t expected_crc32 =
-      stream_0_size == 0
-          ? crc32(0, Z_NULL, 0)
-          : crc32(crc32(0, Z_NULL, 0),
-                  reinterpret_cast<const Bytef*>((*stream_0_data)->data()),
-                  stream_0_size);
+      simple_util::Crc32((*stream_0_data)->data(), stream_0_size);
   if (has_crc32 && read_crc32 != expected_crc32) {
     DVLOG(1) << "EOF record had bad crc.";
     RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH);
@@ -1560,9 +1555,7 @@
 
   // If we read the whole range and we have a crc32, check it.
   if (offset == 0 && len == range->length && range->data_crc32 != 0) {
-    uint32_t actual_crc32 =
-        crc32(crc32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(buf), len);
-    if (actual_crc32 != range->data_crc32) {
+    if (simple_util::Crc32(buf, len) != range->data_crc32) {
       DLOG(WARNING) << "Sparse range crc32 mismatch.";
       return false;
     }
@@ -1582,9 +1575,7 @@
 
   uint32_t new_crc32 = 0;
   if (offset == 0 && len == range->length) {
-    new_crc32 = crc32(crc32(0L, Z_NULL, 0),
-                      reinterpret_cast<const Bytef*>(buf),
-                      len);
+    new_crc32 = simple_util::Crc32(buf, len);
   }
 
   if (new_crc32 != range->data_crc32) {
@@ -1621,8 +1612,7 @@
   DCHECK_GT(len, 0);
   DCHECK(buf);
 
-  uint32_t data_crc32 =
-      crc32(crc32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(buf), len);
+  uint32_t data_crc32 = simple_util::Crc32(buf, len);
 
   SimpleFileSparseRangeHeader header;
   header.sparse_range_magic_number = kSimpleSparseRangeMagicNumber;
diff --git a/net/disk_cache/simple/simple_util.cc b/net/disk_cache/simple/simple_util.cc
index 3844b98..4e0869f 100644
--- a/net/disk_cache/simple/simple_util.cc
+++ b/net/disk_cache/simple/simple_util.cc
@@ -16,6 +16,7 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/time/time.h"
 #include "net/disk_cache/simple/simple_entry_format.h"
+#include "third_party/zlib/zlib.h"
 
 namespace {
 
@@ -102,6 +103,17 @@
   return true;
 }
 
+uint32_t Crc32(const char* data, int length) {
+  uint32_t empty_crc = crc32(0, Z_NULL, 0);
+  if (length == 0)
+    return empty_crc;
+  return crc32(empty_crc, reinterpret_cast<const Bytef*>(data), length);
+}
+
+uint32_t IncrementalCrc32(uint32_t previous_crc, const char* data, int length) {
+  return crc32(previous_crc, reinterpret_cast<const Bytef*>(data), length);
+}
+
 }  // namespace simple_util
 
 }  // namespace disk_cache
diff --git a/net/disk_cache/simple/simple_util.h b/net/disk_cache/simple/simple_util.h
index aa3eb036..ad84607 100644
--- a/net/disk_cache/simple/simple_util.h
+++ b/net/disk_cache/simple/simple_util.h
@@ -82,6 +82,10 @@
 // is possible to immediately create a new file with the same name.
 NET_EXPORT_PRIVATE bool SimpleCacheDeleteFile(const base::FilePath& path);
 
+uint32_t Crc32(const char* data, int length);
+
+uint32_t IncrementalCrc32(uint32_t previous_crc, const char* data, int length);
+
 }  // namespace simple_util
 
 }  // namespace disk_cache
diff --git a/net/http/http_response_info.cc b/net/http/http_response_info.cc
index 0104dbf7..47b0ded 100644
--- a/net/http/http_response_info.cc
+++ b/net/http/http_response_info.cc
@@ -445,6 +445,7 @@
     case CONNECTION_INFO_QUIC_38:
     case CONNECTION_INFO_QUIC_39:
     case CONNECTION_INFO_QUIC_40:
+    case CONNECTION_INFO_QUIC_41:
       return true;
     case NUM_OF_CONNECTION_INFOS:
       NOTREACHED();
@@ -495,6 +496,8 @@
       return "http/2+quic/39";
     case CONNECTION_INFO_QUIC_40:
       return "http/2+quic/40";
+    case CONNECTION_INFO_QUIC_41:
+      return "http/2+quic/41";
     case CONNECTION_INFO_HTTP0_9:
       return "http/0.9";
     case CONNECTION_INFO_HTTP1_0:
diff --git a/net/http/http_response_info.h b/net/http/http_response_info.h
index 9757bb47..ef4d4274 100644
--- a/net/http/http_response_info.h
+++ b/net/http/http_response_info.h
@@ -52,6 +52,7 @@
     CONNECTION_INFO_QUIC_38 = 16,
     CONNECTION_INFO_QUIC_39 = 17,
     CONNECTION_INFO_QUIC_40 = 18,
+    CONNECTION_INFO_QUIC_41 = 19,
     NUM_OF_CONNECTION_INFOS,
   };
 
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json
index db5f7c7..afb0a1e 100644
--- a/net/http/transport_security_state_static.json
+++ b/net/http/transport_security_state_static.json
@@ -29031,7 +29031,6 @@
     { "name": "websiteservice.pro", "include_subdomains": true, "mode": "force-https" },
     { "name": "webspotter.nl", "include_subdomains": true, "mode": "force-https" },
     { "name": "wedos.com", "include_subdomains": true, "mode": "force-https" },
-    { "name": "weeblrpress.com", "include_subdomains": true, "mode": "force-https" },
     { "name": "weeknummers.nl", "include_subdomains": true, "mode": "force-https" },
     { "name": "weerstationgiethoorn.nl", "include_subdomains": true, "mode": "force-https" },
     { "name": "wegvielfalt.de", "include_subdomains": true, "mode": "force-https" },
@@ -29224,6 +29223,4043 @@
     { "name": "zxity.ltd", "include_subdomains": true, "mode": "force-https" },
     { "name": "zxity.uk", "include_subdomains": true, "mode": "force-https" },
     { "name": "zypern-firma.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "1100.so", "include_subdomains": true, "mode": "force-https" },
+    { "name": "1921958389.rsc.cdn77.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "0cdn.ga", "include_subdomains": true, "mode": "force-https" },
+    { "name": "49dollaridahoregisteredagent.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "5gb.space", "include_subdomains": true, "mode": "force-https" },
+    { "name": "247a.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "3133780x.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "5432.cc", "include_subdomains": true, "mode": "force-https" },
+    { "name": "7777av.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "3james.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "6543399.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "5piecesofadvice.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "1218641649.rsc.cdn77.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "4x4.lk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "41199.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "29227.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "0-1.party", "include_subdomains": true, "mode": "force-https" },
+    { "name": "256pages.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "555xl.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "1453914078.rsc.cdn77.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "987987.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "1of16.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "10gbit.ovh", "include_subdomains": true, "mode": "force-https" },
+    { "name": "87577.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "888lu.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "100-downloads.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "5533445.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "33445.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "8888av.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "0xdc.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "023sec.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "33scc.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "6633445.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "8.net.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "11scc.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "776573.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "a7m2.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "5w5.la", "include_subdomains": true, "mode": "force-https" },
+    { "name": "605508.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "7f-wgg.cf", "include_subdomains": true, "mode": "force-https" },
+    { "name": "7733445.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "44scc.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "00881919.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "5kraceforals.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "22scc.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "55scc.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "605508.cc", "include_subdomains": true, "mode": "force-https" },
+    { "name": "9ss6.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "6w6.la", "include_subdomains": true, "mode": "force-https" },
+    { "name": "8833445.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "3xx.link", "include_subdomains": true, "mode": "force-https" },
+    { "name": "1nian.vip", "include_subdomains": true, "mode": "force-https" },
+    { "name": "1nfr.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "academicexperts.us", "include_subdomains": true, "mode": "force-https" },
+    { "name": "abmc.gov", "include_subdomains": true, "mode": "force-https" },
+    { "name": "64bitgaming.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "123midterm.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "721av.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "9933445.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "4web-hosting.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "500k.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "4sics.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "517vpn.cn", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aceinstituteonline.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "99buffets.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "888msc.vip", "include_subdomains": true, "mode": "force-https" },
+    { "name": "advancedoneroofing.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "0005aa.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "03-09-2016.wedding", "include_subdomains": true, "mode": "force-https" },
+    { "name": "5ece.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "adamfontenot.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "acceleratenetworks.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "accelerate.network", "include_subdomains": true, "mode": "force-https" },
+    { "name": "0573wk.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "accuritpresence.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "acsihostingsolutions.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "advancedwriters.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "0222aa.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aeradesign.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "0005pay.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "adoriasoft.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "adzie.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "adinariversloveschool.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "acg.mn", "include_subdomains": true, "mode": "force-https" },
+    { "name": "adzuna.co.nz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "adzuna.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "adventureswithlillie.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "adzuna.sg", "include_subdomains": true, "mode": "force-https" },
+    { "name": "abn-consultants.ie", "include_subdomains": true, "mode": "force-https" },
+    { "name": "0005.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "adprospb.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "abcdef.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "affordablepapers.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "048.tv", "include_subdomains": true, "mode": "force-https" },
+    { "name": "africantourer.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "3778xl.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "8003pay.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aestheticdr.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "9118.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "adzuna.at", "include_subdomains": true, "mode": "force-https" },
+    { "name": "1116pay.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "abosav.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aikenpromotions.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "adminforge.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "44957.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "adzuna.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "adamwallington.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "af-internet.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "2stv.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "acpinformatique.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aebian.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "abrakidabra.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "accolade.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "after.digital", "include_subdomains": true, "mode": "force-https" },
+    { "name": "afonso.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "admino.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aimgroup.co.tz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aestore.by", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aim-consultants.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ak-varazdin.hr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "1117.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "abox-kb.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "adware.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "afrikarl.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "alexandros.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "airclass.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ahiru3.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "9995.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "adamas-magicus.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "8azino777.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "adentalsolution.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "alaxyjewellers.co.za", "include_subdomains": true, "mode": "force-https" },
+    { "name": "acperu.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "almavios.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "agreor.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "afavre.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "allscammers.exposed", "include_subdomains": true, "mode": "force-https" },
+    { "name": "001133.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "acluva.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "abi-2017.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aholic.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "abbas.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "africanexponent.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "algebraaec.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "abobuch.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "allsearch.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "alanhuang.name", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aip-marine.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "akul.co.in", "include_subdomains": true, "mode": "force-https" },
+    { "name": "alexander-beck.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "achalay.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "acoustique-tardy.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "allplayer.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aintevenmad.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "akoch.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "amerhd.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "alfaponny.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ahoy.travel", "include_subdomains": true, "mode": "force-https" },
+    { "name": "3dmusiclab.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "andrewdavidwong.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "agalliasis.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "alpha.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "americanmediainstitute.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "alex97000.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "alainmargot.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "anime1video.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "anime1.moe", "include_subdomains": true, "mode": "force-https" },
+    { "name": "andschwa.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "adventures.is", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ampledesigners.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "alusta.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "8003.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "alarmcomplete.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "almatinki.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "anedot.space", "include_subdomains": true, "mode": "force-https" },
+    { "name": "allangirvan.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "alexandre-blond.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "agamsecurity.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "angusmak.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "amiciidogrescue.org.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "alleskomtgoed.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "accuritconsulting.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "alexandermuetzel.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "allthingsfpl.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "anacreon.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "andrei-coman.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "anypeer.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "anfenglish.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "andrefaber.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "anabol.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "alilialili.ga", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aflfreebets.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "allinagency.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "agroglass.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "apiary.store", "include_subdomains": true, "mode": "force-https" },
+    { "name": "apiary.shop", "include_subdomains": true, "mode": "force-https" },
+    { "name": "apiary.clothing", "include_subdomains": true, "mode": "force-https" },
+    { "name": "apiary.blog", "include_subdomains": true, "mode": "force-https" },
+    { "name": "apiary.supplies", "include_subdomains": true, "mode": "force-https" },
+    { "name": "annedaniels.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "amicalecanyon.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "apiary.supply", "include_subdomains": true, "mode": "force-https" },
+    { "name": "apis.moe", "include_subdomains": true, "mode": "force-https" },
+    { "name": "1116.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ambholding-usedcars.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "altstipendiaten.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "amicsdelbus.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "angeloroberto.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aaronmcguire.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "apisyouwonthate.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "apadrinaunolivo.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "appscloudplus.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "animefluxxx.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aminafrance.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "apience.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "apartmentkroatien.at", "include_subdomains": true, "mode": "force-https" },
+    { "name": "archsec.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "antoinemary.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "alize-theatre.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "alpinepubliclibrary.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "albanien.guide", "include_subdomains": true, "mode": "force-https" },
+    { "name": "agsb.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "andreasanti.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ankwanoma.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "amoozesh98.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "antimine.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "agenciafiscal.pe", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aquireceitas.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aide-valais.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "argovpay.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "amb.tf", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ankenbrand.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "abilitycaresoftware.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "arent.kz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aquatechnologygroup.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "alexdaulby.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "arg.zone", "include_subdomains": true, "mode": "force-https" },
+    { "name": "armenians.online", "include_subdomains": true, "mode": "force-https" },
+    { "name": "annetaan.fi", "include_subdomains": true, "mode": "force-https" },
+    { "name": "asd.gov.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "arifp.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aooobo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "appartementmarsum.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "arkacrao.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "alarme-gps.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "annaenemma.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "arabsexi.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "alarmegps.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "arresttracker.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ajnasz.hu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "anipassion.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "api-connect.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "animationsmusicales.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "antama.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "armyofbane.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "apm.com.tw", "include_subdomains": true, "mode": "force-https" },
+    { "name": "amelandadventure.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "assetvault.co.za", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aquitroc.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "alphie.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "anthonyaires.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "atl-paas.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "atlassian.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "amesvacuumrepair.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "asisee.photography", "include_subdomains": true, "mode": "force-https" },
+    { "name": "animalstropic.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "annangela.moe", "include_subdomains": true, "mode": "force-https" },
+    { "name": "artleading.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "austinsutphin.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "arthan.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "alertonline.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "apptoutou.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "asisee.co.il", "include_subdomains": true, "mode": "force-https" },
+    { "name": "asuka.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "artansoft.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "au2pb.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ar-informatique.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "appel-aide.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "asialeonding.at", "include_subdomains": true, "mode": "force-https" },
+    { "name": "atzenchefin.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "airportlimototoronto.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "anons.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "arnaudminable.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aussieservicedown.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aquadonis.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "astaninki.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aquabio.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "asdyx.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "asanger.biz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "armil.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "assumptionpj.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "au-be.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "asra.gr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "atease-salon.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "arikar.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "automationpro.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "apps.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aristocratps.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "armarinhovirtual.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "armazemdaminiatura.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "appleranch.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "awsmdev.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aspatrimoine.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "australianfreebets.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "arnoldkontz-occasions.lu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "avspot.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "art-et-culture.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "andrea-m.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "audiolibri.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ataton.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "auvernet.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "autos-retro-plaisir.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "360live.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "b-boom.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "atk.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "avanet.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "avnet.ws", "include_subdomains": true, "mode": "force-https" },
+    { "name": "assistance-personnes-agees.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "azu-l.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "atelier-coiffure.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "babeleo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "autoxy.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bandarifamily.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bad.pet", "include_subdomains": true, "mode": "force-https" },
+    { "name": "arturszalak.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "autoecoledumontblanc.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "atelieraphelion.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "badrequest.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ballparkbuns.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "atelier-viennois-cannes.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "authorsguild.in", "include_subdomains": true, "mode": "force-https" },
+    { "name": "azu-l.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "atracaosexshop.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "avtogara-isperih.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "alter-news.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "artdeco-photo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "babycamapp.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "austromorph.space", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aveapps.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "avedesk.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "atds.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ateliernihongo.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bangdream.ga", "include_subdomains": true, "mode": "force-https" },
+    { "name": "autostop-occasions.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bakongcondo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "babai.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "antoinemary.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ax25.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "b-services.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "avvcorda.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "barnrats.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bananensap.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "b-ticket.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bambooforest.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bandar303.win", "include_subdomains": true, "mode": "force-https" },
+    { "name": "balcaonet.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "b4z.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "avid.blue", "include_subdomains": true, "mode": "force-https" },
+    { "name": "atraverscugy.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "autoterminus-used.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "awen.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "barlotta.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "audiorental.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "azso.pro", "include_subdomains": true, "mode": "force-https" },
+    { "name": "answers-online.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "baumannfabrice.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "battleboxx.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "autotechschool.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "baby-digne.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "adambryant.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bearingworks.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bdenzer.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "backsideverbier.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "baladecommune.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "balade-commune.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "beekeeper.blog", "include_subdomains": true, "mode": "force-https" },
+    { "name": "beekeeper.clothing", "include_subdomains": true, "mode": "force-https" },
+    { "name": "beekeeper.supplies", "include_subdomains": true, "mode": "force-https" },
+    { "name": "barta.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "barshout.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "baseballrampage.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "baseballwarehouse.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "autocmall.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "baosuckhoedoisong.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "beckerantiques.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "belfastlocks.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "benburwell.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "benfairclough.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aurora-multimedia.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bambambaby.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "balidesignshop.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "around-the-blog.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bariseau-mottrie.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "banned-bitches.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "averam.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "baciu.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "beautyevent.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aqua-fotowelt.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bc-diffusion.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bestessaycheap.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bfam.tv", "include_subdomains": true, "mode": "force-https" },
+    { "name": "batistareisfloresonline.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "beulen.link", "include_subdomains": true, "mode": "force-https" },
+    { "name": "andreamcnett.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bearded.sexy", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bernhard-seidenspinner.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bedandbreakfast.dk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bedandbreakfasteuropa.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bda-boulevarddesairs.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "belewpictures.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bichonfrise.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bghost.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "beichtgenerator.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "amitse.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "betterworldinternational.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "berlin-flirt.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "berthelier.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "better.fyi", "include_subdomains": true, "mode": "force-https" },
+    { "name": "beaute-eternelle.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bentphotos.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "biaggeo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "arfad.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "beyond-infinity.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "beraru.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bewegungsfluss.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "birdbrowser.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bestwarezone.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "biletua.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bedouille.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "biletru.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "belien-tweedehandswagens.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bikkelbroeders.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "binaryappdev.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bikkelbroeders.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "binaryapparatus.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "beraten-entwickeln-steuern.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bibliotekarien.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "beacinsight.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bestbyte.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "becs.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bernhardkau.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "belastingdienst-in-beeld.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bison.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "batipresta.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bike-discount.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "blenderrecipereviews.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "biblioblog.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "belloy.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bladesmith.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "belloy.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bestschools.top", "include_subdomains": true, "mode": "force-https" },
+    { "name": "blizhost.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bijoux.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "biotechware.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bitpoll.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "blackkeg.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bitsum.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bernexskiclub.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bitpoll.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "blackhillsinfosec.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bakersafari.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "b-cyclesshop.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bilalkilic.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bitsync.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "baugemeinschaftbernstein.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "blackberryforums.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "boincstats.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bistrocean.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bikerebel.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bobkoetsier.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bjtxl.cn", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bookingready.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bookmakersfreebets.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bitwrought.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "beexfit.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bnin.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bohyn.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bodyconshop.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "binam.center", "include_subdomains": true, "mode": "force-https" },
+    { "name": "boekenlegger.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bjgongyi.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "batolis.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bradypatterson.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "blumenwiese.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bioligo.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "biogecho.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bookingdeluxesp.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "biogecho.swiss", "include_subdomains": true, "mode": "force-https" },
+    { "name": "booox.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "boschee.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bornfiber.dk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "blue17.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bouw.live", "include_subdomains": true, "mode": "force-https" },
+    { "name": "brentacampbell.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bloginbeeld.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "briansmith.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "boukoubengo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "brailsford.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bou.lt", "include_subdomains": true, "mode": "force-https" },
+    { "name": "braintm.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "boodmo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "blakecoin.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bondarenko.dn.ua", "include_subdomains": true, "mode": "force-https" },
+    { "name": "brettelliff.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bonnant-associes.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "aprpullmanportermuseum.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "brianfoshee.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "braeunlich-gmbh.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bress.cloud", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bouckaert-usedcars.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "boscoyacht.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bls-fiduciaire.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bsidesf.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "biologis.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "breathingblanket.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bsidesf.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "booktracker-org.appspot.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "brenden.net.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "brightonchilli.org.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "botserver.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "boutiquedecanetas.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "browsedns.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bonnant-partners.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "brrd.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bubhub.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "brainfpv.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "boimmobilier.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "brewsouth.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "btserv.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "broerweb.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bsc01.dyndns.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "buckmulligans.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bs.to", "include_subdomains": true, "mode": "force-https" },
+    { "name": "brianlanders.us", "include_subdomains": true, "mode": "force-https" },
+    { "name": "burnerfitness.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "burlapsac.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bulgarien.guide", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bunzy.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "buehnenbande.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bubba.cc", "include_subdomains": true, "mode": "force-https" },
+    { "name": "buergerdialog.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "britelocate.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "buydissertations.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "by1896.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bug.blue", "include_subdomains": true, "mode": "force-https" },
+    { "name": "by1899.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "buypapercheap.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "burroughsid.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "buyessayscheap.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "buyessay.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "buvinghausen.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "byji.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "buyessays.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "byatte.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bretzner.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "brainball.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "c2o-library.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "burckardtnet.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bronetb2b.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bm-i.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "by1898.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bursahpsamsung.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "boyan.in", "include_subdomains": true, "mode": "force-https" },
+    { "name": "buttercupstraining.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bm-immo.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "butarque.es", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ca5.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "caliderumba.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bronwynlewis.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "capekeen.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cake-time.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "billdestler.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cancreate.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "campistry.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "camda.online", "include_subdomains": true, "mode": "force-https" },
+    { "name": "butian518.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bupu.ml", "include_subdomains": true, "mode": "force-https" },
+    { "name": "caferagazzi.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bytecode.no", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bodyworkbymichael.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "camsky.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "businesscentermarin.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cadetsge.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "calleveryday.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "camelservers.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "caerostris.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "brother-printsmart.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "candicecity.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cashati.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cardelmar.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "buronwater.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cashmaxtexas.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "brave-foods.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "brave-foods.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "catchersgear.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cata.ga", "include_subdomains": true, "mode": "force-https" },
+    { "name": "carre-lutz.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cardelmar.es", "include_subdomains": true, "mode": "force-https" },
+    { "name": "byken.cn", "include_subdomains": true, "mode": "force-https" },
+    { "name": "bragaweb.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "careyshop.cn", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cat-blum.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ceres-corp.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "caughtredhanded.co.nz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "carson-aviation-adventures.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cdns.cloud", "include_subdomains": true, "mode": "force-https" },
+    { "name": "casasuleletrodomesticos.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ccv.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "carringtonrealtygroup.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "camel2243.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "careplasticsurgery.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cevo.com.hr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chad.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "boomsaki.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "boomsakis.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ccv.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ccv.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cafefresco.pe", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cfneia.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "carsimplon.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "celigo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cdda.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ccv-deutschland.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cc-brantomois.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "catburton.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chaurocks.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "charmingsaul.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chatbots.email", "include_subdomains": true, "mode": "force-https" },
+    { "name": "celebphotos.blog", "include_subdomains": true, "mode": "force-https" },
+    { "name": "challengeskins.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chaoticlaw.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cgerstner.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "channeladam.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cheapwritinghelp.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cheapwritingservice.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "checkmateshoes.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ceres1.space", "include_subdomains": true, "mode": "force-https" },
+    { "name": "campingdreams.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "checkmatewebsolutions.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chaplain.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cheapessay.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "catalogoreina.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cheah.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "celiendev.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chordso.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "charitylog.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "celuliteonline.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "centreoeil.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "c3-compose.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chaletpierrot.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chazalet.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chronic101.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "casbia.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "churchlinkpro.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "catharisme.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "catharisme.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chemicalguys-ruhrpott.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chinwag.im", "include_subdomains": true, "mode": "force-https" },
+    { "name": "catharisme.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cheapestgamecards.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chevymotor-occasions.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chrispstreet.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chesspoint.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cityoftitans.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chmurakotori.ml", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chunk.science", "include_subdomains": true, "mode": "force-https" },
+    { "name": "christiangehring.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chipcore.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "championnat-romand-cuisiniers-amateurs.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cityoftitansmmo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ciner.is", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ciss.ltd", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chainedunion.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chiamata-aiuto.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chabaojia.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chrstn.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cipri.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cloud.fail", "include_subdomains": true, "mode": "force-https" },
+    { "name": "clearsky.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cianmawhinney.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "carinsurance.es", "include_subdomains": true, "mode": "force-https" },
+    { "name": "clashersrepublic.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chaldeen.pro", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cip.md", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cdn.sx.cn", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chocodecor.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "carbono.uy", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cinafilm.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "claimnote.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cocalc.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "clingout.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "codes.pk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chmsoft.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "collablynk.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ci5.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cloudtskr.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "codercy.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "citimall.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cogala.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "citcuit.in", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cloveros.ga", "include_subdomains": true, "mode": "force-https" },
+    { "name": "coinlist.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "codeux.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "codesyncro.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "codeux.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "communityflow.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "clubfamily.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "collegepaperworld.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "colorsbycarin.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "clorik.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cmpr.es", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cobaltlp.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chronoproject.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cobaltgp.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "computehealth.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "coincealed.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chocolat-suisse.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cloudfren.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cie-theatre-montfaucon.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cncbazar365.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "conservados.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chsh.moe", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cielbleu.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "comparesoft.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cloppenburg-automobil.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "clubscannan.ie", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cloppenburg-autmobil.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "conmedapps.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "colasjourdain.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chiropratique-neuchatel.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "coolbutbroken.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "collard.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chirosphere.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cocquyt-usedcars.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cloud2go.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "capachitos.cl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chiro-neuchatel.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "computeracademy.co.za", "include_subdomains": true, "mode": "force-https" },
+    { "name": "continuation.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "comyuno.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cloud.bugatti", "include_subdomains": true, "mode": "force-https" },
+    { "name": "coastline.net.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chiropraticien-neuchatel.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "copycrafter.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "coorpacademy.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "computernetwerkwestland.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "contentpass.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "corpkitnw.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "coreapm.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "coreapm.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "corksoncolumbus.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cloudtropia.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "codenlife.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cloudopt.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "compubench.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "couponcodesme.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "controleer-maar-een-ander.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cosmofunnel.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cptoon.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "clindoeilmontagne.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cestunmetier.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chaifeng.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "conceptatelier.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "corlinde.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "claudia-urio.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "comunidadmontepinar.es", "include_subdomains": true, "mode": "force-https" },
+    { "name": "coolvox.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cpcheats.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cometonovascotia.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "core-concepts.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "consejosdenutricion.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "conkret.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cncrans.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "condroz-motors.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "claireidrac.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "conaudisa.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "comefollowme2016.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "connectmy.car", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ctj.im", "include_subdomains": true, "mode": "force-https" },
+    { "name": "coptic-treasures.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "compagniemartin.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "crossfunctional.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "creative-coder.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "curiouscat.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cosmiatria.pe", "include_subdomains": true, "mode": "force-https" },
+    { "name": "conkret.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "colson-occasions.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "conkret.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "colarelli.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "conformist.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "conkret.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "crisp.chat", "include_subdomains": true, "mode": "force-https" },
+    { "name": "conkret.in", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cross-led-sign.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "creeks-coworking.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "costa-rica-reisen.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "crunchy.rocks", "include_subdomains": true, "mode": "force-https" },
+    { "name": "congobunkering.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cuongthach.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "crows.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "currynissanmaparts.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "customwritingservice.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "chasafilli.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cour4g3.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cygnatus.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "creativefreedom.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "craftyphotons.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "coup-dun-soir.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "costa-rica-reisen.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cultivo.bio", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cydetec.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "curvesandwords.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "coroasdefloresonline.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "creditstar.es", "include_subdomains": true, "mode": "force-https" },
+    { "name": "crox.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cqn.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cryptofan.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "d3njjcbhbojbot.cloudfront.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cypressinheritancesaga.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "counter-team.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cruikshank.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ctnguyen.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ctnguyen.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "d3x.pw", "include_subdomains": true, "mode": "force-https" },
+    { "name": "correiodovale.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "da8.cc", "include_subdomains": true, "mode": "force-https" },
+    { "name": "damaged.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "data.world", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dashnearby.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cssai.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "crystalmate.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "culture-school.top", "include_subdomains": true, "mode": "force-https" },
+    { "name": "crazyker.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cubile.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cubia4.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "d4wson.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cryptography.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "create-ls.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cryptology.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "csinterstargeneve.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "daisuki.pw", "include_subdomains": true, "mode": "force-https" },
+    { "name": "davetempleton.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "d1ves.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cotonmusic.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "danwin1210.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cyberspace.today", "include_subdomains": true, "mode": "force-https" },
+    { "name": "darookee.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "crawl.report", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cordeydesign.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "daktarisys.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cspeti.hu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "datacubed.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "creaescola.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cursuri-de-actorie.ro", "include_subdomains": true, "mode": "force-https" },
+    { "name": "darkfire.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cwningen.cymru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cyberspace.community", "include_subdomains": true, "mode": "force-https" },
+    { "name": "darkanzali.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "darylcumbo.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cutner.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "davidstuff.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cospol.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cyumus.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "darioackermann.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dallaslu.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cs2016.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "defender-pro.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dailykos.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dalb.in", "include_subdomains": true, "mode": "force-https" },
+    { "name": "daw.nz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "contraspin.co.nz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ddocu.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "deflumeri.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "davie3.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dai.top", "include_subdomains": true, "mode": "force-https" },
+    { "name": "delahrzolder.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cutelariafiveladeouro.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dcw.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dctxf.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "daoro.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "danotage.tv", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dbyz.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "deniszczuk.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "darshnam.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cypherpunk.at", "include_subdomains": true, "mode": "force-https" },
+    { "name": "davewardle.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dawnbringer.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "demo-server.us", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dermot.org.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dchatelain.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "d-academia.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "davo-usedcars.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "deepsouthsounds.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "d-parts24.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dennisvandenbos.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "deepvalley.tech", "include_subdomains": true, "mode": "force-https" },
+    { "name": "danskringsporta.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "defxing.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "depaddestoeltjes.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "decock-usedcars.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "diamondpkg.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dental-misaki.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dhaynes.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "demotivatorbi.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "delbecqvo.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "diabolic.chat", "include_subdomains": true, "mode": "force-https" },
+    { "name": "decofire.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "depone.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "devlamvzw.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "desila.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "destileria.net.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dalmatiersheusden.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "devalps.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "depotter-usedcars.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "deliandiver.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "desktopfx.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dc-occasies.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "developersclub.website", "include_subdomains": true, "mode": "force-https" },
+    { "name": "depth-co.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "deloittequant.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "diccionarioabierto.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "coteries.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "digitaldatacenter.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dicionariopopular.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "datumou-osusume.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dillynbarber.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "diwei.vip", "include_subdomains": true, "mode": "force-https" },
+    { "name": "digitaldeli.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dissertationhelp.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "designskin.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "degata.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "devjack.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "demeyere-usedcars.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dhl-smart.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "devillers-occasions.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "digitalewelten.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "digitaltechnologies.ltd.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dermatologie-morges.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "diskbit.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "discha.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dieselanimals.lt", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dnsbird.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "detalhecomercio.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dojin.nagoya", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dimes.com.tr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dnsbird.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "docs.re", "include_subdomains": true, "mode": "force-https" },
+    { "name": "doc8643.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "domynetwork.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "domycasestudy.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "domyassignments.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "domyessays.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "domycoursework.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dirko.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "domypapers.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "diodo.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "domycreativewritings.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dogft.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "diamondcare.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "digiworks.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "domainsilk.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "domydissertations.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "domyessay.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "domyhomeworks.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dirtycat.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "domscripting.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "domyreview.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dotneko.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "domyspeech.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "diamsmedia.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "disc.uz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "domyresearchpaper.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dominikanskarepubliken.guide", "include_subdomains": true, "mode": "force-https" },
+    { "name": "domytermpaper.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "domythesis.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "djangogolf.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dewapress.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "disrupters.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dm4productions.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "drdipilla.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "doujin.nagoya", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dmenergy.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "disinisharing.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dog-blum.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dessinemoilademocratie.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "disadattamentolavorativo.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "doomoo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ddepot.us", "include_subdomains": true, "mode": "force-https" },
+    { "name": "doop.im", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dperson.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dfmn.berlin", "include_subdomains": true, "mode": "force-https" },
+    { "name": "diadorafitness.es", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dogoo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "diadorafitness.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dogear.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "diagonale-deco.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dmdre.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cmn-group.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "domyzitrka.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "danandrum.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dryan.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "drybasementkansas.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dpg.no", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dugnet.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dugnet.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dontpayfull.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dugnet.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "droidim.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dugnet.tech", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dr-becarelli-philippe.chirurgiens-dentistes.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cyberprey.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dreamhostremixer.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "driver.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dkcomputers.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dopsi.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "e-tech-solution.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dgitup.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dont.re", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dorkfarm.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dugnet.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "drakenson.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dundalkdonnie.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "donnachie.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "easelforart.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dovro.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ea2drocks.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "eat-sleep-code.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "drupal123.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "e-worksmedia.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "donabeneko.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "driverprofiler.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "donttrust.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dreamithost.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "droidhere.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "deepspace.dedyn.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "echosim.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "duelsow.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dsancomics.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dormebebe.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "doveholesband.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "do-prod.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dullapp.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "droidwave.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ebertek.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dianurse.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "echofoxtrot.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "drageeparadise.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "drabim.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "edtechwebb.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "drybjed.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "echoanalytics.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dejw.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "drastosasports.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "e3q.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "durdle.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "divvymonkey.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "eesistumine2017.ee", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dracon.es", "include_subdomains": true, "mode": "force-https" },
+    { "name": "effectivepapers.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dynx.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "duh.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "digitalcraftmarketing.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dtdsh.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "eeetrust.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "duriaux-dentiste.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "elite-box.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "elhamadimi.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "djbet.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "divvyradio.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "edlinus.cn", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dynamic-networks.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ecoskif.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "elifesciences.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "efaas.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "emeraldonion.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "emupedia.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "eidolons.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "egeozcan.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "encouragemarketing.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ecirtam.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "electragirl.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "elosrah.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "eifelindex.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dtx.sk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "eljef.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "effectivecoffee.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "emergencyessay.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "eladgames.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "east-line.su", "include_subdomains": true, "mode": "force-https" },
+    { "name": "emcspotlight.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dikshant.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dssale.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "devlatron.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ehandel.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "effizienta.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "envescent.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dupisces.com.tw", "include_subdomains": true, "mode": "force-https" },
+    { "name": "die-borts.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "elliff.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dovenzorgmalawi.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "efa-football.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dvnatura.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "emil.click", "include_subdomains": true, "mode": "force-https" },
+    { "name": "elektro-roth.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "eolme.ml", "include_subdomains": true, "mode": "force-https" },
+    { "name": "drlazarina.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "embox.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "elinvention.ovh", "include_subdomains": true, "mode": "force-https" },
+    { "name": "eleusis-zur-verschwiegenheit.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "efflam.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "eled.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "eickhof.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "envoyglobal.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "eickhof.us", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ecoledusabbat.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "epiphyte.network", "include_subdomains": true, "mode": "force-https" },
+    { "name": "eigenbubi.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "elternverein-utzenstorf.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "edgar.cloud", "include_subdomains": true, "mode": "force-https" },
+    { "name": "elsvanderlugt.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "enjoyphoneblog.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ecolife-vrn.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "elpay.kz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "erikheemskerk.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "environmentkirklees.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "drivingtestpro.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dubrovnik-dental.clinic", "include_subdomains": true, "mode": "force-https" },
+    { "name": "essaypro.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "esagente.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "essaylib.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "essaywriting.biz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "escortdisplay.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "emeliefalk.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "erwinschmaeh.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "efeen.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "enet-navigator.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "essayhave.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "entreprise-toiture-clement.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "estafallando.mx", "include_subdomains": true, "mode": "force-https" },
+    { "name": "epmcentroitalia.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "estafallando.es", "include_subdomains": true, "mode": "force-https" },
+    { "name": "engarde.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "elodieclerc.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "essenceofvitalitydetox.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "essayforsale.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "emivauthey.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "eltern-verein.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "economies.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "emond-usedcars.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ellevit.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "dynts.pro", "include_subdomains": true, "mode": "force-https" },
+    { "name": "etaoinwu.win", "include_subdomains": true, "mode": "force-https" },
+    { "name": "enemiesoflight.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "epic-vistas.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ersa-shop.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "epic-vistas.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "epistas.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "epicvistas.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "evanfiddes.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "embassycargo.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "estland.guide", "include_subdomains": true, "mode": "force-https" },
+    { "name": "everain.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "epicvistas.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ebop.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "eworksmedia.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "exeintel.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "evolutionpets.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "energie-sante.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "example.wf", "include_subdomains": true, "mode": "force-https" },
+    { "name": "evilarmy.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "epistas.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "etienne.cc", "include_subdomains": true, "mode": "force-https" },
+    { "name": "epossystems.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "eternalabyss.ml", "include_subdomains": true, "mode": "force-https" },
+    { "name": "echoworld.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ethiobaba.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ethicsburg.gov", "include_subdomains": true, "mode": "force-https" },
+    { "name": "evertonarentwe.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "esquirou-trieves.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "evrica.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "expowerhps.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "eron.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "essentiel-physique.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "entrecieletpierres.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ergovitanet.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "esteticanorte.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "etangs-magazine.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "famousbirthdays.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "extensiontree.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "example.sc", "include_subdomains": true, "mode": "force-https" },
+    { "name": "exaplac.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "exmoe.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "exploravacations.in", "include_subdomains": true, "mode": "force-https" },
+    { "name": "exembit.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "etoile-usedcars.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "etre-soi.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "eth-faucet.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "falconwiz.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "essteebee.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "faberusa.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "extradesktops.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "evodation.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "eteapparel.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fashionunited.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ewallet-optimizer.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "exvs.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "facilitiessurvey.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "espacetemps.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fashionunited.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "evidencebased.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ezwritingservice.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "faithmissionaries.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "efag.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "etudesbibliques.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "exceed.global", "include_subdomains": true, "mode": "force-https" },
+    { "name": "espectro.org.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fantasticcleaners.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "farces.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ecococon.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "evidenceusa.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "esp-berlin.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "feldhousen.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fernandomiguel.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ethicaltek.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "faulty.equipment", "include_subdomains": true, "mode": "force-https" },
+    { "name": "farm24.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "euroalter.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fads-center.online", "include_subdomains": true, "mode": "force-https" },
+    { "name": "exo.do", "include_subdomains": true, "mode": "force-https" },
+    { "name": "faxite.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "etudesbibliques.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fabienne-roux.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "faluninfo.ba", "include_subdomains": true, "mode": "force-https" },
+    { "name": "feigling.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "etudesbibliques.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "felixbarta.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fermanacuratampaparts.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fireboxfood.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "findthatnude.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fiam.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fakeapple.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ferienwohnungen-lastminute.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fireinthedeep.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "feilen.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fam-weyer.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "farrel-f.id", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fcforum.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fjharcu.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fensdorf.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fixmyglitch.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fishermailbox.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "farkas.bz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "faszienrollen-info.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "filme-onlines.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fliino.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "emilyjohnson.ga", "include_subdomains": true, "mode": "force-https" },
+    { "name": "farmaciaformula.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "environment.ai", "include_subdomains": true, "mode": "force-https" },
+    { "name": "flapoverspeed.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fefelovalex.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "financejobs.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "firmament.space", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fastbackmbm.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "filoitoupediou.gr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "finvantage.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "followback.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "florianschmitt.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "faraslot8.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fassi-sport.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "faraslot8.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fleursdesoleil.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "feisim.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "eriador.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fetclips.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "florentynadawn.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "followersya.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fieldtalk.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "flumble.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fornoreason.net.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "filmserver.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "firecry.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "flyssh.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fougner.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "eswap.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "filo.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fini-de-jouer.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "flagshop.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fonseguin.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fidelis-it.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "flanga.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fidelis-it.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fiodental.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "frankyan.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fourdesignstudio.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fine-services.paris", "include_subdomains": true, "mode": "force-https" },
+    { "name": "first4it.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ffta.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "foscamcanada.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "freelance.guide", "include_subdomains": true, "mode": "force-https" },
+    { "name": "exploodo.rocks", "include_subdomains": true, "mode": "force-https" },
+    { "name": "foxyslut.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "foto-roma.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fraselab.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "flyt.online", "include_subdomains": true, "mode": "force-https" },
+    { "name": "freaksites.dk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "frsis2017.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ennea-mediation.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "eqib.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "formula-ot.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "foodsouvenirs.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "foto-robitsch.at", "include_subdomains": true, "mode": "force-https" },
+    { "name": "forty2.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "folkadelic.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "freshmaza.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fromthesoutherncross.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "freebookmakerbets.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "freegame-mugen.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "flucke-creation.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "foryouandyourcustomers.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "funny-joke-pictures.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "freimeldungen.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "flucke-creation.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "flokinet.is", "include_subdomains": true, "mode": "force-https" },
+    { "name": "eccux.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "freifunk-nrw.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "franklinhua.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "friller.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fs-fitness.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "feuetgloire.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "format-paysage.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "freergform.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fussell.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gafunds.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "futrou.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "forge-goerger.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gadabit.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "funniestclip.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fsck.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "g77.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fundchan.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "g2-inc.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gabriel.to", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gagne.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "funkes-ferien.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "frino.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gdb-tutorial.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "friezy.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "francoislepage.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "funnybikini.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fukakukeiba.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fid-elite.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "froehlich.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "freedomflotilla.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gala.kiev.ua", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gatewaybridal.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fokan.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fsck.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "foerster-kunststoff.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "francois-occasions.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ftgho.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fwest98.ovh", "include_subdomains": true, "mode": "force-https" },
+    { "name": "geh.li", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fuelingyourdreams.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gautham.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gamekeysuche.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "espigol.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "g-i-s.vn", "include_subdomains": true, "mode": "force-https" },
+    { "name": "freifamily.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "geopals.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gebn.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fusa-miyamoto.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gdgrzeszow.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fussball-xxl.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "forward-fly-fishing.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fit-4u.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gemsoftheworld.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "geekles.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "geass.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "g3dev.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gamenerd.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "genesismachina.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gginin.today", "include_subdomains": true, "mode": "force-https" },
+    { "name": "geekzone.co.nz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gethow.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gestormensajeria.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "erf-neuilly.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "frtrains.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "getyourphix.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gachter.name", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gentoo-blog.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "georgebrighton.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "george-brighton.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gallun-shop.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gero.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "galeriadobimba.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "genusshotel-riegersburg.at", "include_subdomains": true, "mode": "force-https" },
+    { "name": "geldimblick.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "getmerch.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gamblersgaming.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gegeco.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "getfilterlive.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "geekmind.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fumerolles.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "globalelite.black", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gleanview.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "getyeflask.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "flemingtonaudiparts.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gerald-zojer.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "girlsforum.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "getyou.onl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "globalnomadvintage.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gmc.uy", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gnucashtoqif.us", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gnosticjade.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gidea.nu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gevaulug.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ghaglund.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "geld-im-blick.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "glahcks.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "goemail.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "genealorand.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "glob-coin.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gmx.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "geektopia.es", "include_subdomains": true, "mode": "force-https" },
+    { "name": "georgescarryout.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gmx.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "geoscope.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gmx.es", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ginniemae.gov", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gelis.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gapfa.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gottfridsberg.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fysiovdberg.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "glutenfreelife.co.nz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gmx.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "er-music.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "goffrie.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "grande.coffee", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gigin.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "grayhatter.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gentianes.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "festival.house", "include_subdomains": true, "mode": "force-https" },
+    { "name": "galak.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gfxbench.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "goldfelt.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "givastar.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gpalabs.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gendundrupa.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ginionusedcars.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gravityformspdfextended.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gileadpac.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "goup.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "grayson.sh", "include_subdomains": true, "mode": "force-https" },
+    { "name": "global.hr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gigtroll.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gmanukyan.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gronau-it-cloud-computing.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "goup.com.tr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gillesmorelle.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gagygnole.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "freesourcestl.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gmat.ovh", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gioielleriamolena.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "global-office.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gregoryrealestategroup.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "geneve-naturisme.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gilmoreid.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "govtjobs.blog", "include_subdomains": true, "mode": "force-https" },
+    { "name": "grandefratellonews.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gmx.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gmx.at", "include_subdomains": true, "mode": "force-https" },
+    { "name": "groentefruitzeep.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "guardiansoftheearth.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gmx.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "goldenbadger.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "grasmark.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gst.priv.at", "include_subdomains": true, "mode": "force-https" },
+    { "name": "groentefruitzeep.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hackerone-ext-content.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "grantdb.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gwrtech.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "grayclub.co.il", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gruwa.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "frontline.cloud", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gta5voice.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gst.name", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gmx.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hacker8.cn", "include_subdomains": true, "mode": "force-https" },
+    { "name": "greuel.online", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gw2oracle.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gscloud.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "fcprovadia.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gruebebraeu.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "glbg.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "grawe-blog.at", "include_subdomains": true, "mode": "force-https" },
+    { "name": "guniram.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hainoni.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gootax.pro", "include_subdomains": true, "mode": "force-https" },
+    { "name": "greatideahub.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gwsec.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "guidechecking.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "harukakikuchi.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gratitudeabundancepassion.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gvchannel.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "grolimur.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "habeo.si", "include_subdomains": true, "mode": "force-https" },
+    { "name": "guichet-qualifications.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gritte.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "haze.sucks", "include_subdomains": true, "mode": "force-https" },
+    { "name": "goatcloud.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "grmp.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "greggsfoundation.org.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gloomyspark.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gugert.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "harveyauzorst.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hammer-schnaps.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gedankenworks.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hanfox.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "handyglas.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gynaecology.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "haruue.moe", "include_subdomains": true, "mode": "force-https" },
+    { "name": "guichet-entreprises.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "globalnewsdaily.cf", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gustiaux.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hdguru.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gregoirow.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "healthlabs.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "haschrebellen.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "harion.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "harmfarm.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "heavenlyseals.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hen.ne.ke", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hackingand.coffee", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hadaly.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "goranrango.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "haemmerle.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hellomouse.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "gvpt.sk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hanashi.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hexapt.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hd1tj.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "groupghistelinck-cars.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "heroicpixel.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hack.sb", "include_subdomains": true, "mode": "force-https" },
+    { "name": "helenaknowledge.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "heinzelmann.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "heartbeat24.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "henneke.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "growingmetrics.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "henhenlu.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "harveymilton.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "healththoroughfare.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hetmer.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "guelo.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hanakaraku.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hetmer.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "healthycod.in", "include_subdomains": true, "mode": "force-https" },
+    { "name": "herzig.cc", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hansmund.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hd0222.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "heribe-maruo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hd8003.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71806.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71801.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71812.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "headlinepublishing.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg718.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hd887700.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71803.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71802.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71809.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71807.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71835.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hd0385.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hd887766.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "heimatverein-eitensheim.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg0088.vip", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71811.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71819.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71815.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "helber-it-services.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hickorywinecellar.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71836.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71833.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hermanbrouwer.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hingle.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hd88599.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71822.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71858.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71805.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71813.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71839.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hindmanfuneralhomes.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hd3778.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hd001133.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "herrderzeit.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hitrek.ml", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71857.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71837.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hiraku.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71852.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hd771122.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71851.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71860.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "holytransaction.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hga8687.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "goiaspropaganda.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71856.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hd881133.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hga8685.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71863.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hl7999.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hightower.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hga8587.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hga8758.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hatarisecurity.co.ke", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71861.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "highland-webcams.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "houraiteahouse.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hga8689.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "holodeck.us", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hokify.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "happyagain.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hokify.at", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hga8586.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hokify.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hga8757.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "highlegshop.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg71850.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "honeyhaw.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hollo.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hootworld.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hygo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hopglass.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hopglass.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hizzacked.xxx", "include_subdomains": true, "mode": "force-https" },
+    { "name": "howtogeekpro.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hinrich.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hostingfirst.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hoiku-navi.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "humanity.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hockeyapp.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hostingpunt.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hydronyx.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ibin.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hg881.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hillsboroccpa.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hqq.tv", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hotelmadhuwanvihar.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "huahinpropertylisting.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hotel-le-vaisseau.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "humpen.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ibsglobal.co.za", "include_subdomains": true, "mode": "force-https" },
+    { "name": "i-red.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ibsafrica.co.za", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hype.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hypnos.hu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hoikuen-now.top", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hyperbolic-mayonnaise-interceptor.ovh", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hte.ovh", "include_subdomains": true, "mode": "force-https" },
+    { "name": "icebound.win", "include_subdomains": true, "mode": "force-https" },
+    { "name": "holgerlehner.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "holydragoon.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hyderabadonlinegifts.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hydrodipcenter.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "home-cloud.online", "include_subdomains": true, "mode": "force-https" },
+    { "name": "i1place.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hugolynx.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "horodance.dk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hvdbox.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "i-geld.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "icebound.cc", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ibps.blog", "include_subdomains": true, "mode": "force-https" },
+    { "name": "iemb.cf", "include_subdomains": true, "mode": "force-https" },
+    { "name": "i4m1k0su.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ilweb.es", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ict-crew.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ictcareer.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "idrycleaningi.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "idrinktoomuch.coffee", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ideaplus.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hottheme.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "helvella.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "i-stuff.site", "include_subdomains": true, "mode": "force-https" },
+    { "name": "imperial-legrand.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "idranktoomuch.coffee", "include_subdomains": true, "mode": "force-https" },
+    { "name": "imagebin.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ihollaback.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "imperdin.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "imperdintechnologies.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "huongquynh.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "huitaodang.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "iaeste.no", "include_subdomains": true, "mode": "force-https" },
+    { "name": "imawhale.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "imperiumnova.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "inderagamono.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hannes-speelgoedencadeautjes.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ingber.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hik-cloud.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "implicitdenial.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "imkerverein-moenchswald.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "infinitegroup.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "indiegame.space", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hypotheques24.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ilektronika-farmakeia-online.gr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "inmateintake.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "iga-semi.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "indogermanstartup.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "igamingforums.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "immersion-pictures.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "icabanken.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ievgenialehner.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "insidethefirewall.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ileat.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "icaforsakring.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "informationrx.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "henrikwelk.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "innovativeideaz.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "immobiza.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "innovativebuildingsolutions.co.za", "include_subdomains": true, "mode": "force-https" },
+    { "name": "holidayincotswolds.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "igimusic.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "icsadviseurs.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ingalabs.hu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "internetbugbounty.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "indecipherable.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ingjobs.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "indogermantrade.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "idc-business.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "industrybazar.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "huguesditciles.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "investigazionimoretti.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ifan.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ibrom.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "infocity-tech.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "irmgardkoch.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "imanageproducts.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "inoxio.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "infinity.to", "include_subdomains": true, "mode": "force-https" },
+    { "name": "intradayseasonals.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "intellar.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "irugs.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "instagramtweet.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "int-ext-design.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "innolabfribourg.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "imagerive.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ifosep.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "inventtheworld.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "irugs.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "interlingvo.biz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ingresscode.cn", "include_subdomains": true, "mode": "force-https" },
+    { "name": "inlink.ee", "include_subdomains": true, "mode": "force-https" },
+    { "name": "invinsec.cloud", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hockeymotion.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "istheservicedown.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "istheservicedowncanada.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "istheservicedown.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "image.tf", "include_subdomains": true, "mode": "force-https" },
+    { "name": "itsdcdn.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hydroagro.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "itsmejohn.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "impakho.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "iskogen.nu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "itis.gov", "include_subdomains": true, "mode": "force-https" },
+    { "name": "iskai.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ichasco.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "interview-suite.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ilamparas.mx", "include_subdomains": true, "mode": "force-https" },
+    { "name": "islief.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ipal.tel", "include_subdomains": true, "mode": "force-https" },
+    { "name": "interboursegeneva.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "intimici.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "intermax.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jackyliao123.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jackingramnissanparts.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "iris-design.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "holz.nu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "james-loewen.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "iwpbk.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "isdn.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ivi-co.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ip-hahn.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "j-eck.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "internetinhetbuitengebied.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jabergrutschi.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "horizonshypnosis.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "it-labor.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "insolent.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jaberg-rutschi.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "innwan.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "inventaire.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "iteha.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jeremyc.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "iguana.com.ec", "include_subdomains": true, "mode": "force-https" },
+    { "name": "its-future.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jhaveri.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ixh.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jdsf.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jbt-stl.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "iruarts.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jhwestover.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "janking.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "javilacat.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jamesforman.co.nz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jaguarlandrover-asse.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jamesachambers.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jaguarlandrover-occasions.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jakobkrigovsky.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "itpro-mg.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jimenacocina.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jediweb.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "iwex.swiss", "include_subdomains": true, "mode": "force-https" },
+    { "name": "improklinikken.dk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jaion.ml", "include_subdomains": true, "mode": "force-https" },
+    { "name": "italianshoemanufacturers.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jobtestprep.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jeffreymagee.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jenprace.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jmarciniak.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "johnrockefeller.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "impacter.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "investir.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jasonmili.online", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jardinderline.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jonathanreyes.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jardin-exotique-rennes.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jeremy.hu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "innoventure.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "joelmunch.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "josefottosson.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "joshrickert.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jmbelloteau.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jbs-jardins.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jobsuchmaschine.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jobs4sales.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jelena-adeli.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jobs.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "joelleandpeter.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jobwinner.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "joelcoustrain.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "josc.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "joelle.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jet-stream.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "juegosycodigos.mx", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jrxpress.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "johnmorganpartnership.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jkng.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "joelgonewild.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "joblife.co.za", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jnjdj.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jixun.moe", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jumpinchat.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jordikroon.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jsbentertainment.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "izuba.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jongcs.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jasonradin.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jvn.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jungleducks.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jtwp470.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "julianickel.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "joi-dhl.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "juliawebber.co.za", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jornalalerta.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "joyjohnston.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jorovik.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "johnfulgenzi.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "just-pools.co.za", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jskoelliken.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jasongerber.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kakolightingmuseum.or.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kasnoffskinclinic.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jyggen.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kaydan.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "je-vends.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jsevilleja.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "keb.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jobtestprep.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "k1cp.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jonathanmassacand.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "hostfuture.co.in", "include_subdomains": true, "mode": "force-https" },
+    { "name": "keb.net.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kamikaichimaru.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kerebro.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jbrowndesign.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kayakabovegroundswimmingpools.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jptun.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "keepaa.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kai-ratzeburg.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "issasfrissa.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kaltenbrunner.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kaamoscreations.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kieranweightman.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kickedmycat.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "justgalak.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kevinpirnie.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kazy111.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jstelecom.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jobtestprep.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kevinmorssink.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kedibizworx.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kenalsworld.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kaka.farm", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kelmarsafety.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kiraku.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kickasstorrents.gq", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kiapartsdepartment.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kinozal-tv.appspot.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "juridoc.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kazuhirohigashi.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "karlic.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kanscooking.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "k-pture.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jsjyhzy.cc", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jouetspetitechanson.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "keishiando.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kanganer.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kimana.pe", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jwschuepfheim.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kina.guide", "include_subdomains": true, "mode": "force-https" },
+    { "name": "keepiteasy.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kingofshooting.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ko.si", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kaanduman.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kiehls.pt", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kelm.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "keezin.ga", "include_subdomains": true, "mode": "force-https" },
+    { "name": "julianskitchen.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "klssn.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kolin.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kanuvu.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "knegten-agilis.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kleinsys.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kissgyms.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kosaki.moe", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kevyn.lu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kanzlei-wirtschaftsrecht.berlin", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kogak.ninja", "include_subdomains": true, "mode": "force-https" },
+    { "name": "katata-kango.ac.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "konosuke.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "karlzotter.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kplasticsurgery.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jemangeducheval.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kominfo.go.id", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jief.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "johnnybsecure.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kleinserienproduktion.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kiteschoolzandvoort.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "koptev.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kode-it.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kylebaldw.in", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kitashop.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kiteadventure.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "krugermillions.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kangkai.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kuruppa.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kolizaskrap.bg", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kovspace.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "knight-industries.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kpop.re", "include_subdomains": true, "mode": "force-https" },
+    { "name": "labrasaq8.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "koalapress.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ksukelife.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ktsee.eu.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kirrie.pe.kr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "laflash.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "koningskwartiertje.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "khoury-dulla.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kupimlot.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kwat.chat", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kuba.guide", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kolja-engelmann.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lancelafontaine.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kiteschooledam.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kominfo.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kuma.es", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kiteschoolamsterdam.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lakefrontlittleelm.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "koyaanis.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kursprogramisty.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kiteschoolijmuiden.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kteen.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "la-serendipite.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lafayette-rushford.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kode.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ladylucks.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kuko-crews.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "krag.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kruegerrand-wert.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "latterdaybride.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kundo.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "laurelspaandlash.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lanceyip.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jordanstrustcompany.cn", "include_subdomains": true, "mode": "force-https" },
+    { "name": "la-ganiere.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lasarmas.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "laracode.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "learningis1.st", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kobieta.guru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lastharo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "latremebunda.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lavenderx.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kyoto-k9.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lat.sk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "leetcode.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kyoto-mic.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kpmgpublications.ie", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lamiaposta.email", "include_subdomains": true, "mode": "force-https" },
+    { "name": "latemodern.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lazyclock.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kiwi.digital", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lelehei.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lenkunz.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "leowkahman.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "leech360.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lanroamer.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lazyboston.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "koscielniak-nieruchomosci.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lawn-seeds.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "landbetweenthelakes.us", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kiwipayment.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kiwi.global", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lewdawson.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lenyip.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "launchpad-app2.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lernerspersonalinjury.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lapassiondutrading.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "labella-umbrella.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lenyip.works", "include_subdomains": true, "mode": "force-https" },
+    { "name": "learnerdriving.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "laled.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "latabledebry.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kiwiplace.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "klaim.us", "include_subdomains": true, "mode": "force-https" },
+    { "name": "le0.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lejardindesmesanges.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "laruga.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "legal.farm", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lensual.space", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lewisseals.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lanbroa.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "levanscatering.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lilaccakeboutique.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kiwipayments.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lexiphanic.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "levelcheat.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lewisdatasecurity.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lilismartinis.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "josepbel.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "laemen.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lheinrich.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "leoandpeto.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "letsgetchecked.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lightworkerandempathsupport.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lcht.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "liquidinternet.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "khlee.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lets-ktai.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lesquatredauphins.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "limeburst.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lilygreen.co.za", "include_subdomains": true, "mode": "force-https" },
+    { "name": "legendesdechine.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "linky.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lichess4545.tv", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lichess4545.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "likenosis.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lingeriesilhouette.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lightning-ashe.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lapotagere.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "le-page.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lidl-holidays.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "leponton-lorient.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "laemen.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "librairie-asie.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jordanstrustcompany.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "locker3.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "latitudesign.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lidl-shop.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "locker.email", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lithianissaneugeneparts.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "livepaperhelp.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "livekort.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "laforetenchantee.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lezard-com.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lexxyn.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lacledor.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "laclefdor.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "les-ateliers-de-melineo.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "leavesofchangeweekly.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "jwolt-lx.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "libdeer.so", "include_subdomains": true, "mode": "force-https" },
+    { "name": "laurent-e-levy.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lbgconsultores.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lescomptoirsdepierrot.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kominki-sauny.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "line.co.nz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "linuxdays.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "loli.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "locapos.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "linux.conf.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lacigf.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "longhaircareforum.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "limules.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kotausaha.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "linuxiuvat.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lesberger.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "linearaudio.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lostarq.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lissabon.guide", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lmcm.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "linearaudio.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lipex.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "local360.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lotuscloud.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lolibrary.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "livingforreal.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "llvm.us", "include_subdomains": true, "mode": "force-https" },
+    { "name": "kidsinwoods-interfacesouth.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "little-cake.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ls-rp.es", "include_subdomains": true, "mode": "force-https" },
+    { "name": "liaozheqi.cn", "include_subdomains": true, "mode": "force-https" },
+    { "name": "luk.photo", "include_subdomains": true, "mode": "force-https" },
+    { "name": "littledisney.ro", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lotuscloud.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lensdoctor.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lukaszorn.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lachainedesentrepreneurs.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "luffyhair.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "littleqiu.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "livrariahugodesaovitor.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lojadocristaozinho.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "logopedistalanni.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "logbook.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "loritaboegl.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "livekort.no", "include_subdomains": true, "mode": "force-https" },
+    { "name": "livekortti.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "luk.earth", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lovetravel360.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "loyaleco.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lausannelovers.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "logue.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lodgesdureynou.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lordofthebrick.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lucid-light.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lojasviavento.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lojamascate.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "luisgf.es", "include_subdomains": true, "mode": "force-https" },
+    { "name": "londonkan.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lookatmysco.re", "include_subdomains": true, "mode": "force-https" },
+    { "name": "luclu7.pw", "include_subdomains": true, "mode": "force-https" },
+    { "name": "limoairporttoronto.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lojamulticapmais.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lesmontagne.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mahatmayoga.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lukatz.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "liebach.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "maisretorno.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lysergion.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lisgade.dk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "luismaier.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "loanmatch.sg", "include_subdomains": true, "mode": "force-https" },
+    { "name": "magentaize.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "macstore.pe", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mail.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "malikussa.id", "include_subdomains": true, "mode": "force-https" },
+    { "name": "magebankin.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "manavgabhawala.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "loperetti.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lostingames.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "madirc.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "maomihz.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lzh.one", "include_subdomains": true, "mode": "force-https" },
+    { "name": "madae.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "josephv.website", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ludwigpro.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mailflank.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "maartenprovo.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "makeshiftco.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mac-i-tea.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "malasuk.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "maedchenflohmarkt.at", "include_subdomains": true, "mode": "force-https" },
+    { "name": "littlepincha.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "manipulatedtme.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "le-blog.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "m-orthodontic.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "maedchenflohmarkt.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "loveysa.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "marcianoandtopazio.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "marakovits.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "maliar.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "marketgot.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mastersthesiswriting.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "massagecupping.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "marshmallow.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "madbin.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "macnetwork.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mastichor.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lune-indigo.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "macnetwork.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "markus-ullmann.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mainston.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mastercardpac.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "maroc-bivouac.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "markllego.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "macnetwork.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "marqueswines.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "main-unit.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mckinleytk.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "manav-it.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "maleexcel.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mastd.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "marcelparra.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "massage-vitalite.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lyonelkaufmann.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mattisam.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "marykshoup.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "magazinedabeleza.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lovesmagical.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mannheimbloggt.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "makenaiyo-fx.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mckenry.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mcgovernance.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mcmillanskiclub.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "matthijssen.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mariogeckler.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ma-plancha.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "me-dc.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "memfrob.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "me-center.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "marin-business-center.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "martingansler.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "me-groups.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mazda626.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "melnessgroup.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "marinbusinesscenter.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "maxims-travel.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "manipil.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mathers.ovh", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mapasmundi.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mazurlabs.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mariusschulte.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "marjoleindens.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mediaexpert.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "medyotan.ga", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mensagensaniversario.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "melhoresmarcasdenotebook.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lynxpro.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "medicocompetente.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mekatrotekno.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "margotlondon.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "medtalents.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "melaniebilodeau.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mbdrogenbos-usedcars.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mbwemmel-usedcars.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mgsisk.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mbcars.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "maxipcalls.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "metin2sepeti.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mercanix.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mhatlaw.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mein-muehlhausen.bayern", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mcdona1d.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "maxdev72.freeboxos.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "midtowndentistry.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mediterenopmaandag.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "michi.ovh", "include_subdomains": true, "mode": "force-https" },
+    { "name": "meilleur.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mertarauh.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mertak.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "midterm.us", "include_subdomains": true, "mode": "force-https" },
+    { "name": "miamicityballet.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mestazitrka.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mentaltraining-fuer-musiker.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "meisterritter.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mercedes-benz-usedcars.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "millhousenchurch.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "metrans-spedition.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "medireport.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mikedugan.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mirco-grams.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lusteniny.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "microblading.pe", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mikegarnett.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "medifab.online", "include_subdomains": true, "mode": "force-https" },
+    { "name": "marin-tullet.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "minebier.dk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mgiay.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mfrsgb45.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mf-fischer.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "metrix-money-ptc.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "matviet.vn", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mallhonda.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mmmarco.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "miruc.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "meridianstore.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "misura.re", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mizumax.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mingo.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "looka.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "memepasmal.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "memepasmal.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lydudlejning.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mensch-peter.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "meskdeals.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "metroairvirtual.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "modistryusercontent.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "luxescreenprotector.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mkfs.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "molunerfinn.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "milktea.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mohanmekap.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "miguel.pw", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mobil-bei-uns.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "misrv.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "lookart.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "millionairessecrets.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "meu-solutions.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mixnshake.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "montychristie.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "monloyer.quebec", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mirch.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "meremeti-online.gr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "moresw.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "markus.design", "include_subdomains": true, "mode": "force-https" },
+    { "name": "modcentral.pw", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mattbsg.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mamastore.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mostlyinfinite.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "module.market", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mireillewendling.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "moojp.co.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "momstableonline.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "motosikletevi.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "miguelmartinez.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "monteurzimmerfrei.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "moreserviceleads.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "moneytoday.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "moonrhythm.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "moonrhythm.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mojoco.co.za", "include_subdomains": true, "mode": "force-https" },
+    { "name": "moppeleinhorn.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mojefilmy.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mojizuri.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mrca-sharp.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "moncoach.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mosaique-lachenaie.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "migueldominguez.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mobilisation-generale.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "modcasts.video", "include_subdomains": true, "mode": "force-https" },
+    { "name": "multipleservers.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "moritztremmel.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "motionless.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mizipack.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mindbodytherapymn.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mrbmafrica.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mieuxgrandir.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mstd.tokyo", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mindercasso.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mrstat.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "meganandmarc.us", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mowalls.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "multicomhost.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mft.global", "include_subdomains": true, "mode": "force-https" },
+    { "name": "movio.ga", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mortis.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mountain-rock.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mochanstore.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "moviedeposit.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mountfarmer.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mulej.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "minamo.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mundodapoesia.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mumbaionlinegifts.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mrjooz.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mtrock.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "movienang.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mukka.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "myfreemp3.click", "include_subdomains": true, "mode": "force-https" },
+    { "name": "munkibuilds.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "motransportinfo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "munchcorp.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "my-static-live-808795.c.cdn77.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mosscade.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "myandroid.tools", "include_subdomains": true, "mode": "force-https" },
+    { "name": "myon.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "muahahahaha.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "myandroidtools.pro", "include_subdomains": true, "mode": "force-https" },
+    { "name": "myamity.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "msz-fotografie.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "moveisfit.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "my-static-demo-808795.c.cdn77.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "musik-mentaltraining.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "muzeumkomiksu.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "myriadof.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mycamda.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "music-is-my-life.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "myrent.quebec", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mypanier.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mycofairtrade.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "munirajiwa.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "myoptumhealthcomplexmedical.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mariage-photo.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "myoptumhealthparentsteps.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nailchiodo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "muenchberger.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mystorymonster.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mtfgnettoyage.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mullens-usedcars.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nahura.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "moderatorenpool.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "my-ebook.es", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mycontrolmonitor.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "my-ip.work", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mydarkstar.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mynext.events", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mycloud-system.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "munpanel.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nayanaas.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "myssl.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mingy.ddns.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "meadowfenfarm.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nekodex.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "myself5.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nanfangstone.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "namikawatetsuji.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "myrig.com.ua", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mzorn.photography", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nbtparse.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "moha-swiss.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "moudicat.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "netki.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "napcae.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "myrig.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nebul.at", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nakanishi-paint.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nedwave.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "newbownerton.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mysteryblog.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "monbudget.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nacin.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "newsquantified.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nalukfitness.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nextshutter.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nevolution.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "newcreamforface.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nehoupat.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "netde.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nesolabs.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nailattitude.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "musikverein-elten.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ndcpolipak.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "neostralis.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nella.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nickcraver.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nbur.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "newaccess.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nicolasiung.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mysterymind.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "night2stay.cn", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nebulae.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nexgeneration-solutions.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "night2stay.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "net4it.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "night2stay.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "night2stay.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mydigitalweek.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nhliberty.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "newgrowbook.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nicolajanedesigns.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "negativzinsen.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nicoleoquendo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "michaeln.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nishisbma.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nexus-exit.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nepal-evolution.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nifume.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nodariweb.com.ar", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nigger.racing", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nhimf.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "newizv.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nodefoo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "node-core-app.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nishikino-maki.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nanrenba.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nicul.in", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ninja-galerie.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nexus-vienna.at", "include_subdomains": true, "mode": "force-https" },
+    { "name": "myspicer.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nodeselect.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "mitaines.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nirvanashop.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nipe-systems.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nihon-no-sake.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ngtoys.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "myranicol.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "normalady.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nix.org.ua", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nodepanel.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nicesco.re", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nomsy.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nirna.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nna774.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "newjianzhi.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nikkila.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "niyawe.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "niceb5y.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nextcloud.li", "include_subdomains": true, "mode": "force-https" },
+    { "name": "noeatnosleep.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nodelab-it.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nerdoutstudios.tv", "include_subdomains": true, "mode": "force-https" },
+    { "name": "myblockchain.cloud", "include_subdomains": true, "mode": "force-https" },
+    { "name": "musikzug-bookholzberg.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nikavandenbos.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nsfw-story.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nopaste.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "notboring.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nativs.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "needstyle.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "menanwc.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "northernhamsterclub.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nordinfo.fi", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nowcost.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "newguidance.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "munch.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nanarose.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "noudjalink.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "niceguyit.biz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nofrillsdns.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "myna.go.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nitaonline.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nystudio107.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nothing.org.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "officemovepro.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "niesstar.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nucleuscore.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "newsmotor.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nodesturut.cl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "oatberry.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "octosniff.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nullpointer.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nuel.cl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nsbfalconacademy.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nikimix.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "oklahomanotepro.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "netbows.es", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nlrb.gov", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ojaioliveoil.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nishaswonderland.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "oberoi.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "omarh.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "omyogarishikesh.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "normankranich.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "onlinecollegeessay.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "op11.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "oktomus.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "omronwellness.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "onshuistrust.co.za", "include_subdomains": true, "mode": "force-https" },
+    { "name": "oneiros.cc", "include_subdomains": true, "mode": "force-https" },
+    { "name": "novelvyretraite.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nrdstd.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nota-web.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "oilpaintingsonly.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nishaswonderland.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "okay.cf", "include_subdomains": true, "mode": "force-https" },
+    { "name": "novaopcaofestas.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "optimumwebdesigns.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nupef.org.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "omertabeyond.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "oldtimer-trifft-flugplatz.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "orderessay.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "olympe-transport.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "omranic.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nitifilter.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "offenekommune.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "only-roses.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "onlylebanon.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "online-consulting-corp.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "omniscimus.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "omertabeyond.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "netbows.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "natuterra.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "numerik-games.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "overstockpromote.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "olivlabs.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "opengateway.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "osakeannit.fi", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nxinfo.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "oficinadocelular.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ogkw.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "openstem.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "novelinglife.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "orians.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "oswalds.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "owennelson.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "paizinhovirgula.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "oftamedic.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pakho.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "owapi.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "p3.marketing", "include_subdomains": true, "mode": "force-https" },
+    { "name": "oreto.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "paavolastudio.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "one-s.co.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "otako.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "p4chivtac.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "panicparts.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ovnrain.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "palabr.as", "include_subdomains": true, "mode": "force-https" },
+    { "name": "openiocdb.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "paketwatch.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "openacte.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ninjaspiders.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ofo2.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pasadenasandwichcompany.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "padrepio.in", "include_subdomains": true, "mode": "force-https" },
+    { "name": "oneclic.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "papersmart.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "paperwritinghelp.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "onnee.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "panascais.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "papayame.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "panascais.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ousti.sh", "include_subdomains": true, "mode": "force-https" },
+    { "name": "olasouris.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "passwordscon.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "panascais.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "panascais.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "panascais.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ngocuong.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "passwordscon.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "panascais.host", "include_subdomains": true, "mode": "force-https" },
+    { "name": "panascais.tech", "include_subdomains": true, "mode": "force-https" },
+    { "name": "owlscrap.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "panascais.us", "include_subdomains": true, "mode": "force-https" },
+    { "name": "oyosoft.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "panascais.pw", "include_subdomains": true, "mode": "force-https" },
+    { "name": "panascais.site", "include_subdomains": true, "mode": "force-https" },
+    { "name": "orfeo-engineering.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "olympiads.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "nowprotein.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pahlawanpulsa.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pauldcox.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "panasca.is", "include_subdomains": true, "mode": "force-https" },
+    { "name": "papertracker.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "panascais.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pchelpforum.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "panier-legumes.bio", "include_subdomains": true, "mode": "force-https" },
+    { "name": "paindata.dk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pajadam.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "paarberatung-hn.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pabuzo.vn", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pass.org.my", "include_subdomains": true, "mode": "force-https" },
+    { "name": "panda.tf", "include_subdomains": true, "mode": "force-https" },
+    { "name": "passwd.one", "include_subdomains": true, "mode": "force-https" },
+    { "name": "password.work", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pdfconvert.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "noc.wang", "include_subdomains": true, "mode": "force-https" },
+    { "name": "party-kneipe-bar.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "patadanabouca.pw", "include_subdomains": true, "mode": "force-https" },
+    { "name": "paf-events.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pawelnazaruk.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "paranoidpenguin.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "peterjohnson.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "orz.uno", "include_subdomains": true, "mode": "force-https" },
+    { "name": "patriksima.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pensador.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pensador.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pamatv.hk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "otinane.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "partyschnaps.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pfft.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pelletsprice.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "paris-cyber.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pfmeasure.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "phrasing.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "peeekaaabooo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "passions-art.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pcf92.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pascaline-jouis.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "passworks.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "papelariadante.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "photographyforchange.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "peterlew.is", "include_subdomains": true, "mode": "force-https" },
+    { "name": "petelew.is", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pbreen.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "overthecloud.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "peraparker.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "paulomonteiro.pt", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pinterest.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "olizeite.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "piccirello.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pinterest.engineering", "include_subdomains": true, "mode": "force-https" },
+    { "name": "peterandjoelle.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pinterest.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pera.gs", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pietechsf.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "philipdb.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "orthotictransfers.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pips.rocks", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pill.id", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pinterest.ie", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pinterest.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "peternagy.ie", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pascalchristen.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pizzabottle.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pj539999.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "perrau.lt", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pinterest.at", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pivotanimation.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pinkapple.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "parentheseardenne.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pirateproxy.cc", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pikmy.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "phoenicis.com.ua", "include_subdomains": true, "mode": "force-https" },
+    { "name": "plot.ly", "include_subdomains": true, "mode": "force-https" },
+    { "name": "peekops.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pilotcrowd.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "plaasprodukte.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "plant.ml", "include_subdomains": true, "mode": "force-https" },
+    { "name": "piraten-basel.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "playmaza.live", "include_subdomains": true, "mode": "force-https" },
+    { "name": "persoform.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ownmay.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pmbc.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pirata.ga", "include_subdomains": true, "mode": "force-https" },
+    { "name": "phuong.faith", "include_subdomains": true, "mode": "force-https" },
+    { "name": "paxdei.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pedimoda.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "perucasestoril.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pinceaux.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "petite-maison.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "piekacz.tel", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pluginfactory.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pogs.us", "include_subdomains": true, "mode": "force-https" },
+    { "name": "plus1s.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pluto.life", "include_subdomains": true, "mode": "force-https" },
+    { "name": "piratte.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "plzdontpwn.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "photistic.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "outpostinfo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "plataformadeinformacion.es", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pollingplace.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pnmhomecheckup.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pony.tf", "include_subdomains": true, "mode": "force-https" },
+    { "name": "playwhyyza.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pokemontabletopadventures.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "portalcarriers.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pixelfou.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "popcultureshack.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "plut.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "plaque-funeraire.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "phdwuda.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pomsinoz.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pmsacorp.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "poolinstallers.co.za", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pnsc.is", "include_subdomains": true, "mode": "force-https" },
+    { "name": "photops.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "paybro.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pixelrain.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "platterlauncher.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pokepon.center", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pneuhaus-lemp.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "piseach.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "port.social", "include_subdomains": true, "mode": "force-https" },
+    { "name": "prestonbrant.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "planktonholland.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pornolab-net.appspot.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "plus-u.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "plasvilledescartaveis.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "plumpie.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pharmacieplusfm.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "proctorio.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pornomens.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "potatopro.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pbosquet.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pardnoy.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "plutopia.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "poeg.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "poseidonwaterproofing.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pleine-conscience.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "prac.to", "include_subdomains": true, "mode": "force-https" },
+    { "name": "post.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "plumnet.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "practo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "plasticsurgeryartist.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "polsport.live", "include_subdomains": true, "mode": "force-https" },
+    { "name": "popinga.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "praxis-familienglueck.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pozniak.at", "include_subdomains": true, "mode": "force-https" },
+    { "name": "postcode.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "poba.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "profloorstl.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "properticons.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "projectunity.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "phcimages.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "prinesdoma.at", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pornohub.su", "include_subdomains": true, "mode": "force-https" },
+    { "name": "praxino.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ploofer.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "proveits.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pmconference.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "proovn.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "project.supply", "include_subdomains": true, "mode": "force-https" },
+    { "name": "princessbackpack.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "preigu.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "procharter.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "primaconsulting.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "proxyportal.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "plantastique.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "power-fit.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "profitablewebprojects.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "programsupport300procent.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "privacynow.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "promods.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "privacyscore.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "polkam.go.id", "include_subdomains": true, "mode": "force-https" },
+    { "name": "propepper.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "prodinger.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "plantastique.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "poleacademie.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "proactive.run", "include_subdomains": true, "mode": "force-https" },
+    { "name": "productpeo.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "planetbreath.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "qbnt.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "puentes.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "py-amf.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pyrrhonism.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "prestigerepairs.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "premiumwebdesign.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ptrl.ws", "include_subdomains": true, "mode": "force-https" },
+    { "name": "prevenir.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "presses.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "protonvpn.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "psychic-healer-mariya-i-petrova-boyankinska-b-borovan-bg.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "prepaid-cards.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "polizeiwallis.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pythonic.training", "include_subdomains": true, "mode": "force-https" },
+    { "name": "procert.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "queensrdapartments.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pieterbos.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "quickandroid.tools", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rainbin.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "plushev.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pugilares.com.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rallycycling.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "provisionaldriving.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "quay.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "psydix.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "petrkrapek.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "radishmoon.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "qnatek.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "radondetectionandcontrol.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "queenshaflo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "packagingproject.management", "include_subdomains": true, "mode": "force-https" },
+    { "name": "quaggan.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "raryosu.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "queroreceitasoberana.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rationalcreation.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pulsedursley.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "prestigesigns.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "puzzlepoint.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "psyao.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rabota-x.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "reath.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "qiannews.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "redeemingbeautyminerals.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "raghavdua.in", "include_subdomains": true, "mode": "force-https" },
+    { "name": "puissancemac.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rcraigmurphy.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "realraghavgupta.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rakugokai.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ralphwoessner.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "read.sc", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ralph.bike", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pvagner.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "r7h.at", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rechat.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "redcone.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "radcube.hu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "qrforex.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "public-projects.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "quantum-lviv.pp.ua", "include_subdomains": true, "mode": "force-https" },
+    { "name": "readysell.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rabbit.wales", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rbmafrica.co.za", "include_subdomains": true, "mode": "force-https" },
+    { "name": "readytowear.es", "include_subdomains": true, "mode": "force-https" },
+    { "name": "propagandablog.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "realworldholidays.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rdyrda.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "query-massage.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "qrcontagion.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "redshiftlabs.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rebelz.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "reflexions.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "radical.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "renyiyou.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "public-g.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "reldoc.com.mx", "include_subdomains": true, "mode": "force-https" },
+    { "name": "public-projects.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ptrujillo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "remedyrehab.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rathgeb.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "purrfectcams.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "public-vocals.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "purrfectmembersclub.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "purrfectboudoir.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rapidapp.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "regsec.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "resourceguruapp.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "readydok.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "reverseaustralia.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "recmon.hu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ralf-huebscher.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "richardson.engineering", "include_subdomains": true, "mode": "force-https" },
+    { "name": "revisionnotes.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rednoseday.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "reorz.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "registertovoteflorida.gov", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rekorsanat.com.tr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "regime-maigrir-vite.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rationem.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "repsomelt.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "qifu.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "petbooking.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "raxion.cf", "include_subdomains": true, "mode": "force-https" },
+    { "name": "reverencestudios.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "renezuo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rfeif.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "qifu.org.cn", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ricketyspace.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rishikeshyoga.in", "include_subdomains": true, "mode": "force-https" },
+    { "name": "returnofwar.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "retro.rocks", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rmit.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "righteousendeavour.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "robbertt.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "reco-studio.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "redizoo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "riverford.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "real-bits.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rickmartensen.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "qwans.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "razberry.kr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rmk.si", "include_subdomains": true, "mode": "force-https" },
+    { "name": "riffreporter.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rigabeerbike.lv", "include_subdomains": true, "mode": "force-https" },
+    { "name": "revapost.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rigabeerbike.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "prague-swim.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rgcomportement.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "richardson.systems", "include_subdomains": true, "mode": "force-https" },
+    { "name": "reimann.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "retetenoi.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "qscloud.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "psa.gov", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rolandslate.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rootscope.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rosehosting.reviews", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rootedlifemontessori.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rnb-storenbau.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rorymcdaniel.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rootcommand.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "reclusiam.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "quocdesign.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rognhaugen.no", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rukhaiyar.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "robinevandenbos.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rets.org.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "roadtopgm.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rester-autonome-chez-soi.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "renlen.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rofrank.space", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rockhounds.co.za", "include_subdomains": true, "mode": "force-https" },
+    { "name": "runebet.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rustbyexample.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rubytune.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ristorantefattoamano.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "roryneville.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rijsinkunst.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rob006.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "roosabels.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rmaqequipamentos.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "routerclub.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rotol.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rester-a-domicile.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sadmansh.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "russianorthodoxchurch.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rtate.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rtate.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rolliwelt.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rv-jpshop.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "restaurace-klokocka.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rockcellar.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ruconsole.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rothkranz.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "salixcode.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rvg.zone", "include_subdomains": true, "mode": "force-https" },
+    { "name": "safebasements.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "s8a.us", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rockenfuerlachenhelfen.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "said.my.id", "include_subdomains": true, "mode": "force-https" },
+    { "name": "s3n.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rackerlab.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "runklesecurity.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rpadovani.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rrg-partner.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "robertrijnders.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "samaritan.tech", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sagarhandicraft.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rogersaam.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rtvi.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ruurdboomsma.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rogersremovals.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rage-overload.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "roulinfo.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "pragueswim.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sanooktiew.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "richardson.software", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sanskritiyoga.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rmsides.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "saudeealimentos.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sandrainden.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "savingsomegreen.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rumoterra.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "s4tips.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rummel-platz.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "savingbytes.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rvnoel.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rrdesignsuisse.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "salonestella.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "samm.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sbobetfun.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sanatrans.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sadsu.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sakostacloud.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sashascollections.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sandraindenfotografie.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "roadguard.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "regily.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sayura.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "risaphuketproperty.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rychlikoderi.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rnt.cl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "salensmotors-usedcars.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rucnerobene.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "savisasolutions.co.za", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sanatorii-sverdlovskoy-oblasti.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "routeragency.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sdsmt.engineering", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sanitairwinkel.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "redperegrine.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "schippendale.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "santenatureetcie.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "schmaeh-coaching.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "schraugerrun.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sanitairwinkel.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sayhanabi.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rotter-dam.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "seafood.co.nz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "schweiz.guide", "include_subdomains": true, "mode": "force-https" },
+    { "name": "schrolm.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "security-brokers.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "rhymeswithmogul.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "scorobudem.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "s-d-v.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "saxwereld.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "securityfest.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "seareytraining.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "scramsoft.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "scramget.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "schoeck-elektro.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "saudeeconforto.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sebastian-schmidt.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "scopea.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "segmetic.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "scrambox.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "seinfeldquote.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "samsungmobile.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "savacloud.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "salonsantebienetre.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "s1mplescripts.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "redcomet.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sentinelproject.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "reevu.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "scm-2017.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sapprendre.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sebastian-kraus.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "schnell-abnehmen.tips", "include_subdomains": true, "mode": "force-https" },
+    { "name": "seo.tl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "santi.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "schwarzegar.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "seaplayhomes.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "scalaire.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "schuhbeck.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sekisonn.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "seomen.biz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "seekthe.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sector5.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sens2lavie.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "securefuture.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "schrenkinzl.at", "include_subdomains": true, "mode": "force-https" },
+    { "name": "serbien.guide", "include_subdomains": true, "mode": "force-https" },
+    { "name": "semacode.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "servpanel.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sdvigpress.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "serviceboss.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "securocloud.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "seoprovider.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "shadowict.tech", "include_subdomains": true, "mode": "force-https" },
+    { "name": "shadigee.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "shadowict.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "seacam-store.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "seydaozcan.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "schoknecht.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sernate.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "schoknecht.one", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sh11.pp.ua", "include_subdomains": true, "mode": "force-https" },
+    { "name": "restioson.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sbr.red", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sapuncheta.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "shawnhogan.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "shinghoi.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "selfassess.govt.nz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sg-elektro.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sh4y.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "siamega.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sec-wiki.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sevenet.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "securitybrief.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "shopsouthafrican.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sfhobbies.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "securityarena.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sgtt.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "santorinibbs.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sharezen.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sha2017.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "semenov.su", "include_subdomains": true, "mode": "force-https" },
+    { "name": "santevie.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "shaharyaranjum.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "shikimori.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "seo-portal.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "shieldofachilles.in", "include_subdomains": true, "mode": "force-https" },
+    { "name": "shichibukai.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "schwarzhenri.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sexshopnet.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sheying.tm", "include_subdomains": true, "mode": "force-https" },
+    { "name": "shining.gifts", "include_subdomains": true, "mode": "force-https" },
+    { "name": "shadowsocks.vc", "include_subdomains": true, "mode": "force-https" },
+    { "name": "shikimori.one", "include_subdomains": true, "mode": "force-https" },
+    { "name": "showmethemoney.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "silsha.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "shoppr.dk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "siloportem.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sjd.is", "include_subdomains": true, "mode": "force-https" },
+    { "name": "shiseki.top", "include_subdomains": true, "mode": "force-https" },
+    { "name": "simonpaarlberg.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "shiatsu-institut.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "shk.im", "include_subdomains": true, "mode": "force-https" },
+    { "name": "shoptec.sk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sinefili.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "simonspeich.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sin-nombre-alleria.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "skday.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "simplexgame.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "siku.pro", "include_subdomains": true, "mode": "force-https" },
+    { "name": "skinbet.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sbf888.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "shakespearevet.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "skingame.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "siro.gq", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sincai666.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "shopdopastor.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "seizoushokoyuubangou.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "simoesgoulart.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "seven-purple.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sirena.co.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "singles-berlin.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "skinpwrd.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sfo-fog.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "slik.ai", "include_subdomains": true, "mode": "force-https" },
+    { "name": "single-in-stuttgart.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sjdaws.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "shoshin-aikido.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "silvergoldbull.mw", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sigismonda.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "skylgenet.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "smartwritingservice.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "skatingchina.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "smol.cat", "include_subdomains": true, "mode": "force-https" },
+    { "name": "smallshopit.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "smiledirectsales.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "singee.site", "include_subdomains": true, "mode": "force-https" },
+    { "name": "slip-gaming.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sma-gift.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "silvergoldbull.co.tz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sl0.us", "include_subdomains": true, "mode": "force-https" },
+    { "name": "scistarter.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "silvergoldbull.cm", "include_subdomains": true, "mode": "force-https" },
+    { "name": "smutek.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "snap.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "securoswiss.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "silvergoldbull.ws", "include_subdomains": true, "mode": "force-https" },
+    { "name": "snerith.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "skylocker.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "skylocker.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "silvergoldbull.by", "include_subdomains": true, "mode": "force-https" },
+    { "name": "snowdy.link", "include_subdomains": true, "mode": "force-https" },
+    { "name": "skram.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "slane.cn", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sogola.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "seemeasaperson.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "slrd-isperih.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "socoastal.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "slopeedge.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "solos.im", "include_subdomains": true, "mode": "force-https" },
+    { "name": "silvergoldbull.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "smileandpay.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "smartfit.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "solanum-games.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "seg-leipzig.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "silvergoldbull.hk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sorrowfulunfounded.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "softballrampage.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "silvergoldbull.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "snatch.com.ua", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sophiaandmatt.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "silvergoldbull.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "smsg-dev.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "songsmp3.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "smit.com.ua", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sgtsnookums.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "smartandcom.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "southcoastswords.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "softcreatr.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "seanstrout.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "softclean.pt", "include_subdomains": true, "mode": "force-https" },
+    { "name": "silvergoldbull.nz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sodafilm.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "skyloisirs.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sluplift.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "some.rip", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sm2016.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sozialy.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sevencooks.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "spoopy.link", "include_subdomains": true, "mode": "force-https" },
+    { "name": "silvergoldbull.tw", "include_subdomains": true, "mode": "force-https" },
+    { "name": "snowdy.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "spanien.guide", "include_subdomains": true, "mode": "force-https" },
+    { "name": "silvergoldbull.rs", "include_subdomains": true, "mode": "force-https" },
+    { "name": "speech-balloon.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "snowdy.dk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sonacupalova.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "silvergoldbull.sv", "include_subdomains": true, "mode": "force-https" },
+    { "name": "smuhelper.cn", "include_subdomains": true, "mode": "force-https" },
+    { "name": "silvergoldbull.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "silvergoldbull.li", "include_subdomains": true, "mode": "force-https" },
+    { "name": "silvergoldbull.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "statusbot.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "silvergoldbull.cn", "include_subdomains": true, "mode": "force-https" },
+    { "name": "speedtailors.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sp.com.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "starlim.co.in", "include_subdomains": true, "mode": "force-https" },
+    { "name": "southmelbourne.apartments", "include_subdomains": true, "mode": "force-https" },
+    { "name": "somecrazy.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "springsoffthegrid.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "stardeeps.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "solariilacheie.ro", "include_subdomains": true, "mode": "force-https" },
+    { "name": "soluphant.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "steampunkrobot.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "srinivasan.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "stfw.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "soz6.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "steamgifts.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "socializam.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "steamtrades.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "srbija-nekretnine.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "stitthappens.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sospromotions.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sprachfreudehoch3.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "stevedesmond.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "stlucasmuseum.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "southwaymotors.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "stewartswines.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "strehl.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "stipsan.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "spinner.dnshome.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "shahbeat.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "spendwise.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "stb-strzyzewski.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "storillo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sougi-review.top", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sugarandcloth.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "stytt.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "steamscore.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "shota.vip", "include_subdomains": true, "mode": "force-https" },
+    { "name": "submelon.tech", "include_subdomains": true, "mode": "force-https" },
+    { "name": "strategiclivingblog.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "stijnodink.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "spielezar.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sr-cs.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "stevenwooding.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ssl888.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "staceyhankeinc.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "subterfuge.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "snrub.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "svdreamcatcher.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "stoebermehl.at", "include_subdomains": true, "mode": "force-https" },
+    { "name": "stichtingliab.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "swarfarm.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "superguide.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sslok.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "spolwind.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "stellen.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "substitutealert.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sturge.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "stadtgartenla.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "summer.ga", "include_subdomains": true, "mode": "force-https" },
+    { "name": "surpreem.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sportscollection.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "stratmann-b.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "swarmation.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "spisoggrin.dk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "souris.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "strozik.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "syneart.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sterchi-fromages.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "strila.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sportovnidum.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sukrie.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "strydom.me.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "t12u.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "store10.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "soufastnet.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "stormi.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "suzukimarinepress.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "synergyworkingdogclub.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "supes.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "supercreepsvideo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "stylewish.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sja-se-training.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "stadm.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "survivebox.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "surao.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "stlukesbrandon.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sylvaindurand.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "szerelem.love", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tat2grl85.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "soontm.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sikko.biz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "systoolbox.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tam7t.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tattvaayoga.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "studiovaud.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tdsbhack.cf", "include_subdomains": true, "mode": "force-https" },
+    { "name": "szybkiebieganie.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sysadm.guru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tapestries.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tbonejs.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tastystakes.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "soinvett.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "talon.rip", "include_subdomains": true, "mode": "force-https" },
+    { "name": "svenskaservern.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tankfreunde.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tdsbhack.gq", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tadtadya.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tdsbhack.ml", "include_subdomains": true, "mode": "force-https" },
+    { "name": "student-eshop.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "stringvox.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "student-eshop.sk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tdsbhack.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tajper.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "system-m.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "szunia.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sydney-sehen.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "techhappy.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "technicallyeasy.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "techosmarcelo.com.ar", "include_subdomains": true, "mode": "force-https" },
+    { "name": "techdirt.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "teambakchod.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tdsbhack.ga", "include_subdomains": true, "mode": "force-https" },
+    { "name": "straatderzotten.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "taxmadras.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "taskin.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "teamupturn.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tabithawebb.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tabino.top", "include_subdomains": true, "mode": "force-https" },
+    { "name": "symbiose-immobilier.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "snafarms.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "teddybradford.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "swisselement365.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "taartenfeesies.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "suzi3d.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tatiloley.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "teambeam.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "teambeam.at", "include_subdomains": true, "mode": "force-https" },
+    { "name": "teambeam.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "techmunchies.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tchnics.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "techshift.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "techshift.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "teambeam.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "symbiose-bien-etre.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "teddylu.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "techshift.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tehcrayz.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "teaparty.id", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tb-devel.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "techtuts.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "spillersfamily.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tantei100.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tenerife-villas.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "taxicollectif.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "talkreal.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "taniku-succulent.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "textpedia.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "teletra.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tenberg.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tandblekningidag.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tele-online.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "taxiscollectifs.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "taxi-collectif.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "testi.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "taxi-chamonix.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "taxis-collectifs.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thebasementguys.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "symbiose-com.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tenseapp.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thebodyprinciple.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thailandpharmacy.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "takeitoffline.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "telecharger-open-office.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "telecharger-winrar.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "the-zenti.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "symb.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thebrightons.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "theebookkeepers.co.za", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thajskyraj.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "symbiosecom.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thefbstalker.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "themetacity.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tf2calculator.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thepathsofdiscovery.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "themathbehindthe.science", "include_subdomains": true, "mode": "force-https" },
+    { "name": "swissentreprises.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tempodecolheita.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thecoffeepod.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thesishelp.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tagdocumentary.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "swisscannabis.club", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thebakingclass.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sweetair.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thaimooc.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tekstschrijvers.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thekrewserver.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "theosophie-afrique.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thinkheaddesign.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thetenscrolls.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thecrazytravel.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "theory-test-online.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thanhthinhbui.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thesecurityteam.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thepartner.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thecuppacakery.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "the-webmaster.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "sundanceusa.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thecsw.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thunderkeys.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thalmann.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ticketsource.us", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ticketsource.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tillberg.us", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tandem-trade.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tewarilab.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tiltedwindmillcrafts.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "theralino.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "timbarlotta.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thor.edu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tmhr.moe", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thunderfield-boat.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ti-js.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "therumfordcitizen.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thierry-daellenbach.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tiew.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thomas-ferney.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thgros.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tierarztpraxis-weinert.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tlehseasyads.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "todaciencia.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thinkswap.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tibovanheule.site", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thecherryship.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tele-alarme.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tommounsey.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tilient.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "toheb.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "todosrv.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "telealarme.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thuthuatios.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thomasstevensmusic.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "totoro.pub", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thisistheserver.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "teleallarme.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "telealarmevalais.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "timeglass.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "teledivi.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tele-assistance.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tircentrale.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tpansino.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thorsten-schaefer.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "toka.sg", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thierrybasset.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tokumei.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tinf15b4.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tobyx.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tirionnetwork.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tiroler-kupferschmiede.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "townandcountryus.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "toeightycountries.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "timfiedler.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "themacoaching.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tkjg.fi", "include_subdomains": true, "mode": "force-https" },
+    { "name": "toracon.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "startup.melbourne", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tomica.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tjp.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tobischo.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "trangcongnghe.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "top-obaly.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "traces.ml", "include_subdomains": true, "mode": "force-https" },
+    { "name": "torstensenf.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "topjobs.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tokyomakino.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "trimarchimanuele.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tlsrobot.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tokyovipper.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "troyhuntsucks.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "topicit.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thisoldearth.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tommic.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "top-opakowania.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "truehealthreport.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tavolaquadrada.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "topeng-emas.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "treinonerd.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "theragran.co.id", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tommyweber.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "truekey.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "titelseite.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "trumeet.top", "include_subdomains": true, "mode": "force-https" },
+    { "name": "trialmock.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "transferio.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "travel-dealz.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "theshine.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tsura.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tomyork.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "trendydips.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "transcend.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "trancendances.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tokic.hr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "turnonsocial.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "triageo.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tsumi.moe", "include_subdomains": true, "mode": "force-https" },
+    { "name": "travel-to-nature.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tradietrove.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tniad.mil.id", "include_subdomains": true, "mode": "force-https" },
+    { "name": "trekfriend.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "troedelhannes.at", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thelostyankee.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tucnak.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "turkiet.guide", "include_subdomains": true, "mode": "force-https" },
+    { "name": "treehousebydesign.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "twem.ddns.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "twenty71.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ttll.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thaiforest.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "turtlepwr.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tsukuba.style", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tuts4you.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "twincitynissantxparts.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "turnsticks.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tubeju.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thebest.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tracker-gps.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tucidi.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "traceroute.guru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "twb.berlin", "include_subdomains": true, "mode": "force-https" },
+    { "name": "traceroute.network", "include_subdomains": true, "mode": "force-https" },
+    { "name": "traceroute.link", "include_subdomains": true, "mode": "force-https" },
+    { "name": "trace.guru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "underkin.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "topprice.ua", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ugosadventures.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "u5r.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "trtltravel.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tuxhound.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ufanisi.mx", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ubineering.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "twiri.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "touch-up-net.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tusb.ml", "include_subdomains": true, "mode": "force-https" },
+    { "name": "unikrn.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tvsheerenhoek.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "touchscreentills.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "theory.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tvoru.com.ua", "include_subdomains": true, "mode": "force-https" },
+    { "name": "unusualhatclub.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "undercovercondoms.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "unblocked.pub", "include_subdomains": true, "mode": "force-https" },
+    { "name": "trefcon.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tsng.co.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thesuppercircle.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "uedaviolin.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tous-travaux.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "undercovercondoms.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "urcentral.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "utopialgb.org.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ulalau.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tsng-stg.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "untethereddog.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "upperbeaconsfield.org.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "uflixit.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "twilleys.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "urbansparrow.in", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ungern.guide", "include_subdomains": true, "mode": "force-https" },
+    { "name": "uptoon.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "uvocorp.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "upwork.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "twohuo.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thebeginningisnye.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "trustfield.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "valhalla-agency.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vccmurah.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "umaimise.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vasports.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "valhallacostarica.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "utitreatment.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ultratechlp.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vadennissanofhinesvilleparts.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "thismumdoesntknowbest.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "towywebdesigns.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tondles.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vcmi.download", "include_subdomains": true, "mode": "force-https" },
+    { "name": "upbad.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vernonchan.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "u-tokyo.club", "include_subdomains": true, "mode": "force-https" },
+    { "name": "unfdev.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "usebean.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "totalforcegym.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "unleash.pw", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vicyu.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "united-schools.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "valecnatechnika.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vergeaccessories.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "upload.cat", "include_subdomains": true, "mode": "force-https" },
+    { "name": "viditut.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vacuumreviewcenter.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vaygren.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "unterkunft.guru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ueba1085.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "underlined.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "usr.nz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vanouwerkerk.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vijay-international.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "verymelon.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vishwashantiyoga.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tr0n.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vionicbeach.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "urgences-valais.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "torbay.ga", "include_subdomains": true, "mode": "force-https" },
+    { "name": "teoleonie.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vandermeer.frl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vegepa.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "univercite.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "visistruct.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "victornet.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vermuetje.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "veritafineviolins.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "viktorprevaric.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "velotyretz.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vera.bg", "include_subdomains": true, "mode": "force-https" },
+    { "name": "v789xl.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "verzick.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "veverusak.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vaud-fleurs.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "univitale.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "viptamin.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vallutaja.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vitalyzhukphoto.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vlvvl.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "visaexpert.co.za", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vrlaid.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vaperolles.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "voidshift.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vladislavstoyanov.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "uniformecomgas.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "verstraetenusedcars.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "versfin.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vagabondgal.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "uatgootax.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "virtualvaults.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vconcept.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "visionthroughknowledge.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vconcept.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ventzke.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vivianmaier.cn", "include_subdomains": true, "mode": "force-https" },
+    { "name": "viceversa.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ucch.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vima.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vpn.pics", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vancouvercosmeticsurgery.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vamoaeturismo.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vietnam-lifer.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "void-it.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vistastylebuilder.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "viviennevandenbos.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "warp-radio.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "warp-radio.tv", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vivo.sx", "include_subdomains": true, "mode": "force-https" },
+    { "name": "viking-style.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wavefloatrooms.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "veganosonline.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vroedvrouwella.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "voterstartingpoint.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vip999.cc", "include_subdomains": true, "mode": "force-https" },
+    { "name": "webhostingpros.ml", "include_subdomains": true, "mode": "force-https" },
+    { "name": "villacarmela.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vilight.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wdt.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wafni.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "webproshosting.tk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wadsworth.gallery", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wardsegers.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "voicu.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vlsm.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "webfox.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "webcatechism.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wearesouthafricans.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "viabemestar.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "viralpop.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "viteoscrm.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "waaw.tv", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vriesdonkow.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "visapourailleurs.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "websharks.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wellopp.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "we.serveftp.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "weldwp.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "webbiz.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "webypass.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "webambacht.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "webproxy.pw", "include_subdomains": true, "mode": "force-https" },
+    { "name": "whisperinghoperanch.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wave-ola.es", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vzis.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vitoye.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "westlinwinds.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wehostdnn.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "votre-site-internet.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "web.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "utahlocal.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "webspiral.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "utilitarian.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wesayyesprogram.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "widdleguy.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "whilsttraveling.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wellies.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wasielewski.com.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "werhatunsverraten.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wertheimer-burgrock.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "westmead.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wilseyrealty.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wasi-net.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "westcarrollton.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "webnetmail4u.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wibbe.link", "include_subdomains": true, "mode": "force-https" },
+    { "name": "werwolf-live.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "web2ldap.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wellbeing360.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wildboaratvparts.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "votresiteweb.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "waytt.cf", "include_subdomains": true, "mode": "force-https" },
+    { "name": "weedypedia.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "webrentcars.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wjm2038.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "werehub.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "webliberty.ru", "include_subdomains": true, "mode": "force-https" },
+    { "name": "westendwifi.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "whoturgled.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "worldlist.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wooplagaming.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "worldessays.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "winfield.me.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "willems-kristiansen.dk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "whitby-brewery.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wp-securehosting.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "windowstech.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "whitepharmacy.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "worst.horse", "include_subdomains": true, "mode": "force-https" },
+    { "name": "win7stylebuilder.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "webies.ro", "include_subdomains": true, "mode": "force-https" },
+    { "name": "woshiluo.site", "include_subdomains": true, "mode": "force-https" },
+    { "name": "windsock-app.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vocalviews.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wprevs.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "webcookies.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wiliquet.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vos-fleurs.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vos-fleurs.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "willkommen-fuerstenberg.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "worldofvnc.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "winsome.world", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wozalapha.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "writemyessays.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wromeapp.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "writemyessay.info", "include_subdomains": true, "mode": "force-https" },
+    { "name": "writemytermpapers.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "writemypaperhub.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "worldfree4.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "writepro.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "writing-job-online.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wipc.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "write-right.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wsup.social", "include_subdomains": true, "mode": "force-https" },
+    { "name": "writing-expert.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "writecustomessay.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wirbatz.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "whiskyglazen.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wpturnedup.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "victoreriksson.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "writingcities.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wpdirecto.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wpcharged.nz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "writingtoserve.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "worcade.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wug.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "worldstone777.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vir-tec.eu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xjjeeps.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wizardspire.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "tutiendaroja.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xawen.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "webaholic.co.in", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wordher.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wolfenland.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wrdcfiles.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wmoda.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wweforums.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wimpernforyou.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wrongware.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wo-ist-elvira.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vpnservice.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wieobensounten.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "whatsupoutdoor.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wubify.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xferion.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xkblog.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "woodev.us", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wrapitup.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "www-33445.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "www.re", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xmedius.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--gmq92k.nagoya", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wikipeter.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--l8j9d2b.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--baron-bonzenbru-elb.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "woheni.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--u9jy16ncfao19mo8i.nagoya", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xgame.com.tr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "woomu.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "vysko.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wvw698.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xiaoniaoyou.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wangkezun.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--w22a.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--tigreray-i1a.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "www-1117.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--80ablh1c.online", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xtom.chat", "include_subdomains": true, "mode": "force-https" },
+    { "name": "www-9995.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "www-39988.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wpsnelheid.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--sdkwa9azd389v01ya.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "womenshairlossproject.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xuming.studio", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xrp.pw", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--lna-2000-9za.nu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xtom.com.hk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yamm.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "www-8003.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "www-0385.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xt.om", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xtom.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--lna-4000-9za.nu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xts.bike", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yarravilletownhouses.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "www-djbet.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "y11n.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "www-001133.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.com.tr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xubo666.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "whitealps.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.at", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.co.nz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xyzulu.hosting", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.com.hk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.com.au", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.be", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.co.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wscbiolo.id", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.com.ar", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.cl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.com.sg", "include_subdomains": true, "mode": "force-https" },
+    { "name": "whitealps.at", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.com.ph", "include_subdomains": true, "mode": "force-https" },
+    { "name": "www-1116.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.com.tw", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--uist1idrju3i.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "whitealps.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.cz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "whitealps.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.fi", "include_subdomains": true, "mode": "force-https" },
+    { "name": "whitealps.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.co.uk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yemalu.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yoshitsugu.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yachigoya.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.es", "include_subdomains": true, "mode": "force-https" },
+    { "name": "youdamom.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xjd.vision", "include_subdomains": true, "mode": "force-https" },
+    { "name": "www-88599.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.com.mx", "include_subdomains": true, "mode": "force-https" },
+    { "name": "websiteforlease.ca", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yogaschoolrishikesh.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.dk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.ie", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "whitealps.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.pl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yiyuanzhong.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.it", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yubico.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.se", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.pt", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xpj.bet", "include_subdomains": true, "mode": "force-https" },
+    { "name": "youhacked.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.my", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yelp.no", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yoga-zentrum-narayani.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yubikey.dk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "youfencun.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yubico.dk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ysicorp.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yubico.es", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xj8876.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ytpak.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yingsuo.ltd", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yuntama.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yaay.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zeitoununiversity.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zarmarket.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zentask.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yobify.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zenofa.co.id", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zalamea.ph", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zfly.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "youmonit.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zamow.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yourticketbooking.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zhiin.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yoursbookstore.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "ylilauta.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--uorz58b8p0bpwa.biz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yryz.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zerofox.gq", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yotta-zetta.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zoola.io", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zooxdata.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zekinteractive.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yumeconcert.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yggdar.ga", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zeilles.nu", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yanngraf.ch", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yourforex.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zeilenmethans.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yue2.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zlima12.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yanngraf.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zrniecka-pre-sny.sk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zepect.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zfree.co.nz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zevelev.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zvz.im", "include_subdomains": true, "mode": "force-https" },
+    { "name": "znacite.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "yue.la", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zijung.me", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zoofaeth.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zhuji.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zx7r.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zacavi.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zhuji.com.cn", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zzb510.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zzb6688.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zusjesvandenbos.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zwembadheeten.nl", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zonemaster.fr", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zilsen.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zopy.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zurickrelogios.com.br", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zilon.com.co", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zentience.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--dckya4a0bya6x.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xnet-x.net", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zsrbcs.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--dcko6fsa5b1a8gyicbc.biz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--e--k83a5h244w54gttk.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--qckqc0nxbyc4cdb4527err7c.biz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--dckya4a0bya6x.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--ecki0cd0bu9a4nsjb.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--e--ig4a4c3f6bvc5et632i.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--pck4e3a2ex597b4ml.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--e--0g4aiy1b8rmfg3o.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zug-anwalt.de", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--vck8crcu789ajtaj92eura.xyz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--t8j4aa4nkg1h9bwcvud.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "wpunpacked.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--r8jzaf7977b09e.com", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--zck9a4b352yuua.jp", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--vck8crc010pu14e.biz", "include_subdomains": true, "mode": "force-https" },
+    { "name": "youss.cc", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zentience.dk", "include_subdomains": true, "mode": "force-https" },
+    { "name": "zentience.org", "include_subdomains": true, "mode": "force-https" },
+    { "name": "xn--t8j4aa4nzg3a5euoxcwee.xyz", "include_subdomains": true, "mode": "force-https" },
     // END OF BULK ENTRIES
 
     // Manual additions and changes in Chrome 51 or later that do not belong in a
@@ -29291,57 +33327,95 @@
     { "name": "matteomarescotti.it", "include_subdomains": true, "mode": "force-https", "expect_staple": true, "expect_staple_report_uri": "https://matteomarescotti.report-uri.io/r/default/staple/reportOnly", "include_subdomains_for_expect_staple": true },
     { "name": "www.cnet.com", "include_subdomains": true, "mode": "force-https" },
     {
-        "name": "alessandroz.pro",
-        "mode": "force-https", "include_subdomains": true,
-        "expect_staple": true, "include_subdomains_for_expect_staple": true,
-        "expect_staple_report_uri": "https://azreport.report-uri.io/r/default/staple/reportOnly"
+      "name": "alessandroz.pro",
+      "mode": "force-https", "include_subdomains": true,
+      "expect_staple": true, "include_subdomains_for_expect_staple": true,
+      "expect_staple_report_uri": "https://azreport.report-uri.io/r/default/staple/reportOnly"
     },
     {
-        "name": "minecraftforum.de",
-        "mode": "force-https", "include_subdomains": true,
-        "expect_staple": true, "include_subdomains_for_expect_staple": true,
-        "expect_staple_report_uri": "https://minecraft.report-uri.io/r/default/staple/reportOnly"
+      "name": "minecraftforum.de",
+      "mode": "force-https", "include_subdomains": true,
+      "expect_staple": true, "include_subdomains_for_expect_staple": true,
+      "expect_staple_report_uri": "https://minecraft.report-uri.io/r/default/staple/reportOnly"
     },
     {
-        "name": "tobiassachs.de",
-        "mode": "force-https", "include_subdomains": true,
-        "expect_staple": true, "include_subdomains_for_expect_staple": true,
-        "expect_staple_report_uri": "https://tobiassachs.report-uri.io/r/default/staple/reportOnly",
-        "expect_ct": true,
-        "expect_ct_report_uri": "https://tobiassachs.report-uri.io/r/default/ct/reportOnly"
+      "name": "tobiassachs.de",
+      "mode": "force-https", "include_subdomains": true,
+      "expect_staple": true, "include_subdomains_for_expect_staple": true,
+      "expect_staple_report_uri": "https://tobiassachs.report-uri.io/r/default/staple/reportOnly",
+      "expect_ct": true,
+      "expect_ct_report_uri": "https://tobiassachs.report-uri.io/r/default/ct/reportOnly"
     },
     {
-        "name": "gc-mc.de",
-        "mode": "force-https", "include_subdomains": true,
-        "expect_staple": true, "include_subdomains_for_expect_staple": true,
-        "expect_staple_report_uri": "https://tobiassachs.report-uri.io/r/default/staple/reportOnly",
-        "expect_ct": true,
-        "expect_ct_report_uri": "https://tobiassachs.report-uri.io/r/default/ct/reportOnly"
+      "name": "gc-mc.de",
+      "mode": "force-https", "include_subdomains": true,
+      "expect_staple": true, "include_subdomains_for_expect_staple": true,
+      "expect_staple_report_uri": "https://tobiassachs.report-uri.io/r/default/staple/reportOnly",
+      "expect_ct": true,
+      "expect_ct_report_uri": "https://tobiassachs.report-uri.io/r/default/ct/reportOnly"
     },
     {
-        "name": "knightsblog.de",
-        "mode": "force-https", "include_subdomains": true,
-        "expect_staple": true, "include_subdomains_for_expect_staple": true,
-        "expect_staple_report_uri": "https://tobiassachs.report-uri.io/r/default/staple/reportOnly",
-        "expect_ct": true,
-        "expect_ct_report_uri": "https://tobiassachs.report-uri.io/r/default/ct/reportOnly"
+      "name": "knightsblog.de",
+      "mode": "force-https", "include_subdomains": true,
+      "expect_staple": true, "include_subdomains_for_expect_staple": true,
+      "expect_staple_report_uri": "https://tobiassachs.report-uri.io/r/default/staple/reportOnly",
+      "expect_ct": true,
+      "expect_ct_report_uri": "https://tobiassachs.report-uri.io/r/default/ct/reportOnly"
     },
     {
-        "name": "secretintelligence.0.me.uk",
-        "mode": "force-https", "include_subdomains": true,
-        "pins": "ncsccs",
-        "expect_staple": true, "include_subdomains_for_expect_staple": true,
-        "expect_staple_report_uri": "https://log.ncsccs.com/report/expectocsp",
-        "expect_ct": true,
-        "expect_ct_report_uri": "https://log.ncsccs.com/report/expectct"
+      "name": "secretintelligence.0.me.uk",
+      "mode": "force-https", "include_subdomains": true,
+      "pins": "ncsccs",
+      "expect_staple": true, "include_subdomains_for_expect_staple": true,
+      "expect_staple_report_uri": "https://log.ncsccs.com/report/expectocsp",
+      "expect_ct": true,
+      "expect_ct_report_uri": "https://log.ncsccs.com/report/expectct"
     },
-    // hstspreload.org can't scan IPv6-only sites due to Google Cloud limitations.
-    { "name": "ipv6only.network", "include_subdomains": true, "mode": "force-https" },
-    { "name": "cloudflare.com", "include_subdomains": false, "mode": "force-https", "expect_staple": true, "expect_staple_report_uri": "https://staple.watch/cdn-cgi/beacon/expect-staple" },
-    { "name": "www.cloudflare.com", "include_subdomains": false, "mode": "force-https", "expect_staple": true, "expect_staple_report_uri": "https://staple.watch/cdn-cgi/beacon/expect-staple" },
-    { "name": "api.cloudflare.com", "include_subdomains": false, "mode": "force-https", "expect_staple": true, "expect_staple_report_uri": "https://staple.watch/cdn-cgi/beacon/expect-staple" },
+    {
+      "name": "cloudflare.com",
+      "mode": "force-https", "include_subdomains": false,
+      "expect_staple": true,
+      "expect_staple_report_uri": "https://staple.watch/cdn-cgi/beacon/expect-staple"
+    },
+    {
+      "name": "www.cloudflare.com",
+      "mode": "force-https", "include_subdomains": false,
+      "expect_staple": true,
+      "expect_staple_report_uri": "https://staple.watch/cdn-cgi/beacon/expect-staple"
+    },
+    {
+      "name": "api.cloudflare.com",
+      "mode": "force-https", "include_subdomains": false,
+      "expect_staple": true,
+      "expect_staple_report_uri": "https://staple.watch/cdn-cgi/beacon/expect-staple"
+    },
+    {
+      "name": "weeblrpress.com",
+      "mode": "force-https", "include_subdomains": true,
+      "expect_staple": true, "include_subdomains_for_expect_staple": true,
+      "expect_staple_report_uri": "https://weeblr.report-uri.io/r/default/staple/reportOnly"
+    },
     // END OF MANUAL ENTRIES
 
+    // TODO(lgarron): hstspreload.org can't scan IPv6-only sites due to Google
+    // Cloud limitations. Move these entries to the bulk entries once they can
+    // be handled automatically: github.com/chromium/hstspreload.org/issues/43
+    // START OF IPV6-ONLY ENTRIES
+    { "name": "ipv6only.network", "include_subdomains": true, "mode": "force-https" },
+    // END OF IPV6-ONLY ENTRIES
+
+    // eTLD owners who are working towards wide HSTS adoption can request to
+    // preload entries at registration time.
+    // START OF ETLD-OWNER REQUESTED ENTRIES
+    { "name": "digital.gov", "include_subdomains": true, "mode": "force-https" },
+    { "name": "cdcpartners.gov", "include_subdomains": true, "mode": "force-https" },
+    { "name": "smarterskies.gov", "include_subdomains": true, "mode": "force-https" },
+    { "name": "atcreform.gov", "include_subdomains": true, "mode": "force-https" },
+    { "name": "myfdic.gov", "include_subdomains": true, "mode": "force-https" },
+    { "name": "innovation.gov", "include_subdomains": true, "mode": "force-https" },
+    { "name": "trainingproviderresults.gov", "include_subdomains": true, "mode": "force-https" },
+    // END OF ETLD-OWNER REQUESTED ENTRIES
+
     // To avoid trailing comma changes from showing up in diffs, we place a
     // single entry at the end.
     { "name": "hstspreload.org", "include_subdomains": true, "mode": "force-https" }
diff --git a/net/quic/chromium/quic_http_stream.cc b/net/quic/chromium/quic_http_stream.cc
index e29e28f..7e133af 100644
--- a/net/quic/chromium/quic_http_stream.cc
+++ b/net/quic/chromium/quic_http_stream.cc
@@ -90,6 +90,8 @@
       return HttpResponseInfo::CONNECTION_INFO_QUIC_39;
     case QUIC_VERSION_40:
       return HttpResponseInfo::CONNECTION_INFO_QUIC_40;
+    case QUIC_VERSION_41:
+      return HttpResponseInfo::CONNECTION_INFO_QUIC_41;
   }
   NOTREACHED();
   return HttpResponseInfo::CONNECTION_INFO_QUIC_UNKNOWN_VERSION;
diff --git a/net/quic/core/crypto/crypto_framer.h b/net/quic/core/crypto/crypto_framer.h
index 3daf862..9ff7036 100644
--- a/net/quic/core/crypto/crypto_framer.h
+++ b/net/quic/core/crypto/crypto_framer.h
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include "net/quic/core/crypto/crypto_handshake_message.h"
+#include "net/quic/core/crypto/crypto_message_parser.h"
 #include "net/quic/core/quic_packets.h"
 #include "net/quic/platform/api/quic_export.h"
 
@@ -32,22 +33,6 @@
   virtual void OnHandshakeMessage(const CryptoHandshakeMessage& message) = 0;
 };
 
-class QUIC_EXPORT_PRIVATE CryptoMessageParser {
- public:
-  virtual ~CryptoMessageParser() {}
-
-  virtual QuicErrorCode error() const = 0;
-  virtual const std::string& error_detail() const = 0;
-
-  // Processes input data, which must be delivered in order. Returns
-  // false if there was an error, and true otherwise.
-  virtual bool ProcessInput(QuicStringPiece input, Perspective perspective) = 0;
-
-  // Returns the number of bytes of buffered input data remaining to be
-  // parsed.
-  virtual size_t InputBytesRemaining() const = 0;
-};
-
 // A class for framing the crypto messages that are exchanged in a QUIC
 // session.
 class QUIC_EXPORT_PRIVATE CryptoFramer : public CryptoMessageParser {
diff --git a/net/quic/core/crypto/crypto_message_parser.h b/net/quic/core/crypto/crypto_message_parser.h
new file mode 100644
index 0000000..3f08b351
--- /dev/null
+++ b/net/quic/core/crypto/crypto_message_parser.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_CORE_CRYPTO_CRYPTO_MESSAGE_PARSER_H_
+#define NET_QUIC_CORE_CRYPTO_CRYPTO_MESSAGE_PARSER_H_
+
+#include "net/quic/core/quic_error_codes.h"
+#include "net/quic/core/quic_types.h"
+#include "net/quic/platform/api/quic_string_piece.h"
+
+namespace net {
+
+class QUIC_EXPORT_PRIVATE CryptoMessageParser {
+ public:
+  virtual ~CryptoMessageParser() {}
+
+  virtual QuicErrorCode error() const = 0;
+  virtual const std::string& error_detail() const = 0;
+
+  // Processes input data, which must be delivered in order. Returns
+  // false if there was an error, and true otherwise.
+  virtual bool ProcessInput(QuicStringPiece input, Perspective perspective) = 0;
+
+  // Returns the number of bytes of buffered input data remaining to be
+  // parsed.
+  virtual size_t InputBytesRemaining() const = 0;
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_CRYPTO_CRYPTO_MESSAGE_PARSER_H_
diff --git a/net/quic/core/frames/quic_ack_frame.cc b/net/quic/core/frames/quic_ack_frame.cc
index 77016b9d..a86f6d0 100644
--- a/net/quic/core/frames/quic_ack_frame.cc
+++ b/net/quic/core/frames/quic_ack_frame.cc
@@ -203,12 +203,13 @@
   const QuicPacketNumber old_min = Min();
   if (use_deque_) {
     while (!packet_number_deque_.empty()) {
-      if (packet_number_deque_[0].max() < higher) {
+      if (packet_number_deque_.front().max() < higher) {
         packet_number_deque_.pop_front();
-      } else if (packet_number_deque_[0].min() < higher &&
-                 packet_number_deque_[0].max() >= higher) {
-        packet_number_deque_[0].SetMin(higher);
-        if (packet_number_deque_[0].max() == packet_number_deque_[0].min()) {
+      } else if (packet_number_deque_.front().min() < higher &&
+                 packet_number_deque_.front().max() >= higher) {
+        packet_number_deque_.front().SetMin(higher);
+        if (packet_number_deque_.front().max() ==
+            packet_number_deque_.front().min()) {
           packet_number_deque_.pop_front();
         }
         break;
@@ -239,18 +240,25 @@
 
 bool PacketNumberQueue::Contains(QuicPacketNumber packet_number) const {
   if (use_deque_) {
-    // TODO(lilika): Consider using std::binary_search based on profiles
-    // http://www.cplusplus.com/reference/algorithm/binary_search/
     if (packet_number_deque_.empty()) {
       return false;
     }
-    for (Interval<QuicPacketNumber> interval : packet_number_deque_) {
-      if (packet_number < interval.min()) {
-        return false;
+    int low = 0;
+    int high = packet_number_deque_.size() - 1;
+
+    while (low <= high) {
+      int mid = (low + high) / 2;
+      if (packet_number_deque_[mid].min() > packet_number) {
+        high = mid - 1;
+        continue;
       }
-      if (interval.min() <= packet_number && interval.max() > packet_number) {
-        return true;
+      if (packet_number_deque_[mid].max() <= packet_number) {
+        low = mid + 1;
+        continue;
       }
+      DCHECK(packet_number_deque_[mid].max() > packet_number);
+      DCHECK(packet_number_deque_[mid].min() <= packet_number);
+      return true;
     }
     return false;
   } else {
@@ -269,7 +277,7 @@
 QuicPacketNumber PacketNumberQueue::Min() const {
   DCHECK(!Empty());
   if (use_deque_) {
-    return packet_number_deque_[0].min();
+    return packet_number_deque_.front().min();
   } else {
     return packet_number_intervals_.begin()->min();
   }
@@ -278,7 +286,7 @@
 QuicPacketNumber PacketNumberQueue::Max() const {
   DCHECK(!Empty());
   if (use_deque_) {
-    return packet_number_deque_[packet_number_deque_.size() - 1].max() - 1;
+    return packet_number_deque_.back().max() - 1;
   } else {
     return packet_number_intervals_.rbegin()->max() - 1;
   }
diff --git a/net/quic/core/quic_connection.cc b/net/quic/core/quic_connection.cc
index 99a1280..43964e8c 100644
--- a/net/quic/core/quic_connection.cc
+++ b/net/quic/core/quic_connection.cc
@@ -536,6 +536,10 @@
     return;
   }
 
+  if (FLAGS_quic_reloadable_flag_quic_to_backend_multi_version) {
+    server_supported_versions_ = packet.versions;
+  }
+
   if (!SelectMutualVersion(packet.versions)) {
     CloseConnection(
         QUIC_INVALID_VERSION,
@@ -549,7 +553,9 @@
 
   QUIC_DLOG(INFO) << ENDPOINT
                   << "Negotiated version: " << QuicVersionToString(version());
-  server_supported_versions_ = packet.versions;
+  if (!FLAGS_quic_reloadable_flag_quic_to_backend_multi_version) {
+    server_supported_versions_ = packet.versions;
+  }
   version_negotiation_state_ = NEGOTIATION_IN_PROGRESS;
   RetransmitUnackedPackets(ALL_UNACKED_RETRANSMISSION);
 }
diff --git a/net/quic/core/quic_connection_test.cc b/net/quic/core/quic_connection_test.cc
index ec9ebb4..1511bc974 100644
--- a/net/quic/core/quic_connection_test.cc
+++ b/net/quic/core/quic_connection_test.cc
@@ -5255,6 +5255,16 @@
                               ConnectionCloseBehavior::SILENT_CLOSE);
 }
 
+// Regression test for b/63620844.
+TEST_P(QuicConnectionTest, FailedToWriteHandshakePacket) {
+  FLAGS_quic_reloadable_flag_quic_clear_packet_before_handed_over = true;
+  SimulateNextPacketTooLarge();
+  EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PACKET_WRITE_ERROR, _,
+                                           ConnectionCloseSource::FROM_SELF))
+      .Times(1);
+  connection_.SendCryptoStreamData();
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace net
diff --git a/net/quic/core/quic_crypto_client_handshaker.cc b/net/quic/core/quic_crypto_client_handshaker.cc
new file mode 100644
index 0000000..2fe6c6f6
--- /dev/null
+++ b/net/quic/core/quic_crypto_client_handshaker.cc
@@ -0,0 +1,698 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/core/quic_crypto_client_handshaker.h"
+
+#include <memory>
+
+#include "base/metrics/histogram_macros.h"
+#include "base/metrics/sparse_histogram.h"
+#include "net/quic/core/crypto/crypto_protocol.h"
+#include "net/quic/core/crypto/crypto_utils.h"
+#include "net/quic/core/quic_session.h"
+#include "net/quic/platform/api/quic_flags.h"
+#include "net/quic/platform/api/quic_logging.h"
+#include "net/quic/platform/api/quic_str_cat.h"
+
+using std::string;
+
+namespace net {
+
+QuicCryptoClientHandshaker::ChannelIDSourceCallbackImpl::
+    ChannelIDSourceCallbackImpl(QuicCryptoClientHandshaker* parent)
+    : parent_(parent) {}
+
+QuicCryptoClientHandshaker::ChannelIDSourceCallbackImpl::
+    ~ChannelIDSourceCallbackImpl() {}
+
+void QuicCryptoClientHandshaker::ChannelIDSourceCallbackImpl::Run(
+    std::unique_ptr<ChannelIDKey>* channel_id_key) {
+  if (parent_ == nullptr) {
+    return;
+  }
+
+  parent_->channel_id_key_ = std::move(*channel_id_key);
+  parent_->channel_id_source_callback_run_ = true;
+  parent_->channel_id_source_callback_ = nullptr;
+  parent_->DoHandshakeLoop(nullptr);
+
+  // The ChannelIDSource owns this object and will delete it when this method
+  // returns.
+}
+
+void QuicCryptoClientHandshaker::ChannelIDSourceCallbackImpl::Cancel() {
+  parent_ = nullptr;
+}
+
+QuicCryptoClientHandshaker::ProofVerifierCallbackImpl::
+    ProofVerifierCallbackImpl(QuicCryptoClientHandshaker* parent)
+    : parent_(parent) {}
+
+QuicCryptoClientHandshaker::ProofVerifierCallbackImpl::
+    ~ProofVerifierCallbackImpl() {}
+
+void QuicCryptoClientHandshaker::ProofVerifierCallbackImpl::Run(
+    bool ok,
+    const string& error_details,
+    std::unique_ptr<ProofVerifyDetails>* details) {
+  if (parent_ == nullptr) {
+    return;
+  }
+
+  parent_->verify_ok_ = ok;
+  parent_->verify_error_details_ = error_details;
+  parent_->verify_details_ = std::move(*details);
+  parent_->proof_verify_callback_ = nullptr;
+  parent_->DoHandshakeLoop(nullptr);
+
+  // The ProofVerifier owns this object and will delete it when this method
+  // returns.
+}
+
+void QuicCryptoClientHandshaker::ProofVerifierCallbackImpl::Cancel() {
+  parent_ = nullptr;
+}
+
+QuicCryptoClientHandshaker::QuicCryptoClientHandshaker(
+    const QuicServerId& server_id,
+    QuicCryptoClientStream* stream,
+    QuicSession* session,
+    ProofVerifyContext* verify_context,
+    QuicCryptoClientConfig* crypto_config,
+    QuicCryptoClientStream::ProofHandler* proof_handler)
+    : QuicCryptoHandshaker(stream, session),
+      stream_(stream),
+      session_(session),
+      next_state_(STATE_IDLE),
+      num_client_hellos_(0),
+      crypto_config_(crypto_config),
+      server_id_(server_id),
+      generation_counter_(0),
+      channel_id_sent_(false),
+      channel_id_source_callback_run_(false),
+      channel_id_source_callback_(nullptr),
+      verify_context_(verify_context),
+      proof_verify_callback_(nullptr),
+      proof_handler_(proof_handler),
+      verify_ok_(false),
+      stateless_reject_received_(false),
+      num_scup_messages_received_(0),
+      encryption_established_(false),
+      handshake_confirmed_(false),
+      crypto_negotiated_params_(new QuicCryptoNegotiatedParameters) {}
+
+QuicCryptoClientHandshaker::~QuicCryptoClientHandshaker() {
+  if (channel_id_source_callback_) {
+    channel_id_source_callback_->Cancel();
+  }
+  if (proof_verify_callback_) {
+    proof_verify_callback_->Cancel();
+  }
+}
+
+void QuicCryptoClientHandshaker::OnHandshakeMessage(
+    const CryptoHandshakeMessage& message) {
+  QuicCryptoHandshaker::OnHandshakeMessage(message);
+  if (message.tag() == kSCUP) {
+    if (!handshake_confirmed()) {
+      stream_->CloseConnectionWithDetails(
+          QUIC_CRYPTO_UPDATE_BEFORE_HANDSHAKE_COMPLETE,
+          "Early SCUP disallowed");
+      return;
+    }
+
+    // |message| is an update from the server, so we treat it differently from a
+    // handshake message.
+    HandleServerConfigUpdateMessage(message);
+    num_scup_messages_received_++;
+    return;
+  }
+
+  // Do not process handshake messages after the handshake is confirmed.
+  if (handshake_confirmed()) {
+    stream_->CloseConnectionWithDetails(
+        QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE,
+        "Unexpected handshake message");
+    return;
+  }
+
+  DoHandshakeLoop(&message);
+}
+
+bool QuicCryptoClientHandshaker::CryptoConnect() {
+  next_state_ = STATE_INITIALIZE;
+  DoHandshakeLoop(nullptr);
+  return session()->connection()->connected();
+}
+
+int QuicCryptoClientHandshaker::num_sent_client_hellos() const {
+  return num_client_hellos_;
+}
+
+int QuicCryptoClientHandshaker::num_scup_messages_received() const {
+  return num_scup_messages_received_;
+}
+
+bool QuicCryptoClientHandshaker::WasChannelIDSent() const {
+  return channel_id_sent_;
+}
+
+bool QuicCryptoClientHandshaker::WasChannelIDSourceCallbackRun() const {
+  return channel_id_source_callback_run_;
+}
+
+string QuicCryptoClientHandshaker::chlo_hash() const {
+  return chlo_hash_;
+}
+
+bool QuicCryptoClientHandshaker::encryption_established() const {
+  return encryption_established_;
+}
+
+bool QuicCryptoClientHandshaker::handshake_confirmed() const {
+  return handshake_confirmed_;
+}
+
+const QuicCryptoNegotiatedParameters&
+QuicCryptoClientHandshaker::crypto_negotiated_params() const {
+  return *crypto_negotiated_params_;
+}
+
+CryptoMessageParser* QuicCryptoClientHandshaker::crypto_message_parser() {
+  return QuicCryptoHandshaker::crypto_message_parser();
+}
+
+void QuicCryptoClientHandshaker::HandleServerConfigUpdateMessage(
+    const CryptoHandshakeMessage& server_config_update) {
+  DCHECK(server_config_update.tag() == kSCUP);
+  string error_details;
+  QuicCryptoClientConfig::CachedState* cached =
+      crypto_config_->LookupOrCreate(server_id_);
+  QuicErrorCode error = crypto_config_->ProcessServerConfigUpdate(
+      server_config_update, session()->connection()->clock()->WallNow(),
+      session()->connection()->version(), chlo_hash_, cached,
+      crypto_negotiated_params_, &error_details);
+
+  if (error != QUIC_NO_ERROR) {
+    stream_->CloseConnectionWithDetails(
+        error, "Server config update invalid: " + error_details);
+    return;
+  }
+
+  DCHECK(handshake_confirmed());
+  if (proof_verify_callback_) {
+    proof_verify_callback_->Cancel();
+  }
+  next_state_ = STATE_INITIALIZE_SCUP;
+  DoHandshakeLoop(nullptr);
+}
+
+void QuicCryptoClientHandshaker::DoHandshakeLoop(
+    const CryptoHandshakeMessage* in) {
+  QuicCryptoClientConfig::CachedState* cached =
+      crypto_config_->LookupOrCreate(server_id_);
+
+  QuicAsyncStatus rv = QUIC_SUCCESS;
+  do {
+    CHECK_NE(STATE_NONE, next_state_);
+    const State state = next_state_;
+    next_state_ = STATE_IDLE;
+    rv = QUIC_SUCCESS;
+    switch (state) {
+      case STATE_INITIALIZE:
+        DoInitialize(cached);
+        break;
+      case STATE_SEND_CHLO:
+        DoSendCHLO(cached);
+        return;  // return waiting to hear from server.
+      case STATE_RECV_REJ:
+        DoReceiveREJ(in, cached);
+        break;
+      case STATE_VERIFY_PROOF:
+        rv = DoVerifyProof(cached);
+        break;
+      case STATE_VERIFY_PROOF_COMPLETE:
+        DoVerifyProofComplete(cached);
+        break;
+      case STATE_GET_CHANNEL_ID:
+        rv = DoGetChannelID(cached);
+        break;
+      case STATE_GET_CHANNEL_ID_COMPLETE:
+        DoGetChannelIDComplete();
+        break;
+      case STATE_RECV_SHLO:
+        DoReceiveSHLO(in, cached);
+        break;
+      case STATE_IDLE:
+        // This means that the peer sent us a message that we weren't expecting.
+        stream_->CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
+                                            "Handshake in idle state");
+        return;
+      case STATE_INITIALIZE_SCUP:
+        DoInitializeServerConfigUpdate(cached);
+        break;
+      case STATE_NONE:
+        QUIC_NOTREACHED();
+        return;  // We are done.
+    }
+  } while (rv != QUIC_PENDING && next_state_ != STATE_NONE);
+}
+
+void QuicCryptoClientHandshaker::DoInitialize(
+    QuicCryptoClientConfig::CachedState* cached) {
+  if (!cached->IsEmpty() && !cached->signature().empty()) {
+    // Note that we verify the proof even if the cached proof is valid.
+    // This allows us to respond to CA trust changes or certificate
+    // expiration because it may have been a while since we last verified
+    // the proof.
+    DCHECK(crypto_config_->proof_verifier());
+    // Track proof verification time when cached server config is used.
+    proof_verify_start_time_ = base::TimeTicks::Now();
+    chlo_hash_ = cached->chlo_hash();
+    // If the cached state needs to be verified, do it now.
+    next_state_ = STATE_VERIFY_PROOF;
+  } else {
+    next_state_ = STATE_GET_CHANNEL_ID;
+  }
+}
+
+void QuicCryptoClientHandshaker::DoSendCHLO(
+    QuicCryptoClientConfig::CachedState* cached) {
+  if (stateless_reject_received_) {
+    // If we've gotten to this point, we've sent at least one hello
+    // and received a stateless reject in response.  We cannot
+    // continue to send hellos because the server has abandoned state
+    // for this connection.  Abandon further handshakes.
+    next_state_ = STATE_NONE;
+    if (session()->connection()->connected()) {
+      session()->connection()->CloseConnection(
+          QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, "stateless reject received",
+          ConnectionCloseBehavior::SILENT_CLOSE);
+    }
+    return;
+  }
+
+  // Send the client hello in plaintext.
+  session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE);
+  encryption_established_ = false;
+  if (num_client_hellos_ > QuicCryptoClientStream::kMaxClientHellos) {
+    stream_->CloseConnectionWithDetails(
+        QUIC_CRYPTO_TOO_MANY_REJECTS,
+        QuicStrCat("More than ", QuicCryptoClientStream::kMaxClientHellos,
+                   " rejects"));
+    return;
+  }
+  num_client_hellos_++;
+
+  CryptoHandshakeMessage out;
+  DCHECK(session() != nullptr);
+  DCHECK(session()->config() != nullptr);
+  // Send all the options, regardless of whether we're sending an
+  // inchoate or subsequent hello.
+  session()->config()->ToHandshakeMessage(&out);
+
+  // Send a local timestamp to the server.
+  out.SetValue(kCTIM,
+               session()->connection()->clock()->WallNow().ToUNIXSeconds());
+
+  if (!cached->IsComplete(session()->connection()->clock()->WallNow())) {
+    crypto_config_->FillInchoateClientHello(
+        server_id_, session()->connection()->supported_versions().front(),
+        cached, session()->connection()->random_generator(),
+        /* demand_x509_proof= */ true, crypto_negotiated_params_, &out);
+    // Pad the inchoate client hello to fill up a packet.
+    const QuicByteCount kFramingOverhead = 50;  // A rough estimate.
+    const QuicByteCount max_packet_size =
+        session()->connection()->max_packet_length();
+    if (max_packet_size <= kFramingOverhead) {
+      QUIC_DLOG(DFATAL) << "max_packet_length (" << max_packet_size
+                        << ") has no room for framing overhead.";
+      stream_->CloseConnectionWithDetails(QUIC_INTERNAL_ERROR,
+                                          "max_packet_size too smalll");
+      return;
+    }
+    if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) {
+      QUIC_DLOG(DFATAL) << "Client hello won't fit in a single packet.";
+      stream_->CloseConnectionWithDetails(QUIC_INTERNAL_ERROR,
+                                          "CHLO too large");
+      return;
+    }
+    // TODO(rch): Remove this when we remove:
+    // FLAGS_quic_reloadable_flag_quic_use_chlo_packet_size
+    out.set_minimum_size(
+        static_cast<size_t>(max_packet_size - kFramingOverhead));
+    next_state_ = STATE_RECV_REJ;
+    CryptoUtils::HashHandshakeMessage(out, &chlo_hash_, Perspective::IS_CLIENT);
+    SendHandshakeMessage(out);
+    return;
+  }
+
+  // If the server nonce is empty, copy over the server nonce from a previous
+  // SREJ, if there is one.
+  if (FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support &&
+      crypto_negotiated_params_->server_nonce.empty() &&
+      cached->has_server_nonce()) {
+    crypto_negotiated_params_->server_nonce = cached->GetNextServerNonce();
+    DCHECK(!crypto_negotiated_params_->server_nonce.empty());
+  }
+
+  string error_details;
+  QuicErrorCode error = crypto_config_->FillClientHello(
+      server_id_, session()->connection()->connection_id(),
+      session()->connection()->supported_versions().front(), cached,
+      session()->connection()->clock()->WallNow(),
+      session()->connection()->random_generator(), channel_id_key_.get(),
+      crypto_negotiated_params_, &out, &error_details);
+  if (error != QUIC_NO_ERROR) {
+    // Flush the cached config so that, if it's bad, the server has a
+    // chance to send us another in the future.
+    cached->InvalidateServerConfig();
+    stream_->CloseConnectionWithDetails(error, error_details);
+    return;
+  }
+  CryptoUtils::HashHandshakeMessage(out, &chlo_hash_, Perspective::IS_CLIENT);
+  channel_id_sent_ = (channel_id_key_.get() != nullptr);
+  if (cached->proof_verify_details()) {
+    proof_handler_->OnProofVerifyDetailsAvailable(
+        *cached->proof_verify_details());
+  }
+  next_state_ = STATE_RECV_SHLO;
+  SendHandshakeMessage(out);
+  // Be prepared to decrypt with the new server write key.
+  session()->connection()->SetAlternativeDecrypter(
+      ENCRYPTION_INITIAL,
+      crypto_negotiated_params_->initial_crypters.decrypter.release(),
+      true /* latch once used */);
+  // Send subsequent packets under encryption on the assumption that the
+  // server will accept the handshake.
+  session()->connection()->SetEncrypter(
+      ENCRYPTION_INITIAL,
+      crypto_negotiated_params_->initial_crypters.encrypter.release());
+  session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
+
+  // TODO(ianswett): Merge ENCRYPTION_REESTABLISHED and
+  // ENCRYPTION_FIRST_ESTABLSIHED
+  encryption_established_ = true;
+  session()->OnCryptoHandshakeEvent(QuicSession::ENCRYPTION_REESTABLISHED);
+}
+
+void QuicCryptoClientHandshaker::DoReceiveREJ(
+    const CryptoHandshakeMessage* in,
+    QuicCryptoClientConfig::CachedState* cached) {
+  // We sent a dummy CHLO because we didn't have enough information to
+  // perform a handshake, or we sent a full hello that the server
+  // rejected. Here we hope to have a REJ that contains the information
+  // that we need.
+  if ((in->tag() != kREJ) && (in->tag() != kSREJ)) {
+    next_state_ = STATE_NONE;
+    stream_->CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
+                                        "Expected REJ");
+    return;
+  }
+
+  QuicTagVector reject_reasons;
+  static_assert(sizeof(QuicTag) == sizeof(uint32_t), "header out of sync");
+  if (in->GetTaglist(kRREJ, &reject_reasons) == QUIC_NO_ERROR) {
+    uint32_t packed_error = 0;
+    for (size_t i = 0; i < reject_reasons.size(); ++i) {
+      // HANDSHAKE_OK is 0 and don't report that as error.
+      if (reject_reasons[i] == HANDSHAKE_OK || reject_reasons[i] >= 32) {
+        continue;
+      }
+      HandshakeFailureReason reason =
+          static_cast<HandshakeFailureReason>(reject_reasons[i]);
+      packed_error |= 1 << (reason - 1);
+    }
+    DVLOG(1) << "Reasons for rejection: " << packed_error;
+    if (num_client_hellos_ == QuicCryptoClientStream::kMaxClientHellos) {
+      UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicClientHelloRejectReasons.TooMany",
+                                  packed_error);
+    }
+    UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicClientHelloRejectReasons.Secure",
+                                packed_error);
+  }
+
+  // Receipt of a REJ message means that the server received the CHLO
+  // so we can cancel and retransmissions.
+  session()->connection()->NeuterUnencryptedPackets();
+
+  stateless_reject_received_ = in->tag() == kSREJ;
+  string error_details;
+  QuicErrorCode error = crypto_config_->ProcessRejection(
+      *in, session()->connection()->clock()->WallNow(),
+      session()->connection()->version(), chlo_hash_, cached,
+      crypto_negotiated_params_, &error_details);
+
+  if (error != QUIC_NO_ERROR) {
+    next_state_ = STATE_NONE;
+    stream_->CloseConnectionWithDetails(error, error_details);
+    return;
+  }
+  if (!cached->proof_valid()) {
+    if (!cached->signature().empty()) {
+      // Note that we only verify the proof if the cached proof is not
+      // valid. If the cached proof is valid here, someone else must have
+      // just added the server config to the cache and verified the proof,
+      // so we can assume no CA trust changes or certificate expiration
+      // has happened since then.
+      next_state_ = STATE_VERIFY_PROOF;
+      return;
+    }
+  }
+  next_state_ = STATE_GET_CHANNEL_ID;
+}
+
+QuicAsyncStatus QuicCryptoClientHandshaker::DoVerifyProof(
+    QuicCryptoClientConfig::CachedState* cached) {
+  ProofVerifier* verifier = crypto_config_->proof_verifier();
+  DCHECK(verifier);
+  next_state_ = STATE_VERIFY_PROOF_COMPLETE;
+  generation_counter_ = cached->generation_counter();
+
+  ProofVerifierCallbackImpl* proof_verify_callback =
+      new ProofVerifierCallbackImpl(this);
+
+  verify_ok_ = false;
+
+  QuicAsyncStatus status = verifier->VerifyProof(
+      server_id_.host(), server_id_.port(), cached->server_config(),
+      session()->connection()->version(), chlo_hash_, cached->certs(),
+      cached->cert_sct(), cached->signature(), verify_context_.get(),
+      &verify_error_details_, &verify_details_,
+      std::unique_ptr<ProofVerifierCallback>(proof_verify_callback));
+
+  switch (status) {
+    case QUIC_PENDING:
+      proof_verify_callback_ = proof_verify_callback;
+      QUIC_DVLOG(1) << "Doing VerifyProof";
+      break;
+    case QUIC_FAILURE:
+      break;
+    case QUIC_SUCCESS:
+      verify_ok_ = true;
+      break;
+  }
+  return status;
+}
+
+void QuicCryptoClientHandshaker::DoVerifyProofComplete(
+    QuicCryptoClientConfig::CachedState* cached) {
+  if (!proof_verify_start_time_.is_null()) {
+    UMA_HISTOGRAM_TIMES("Net.QuicSession.VerifyProofTime.CachedServerConfig",
+                        base::TimeTicks::Now() - proof_verify_start_time_);
+  }
+  if (!verify_ok_) {
+    if (verify_details_.get()) {
+      proof_handler_->OnProofVerifyDetailsAvailable(*verify_details_);
+    }
+    if (num_client_hellos_ == 0) {
+      cached->Clear();
+      next_state_ = STATE_INITIALIZE;
+      return;
+    }
+    next_state_ = STATE_NONE;
+    UMA_HISTOGRAM_BOOLEAN("Net.QuicVerifyProofFailed.HandshakeConfirmed",
+                          handshake_confirmed());
+    stream_->CloseConnectionWithDetails(
+        QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_);
+    return;
+  }
+
+  // Check if generation_counter has changed between STATE_VERIFY_PROOF and
+  // STATE_VERIFY_PROOF_COMPLETE state changes.
+  if (generation_counter_ != cached->generation_counter()) {
+    next_state_ = STATE_VERIFY_PROOF;
+  } else {
+    SetCachedProofValid(cached);
+    cached->SetProofVerifyDetails(verify_details_.release());
+    if (!handshake_confirmed()) {
+      next_state_ = STATE_GET_CHANNEL_ID;
+    } else {
+      // TODO: Enable Expect-Staple. https://crbug.com/631101
+      next_state_ = STATE_NONE;
+    }
+  }
+}
+
+QuicAsyncStatus QuicCryptoClientHandshaker::DoGetChannelID(
+    QuicCryptoClientConfig::CachedState* cached) {
+  next_state_ = STATE_GET_CHANNEL_ID_COMPLETE;
+  channel_id_key_.reset();
+  if (!RequiresChannelID(cached)) {
+    next_state_ = STATE_SEND_CHLO;
+    return QUIC_SUCCESS;
+  }
+
+  ChannelIDSourceCallbackImpl* channel_id_source_callback =
+      new ChannelIDSourceCallbackImpl(this);
+  QuicAsyncStatus status = crypto_config_->channel_id_source()->GetChannelIDKey(
+      server_id_.host(), &channel_id_key_, channel_id_source_callback);
+
+  switch (status) {
+    case QUIC_PENDING:
+      channel_id_source_callback_ = channel_id_source_callback;
+      QUIC_DVLOG(1) << "Looking up channel ID";
+      break;
+    case QUIC_FAILURE:
+      next_state_ = STATE_NONE;
+      delete channel_id_source_callback;
+      stream_->CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
+                                          "Channel ID lookup failed");
+      break;
+    case QUIC_SUCCESS:
+      delete channel_id_source_callback;
+      break;
+  }
+  return status;
+}
+
+void QuicCryptoClientHandshaker::DoGetChannelIDComplete() {
+  if (!channel_id_key_.get()) {
+    next_state_ = STATE_NONE;
+    stream_->CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
+                                        "Channel ID lookup failed");
+    return;
+  }
+  next_state_ = STATE_SEND_CHLO;
+}
+
+void QuicCryptoClientHandshaker::DoReceiveSHLO(
+    const CryptoHandshakeMessage* in,
+    QuicCryptoClientConfig::CachedState* cached) {
+  next_state_ = STATE_NONE;
+  // We sent a CHLO that we expected to be accepted and now we're
+  // hoping for a SHLO from the server to confirm that.  First check
+  // to see whether the response was a reject, and if so, move on to
+  // the reject-processing state.
+  if ((in->tag() == kREJ) || (in->tag() == kSREJ)) {
+    // alternative_decrypter will be nullptr if the original alternative
+    // decrypter latched and became the primary decrypter. That happens
+    // if we received a message encrypted with the INITIAL key.
+    if (session()->connection()->alternative_decrypter() == nullptr) {
+      // The rejection was sent encrypted!
+      stream_->CloseConnectionWithDetails(
+          QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT, "encrypted REJ message");
+      return;
+    }
+    next_state_ = STATE_RECV_REJ;
+    return;
+  }
+
+  if (in->tag() != kSHLO) {
+    stream_->CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
+                                        "Expected SHLO or REJ");
+    return;
+  }
+
+  // alternative_decrypter will be nullptr if the original alternative
+  // decrypter latched and became the primary decrypter. That happens
+  // if we received a message encrypted with the INITIAL key.
+  if (session()->connection()->alternative_decrypter() != nullptr) {
+    // The server hello was sent without encryption.
+    stream_->CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
+                                        "unencrypted SHLO message");
+    return;
+  }
+
+  string error_details;
+  QuicErrorCode error = crypto_config_->ProcessServerHello(
+      *in, session()->connection()->connection_id(),
+      session()->connection()->version(),
+      session()->connection()->server_supported_versions(), cached,
+      crypto_negotiated_params_, &error_details);
+
+  if (error != QUIC_NO_ERROR) {
+    stream_->CloseConnectionWithDetails(
+        error, "Server hello invalid: " + error_details);
+    return;
+  }
+  error = session()->config()->ProcessPeerHello(*in, SERVER, &error_details);
+  if (error != QUIC_NO_ERROR) {
+    stream_->CloseConnectionWithDetails(
+        error, "Server hello invalid: " + error_details);
+    return;
+  }
+  session()->OnConfigNegotiated();
+
+  CrypterPair* crypters = &crypto_negotiated_params_->forward_secure_crypters;
+  // TODO(agl): we don't currently latch this decrypter because the idea
+  // has been floated that the server shouldn't send packets encrypted
+  // with the FORWARD_SECURE key until it receives a FORWARD_SECURE
+  // packet from the client.
+  session()->connection()->SetAlternativeDecrypter(
+      ENCRYPTION_FORWARD_SECURE, crypters->decrypter.release(),
+      false /* don't latch */);
+  session()->connection()->SetEncrypter(ENCRYPTION_FORWARD_SECURE,
+                                        crypters->encrypter.release());
+  session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+
+  handshake_confirmed_ = true;
+  session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
+  session()->connection()->OnHandshakeComplete();
+}
+
+void QuicCryptoClientHandshaker::DoInitializeServerConfigUpdate(
+    QuicCryptoClientConfig::CachedState* cached) {
+  bool update_ignored = false;
+  if (!cached->IsEmpty() && !cached->signature().empty()) {
+    // Note that we verify the proof even if the cached proof is valid.
+    DCHECK(crypto_config_->proof_verifier());
+    next_state_ = STATE_VERIFY_PROOF;
+  } else {
+    update_ignored = true;
+    next_state_ = STATE_NONE;
+  }
+  UMA_HISTOGRAM_COUNTS_1M("Net.QuicNumServerConfig.UpdateMessagesIgnored",
+                          update_ignored);
+}
+
+void QuicCryptoClientHandshaker::SetCachedProofValid(
+    QuicCryptoClientConfig::CachedState* cached) {
+  cached->SetProofValid();
+  proof_handler_->OnProofValid(*cached);
+}
+
+bool QuicCryptoClientHandshaker::RequiresChannelID(
+    QuicCryptoClientConfig::CachedState* cached) {
+  if (server_id_.privacy_mode() == PRIVACY_MODE_ENABLED ||
+      !crypto_config_->channel_id_source()) {
+    return false;
+  }
+  const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
+  if (!scfg) {  // scfg may be null then we send an inchoate CHLO.
+    return false;
+  }
+  QuicTagVector their_proof_demands;
+  if (scfg->GetTaglist(kPDMD, &their_proof_demands) != QUIC_NO_ERROR) {
+    return false;
+  }
+  for (const QuicTag tag : their_proof_demands) {
+    if (tag == kCHID) {
+      return true;
+    }
+  }
+  return false;
+}
+
+}  // namespace net
diff --git a/net/quic/core/quic_crypto_client_handshaker.h b/net/quic/core/quic_crypto_client_handshaker.h
new file mode 100644
index 0000000..ad5e79b
--- /dev/null
+++ b/net/quic/core/quic_crypto_client_handshaker.h
@@ -0,0 +1,240 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_CORE_QUIC_CRYPTO_CLIENT_HANDSHAKER_H_
+#define NET_QUIC_CORE_QUIC_CRYPTO_CLIENT_HANDSHAKER_H_
+
+#include "net/quic/core/crypto/channel_id.h"
+#include "net/quic/core/crypto/proof_verifier.h"
+#include "net/quic/core/crypto/quic_crypto_client_config.h"
+#include "net/quic/core/quic_crypto_client_stream.h"
+#include "net/quic/core/quic_server_id.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+namespace test {
+class QuicChromiumClientSessionPeer;
+}  // namespace test
+
+// An implementation of QuicCryptoClientStream::HandshakerDelegate which uses
+// QUIC crypto as the crypto handshake protocol.
+class QUIC_EXPORT_PRIVATE QuicCryptoClientHandshaker
+    : public QuicCryptoClientStream::HandshakerDelegate,
+      public QuicCryptoHandshaker {
+ public:
+  QuicCryptoClientHandshaker(
+      const QuicServerId& server_id,
+      QuicCryptoClientStream* stream,
+      QuicSession* session,
+      ProofVerifyContext* verify_context,
+      QuicCryptoClientConfig* crypto_config,
+      QuicCryptoClientStream::ProofHandler* proof_handler);
+
+  ~QuicCryptoClientHandshaker() override;
+
+  // From QuicCryptoClientStream::HandshakerDelegate
+  bool CryptoConnect() override;
+  int num_sent_client_hellos() const override;
+  int num_scup_messages_received() const override;
+  bool WasChannelIDSent() const override;
+  bool WasChannelIDSourceCallbackRun() const override;
+  std::string chlo_hash() const override;
+  bool encryption_established() const override;
+  bool handshake_confirmed() const override;
+  const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
+      const override;
+  CryptoMessageParser* crypto_message_parser() override;
+
+  // From QuicCryptoHandshaker
+  void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
+
+ private:
+  // ChannelIDSourceCallbackImpl is passed as the callback method to
+  // GetChannelIDKey. The ChannelIDSource calls this class with the result of
+  // channel ID lookup when lookup is performed asynchronously.
+  class ChannelIDSourceCallbackImpl : public ChannelIDSourceCallback {
+   public:
+    explicit ChannelIDSourceCallbackImpl(QuicCryptoClientHandshaker* parent);
+    ~ChannelIDSourceCallbackImpl() override;
+
+    // ChannelIDSourceCallback interface.
+    void Run(std::unique_ptr<ChannelIDKey>* channel_id_key) override;
+
+    // Cancel causes any future callbacks to be ignored. It must be called on
+    // the same thread as the callback will be made on.
+    void Cancel();
+
+   private:
+    QuicCryptoClientHandshaker* parent_;
+  };
+
+  // ProofVerifierCallbackImpl is passed as the callback method to VerifyProof.
+  // The ProofVerifier calls this class with the result of proof verification
+  // when verification is performed asynchronously.
+  class ProofVerifierCallbackImpl : public ProofVerifierCallback {
+   public:
+    explicit ProofVerifierCallbackImpl(QuicCryptoClientHandshaker* parent);
+    ~ProofVerifierCallbackImpl() override;
+
+    // ProofVerifierCallback interface.
+    void Run(bool ok,
+             const std::string& error_details,
+             std::unique_ptr<ProofVerifyDetails>* details) override;
+
+    // Cancel causes any future callbacks to be ignored. It must be called on
+    // the same thread as the callback will be made on.
+    void Cancel();
+
+   private:
+    QuicCryptoClientHandshaker* parent_;
+  };
+
+  friend class test::QuicChromiumClientSessionPeer;
+
+  enum State {
+    STATE_IDLE,
+    STATE_INITIALIZE,
+    STATE_SEND_CHLO,
+    STATE_RECV_REJ,
+    STATE_VERIFY_PROOF,
+    STATE_VERIFY_PROOF_COMPLETE,
+    STATE_GET_CHANNEL_ID,
+    STATE_GET_CHANNEL_ID_COMPLETE,
+    STATE_RECV_SHLO,
+    STATE_INITIALIZE_SCUP,
+    STATE_NONE,
+  };
+
+  // Handles new server config and optional source-address token provided by the
+  // server during a connection.
+  void HandleServerConfigUpdateMessage(
+      const CryptoHandshakeMessage& server_config_update);
+
+  // DoHandshakeLoop performs a step of the handshake state machine. Note that
+  // |in| may be nullptr if the call did not result from a received message.
+  void DoHandshakeLoop(const CryptoHandshakeMessage* in);
+
+  // Start the handshake process.
+  void DoInitialize(QuicCryptoClientConfig::CachedState* cached);
+
+  // Send either InchoateClientHello or ClientHello message to the server.
+  void DoSendCHLO(QuicCryptoClientConfig::CachedState* cached);
+
+  // Process REJ message from the server.
+  void DoReceiveREJ(const CryptoHandshakeMessage* in,
+                    QuicCryptoClientConfig::CachedState* cached);
+
+  // Start the proof verification process. Returns the QuicAsyncStatus returned
+  // by the ProofVerifier's VerifyProof.
+  QuicAsyncStatus DoVerifyProof(QuicCryptoClientConfig::CachedState* cached);
+
+  // If proof is valid then it sets the proof as valid (which persists the
+  // server config). If not, it closes the connection.
+  void DoVerifyProofComplete(QuicCryptoClientConfig::CachedState* cached);
+
+  // Start the look up of Channel ID process. Returns either QUIC_SUCCESS if
+  // RequiresChannelID returns false or QuicAsyncStatus returned by
+  // GetChannelIDKey.
+  QuicAsyncStatus DoGetChannelID(QuicCryptoClientConfig::CachedState* cached);
+
+  // If there is no channel ID, then close the connection otherwise transtion to
+  // STATE_SEND_CHLO state.
+  void DoGetChannelIDComplete();
+
+  // Process SHLO message from the server.
+  void DoReceiveSHLO(const CryptoHandshakeMessage* in,
+                     QuicCryptoClientConfig::CachedState* cached);
+
+  // Start the proof verification if |server_id_| is https and |cached| has
+  // signature.
+  void DoInitializeServerConfigUpdate(
+      QuicCryptoClientConfig::CachedState* cached);
+
+  // Called to set the proof of |cached| valid.  Also invokes the session's
+  // OnProofValid() method.
+  void SetCachedProofValid(QuicCryptoClientConfig::CachedState* cached);
+
+  // Returns true if the server crypto config in |cached| requires a ChannelID
+  // and the client config settings also allow sending a ChannelID.
+  bool RequiresChannelID(QuicCryptoClientConfig::CachedState* cached);
+
+  // Returns the QuicSession that this stream belongs to.
+  QuicSession* session() const { return session_; }
+
+  QuicCryptoClientStream* stream_;
+
+  QuicSession* session_;
+
+  State next_state_;
+  // num_client_hellos_ contains the number of client hello messages that this
+  // connection has sent.
+  int num_client_hellos_;
+
+  QuicCryptoClientConfig* const crypto_config_;
+
+  // SHA-256 hash of the most recently sent CHLO.
+  std::string chlo_hash_;
+
+  // Server's (hostname, port, is_https, privacy_mode) tuple.
+  const QuicServerId server_id_;
+
+  // Generation counter from QuicCryptoClientConfig's CachedState.
+  uint64_t generation_counter_;
+
+  // True if a channel ID was sent.
+  bool channel_id_sent_;
+
+  // True if channel_id_source_callback_ was run.
+  bool channel_id_source_callback_run_;
+
+  // channel_id_source_callback_ contains the callback object that we passed
+  // to an asynchronous channel ID lookup. The ChannelIDSource owns this
+  // object.
+  ChannelIDSourceCallbackImpl* channel_id_source_callback_;
+
+  // These members are used to store the result of an asynchronous channel ID
+  // lookup. These members must not be used after
+  // STATE_GET_CHANNEL_ID_COMPLETE.
+  std::unique_ptr<ChannelIDKey> channel_id_key_;
+
+  // verify_context_ contains the context object that we pass to asynchronous
+  // proof verifications.
+  std::unique_ptr<ProofVerifyContext> verify_context_;
+
+  // proof_verify_callback_ contains the callback object that we passed to an
+  // asynchronous proof verification. The ProofVerifier owns this object.
+  ProofVerifierCallbackImpl* proof_verify_callback_;
+  // proof_handler_ contains the callback object used by a quic client
+  // for proof verification. It is not owned by this class.
+  QuicCryptoClientStream::ProofHandler* proof_handler_;
+
+  // These members are used to store the result of an asynchronous proof
+  // verification. These members must not be used after
+  // STATE_VERIFY_PROOF_COMPLETE.
+  bool verify_ok_;
+  std::string verify_error_details_;
+  std::unique_ptr<ProofVerifyDetails> verify_details_;
+
+  // True if the server responded to a previous CHLO with a stateless
+  // reject.  Used for book-keeping between the STATE_RECV_REJ,
+  // STATE_VERIFY_PROOF*, and subsequent STATE_SEND_CHLO state.
+  bool stateless_reject_received_;
+
+  // Only used in chromium, not internally.
+  base::TimeTicks proof_verify_start_time_;
+
+  int num_scup_messages_received_;
+
+  bool encryption_established_;
+  bool handshake_confirmed_;
+  QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters>
+      crypto_negotiated_params_;
+
+  DISALLOW_COPY_AND_ASSIGN(QuicCryptoClientHandshaker);
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_QUIC_CRYPTO_CLIENT_HANDSHAKER_H_
diff --git a/net/quic/core/quic_crypto_client_stream.cc b/net/quic/core/quic_crypto_client_stream.cc
index 251d1301..1599716c 100644
--- a/net/quic/core/quic_crypto_client_stream.cc
+++ b/net/quic/core/quic_crypto_client_stream.cc
@@ -11,6 +11,7 @@
 #include "net/quic/core/crypto/crypto_protocol.h"
 #include "net/quic/core/crypto/crypto_utils.h"
 #include "net/quic/core/crypto/null_encrypter.h"
+#include "net/quic/core/quic_crypto_client_handshaker.h"
 #include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_session.h"
 #include "net/quic/core/quic_utils.h"
@@ -27,61 +28,6 @@
 QuicCryptoClientStreamBase::QuicCryptoClientStreamBase(QuicSession* session)
     : QuicCryptoStream(session) {}
 
-QuicCryptoClientHandshaker::ChannelIDSourceCallbackImpl::
-    ChannelIDSourceCallbackImpl(QuicCryptoClientHandshaker* parent)
-    : parent_(parent) {}
-
-QuicCryptoClientHandshaker::ChannelIDSourceCallbackImpl::
-    ~ChannelIDSourceCallbackImpl() {}
-
-void QuicCryptoClientHandshaker::ChannelIDSourceCallbackImpl::Run(
-    std::unique_ptr<ChannelIDKey>* channel_id_key) {
-  if (parent_ == nullptr) {
-    return;
-  }
-
-  parent_->channel_id_key_ = std::move(*channel_id_key);
-  parent_->channel_id_source_callback_run_ = true;
-  parent_->channel_id_source_callback_ = nullptr;
-  parent_->DoHandshakeLoop(nullptr);
-
-  // The ChannelIDSource owns this object and will delete it when this method
-  // returns.
-}
-
-void QuicCryptoClientHandshaker::ChannelIDSourceCallbackImpl::Cancel() {
-  parent_ = nullptr;
-}
-
-QuicCryptoClientHandshaker::ProofVerifierCallbackImpl::
-    ProofVerifierCallbackImpl(QuicCryptoClientHandshaker* parent)
-    : parent_(parent) {}
-
-QuicCryptoClientHandshaker::ProofVerifierCallbackImpl::
-    ~ProofVerifierCallbackImpl() {}
-
-void QuicCryptoClientHandshaker::ProofVerifierCallbackImpl::Run(
-    bool ok,
-    const string& error_details,
-    std::unique_ptr<ProofVerifyDetails>* details) {
-  if (parent_ == nullptr) {
-    return;
-  }
-
-  parent_->verify_ok_ = ok;
-  parent_->verify_error_details_ = error_details;
-  parent_->verify_details_ = std::move(*details);
-  parent_->proof_verify_callback_ = nullptr;
-  parent_->DoHandshakeLoop(nullptr);
-
-  // The ProofVerifier owns this object and will delete it when this method
-  // returns.
-}
-
-void QuicCryptoClientHandshaker::ProofVerifierCallbackImpl::Cancel() {
-  parent_ = nullptr;
-}
-
 QuicCryptoClientStream::QuicCryptoClientStream(
     const QuicServerId& server_id,
     QuicSession* session,
@@ -137,625 +83,4 @@
   return handshaker_->chlo_hash();
 }
 
-QuicCryptoClientHandshaker::QuicCryptoClientHandshaker(
-    const QuicServerId& server_id,
-    QuicCryptoClientStream* stream,
-    QuicSession* session,
-    ProofVerifyContext* verify_context,
-    QuicCryptoClientConfig* crypto_config,
-    QuicCryptoClientStream::ProofHandler* proof_handler)
-    : QuicCryptoHandshaker(stream, session),
-      stream_(stream),
-      session_(session),
-      next_state_(STATE_IDLE),
-      num_client_hellos_(0),
-      crypto_config_(crypto_config),
-      server_id_(server_id),
-      generation_counter_(0),
-      channel_id_sent_(false),
-      channel_id_source_callback_run_(false),
-      channel_id_source_callback_(nullptr),
-      verify_context_(verify_context),
-      proof_verify_callback_(nullptr),
-      proof_handler_(proof_handler),
-      verify_ok_(false),
-      stateless_reject_received_(false),
-      num_scup_messages_received_(0),
-      encryption_established_(false),
-      handshake_confirmed_(false),
-      crypto_negotiated_params_(new QuicCryptoNegotiatedParameters) {}
-
-QuicCryptoClientHandshaker::~QuicCryptoClientHandshaker() {
-  if (channel_id_source_callback_) {
-    channel_id_source_callback_->Cancel();
-  }
-  if (proof_verify_callback_) {
-    proof_verify_callback_->Cancel();
-  }
-}
-
-void QuicCryptoClientHandshaker::OnHandshakeMessage(
-    const CryptoHandshakeMessage& message) {
-  QuicCryptoHandshaker::OnHandshakeMessage(message);
-  if (message.tag() == kSCUP) {
-    if (!handshake_confirmed()) {
-      stream_->CloseConnectionWithDetails(
-          QUIC_CRYPTO_UPDATE_BEFORE_HANDSHAKE_COMPLETE,
-          "Early SCUP disallowed");
-      return;
-    }
-
-    // |message| is an update from the server, so we treat it differently from a
-    // handshake message.
-    HandleServerConfigUpdateMessage(message);
-    num_scup_messages_received_++;
-    return;
-  }
-
-  // Do not process handshake messages after the handshake is confirmed.
-  if (handshake_confirmed()) {
-    stream_->CloseConnectionWithDetails(
-        QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE,
-        "Unexpected handshake message");
-    return;
-  }
-
-  DoHandshakeLoop(&message);
-}
-
-bool QuicCryptoClientHandshaker::CryptoConnect() {
-  next_state_ = STATE_INITIALIZE;
-  DoHandshakeLoop(nullptr);
-  return session()->connection()->connected();
-}
-
-int QuicCryptoClientHandshaker::num_sent_client_hellos() const {
-  return num_client_hellos_;
-}
-
-int QuicCryptoClientHandshaker::num_scup_messages_received() const {
-  return num_scup_messages_received_;
-}
-
-bool QuicCryptoClientHandshaker::WasChannelIDSent() const {
-  return channel_id_sent_;
-}
-
-bool QuicCryptoClientHandshaker::WasChannelIDSourceCallbackRun() const {
-  return channel_id_source_callback_run_;
-}
-
-string QuicCryptoClientHandshaker::chlo_hash() const {
-  return chlo_hash_;
-}
-
-bool QuicCryptoClientHandshaker::encryption_established() const {
-  return encryption_established_;
-}
-
-bool QuicCryptoClientHandshaker::handshake_confirmed() const {
-  return handshake_confirmed_;
-}
-
-const QuicCryptoNegotiatedParameters&
-QuicCryptoClientHandshaker::crypto_negotiated_params() const {
-  return *crypto_negotiated_params_;
-}
-
-CryptoMessageParser* QuicCryptoClientHandshaker::crypto_message_parser() {
-  return QuicCryptoHandshaker::crypto_message_parser();
-}
-
-void QuicCryptoClientHandshaker::HandleServerConfigUpdateMessage(
-    const CryptoHandshakeMessage& server_config_update) {
-  DCHECK(server_config_update.tag() == kSCUP);
-  string error_details;
-  QuicCryptoClientConfig::CachedState* cached =
-      crypto_config_->LookupOrCreate(server_id_);
-  QuicErrorCode error = crypto_config_->ProcessServerConfigUpdate(
-      server_config_update, session()->connection()->clock()->WallNow(),
-      session()->connection()->version(), chlo_hash_, cached,
-      crypto_negotiated_params_, &error_details);
-
-  if (error != QUIC_NO_ERROR) {
-    stream_->CloseConnectionWithDetails(
-        error, "Server config update invalid: " + error_details);
-    return;
-  }
-
-  DCHECK(handshake_confirmed());
-  if (proof_verify_callback_) {
-    proof_verify_callback_->Cancel();
-  }
-  next_state_ = STATE_INITIALIZE_SCUP;
-  DoHandshakeLoop(nullptr);
-}
-
-void QuicCryptoClientHandshaker::DoHandshakeLoop(
-    const CryptoHandshakeMessage* in) {
-  QuicCryptoClientConfig::CachedState* cached =
-      crypto_config_->LookupOrCreate(server_id_);
-
-  QuicAsyncStatus rv = QUIC_SUCCESS;
-  do {
-    CHECK_NE(STATE_NONE, next_state_);
-    const State state = next_state_;
-    next_state_ = STATE_IDLE;
-    rv = QUIC_SUCCESS;
-    switch (state) {
-      case STATE_INITIALIZE:
-        DoInitialize(cached);
-        break;
-      case STATE_SEND_CHLO:
-        DoSendCHLO(cached);
-        return;  // return waiting to hear from server.
-      case STATE_RECV_REJ:
-        DoReceiveREJ(in, cached);
-        break;
-      case STATE_VERIFY_PROOF:
-        rv = DoVerifyProof(cached);
-        break;
-      case STATE_VERIFY_PROOF_COMPLETE:
-        DoVerifyProofComplete(cached);
-        break;
-      case STATE_GET_CHANNEL_ID:
-        rv = DoGetChannelID(cached);
-        break;
-      case STATE_GET_CHANNEL_ID_COMPLETE:
-        DoGetChannelIDComplete();
-        break;
-      case STATE_RECV_SHLO:
-        DoReceiveSHLO(in, cached);
-        break;
-      case STATE_IDLE:
-        // This means that the peer sent us a message that we weren't expecting.
-        stream_->CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
-                                            "Handshake in idle state");
-        return;
-      case STATE_INITIALIZE_SCUP:
-        DoInitializeServerConfigUpdate(cached);
-        break;
-      case STATE_NONE:
-        QUIC_NOTREACHED();
-        return;  // We are done.
-    }
-  } while (rv != QUIC_PENDING && next_state_ != STATE_NONE);
-}
-
-void QuicCryptoClientHandshaker::DoInitialize(
-    QuicCryptoClientConfig::CachedState* cached) {
-  if (!cached->IsEmpty() && !cached->signature().empty()) {
-    // Note that we verify the proof even if the cached proof is valid.
-    // This allows us to respond to CA trust changes or certificate
-    // expiration because it may have been a while since we last verified
-    // the proof.
-    DCHECK(crypto_config_->proof_verifier());
-    // Track proof verification time when cached server config is used.
-    proof_verify_start_time_ = base::TimeTicks::Now();
-    chlo_hash_ = cached->chlo_hash();
-    // If the cached state needs to be verified, do it now.
-    next_state_ = STATE_VERIFY_PROOF;
-  } else {
-    next_state_ = STATE_GET_CHANNEL_ID;
-  }
-}
-
-void QuicCryptoClientHandshaker::DoSendCHLO(
-    QuicCryptoClientConfig::CachedState* cached) {
-  if (stateless_reject_received_) {
-    // If we've gotten to this point, we've sent at least one hello
-    // and received a stateless reject in response.  We cannot
-    // continue to send hellos because the server has abandoned state
-    // for this connection.  Abandon further handshakes.
-    next_state_ = STATE_NONE;
-    if (session()->connection()->connected()) {
-      session()->connection()->CloseConnection(
-          QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, "stateless reject received",
-          ConnectionCloseBehavior::SILENT_CLOSE);
-    }
-    return;
-  }
-
-  // Send the client hello in plaintext.
-  session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE);
-  encryption_established_ = false;
-  if (num_client_hellos_ > QuicCryptoClientStream::kMaxClientHellos) {
-    stream_->CloseConnectionWithDetails(
-        QUIC_CRYPTO_TOO_MANY_REJECTS,
-        QuicStrCat("More than ", QuicCryptoClientStream::kMaxClientHellos,
-                   " rejects"));
-    return;
-  }
-  num_client_hellos_++;
-
-  CryptoHandshakeMessage out;
-  DCHECK(session() != nullptr);
-  DCHECK(session()->config() != nullptr);
-  // Send all the options, regardless of whether we're sending an
-  // inchoate or subsequent hello.
-  session()->config()->ToHandshakeMessage(&out);
-
-  // Send a local timestamp to the server.
-  out.SetValue(kCTIM,
-               session()->connection()->clock()->WallNow().ToUNIXSeconds());
-
-  if (!cached->IsComplete(session()->connection()->clock()->WallNow())) {
-    crypto_config_->FillInchoateClientHello(
-        server_id_, session()->connection()->supported_versions().front(),
-        cached, session()->connection()->random_generator(),
-        /* demand_x509_proof= */ true, crypto_negotiated_params_, &out);
-    // Pad the inchoate client hello to fill up a packet.
-    const QuicByteCount kFramingOverhead = 50;  // A rough estimate.
-    const QuicByteCount max_packet_size =
-        session()->connection()->max_packet_length();
-    if (max_packet_size <= kFramingOverhead) {
-      QUIC_DLOG(DFATAL) << "max_packet_length (" << max_packet_size
-                        << ") has no room for framing overhead.";
-      stream_->CloseConnectionWithDetails(QUIC_INTERNAL_ERROR,
-                                          "max_packet_size too smalll");
-      return;
-    }
-    if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) {
-      QUIC_DLOG(DFATAL) << "Client hello won't fit in a single packet.";
-      stream_->CloseConnectionWithDetails(QUIC_INTERNAL_ERROR,
-                                          "CHLO too large");
-      return;
-    }
-    // TODO(rch): Remove this when we remove:
-    // FLAGS_quic_reloadable_flag_quic_use_chlo_packet_size
-    out.set_minimum_size(
-        static_cast<size_t>(max_packet_size - kFramingOverhead));
-    next_state_ = STATE_RECV_REJ;
-    CryptoUtils::HashHandshakeMessage(out, &chlo_hash_, Perspective::IS_CLIENT);
-    SendHandshakeMessage(out);
-    return;
-  }
-
-  // If the server nonce is empty, copy over the server nonce from a previous
-  // SREJ, if there is one.
-  if (FLAGS_quic_reloadable_flag_enable_quic_stateless_reject_support &&
-      crypto_negotiated_params_->server_nonce.empty() &&
-      cached->has_server_nonce()) {
-    crypto_negotiated_params_->server_nonce = cached->GetNextServerNonce();
-    DCHECK(!crypto_negotiated_params_->server_nonce.empty());
-  }
-
-  string error_details;
-  QuicErrorCode error = crypto_config_->FillClientHello(
-      server_id_, session()->connection()->connection_id(),
-      session()->connection()->supported_versions().front(), cached,
-      session()->connection()->clock()->WallNow(),
-      session()->connection()->random_generator(), channel_id_key_.get(),
-      crypto_negotiated_params_, &out, &error_details);
-  if (error != QUIC_NO_ERROR) {
-    // Flush the cached config so that, if it's bad, the server has a
-    // chance to send us another in the future.
-    cached->InvalidateServerConfig();
-    stream_->CloseConnectionWithDetails(error, error_details);
-    return;
-  }
-  CryptoUtils::HashHandshakeMessage(out, &chlo_hash_, Perspective::IS_CLIENT);
-  channel_id_sent_ = (channel_id_key_.get() != nullptr);
-  if (cached->proof_verify_details()) {
-    proof_handler_->OnProofVerifyDetailsAvailable(
-        *cached->proof_verify_details());
-  }
-  next_state_ = STATE_RECV_SHLO;
-  SendHandshakeMessage(out);
-  // Be prepared to decrypt with the new server write key.
-  session()->connection()->SetAlternativeDecrypter(
-      ENCRYPTION_INITIAL,
-      crypto_negotiated_params_->initial_crypters.decrypter.release(),
-      true /* latch once used */);
-  // Send subsequent packets under encryption on the assumption that the
-  // server will accept the handshake.
-  session()->connection()->SetEncrypter(
-      ENCRYPTION_INITIAL,
-      crypto_negotiated_params_->initial_crypters.encrypter.release());
-  session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
-
-  // TODO(ianswett): Merge ENCRYPTION_REESTABLISHED and
-  // ENCRYPTION_FIRST_ESTABLSIHED
-  encryption_established_ = true;
-  session()->OnCryptoHandshakeEvent(QuicSession::ENCRYPTION_REESTABLISHED);
-}
-
-void QuicCryptoClientHandshaker::DoReceiveREJ(
-    const CryptoHandshakeMessage* in,
-    QuicCryptoClientConfig::CachedState* cached) {
-  // We sent a dummy CHLO because we didn't have enough information to
-  // perform a handshake, or we sent a full hello that the server
-  // rejected. Here we hope to have a REJ that contains the information
-  // that we need.
-  if ((in->tag() != kREJ) && (in->tag() != kSREJ)) {
-    next_state_ = STATE_NONE;
-    stream_->CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
-                                        "Expected REJ");
-    return;
-  }
-
-  QuicTagVector reject_reasons;
-  static_assert(sizeof(QuicTag) == sizeof(uint32_t), "header out of sync");
-  if (in->GetTaglist(kRREJ, &reject_reasons) == QUIC_NO_ERROR) {
-    uint32_t packed_error = 0;
-    for (size_t i = 0; i < reject_reasons.size(); ++i) {
-      // HANDSHAKE_OK is 0 and don't report that as error.
-      if (reject_reasons[i] == HANDSHAKE_OK || reject_reasons[i] >= 32) {
-        continue;
-      }
-      HandshakeFailureReason reason =
-          static_cast<HandshakeFailureReason>(reject_reasons[i]);
-      packed_error |= 1 << (reason - 1);
-    }
-    DVLOG(1) << "Reasons for rejection: " << packed_error;
-    if (num_client_hellos_ == QuicCryptoClientStream::kMaxClientHellos) {
-      UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicClientHelloRejectReasons.TooMany",
-                                  packed_error);
-    }
-    UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicClientHelloRejectReasons.Secure",
-                                packed_error);
-  }
-
-  // Receipt of a REJ message means that the server received the CHLO
-  // so we can cancel and retransmissions.
-  session()->connection()->NeuterUnencryptedPackets();
-
-  stateless_reject_received_ = in->tag() == kSREJ;
-  string error_details;
-  QuicErrorCode error = crypto_config_->ProcessRejection(
-      *in, session()->connection()->clock()->WallNow(),
-      session()->connection()->version(), chlo_hash_, cached,
-      crypto_negotiated_params_, &error_details);
-
-  if (error != QUIC_NO_ERROR) {
-    next_state_ = STATE_NONE;
-    stream_->CloseConnectionWithDetails(error, error_details);
-    return;
-  }
-  if (!cached->proof_valid()) {
-    if (!cached->signature().empty()) {
-      // Note that we only verify the proof if the cached proof is not
-      // valid. If the cached proof is valid here, someone else must have
-      // just added the server config to the cache and verified the proof,
-      // so we can assume no CA trust changes or certificate expiration
-      // has happened since then.
-      next_state_ = STATE_VERIFY_PROOF;
-      return;
-    }
-  }
-  next_state_ = STATE_GET_CHANNEL_ID;
-}
-
-QuicAsyncStatus QuicCryptoClientHandshaker::DoVerifyProof(
-    QuicCryptoClientConfig::CachedState* cached) {
-  ProofVerifier* verifier = crypto_config_->proof_verifier();
-  DCHECK(verifier);
-  next_state_ = STATE_VERIFY_PROOF_COMPLETE;
-  generation_counter_ = cached->generation_counter();
-
-  ProofVerifierCallbackImpl* proof_verify_callback =
-      new ProofVerifierCallbackImpl(this);
-
-  verify_ok_ = false;
-
-  QuicAsyncStatus status = verifier->VerifyProof(
-      server_id_.host(), server_id_.port(), cached->server_config(),
-      session()->connection()->version(), chlo_hash_, cached->certs(),
-      cached->cert_sct(), cached->signature(), verify_context_.get(),
-      &verify_error_details_, &verify_details_,
-      std::unique_ptr<ProofVerifierCallback>(proof_verify_callback));
-
-  switch (status) {
-    case QUIC_PENDING:
-      proof_verify_callback_ = proof_verify_callback;
-      QUIC_DVLOG(1) << "Doing VerifyProof";
-      break;
-    case QUIC_FAILURE:
-      break;
-    case QUIC_SUCCESS:
-      verify_ok_ = true;
-      break;
-  }
-  return status;
-}
-
-void QuicCryptoClientHandshaker::DoVerifyProofComplete(
-    QuicCryptoClientConfig::CachedState* cached) {
-  if (!proof_verify_start_time_.is_null()) {
-    UMA_HISTOGRAM_TIMES("Net.QuicSession.VerifyProofTime.CachedServerConfig",
-                        base::TimeTicks::Now() - proof_verify_start_time_);
-  }
-  if (!verify_ok_) {
-    if (verify_details_.get()) {
-      proof_handler_->OnProofVerifyDetailsAvailable(*verify_details_);
-    }
-    if (num_client_hellos_ == 0) {
-      cached->Clear();
-      next_state_ = STATE_INITIALIZE;
-      return;
-    }
-    next_state_ = STATE_NONE;
-    UMA_HISTOGRAM_BOOLEAN("Net.QuicVerifyProofFailed.HandshakeConfirmed",
-                          handshake_confirmed());
-    stream_->CloseConnectionWithDetails(
-        QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_);
-    return;
-  }
-
-  // Check if generation_counter has changed between STATE_VERIFY_PROOF and
-  // STATE_VERIFY_PROOF_COMPLETE state changes.
-  if (generation_counter_ != cached->generation_counter()) {
-    next_state_ = STATE_VERIFY_PROOF;
-  } else {
-    SetCachedProofValid(cached);
-    cached->SetProofVerifyDetails(verify_details_.release());
-    if (!handshake_confirmed()) {
-      next_state_ = STATE_GET_CHANNEL_ID;
-    } else {
-      // TODO: Enable Expect-Staple. https://crbug.com/631101
-      next_state_ = STATE_NONE;
-    }
-  }
-}
-
-QuicAsyncStatus QuicCryptoClientHandshaker::DoGetChannelID(
-    QuicCryptoClientConfig::CachedState* cached) {
-  next_state_ = STATE_GET_CHANNEL_ID_COMPLETE;
-  channel_id_key_.reset();
-  if (!RequiresChannelID(cached)) {
-    next_state_ = STATE_SEND_CHLO;
-    return QUIC_SUCCESS;
-  }
-
-  ChannelIDSourceCallbackImpl* channel_id_source_callback =
-      new ChannelIDSourceCallbackImpl(this);
-  QuicAsyncStatus status = crypto_config_->channel_id_source()->GetChannelIDKey(
-      server_id_.host(), &channel_id_key_, channel_id_source_callback);
-
-  switch (status) {
-    case QUIC_PENDING:
-      channel_id_source_callback_ = channel_id_source_callback;
-      QUIC_DVLOG(1) << "Looking up channel ID";
-      break;
-    case QUIC_FAILURE:
-      next_state_ = STATE_NONE;
-      delete channel_id_source_callback;
-      stream_->CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
-                                          "Channel ID lookup failed");
-      break;
-    case QUIC_SUCCESS:
-      delete channel_id_source_callback;
-      break;
-  }
-  return status;
-}
-
-void QuicCryptoClientHandshaker::DoGetChannelIDComplete() {
-  if (!channel_id_key_.get()) {
-    next_state_ = STATE_NONE;
-    stream_->CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
-                                        "Channel ID lookup failed");
-    return;
-  }
-  next_state_ = STATE_SEND_CHLO;
-}
-
-void QuicCryptoClientHandshaker::DoReceiveSHLO(
-    const CryptoHandshakeMessage* in,
-    QuicCryptoClientConfig::CachedState* cached) {
-  next_state_ = STATE_NONE;
-  // We sent a CHLO that we expected to be accepted and now we're
-  // hoping for a SHLO from the server to confirm that.  First check
-  // to see whether the response was a reject, and if so, move on to
-  // the reject-processing state.
-  if ((in->tag() == kREJ) || (in->tag() == kSREJ)) {
-    // alternative_decrypter will be nullptr if the original alternative
-    // decrypter latched and became the primary decrypter. That happens
-    // if we received a message encrypted with the INITIAL key.
-    if (session()->connection()->alternative_decrypter() == nullptr) {
-      // The rejection was sent encrypted!
-      stream_->CloseConnectionWithDetails(
-          QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT, "encrypted REJ message");
-      return;
-    }
-    next_state_ = STATE_RECV_REJ;
-    return;
-  }
-
-  if (in->tag() != kSHLO) {
-    stream_->CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
-                                        "Expected SHLO or REJ");
-    return;
-  }
-
-  // alternative_decrypter will be nullptr if the original alternative
-  // decrypter latched and became the primary decrypter. That happens
-  // if we received a message encrypted with the INITIAL key.
-  if (session()->connection()->alternative_decrypter() != nullptr) {
-    // The server hello was sent without encryption.
-    stream_->CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
-                                        "unencrypted SHLO message");
-    return;
-  }
-
-  string error_details;
-  QuicErrorCode error = crypto_config_->ProcessServerHello(
-      *in, session()->connection()->connection_id(),
-      session()->connection()->version(),
-      session()->connection()->server_supported_versions(), cached,
-      crypto_negotiated_params_, &error_details);
-
-  if (error != QUIC_NO_ERROR) {
-    stream_->CloseConnectionWithDetails(
-        error, "Server hello invalid: " + error_details);
-    return;
-  }
-  error = session()->config()->ProcessPeerHello(*in, SERVER, &error_details);
-  if (error != QUIC_NO_ERROR) {
-    stream_->CloseConnectionWithDetails(
-        error, "Server hello invalid: " + error_details);
-    return;
-  }
-  session()->OnConfigNegotiated();
-
-  CrypterPair* crypters = &crypto_negotiated_params_->forward_secure_crypters;
-  // TODO(agl): we don't currently latch this decrypter because the idea
-  // has been floated that the server shouldn't send packets encrypted
-  // with the FORWARD_SECURE key until it receives a FORWARD_SECURE
-  // packet from the client.
-  session()->connection()->SetAlternativeDecrypter(
-      ENCRYPTION_FORWARD_SECURE, crypters->decrypter.release(),
-      false /* don't latch */);
-  session()->connection()->SetEncrypter(ENCRYPTION_FORWARD_SECURE,
-                                        crypters->encrypter.release());
-  session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
-
-  handshake_confirmed_ = true;
-  session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
-  session()->connection()->OnHandshakeComplete();
-}
-
-void QuicCryptoClientHandshaker::DoInitializeServerConfigUpdate(
-    QuicCryptoClientConfig::CachedState* cached) {
-  bool update_ignored = false;
-  if (!cached->IsEmpty() && !cached->signature().empty()) {
-    // Note that we verify the proof even if the cached proof is valid.
-    DCHECK(crypto_config_->proof_verifier());
-    next_state_ = STATE_VERIFY_PROOF;
-  } else {
-    update_ignored = true;
-    next_state_ = STATE_NONE;
-  }
-  UMA_HISTOGRAM_COUNTS_1M("Net.QuicNumServerConfig.UpdateMessagesIgnored",
-                          update_ignored);
-}
-
-void QuicCryptoClientHandshaker::SetCachedProofValid(
-    QuicCryptoClientConfig::CachedState* cached) {
-  cached->SetProofValid();
-  proof_handler_->OnProofValid(*cached);
-}
-
-bool QuicCryptoClientHandshaker::RequiresChannelID(
-    QuicCryptoClientConfig::CachedState* cached) {
-  if (server_id_.privacy_mode() == PRIVACY_MODE_ENABLED ||
-      !crypto_config_->channel_id_source()) {
-    return false;
-  }
-  const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
-  if (!scfg) {  // scfg may be null then we send an inchoate CHLO.
-    return false;
-  }
-  QuicTagVector their_proof_demands;
-  if (scfg->GetTaglist(kPDMD, &their_proof_demands) != QUIC_NO_ERROR) {
-    return false;
-  }
-  for (const QuicTag tag : their_proof_demands) {
-    if (tag == kCHID) {
-      return true;
-    }
-  }
-  return false;
-}
-
 }  // namespace net
diff --git a/net/quic/core/quic_crypto_client_stream.h b/net/quic/core/quic_crypto_client_stream.h
index ecb06e0..af47c9b3 100644
--- a/net/quic/core/quic_crypto_client_stream.h
+++ b/net/quic/core/quic_crypto_client_stream.h
@@ -14,16 +14,13 @@
 #include "net/quic/core/crypto/proof_verifier.h"
 #include "net/quic/core/crypto/quic_crypto_client_config.h"
 #include "net/quic/core/quic_config.h"
+#include "net/quic/core/quic_crypto_handshaker.h"
 #include "net/quic/core/quic_crypto_stream.h"
 #include "net/quic/core/quic_server_id.h"
 #include "net/quic/platform/api/quic_export.h"
 
 namespace net {
 
-namespace test {
-class QuicChromiumClientSessionPeer;
-}  // namespace test
-
 class QUIC_EXPORT_PRIVATE QuicCryptoClientStreamBase : public QuicCryptoStream {
  public:
   explicit QuicCryptoClientStreamBase(QuicSession* session);
@@ -163,223 +160,6 @@
   DISALLOW_COPY_AND_ASSIGN(QuicCryptoClientStream);
 };
 
-// An implementation of QuicCryptoClientStream::HandshakerDelegate which uses
-// QUIC crypto as the crypto handshake protocol.
-class QUIC_EXPORT_PRIVATE QuicCryptoClientHandshaker
-    : public QuicCryptoClientStream::HandshakerDelegate,
-      public QuicCryptoHandshaker {
- public:
-  QuicCryptoClientHandshaker(
-      const QuicServerId& server_id,
-      QuicCryptoClientStream* stream,
-      QuicSession* session,
-      ProofVerifyContext* verify_context,
-      QuicCryptoClientConfig* crypto_config,
-      QuicCryptoClientStream::ProofHandler* proof_handler);
-
-  ~QuicCryptoClientHandshaker() override;
-
-  // From QuicCryptoClientStream::HandshakerDelegate
-  bool CryptoConnect() override;
-  int num_sent_client_hellos() const override;
-  int num_scup_messages_received() const override;
-  bool WasChannelIDSent() const override;
-  bool WasChannelIDSourceCallbackRun() const override;
-  std::string chlo_hash() const override;
-  bool encryption_established() const override;
-  bool handshake_confirmed() const override;
-  const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
-      const override;
-  CryptoMessageParser* crypto_message_parser() override;
-
-  // From QuicCryptoHandshaker
-  void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
-
- private:
-  // ChannelIDSourceCallbackImpl is passed as the callback method to
-  // GetChannelIDKey. The ChannelIDSource calls this class with the result of
-  // channel ID lookup when lookup is performed asynchronously.
-  class ChannelIDSourceCallbackImpl : public ChannelIDSourceCallback {
-   public:
-    explicit ChannelIDSourceCallbackImpl(QuicCryptoClientHandshaker* parent);
-    ~ChannelIDSourceCallbackImpl() override;
-
-    // ChannelIDSourceCallback interface.
-    void Run(std::unique_ptr<ChannelIDKey>* channel_id_key) override;
-
-    // Cancel causes any future callbacks to be ignored. It must be called on
-    // the same thread as the callback will be made on.
-    void Cancel();
-
-   private:
-    QuicCryptoClientHandshaker* parent_;
-  };
-
-  // ProofVerifierCallbackImpl is passed as the callback method to VerifyProof.
-  // The ProofVerifier calls this class with the result of proof verification
-  // when verification is performed asynchronously.
-  class ProofVerifierCallbackImpl : public ProofVerifierCallback {
-   public:
-    explicit ProofVerifierCallbackImpl(QuicCryptoClientHandshaker* parent);
-    ~ProofVerifierCallbackImpl() override;
-
-    // ProofVerifierCallback interface.
-    void Run(bool ok,
-             const std::string& error_details,
-             std::unique_ptr<ProofVerifyDetails>* details) override;
-
-    // Cancel causes any future callbacks to be ignored. It must be called on
-    // the same thread as the callback will be made on.
-    void Cancel();
-
-   private:
-    QuicCryptoClientHandshaker* parent_;
-  };
-
-  friend class test::QuicChromiumClientSessionPeer;
-
-  enum State {
-    STATE_IDLE,
-    STATE_INITIALIZE,
-    STATE_SEND_CHLO,
-    STATE_RECV_REJ,
-    STATE_VERIFY_PROOF,
-    STATE_VERIFY_PROOF_COMPLETE,
-    STATE_GET_CHANNEL_ID,
-    STATE_GET_CHANNEL_ID_COMPLETE,
-    STATE_RECV_SHLO,
-    STATE_INITIALIZE_SCUP,
-    STATE_NONE,
-  };
-
-  // Handles new server config and optional source-address token provided by the
-  // server during a connection.
-  void HandleServerConfigUpdateMessage(
-      const CryptoHandshakeMessage& server_config_update);
-
-  // DoHandshakeLoop performs a step of the handshake state machine. Note that
-  // |in| may be nullptr if the call did not result from a received message.
-  void DoHandshakeLoop(const CryptoHandshakeMessage* in);
-
-  // Start the handshake process.
-  void DoInitialize(QuicCryptoClientConfig::CachedState* cached);
-
-  // Send either InchoateClientHello or ClientHello message to the server.
-  void DoSendCHLO(QuicCryptoClientConfig::CachedState* cached);
-
-  // Process REJ message from the server.
-  void DoReceiveREJ(const CryptoHandshakeMessage* in,
-                    QuicCryptoClientConfig::CachedState* cached);
-
-  // Start the proof verification process. Returns the QuicAsyncStatus returned
-  // by the ProofVerifier's VerifyProof.
-  QuicAsyncStatus DoVerifyProof(QuicCryptoClientConfig::CachedState* cached);
-
-  // If proof is valid then it sets the proof as valid (which persists the
-  // server config). If not, it closes the connection.
-  void DoVerifyProofComplete(QuicCryptoClientConfig::CachedState* cached);
-
-  // Start the look up of Channel ID process. Returns either QUIC_SUCCESS if
-  // RequiresChannelID returns false or QuicAsyncStatus returned by
-  // GetChannelIDKey.
-  QuicAsyncStatus DoGetChannelID(QuicCryptoClientConfig::CachedState* cached);
-
-  // If there is no channel ID, then close the connection otherwise transtion to
-  // STATE_SEND_CHLO state.
-  void DoGetChannelIDComplete();
-
-  // Process SHLO message from the server.
-  void DoReceiveSHLO(const CryptoHandshakeMessage* in,
-                     QuicCryptoClientConfig::CachedState* cached);
-
-  // Start the proof verification if |server_id_| is https and |cached| has
-  // signature.
-  void DoInitializeServerConfigUpdate(
-      QuicCryptoClientConfig::CachedState* cached);
-
-  // Called to set the proof of |cached| valid.  Also invokes the session's
-  // OnProofValid() method.
-  void SetCachedProofValid(QuicCryptoClientConfig::CachedState* cached);
-
-  // Returns true if the server crypto config in |cached| requires a ChannelID
-  // and the client config settings also allow sending a ChannelID.
-  bool RequiresChannelID(QuicCryptoClientConfig::CachedState* cached);
-
-  // Returns the QuicSession that this stream belongs to.
-  QuicSession* session() const { return session_; }
-
-  QuicCryptoClientStream* stream_;
-
-  QuicSession* session_;
-
-  State next_state_;
-  // num_client_hellos_ contains the number of client hello messages that this
-  // connection has sent.
-  int num_client_hellos_;
-
-  QuicCryptoClientConfig* const crypto_config_;
-
-  // SHA-256 hash of the most recently sent CHLO.
-  std::string chlo_hash_;
-
-  // Server's (hostname, port, is_https, privacy_mode) tuple.
-  const QuicServerId server_id_;
-
-  // Generation counter from QuicCryptoClientConfig's CachedState.
-  uint64_t generation_counter_;
-
-  // True if a channel ID was sent.
-  bool channel_id_sent_;
-
-  // True if channel_id_source_callback_ was run.
-  bool channel_id_source_callback_run_;
-
-  // channel_id_source_callback_ contains the callback object that we passed
-  // to an asynchronous channel ID lookup. The ChannelIDSource owns this
-  // object.
-  ChannelIDSourceCallbackImpl* channel_id_source_callback_;
-
-  // These members are used to store the result of an asynchronous channel ID
-  // lookup. These members must not be used after
-  // STATE_GET_CHANNEL_ID_COMPLETE.
-  std::unique_ptr<ChannelIDKey> channel_id_key_;
-
-  // verify_context_ contains the context object that we pass to asynchronous
-  // proof verifications.
-  std::unique_ptr<ProofVerifyContext> verify_context_;
-
-  // proof_verify_callback_ contains the callback object that we passed to an
-  // asynchronous proof verification. The ProofVerifier owns this object.
-  ProofVerifierCallbackImpl* proof_verify_callback_;
-  // proof_handler_ contains the callback object used by a quic client
-  // for proof verification. It is not owned by this class.
-  QuicCryptoClientStream::ProofHandler* proof_handler_;
-
-  // These members are used to store the result of an asynchronous proof
-  // verification. These members must not be used after
-  // STATE_VERIFY_PROOF_COMPLETE.
-  bool verify_ok_;
-  std::string verify_error_details_;
-  std::unique_ptr<ProofVerifyDetails> verify_details_;
-
-  // True if the server responded to a previous CHLO with a stateless
-  // reject.  Used for book-keeping between the STATE_RECV_REJ,
-  // STATE_VERIFY_PROOF*, and subsequent STATE_SEND_CHLO state.
-  bool stateless_reject_received_;
-
-  // Only used in chromium, not internally.
-  base::TimeTicks proof_verify_start_time_;
-
-  int num_scup_messages_received_;
-
-  bool encryption_established_;
-  bool handshake_confirmed_;
-  QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters>
-      crypto_negotiated_params_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicCryptoClientHandshaker);
-};
-
 }  // namespace net
 
 #endif  // NET_QUIC_CORE_QUIC_CRYPTO_CLIENT_STREAM_H_
diff --git a/net/quic/core/quic_crypto_handshaker.cc b/net/quic/core/quic_crypto_handshaker.cc
new file mode 100644
index 0000000..39a9a4e9c
--- /dev/null
+++ b/net/quic/core/quic_crypto_handshaker.cc
@@ -0,0 +1,51 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/core/quic_crypto_handshaker.h"
+
+#include "net/quic/core/quic_session.h"
+
+namespace net {
+
+#define ENDPOINT                                                   \
+  (session()->perspective() == Perspective::IS_SERVER ? "Server: " \
+                                                      : "Client:"  \
+                                                        " ")
+
+QuicCryptoHandshaker::QuicCryptoHandshaker(QuicCryptoStream* stream,
+                                           QuicSession* session)
+    : stream_(stream), session_(session) {
+  crypto_framer_.set_visitor(this);
+}
+
+QuicCryptoHandshaker::~QuicCryptoHandshaker() {}
+
+void QuicCryptoHandshaker::SendHandshakeMessage(
+    const CryptoHandshakeMessage& message) {
+  QUIC_DVLOG(1) << ENDPOINT << "Sending "
+                << message.DebugString(session()->perspective());
+  session()->connection()->NeuterUnencryptedPackets();
+  session()->OnCryptoHandshakeMessageSent(message);
+  const QuicData& data = message.GetSerialized(session()->perspective());
+  stream_->WriteOrBufferData(QuicStringPiece(data.data(), data.length()), false,
+                             nullptr);
+}
+
+void QuicCryptoHandshaker::OnError(CryptoFramer* framer) {
+  QUIC_DLOG(WARNING) << "Error processing crypto data: "
+                     << QuicErrorCodeToString(framer->error());
+}
+
+void QuicCryptoHandshaker::OnHandshakeMessage(
+    const CryptoHandshakeMessage& message) {
+  QUIC_DVLOG(1) << ENDPOINT << "Received "
+                << message.DebugString(session()->perspective());
+  session()->OnCryptoHandshakeMessageReceived(message);
+}
+
+CryptoMessageParser* QuicCryptoHandshaker::crypto_message_parser() {
+  return &crypto_framer_;
+}
+
+}  // namespace net
diff --git a/net/quic/core/quic_crypto_handshaker.h b/net/quic/core/quic_crypto_handshaker.h
new file mode 100644
index 0000000..76deb37
--- /dev/null
+++ b/net/quic/core/quic_crypto_handshaker.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_CORE_QUIC_CRYPTO_HANDSHAKER_H_
+#define NET_QUIC_CORE_QUIC_CRYPTO_HANDSHAKER_H_
+
+#include "net/quic/core/quic_crypto_stream.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+class QUIC_EXPORT_PRIVATE QuicCryptoHandshaker
+    : public CryptoFramerVisitorInterface {
+ public:
+  QuicCryptoHandshaker(QuicCryptoStream* stream, QuicSession* session);
+
+  ~QuicCryptoHandshaker() override;
+
+  // Sends |message| to the peer.
+  // TODO(wtc): return a success/failure status.
+  void SendHandshakeMessage(const CryptoHandshakeMessage& message);
+
+  void OnError(CryptoFramer* framer) override;
+  void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
+
+  CryptoMessageParser* crypto_message_parser();
+
+ private:
+  QuicSession* session() { return session_; }
+
+  QuicCryptoStream* stream_;
+  QuicSession* session_;
+
+  CryptoFramer crypto_framer_;
+
+  DISALLOW_COPY_AND_ASSIGN(QuicCryptoHandshaker);
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_QUIC_CRYPTO_HANDSHAKER_H_
diff --git a/net/quic/core/quic_crypto_server_handshaker.cc b/net/quic/core/quic_crypto_server_handshaker.cc
new file mode 100644
index 0000000..d5102ce9
--- /dev/null
+++ b/net/quic/core/quic_crypto_server_handshaker.cc
@@ -0,0 +1,482 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/core/quic_crypto_server_handshaker.h"
+
+#include <memory>
+
+#include "net/quic/platform/api/quic_text_utils.h"
+#include "third_party/boringssl/src/include/openssl/sha.h"
+
+using std::string;
+
+namespace net {
+
+class QuicCryptoServerHandshaker::ProcessClientHelloCallback
+    : public ProcessClientHelloResultCallback {
+ public:
+  ProcessClientHelloCallback(
+      QuicCryptoServerHandshaker* parent,
+      const QuicReferenceCountedPointer<
+          ValidateClientHelloResultCallback::Result>& result)
+      : parent_(parent), result_(result) {}
+
+  void Run(QuicErrorCode error,
+           const string& error_details,
+           std::unique_ptr<CryptoHandshakeMessage> message,
+           std::unique_ptr<DiversificationNonce> diversification_nonce,
+           std::unique_ptr<net::ProofSource::Details> proof_source_details)
+      override {
+    if (parent_ == nullptr) {
+      return;
+    }
+
+    parent_->FinishProcessingHandshakeMessageAfterProcessClientHello(
+        *result_, error, error_details, std::move(message),
+        std::move(diversification_nonce), std::move(proof_source_details));
+  }
+
+  void Cancel() { parent_ = nullptr; }
+
+ private:
+  QuicCryptoServerHandshaker* parent_;
+  QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+      result_;
+};
+
+QuicCryptoServerHandshaker::QuicCryptoServerHandshaker(
+    const QuicCryptoServerConfig* crypto_config,
+    QuicCryptoServerStream* stream,
+    QuicCompressedCertsCache* compressed_certs_cache,
+    bool use_stateless_rejects_if_peer_supported,
+    QuicSession* session,
+    QuicCryptoServerStream::Helper* helper)
+    : QuicCryptoHandshaker(stream, session),
+      stream_(stream),
+      session_(session),
+      crypto_config_(crypto_config),
+      compressed_certs_cache_(compressed_certs_cache),
+      signed_config_(new QuicSignedServerConfig),
+      helper_(helper),
+      num_handshake_messages_(0),
+      num_handshake_messages_with_server_nonces_(0),
+      send_server_config_update_cb_(nullptr),
+      num_server_config_update_messages_sent_(0),
+      use_stateless_rejects_if_peer_supported_(
+          use_stateless_rejects_if_peer_supported),
+      peer_supports_stateless_rejects_(false),
+      zero_rtt_attempted_(false),
+      chlo_packet_size_(0),
+      validate_client_hello_cb_(nullptr),
+      process_client_hello_cb_(nullptr),
+      encryption_established_(false),
+      handshake_confirmed_(false),
+      crypto_negotiated_params_(new QuicCryptoNegotiatedParameters) {}
+
+QuicCryptoServerHandshaker::~QuicCryptoServerHandshaker() {
+  CancelOutstandingCallbacks();
+}
+
+void QuicCryptoServerHandshaker::CancelOutstandingCallbacks() {
+  // Detach from the validation callback.  Calling this multiple times is safe.
+  if (validate_client_hello_cb_ != nullptr) {
+    validate_client_hello_cb_->Cancel();
+    validate_client_hello_cb_ = nullptr;
+  }
+  if (send_server_config_update_cb_ != nullptr) {
+    send_server_config_update_cb_->Cancel();
+    send_server_config_update_cb_ = nullptr;
+  }
+  if (process_client_hello_cb_ != nullptr) {
+    process_client_hello_cb_->Cancel();
+    process_client_hello_cb_ = nullptr;
+  }
+}
+
+void QuicCryptoServerHandshaker::OnHandshakeMessage(
+    const CryptoHandshakeMessage& message) {
+  QuicCryptoHandshaker::OnHandshakeMessage(message);
+  ++num_handshake_messages_;
+  chlo_packet_size_ = session()->connection()->GetCurrentPacket().length();
+
+  // Do not process handshake messages after the handshake is confirmed.
+  if (handshake_confirmed_) {
+    stream_->CloseConnectionWithDetails(
+        QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE,
+        "Unexpected handshake message from client");
+    return;
+  }
+
+  if (message.tag() != kCHLO) {
+    stream_->CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
+                                        "Handshake packet not CHLO");
+    return;
+  }
+
+  if (validate_client_hello_cb_ != nullptr ||
+      process_client_hello_cb_ != nullptr) {
+    // Already processing some other handshake message.  The protocol
+    // does not allow for clients to send multiple handshake messages
+    // before the server has a chance to respond.
+    stream_->CloseConnectionWithDetails(
+        QUIC_CRYPTO_MESSAGE_WHILE_VALIDATING_CLIENT_HELLO,
+        "Unexpected handshake message while processing CHLO");
+    return;
+  }
+
+  CryptoUtils::HashHandshakeMessage(message, &chlo_hash_,
+                                    Perspective::IS_SERVER);
+
+  std::unique_ptr<ValidateCallback> cb(new ValidateCallback(this));
+  DCHECK(validate_client_hello_cb_ == nullptr);
+  DCHECK(process_client_hello_cb_ == nullptr);
+  validate_client_hello_cb_ = cb.get();
+  crypto_config_->ValidateClientHello(
+      message, GetClientAddress().host(),
+      session()->connection()->self_address(), version(),
+      session()->connection()->clock(), signed_config_, std::move(cb));
+}
+
+void QuicCryptoServerHandshaker::FinishProcessingHandshakeMessage(
+    QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+        result,
+    std::unique_ptr<ProofSource::Details> details) {
+  const CryptoHandshakeMessage& message = result->client_hello;
+
+  // Clear the callback that got us here.
+  DCHECK(validate_client_hello_cb_ != nullptr);
+  DCHECK(process_client_hello_cb_ == nullptr);
+  validate_client_hello_cb_ = nullptr;
+
+  if (use_stateless_rejects_if_peer_supported_) {
+    peer_supports_stateless_rejects_ =
+        QuicCryptoServerStreamBase::DoesPeerSupportStatelessRejects(message);
+  }
+
+  std::unique_ptr<ProcessClientHelloCallback> cb(
+      new ProcessClientHelloCallback(this, result));
+  process_client_hello_cb_ = cb.get();
+  ProcessClientHello(result, std::move(details), std::move(cb));
+}
+
+void QuicCryptoServerHandshaker::
+    FinishProcessingHandshakeMessageAfterProcessClientHello(
+        const ValidateClientHelloResultCallback::Result& result,
+        QuicErrorCode error,
+        const string& error_details,
+        std::unique_ptr<CryptoHandshakeMessage> reply,
+        std::unique_ptr<DiversificationNonce> diversification_nonce,
+        std::unique_ptr<ProofSource::Details> proof_source_details) {
+  // Clear the callback that got us here.
+  DCHECK(process_client_hello_cb_ != nullptr);
+  DCHECK(validate_client_hello_cb_ == nullptr);
+  process_client_hello_cb_ = nullptr;
+
+  const CryptoHandshakeMessage& message = result.client_hello;
+  if (error != QUIC_NO_ERROR) {
+    stream_->CloseConnectionWithDetails(error, error_details);
+    return;
+  }
+
+  if (reply->tag() != kSHLO) {
+    if (reply->tag() == kSREJ) {
+      DCHECK(use_stateless_rejects_if_peer_supported_);
+      DCHECK(peer_supports_stateless_rejects_);
+      // Before sending the SREJ, cause the connection to save crypto packets
+      // so that they can be added to the time wait list manager and
+      // retransmitted.
+      session()->connection()->EnableSavingCryptoPackets();
+    }
+    SendHandshakeMessage(*reply);
+
+    if (reply->tag() == kSREJ) {
+      DCHECK(use_stateless_rejects_if_peer_supported_);
+      DCHECK(peer_supports_stateless_rejects_);
+      DCHECK(!handshake_confirmed());
+      QUIC_DLOG(INFO) << "Closing connection "
+                      << session()->connection()->connection_id()
+                      << " because of a stateless reject.";
+      session()->connection()->CloseConnection(
+          QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, "stateless reject",
+          ConnectionCloseBehavior::SILENT_CLOSE);
+    }
+    return;
+  }
+
+  // If we are returning a SHLO then we accepted the handshake.  Now
+  // process the negotiated configuration options as part of the
+  // session config.
+  QuicConfig* config = session()->config();
+  OverrideQuicConfigDefaults(config);
+  string process_error_details;
+  const QuicErrorCode process_error =
+      config->ProcessPeerHello(message, CLIENT, &process_error_details);
+  if (process_error != QUIC_NO_ERROR) {
+    stream_->CloseConnectionWithDetails(process_error, process_error_details);
+    return;
+  }
+
+  session()->OnConfigNegotiated();
+
+  config->ToHandshakeMessage(reply.get());
+
+  // Receiving a full CHLO implies the client is prepared to decrypt with
+  // the new server write key.  We can start to encrypt with the new server
+  // write key.
+  //
+  // NOTE: the SHLO will be encrypted with the new server write key.
+  session()->connection()->SetEncrypter(
+      ENCRYPTION_INITIAL,
+      crypto_negotiated_params_->initial_crypters.encrypter.release());
+  session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
+  // Set the decrypter immediately so that we no longer accept unencrypted
+  // packets.
+  session()->connection()->SetDecrypter(
+      ENCRYPTION_INITIAL,
+      crypto_negotiated_params_->initial_crypters.decrypter.release());
+  session()->connection()->SetDiversificationNonce(*diversification_nonce);
+
+  SendHandshakeMessage(*reply);
+
+  session()->connection()->SetEncrypter(
+      ENCRYPTION_FORWARD_SECURE,
+      crypto_negotiated_params_->forward_secure_crypters.encrypter.release());
+  session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+
+  session()->connection()->SetAlternativeDecrypter(
+      ENCRYPTION_FORWARD_SECURE,
+      crypto_negotiated_params_->forward_secure_crypters.decrypter.release(),
+      false /* don't latch */);
+
+  encryption_established_ = true;
+  handshake_confirmed_ = true;
+  session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
+}
+
+void QuicCryptoServerHandshaker::SendServerConfigUpdate(
+    const CachedNetworkParameters* cached_network_params) {
+  if (!handshake_confirmed_) {
+    return;
+  }
+
+  if (send_server_config_update_cb_ != nullptr) {
+    QUIC_DVLOG(1)
+        << "Skipped server config update since one is already in progress";
+    return;
+  }
+
+  std::unique_ptr<SendServerConfigUpdateCallback> cb(
+      new SendServerConfigUpdateCallback(this));
+  send_server_config_update_cb_ = cb.get();
+
+  crypto_config_->BuildServerConfigUpdateMessage(
+      session()->connection()->version(), chlo_hash_,
+      previous_source_address_tokens_, session()->connection()->self_address(),
+      GetClientAddress().host(), session()->connection()->clock(),
+      session()->connection()->random_generator(), compressed_certs_cache_,
+      *crypto_negotiated_params_, cached_network_params,
+      (session()->config()->HasReceivedConnectionOptions()
+           ? session()->config()->ReceivedConnectionOptions()
+           : QuicTagVector()),
+      std::move(cb));
+}
+
+QuicCryptoServerHandshaker::SendServerConfigUpdateCallback::
+    SendServerConfigUpdateCallback(QuicCryptoServerHandshaker* parent)
+    : parent_(parent) {}
+
+void QuicCryptoServerHandshaker::SendServerConfigUpdateCallback::Cancel() {
+  parent_ = nullptr;
+}
+
+// From BuildServerConfigUpdateMessageResultCallback
+void QuicCryptoServerHandshaker::SendServerConfigUpdateCallback::Run(
+    bool ok,
+    const CryptoHandshakeMessage& message) {
+  if (parent_ == nullptr) {
+    return;
+  }
+  parent_->FinishSendServerConfigUpdate(ok, message);
+}
+
+void QuicCryptoServerHandshaker::FinishSendServerConfigUpdate(
+    bool ok,
+    const CryptoHandshakeMessage& message) {
+  // Clear the callback that got us here.
+  DCHECK(send_server_config_update_cb_ != nullptr);
+  send_server_config_update_cb_ = nullptr;
+
+  if (!ok) {
+    QUIC_DVLOG(1) << "Server: Failed to build server config update (SCUP)!";
+    return;
+  }
+
+  QUIC_DVLOG(1) << "Server: Sending server config update: "
+                << message.DebugString(Perspective::IS_SERVER);
+  const QuicData& data = message.GetSerialized(Perspective::IS_SERVER);
+  stream_->WriteOrBufferData(QuicStringPiece(data.data(), data.length()), false,
+                             nullptr);
+
+  ++num_server_config_update_messages_sent_;
+}
+
+uint8_t QuicCryptoServerHandshaker::NumHandshakeMessages() const {
+  return num_handshake_messages_;
+}
+
+uint8_t QuicCryptoServerHandshaker::NumHandshakeMessagesWithServerNonces()
+    const {
+  return num_handshake_messages_with_server_nonces_;
+}
+
+int QuicCryptoServerHandshaker::NumServerConfigUpdateMessagesSent() const {
+  return num_server_config_update_messages_sent_;
+}
+
+const CachedNetworkParameters*
+QuicCryptoServerHandshaker::PreviousCachedNetworkParams() const {
+  return previous_cached_network_params_.get();
+}
+
+bool QuicCryptoServerHandshaker::UseStatelessRejectsIfPeerSupported() const {
+  return use_stateless_rejects_if_peer_supported_;
+}
+
+bool QuicCryptoServerHandshaker::PeerSupportsStatelessRejects() const {
+  return peer_supports_stateless_rejects_;
+}
+
+bool QuicCryptoServerHandshaker::ZeroRttAttempted() const {
+  return zero_rtt_attempted_;
+}
+
+void QuicCryptoServerHandshaker::SetPeerSupportsStatelessRejects(
+    bool peer_supports_stateless_rejects) {
+  peer_supports_stateless_rejects_ = peer_supports_stateless_rejects;
+}
+
+void QuicCryptoServerHandshaker::SetPreviousCachedNetworkParams(
+    CachedNetworkParameters cached_network_params) {
+  previous_cached_network_params_.reset(
+      new CachedNetworkParameters(cached_network_params));
+}
+
+bool QuicCryptoServerHandshaker::ShouldSendExpectCTHeader() const {
+  return signed_config_->proof.send_expect_ct_header;
+}
+
+bool QuicCryptoServerHandshaker::GetBase64SHA256ClientChannelID(
+    string* output) const {
+  if (!encryption_established() ||
+      crypto_negotiated_params_->channel_id.empty()) {
+    return false;
+  }
+
+  const string& channel_id(crypto_negotiated_params_->channel_id);
+  uint8_t digest[SHA256_DIGEST_LENGTH];
+  SHA256(reinterpret_cast<const uint8_t*>(channel_id.data()), channel_id.size(),
+         digest);
+
+  QuicTextUtils::Base64Encode(digest, arraysize(digest), output);
+  return true;
+}
+
+bool QuicCryptoServerHandshaker::encryption_established() const {
+  return encryption_established_;
+}
+
+bool QuicCryptoServerHandshaker::handshake_confirmed() const {
+  return handshake_confirmed_;
+}
+
+const QuicCryptoNegotiatedParameters&
+QuicCryptoServerHandshaker::crypto_negotiated_params() const {
+  return *crypto_negotiated_params_;
+}
+
+CryptoMessageParser* QuicCryptoServerHandshaker::crypto_message_parser() {
+  return QuicCryptoHandshaker::crypto_message_parser();
+}
+
+void QuicCryptoServerHandshaker::ProcessClientHello(
+    QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+        result,
+    std::unique_ptr<ProofSource::Details> proof_source_details,
+    std::unique_ptr<ProcessClientHelloResultCallback> done_cb) {
+  const CryptoHandshakeMessage& message = result->client_hello;
+  string error_details;
+  if (!helper_->CanAcceptClientHello(
+          message, session()->connection()->self_address(), &error_details)) {
+    done_cb->Run(QUIC_HANDSHAKE_FAILED, error_details, nullptr, nullptr,
+                 nullptr);
+    return;
+  }
+  if (!result->info.server_nonce.empty()) {
+    ++num_handshake_messages_with_server_nonces_;
+  }
+
+  if (num_handshake_messages_ == 1) {
+    // Client attempts zero RTT handshake by sending a non-inchoate CHLO.
+    QuicStringPiece public_value;
+    zero_rtt_attempted_ = message.GetStringPiece(kPUBS, &public_value);
+  }
+
+  // Store the bandwidth estimate from the client.
+  if (result->cached_network_params.bandwidth_estimate_bytes_per_second() > 0) {
+    previous_cached_network_params_.reset(
+        new CachedNetworkParameters(result->cached_network_params));
+  }
+  previous_source_address_tokens_ = result->info.source_address_tokens;
+
+  const bool use_stateless_rejects_in_crypto_config =
+      use_stateless_rejects_if_peer_supported_ &&
+      peer_supports_stateless_rejects_;
+  QuicConnection* connection = session()->connection();
+  const QuicConnectionId server_designated_connection_id =
+      GenerateConnectionIdForReject(use_stateless_rejects_in_crypto_config);
+  crypto_config_->ProcessClientHello(
+      result, /*reject_only=*/false, connection->connection_id(),
+      connection->self_address(), GetClientAddress(), version(),
+      connection->supported_versions(), use_stateless_rejects_in_crypto_config,
+      server_designated_connection_id, connection->clock(),
+      connection->random_generator(), compressed_certs_cache_,
+      crypto_negotiated_params_, signed_config_,
+      QuicCryptoStream::CryptoMessageFramingOverhead(version()),
+      chlo_packet_size_, std::move(done_cb));
+}
+
+void QuicCryptoServerHandshaker::OverrideQuicConfigDefaults(
+    QuicConfig* config) {}
+
+QuicCryptoServerHandshaker::ValidateCallback::ValidateCallback(
+    QuicCryptoServerHandshaker* parent)
+    : parent_(parent) {}
+
+void QuicCryptoServerHandshaker::ValidateCallback::Cancel() {
+  parent_ = nullptr;
+}
+
+void QuicCryptoServerHandshaker::ValidateCallback::Run(
+    QuicReferenceCountedPointer<Result> result,
+    std::unique_ptr<ProofSource::Details> details) {
+  if (parent_ != nullptr) {
+    parent_->FinishProcessingHandshakeMessage(std::move(result),
+                                              std::move(details));
+  }
+}
+
+QuicConnectionId QuicCryptoServerHandshaker::GenerateConnectionIdForReject(
+    bool use_stateless_rejects) {
+  if (!use_stateless_rejects) {
+    return 0;
+  }
+  return helper_->GenerateConnectionIdForReject(
+      session()->connection()->connection_id());
+}
+
+const QuicSocketAddress QuicCryptoServerHandshaker::GetClientAddress() {
+  return session()->connection()->peer_address();
+}
+
+}  // namespace net
diff --git a/net/quic/core/quic_crypto_server_handshaker.h b/net/quic/core/quic_crypto_server_handshaker.h
new file mode 100644
index 0000000..6fffb98
--- /dev/null
+++ b/net/quic/core/quic_crypto_server_handshaker.h
@@ -0,0 +1,240 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_CORE_QUIC_CRYPTO_SERVER_HANDSHAKER_H_
+#define NET_QUIC_CORE_QUIC_CRYPTO_SERVER_HANDSHAKER_H_
+
+#include "net/quic/core/quic_crypto_handshaker.h"
+#include "net/quic/core/quic_crypto_server_stream.h"
+#include "net/quic/core/quic_session.h"
+#include "net/quic/platform/api/quic_export.h"
+
+namespace net {
+
+namespace test {
+class QuicCryptoServerStreamPeer;
+}  // namespace test
+
+class QUIC_EXPORT_PRIVATE QuicCryptoServerHandshaker
+    : public QuicCryptoServerStream::HandshakerDelegate,
+      public QuicCryptoHandshaker {
+ public:
+  // |crypto_config| must outlive the stream.
+  // |session| must outlive the stream.
+  // |helper| must outlive the stream.
+  QuicCryptoServerHandshaker(const QuicCryptoServerConfig* crypto_config,
+                             QuicCryptoServerStream* stream,
+                             QuicCompressedCertsCache* compressed_certs_cache,
+                             bool use_stateless_rejects_if_peer_supported,
+                             QuicSession* session,
+                             QuicCryptoServerStream::Helper* helper);
+
+  ~QuicCryptoServerHandshaker() override;
+
+  // From HandshakerDelegate
+  void CancelOutstandingCallbacks() override;
+  bool GetBase64SHA256ClientChannelID(std::string* output) const override;
+  void SendServerConfigUpdate(
+      const CachedNetworkParameters* cached_network_params) override;
+  uint8_t NumHandshakeMessages() const override;
+  uint8_t NumHandshakeMessagesWithServerNonces() const override;
+  int NumServerConfigUpdateMessagesSent() const override;
+  const CachedNetworkParameters* PreviousCachedNetworkParams() const override;
+  bool UseStatelessRejectsIfPeerSupported() const override;
+  bool PeerSupportsStatelessRejects() const override;
+  bool ZeroRttAttempted() const override;
+  void SetPeerSupportsStatelessRejects(
+      bool peer_supports_stateless_rejects) override;
+  void SetPreviousCachedNetworkParams(
+      CachedNetworkParameters cached_network_params) override;
+  bool ShouldSendExpectCTHeader() const override;
+
+  // From QuicCryptoStream
+  bool encryption_established() const override;
+  bool handshake_confirmed() const override;
+  const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
+      const override;
+  CryptoMessageParser* crypto_message_parser() override;
+
+  // From QuicCryptoHandshaker
+  void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
+
+ protected:
+  virtual void ProcessClientHello(
+      QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+          result,
+      std::unique_ptr<ProofSource::Details> proof_source_details,
+      std::unique_ptr<ProcessClientHelloResultCallback> done_cb);
+
+  // Hook that allows the server to set QuicConfig defaults just
+  // before going through the parameter negotiation step.
+  virtual void OverrideQuicConfigDefaults(QuicConfig* config);
+
+  // Returns client address used to generate and validate source address token.
+  virtual const QuicSocketAddress GetClientAddress();
+
+ private:
+  friend class test::QuicCryptoServerStreamPeer;
+
+  class ValidateCallback : public ValidateClientHelloResultCallback {
+   public:
+    explicit ValidateCallback(QuicCryptoServerHandshaker* parent);
+    // To allow the parent to detach itself from the callback before deletion.
+    void Cancel();
+
+    // From ValidateClientHelloResultCallback
+    void Run(QuicReferenceCountedPointer<Result> result,
+             std::unique_ptr<ProofSource::Details> details) override;
+
+   private:
+    QuicCryptoServerHandshaker* parent_;
+
+    DISALLOW_COPY_AND_ASSIGN(ValidateCallback);
+  };
+
+  class SendServerConfigUpdateCallback
+      : public BuildServerConfigUpdateMessageResultCallback {
+   public:
+    explicit SendServerConfigUpdateCallback(QuicCryptoServerHandshaker* parent);
+    SendServerConfigUpdateCallback(const SendServerConfigUpdateCallback&) =
+        delete;
+    void operator=(const SendServerConfigUpdateCallback&) = delete;
+
+    // To allow the parent to detach itself from the callback before deletion.
+    void Cancel();
+
+    // From BuildServerConfigUpdateMessageResultCallback
+    void Run(bool ok, const CryptoHandshakeMessage& message) override;
+
+   private:
+    QuicCryptoServerHandshaker* parent_;
+  };
+
+  // Invoked by ValidateCallback::RunImpl once initial validation of
+  // the client hello is complete.  Finishes processing of the client
+  // hello message and handles handshake success/failure.
+  void FinishProcessingHandshakeMessage(
+      QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
+          result,
+      std::unique_ptr<ProofSource::Details> details);
+
+  class ProcessClientHelloCallback;
+  friend class ProcessClientHelloCallback;
+
+  // Portion of FinishProcessingHandshakeMessage which executes after
+  // ProcessClientHello has been called.
+  void FinishProcessingHandshakeMessageAfterProcessClientHello(
+      const ValidateClientHelloResultCallback::Result& result,
+      QuicErrorCode error,
+      const std::string& error_details,
+      std::unique_ptr<CryptoHandshakeMessage> reply,
+      std::unique_ptr<DiversificationNonce> diversification_nonce,
+      std::unique_ptr<ProofSource::Details> proof_source_details);
+
+  // Invoked by SendServerConfigUpdateCallback::RunImpl once the proof has been
+  // received.  |ok| indicates whether or not the proof was successfully
+  // acquired, and |message| holds the partially-constructed message from
+  // SendServerConfigUpdate.
+  void FinishSendServerConfigUpdate(bool ok,
+                                    const CryptoHandshakeMessage& message);
+
+  // Returns a new ConnectionId to be used for statelessly rejected connections
+  // if |use_stateless_rejects| is true. Returns 0 otherwise.
+  QuicConnectionId GenerateConnectionIdForReject(bool use_stateless_rejects);
+
+  // Returns the QuicSession that this stream belongs to.
+  QuicSession* session() const { return session_; }
+
+  // Returns the QuicVersion of the connection.
+  QuicVersion version() const { return session_->connection()->version(); }
+
+  QuicCryptoServerStream* stream_;
+
+  QuicSession* session_;
+
+  // crypto_config_ contains crypto parameters for the handshake.
+  const QuicCryptoServerConfig* crypto_config_;
+
+  // compressed_certs_cache_ contains a set of most recently compressed certs.
+  // Owned by QuicDispatcher.
+  QuicCompressedCertsCache* compressed_certs_cache_;
+
+  // Server's certificate chain and signature of the server config, as provided
+  // by ProofSource::GetProof.
+  QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
+
+  // Hash of the last received CHLO message which can be used for generating
+  // server config update messages.
+  std::string chlo_hash_;
+
+  // Pointer to the helper for this crypto stream. Must outlive this stream.
+  QuicCryptoServerStream::Helper* helper_;
+
+  // Number of handshake messages received by this stream.
+  uint8_t num_handshake_messages_;
+
+  // Number of handshake messages received by this stream that contain
+  // server nonces (indicating that this is a non-zero-RTT handshake
+  // attempt).
+  uint8_t num_handshake_messages_with_server_nonces_;
+
+  // Pointer to the active callback that will receive the result of
+  // BuildServerConfigUpdateMessage and forward it to
+  // FinishSendServerConfigUpdate.  nullptr if no update message is currently
+  // being built.
+  SendServerConfigUpdateCallback* send_server_config_update_cb_;
+
+  // Number of server config update (SCUP) messages sent by this stream.
+  int num_server_config_update_messages_sent_;
+
+  // If the client provides CachedNetworkParameters in the STK in the CHLO, then
+  // store here, and send back in future STKs if we have no better bandwidth
+  // estimate to send.
+  std::unique_ptr<CachedNetworkParameters> previous_cached_network_params_;
+
+  // Contains any source address tokens which were present in the CHLO.
+  SourceAddressTokens previous_source_address_tokens_;
+
+  // If true, the server should use stateless rejects, so long as the
+  // client supports them, as indicated by
+  // peer_supports_stateless_rejects_.
+  bool use_stateless_rejects_if_peer_supported_;
+
+  // Set to true, once the server has received information from the
+  // client that it supports stateless reject.
+  //  TODO(jokulik): Remove once client stateless reject support
+  // becomes the default.
+  bool peer_supports_stateless_rejects_;
+
+  // True if client attempts 0-rtt handshake (which can succeed or fail). If
+  // stateless rejects are used, this variable will be false for the stateless
+  // rejected connection and true for subsequent connections.
+  bool zero_rtt_attempted_;
+
+  // Size of the packet containing the most recently received CHLO.
+  QuicByteCount chlo_packet_size_;
+
+  // Pointer to the active callback that will receive the result of the client
+  // hello validation request and forward it to FinishProcessingHandshakeMessage
+  // for processing.  nullptr if no handshake message is being validated.  Note
+  // that this field is mutually exclusive with process_client_hello_cb_.
+  ValidateCallback* validate_client_hello_cb_;
+
+  // Pointer to the active callback which will receive the results of
+  // ProcessClientHello and forward it to
+  // FinishProcessingHandshakeMessageAfterProcessClientHello.  Note that this
+  // field is mutually exclusive with validate_client_hello_cb_.
+  ProcessClientHelloCallback* process_client_hello_cb_;
+
+  bool encryption_established_;
+  bool handshake_confirmed_;
+  QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters>
+      crypto_negotiated_params_;
+
+  DISALLOW_COPY_AND_ASSIGN(QuicCryptoServerHandshaker);
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CORE_QUIC_CRYPTO_SERVER_HANDSHAKER_H_
diff --git a/net/quic/core/quic_crypto_server_stream.cc b/net/quic/core/quic_crypto_server_stream.cc
index 7119a8e67..d9d2c83c 100644
--- a/net/quic/core/quic_crypto_server_stream.cc
+++ b/net/quic/core/quic_crypto_server_stream.cc
@@ -12,50 +12,17 @@
 #include "net/quic/core/crypto/quic_random.h"
 #include "net/quic/core/proto/cached_network_parameters.pb.h"
 #include "net/quic/core/quic_config.h"
+#include "net/quic/core/quic_crypto_server_handshaker.h"
 #include "net/quic/core/quic_packets.h"
 #include "net/quic/core/quic_session.h"
 #include "net/quic/platform/api/quic_flags.h"
 #include "net/quic/platform/api/quic_logging.h"
 #include "net/quic/platform/api/quic_string_piece.h"
-#include "net/quic/platform/api/quic_text_utils.h"
-#include "third_party/boringssl/src/include/openssl/sha.h"
 
 using std::string;
 
 namespace net {
 
-class QuicCryptoServerHandshaker::ProcessClientHelloCallback
-    : public ProcessClientHelloResultCallback {
- public:
-  ProcessClientHelloCallback(
-      QuicCryptoServerHandshaker* parent,
-      const QuicReferenceCountedPointer<
-          ValidateClientHelloResultCallback::Result>& result)
-      : parent_(parent), result_(result) {}
-
-  void Run(QuicErrorCode error,
-           const string& error_details,
-           std::unique_ptr<CryptoHandshakeMessage> message,
-           std::unique_ptr<DiversificationNonce> diversification_nonce,
-           std::unique_ptr<net::ProofSource::Details> proof_source_details)
-      override {
-    if (parent_ == nullptr) {
-      return;
-    }
-
-    parent_->FinishProcessingHandshakeMessageAfterProcessClientHello(
-        *result_, error, error_details, std::move(message),
-        std::move(diversification_nonce), std::move(proof_source_details));
-  }
-
-  void Cancel() { parent_ = nullptr; }
-
- private:
-  QuicCryptoServerHandshaker* parent_;
-  QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
-      result_;
-};
-
 QuicCryptoServerStreamBase::QuicCryptoServerStreamBase(QuicSession* session)
     : QuicCryptoStream(session) {}
 
@@ -172,438 +139,4 @@
   return handshaker_.get();
 }
 
-QuicCryptoServerHandshaker::QuicCryptoServerHandshaker(
-    const QuicCryptoServerConfig* crypto_config,
-    QuicCryptoServerStream* stream,
-    QuicCompressedCertsCache* compressed_certs_cache,
-    bool use_stateless_rejects_if_peer_supported,
-    QuicSession* session,
-    QuicCryptoServerStream::Helper* helper)
-    : QuicCryptoHandshaker(stream, session),
-      stream_(stream),
-      session_(session),
-      crypto_config_(crypto_config),
-      compressed_certs_cache_(compressed_certs_cache),
-      signed_config_(new QuicSignedServerConfig),
-      helper_(helper),
-      num_handshake_messages_(0),
-      num_handshake_messages_with_server_nonces_(0),
-      send_server_config_update_cb_(nullptr),
-      num_server_config_update_messages_sent_(0),
-      use_stateless_rejects_if_peer_supported_(
-          use_stateless_rejects_if_peer_supported),
-      peer_supports_stateless_rejects_(false),
-      zero_rtt_attempted_(false),
-      chlo_packet_size_(0),
-      validate_client_hello_cb_(nullptr),
-      process_client_hello_cb_(nullptr),
-      encryption_established_(false),
-      handshake_confirmed_(false),
-      crypto_negotiated_params_(new QuicCryptoNegotiatedParameters) {}
-
-QuicCryptoServerHandshaker::~QuicCryptoServerHandshaker() {
-  CancelOutstandingCallbacks();
-}
-
-void QuicCryptoServerHandshaker::CancelOutstandingCallbacks() {
-  // Detach from the validation callback.  Calling this multiple times is safe.
-  if (validate_client_hello_cb_ != nullptr) {
-    validate_client_hello_cb_->Cancel();
-    validate_client_hello_cb_ = nullptr;
-  }
-  if (send_server_config_update_cb_ != nullptr) {
-    send_server_config_update_cb_->Cancel();
-    send_server_config_update_cb_ = nullptr;
-  }
-  if (process_client_hello_cb_ != nullptr) {
-    process_client_hello_cb_->Cancel();
-    process_client_hello_cb_ = nullptr;
-  }
-}
-
-void QuicCryptoServerHandshaker::OnHandshakeMessage(
-    const CryptoHandshakeMessage& message) {
-  QuicCryptoHandshaker::OnHandshakeMessage(message);
-  ++num_handshake_messages_;
-  chlo_packet_size_ = session()->connection()->GetCurrentPacket().length();
-
-  // Do not process handshake messages after the handshake is confirmed.
-  if (handshake_confirmed_) {
-    stream_->CloseConnectionWithDetails(
-        QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE,
-        "Unexpected handshake message from client");
-    return;
-  }
-
-  if (message.tag() != kCHLO) {
-    stream_->CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
-                                        "Handshake packet not CHLO");
-    return;
-  }
-
-  if (validate_client_hello_cb_ != nullptr ||
-      process_client_hello_cb_ != nullptr) {
-    // Already processing some other handshake message.  The protocol
-    // does not allow for clients to send multiple handshake messages
-    // before the server has a chance to respond.
-    stream_->CloseConnectionWithDetails(
-        QUIC_CRYPTO_MESSAGE_WHILE_VALIDATING_CLIENT_HELLO,
-        "Unexpected handshake message while processing CHLO");
-    return;
-  }
-
-  CryptoUtils::HashHandshakeMessage(message, &chlo_hash_,
-                                    Perspective::IS_SERVER);
-
-  std::unique_ptr<ValidateCallback> cb(new ValidateCallback(this));
-  DCHECK(validate_client_hello_cb_ == nullptr);
-  DCHECK(process_client_hello_cb_ == nullptr);
-  validate_client_hello_cb_ = cb.get();
-  crypto_config_->ValidateClientHello(
-      message, GetClientAddress().host(),
-      session()->connection()->self_address(), version(),
-      session()->connection()->clock(), signed_config_, std::move(cb));
-}
-
-void QuicCryptoServerHandshaker::FinishProcessingHandshakeMessage(
-    QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
-        result,
-    std::unique_ptr<ProofSource::Details> details) {
-  const CryptoHandshakeMessage& message = result->client_hello;
-
-  // Clear the callback that got us here.
-  DCHECK(validate_client_hello_cb_ != nullptr);
-  DCHECK(process_client_hello_cb_ == nullptr);
-  validate_client_hello_cb_ = nullptr;
-
-  if (use_stateless_rejects_if_peer_supported_) {
-    peer_supports_stateless_rejects_ =
-        QuicCryptoServerStreamBase::DoesPeerSupportStatelessRejects(message);
-  }
-
-  std::unique_ptr<ProcessClientHelloCallback> cb(
-      new ProcessClientHelloCallback(this, result));
-  process_client_hello_cb_ = cb.get();
-  ProcessClientHello(result, std::move(details), std::move(cb));
-}
-
-void QuicCryptoServerHandshaker::
-    FinishProcessingHandshakeMessageAfterProcessClientHello(
-        const ValidateClientHelloResultCallback::Result& result,
-        QuicErrorCode error,
-        const string& error_details,
-        std::unique_ptr<CryptoHandshakeMessage> reply,
-        std::unique_ptr<DiversificationNonce> diversification_nonce,
-        std::unique_ptr<ProofSource::Details> proof_source_details) {
-  // Clear the callback that got us here.
-  DCHECK(process_client_hello_cb_ != nullptr);
-  DCHECK(validate_client_hello_cb_ == nullptr);
-  process_client_hello_cb_ = nullptr;
-
-  const CryptoHandshakeMessage& message = result.client_hello;
-  if (error != QUIC_NO_ERROR) {
-    stream_->CloseConnectionWithDetails(error, error_details);
-    return;
-  }
-
-  if (reply->tag() != kSHLO) {
-    if (reply->tag() == kSREJ) {
-      DCHECK(use_stateless_rejects_if_peer_supported_);
-      DCHECK(peer_supports_stateless_rejects_);
-      // Before sending the SREJ, cause the connection to save crypto packets
-      // so that they can be added to the time wait list manager and
-      // retransmitted.
-      session()->connection()->EnableSavingCryptoPackets();
-    }
-    SendHandshakeMessage(*reply);
-
-    if (reply->tag() == kSREJ) {
-      DCHECK(use_stateless_rejects_if_peer_supported_);
-      DCHECK(peer_supports_stateless_rejects_);
-      DCHECK(!handshake_confirmed());
-      QUIC_DLOG(INFO) << "Closing connection "
-                      << session()->connection()->connection_id()
-                      << " because of a stateless reject.";
-      session()->connection()->CloseConnection(
-          QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT, "stateless reject",
-          ConnectionCloseBehavior::SILENT_CLOSE);
-    }
-    return;
-  }
-
-  // If we are returning a SHLO then we accepted the handshake.  Now
-  // process the negotiated configuration options as part of the
-  // session config.
-  QuicConfig* config = session()->config();
-  OverrideQuicConfigDefaults(config);
-  string process_error_details;
-  const QuicErrorCode process_error =
-      config->ProcessPeerHello(message, CLIENT, &process_error_details);
-  if (process_error != QUIC_NO_ERROR) {
-    stream_->CloseConnectionWithDetails(process_error, process_error_details);
-    return;
-  }
-
-  session()->OnConfigNegotiated();
-
-  config->ToHandshakeMessage(reply.get());
-
-  // Receiving a full CHLO implies the client is prepared to decrypt with
-  // the new server write key.  We can start to encrypt with the new server
-  // write key.
-  //
-  // NOTE: the SHLO will be encrypted with the new server write key.
-  session()->connection()->SetEncrypter(
-      ENCRYPTION_INITIAL,
-      crypto_negotiated_params_->initial_crypters.encrypter.release());
-  session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
-  // Set the decrypter immediately so that we no longer accept unencrypted
-  // packets.
-  session()->connection()->SetDecrypter(
-      ENCRYPTION_INITIAL,
-      crypto_negotiated_params_->initial_crypters.decrypter.release());
-  session()->connection()->SetDiversificationNonce(*diversification_nonce);
-
-  SendHandshakeMessage(*reply);
-
-  session()->connection()->SetEncrypter(
-      ENCRYPTION_FORWARD_SECURE,
-      crypto_negotiated_params_->forward_secure_crypters.encrypter.release());
-  session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
-
-  session()->connection()->SetAlternativeDecrypter(
-      ENCRYPTION_FORWARD_SECURE,
-      crypto_negotiated_params_->forward_secure_crypters.decrypter.release(),
-      false /* don't latch */);
-
-  encryption_established_ = true;
-  handshake_confirmed_ = true;
-  session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
-}
-
-void QuicCryptoServerHandshaker::SendServerConfigUpdate(
-    const CachedNetworkParameters* cached_network_params) {
-  if (!handshake_confirmed_) {
-    return;
-  }
-
-  if (send_server_config_update_cb_ != nullptr) {
-    QUIC_DVLOG(1)
-        << "Skipped server config update since one is already in progress";
-    return;
-  }
-
-  std::unique_ptr<SendServerConfigUpdateCallback> cb(
-      new SendServerConfigUpdateCallback(this));
-  send_server_config_update_cb_ = cb.get();
-
-  crypto_config_->BuildServerConfigUpdateMessage(
-      session()->connection()->version(), chlo_hash_,
-      previous_source_address_tokens_, session()->connection()->self_address(),
-      GetClientAddress().host(), session()->connection()->clock(),
-      session()->connection()->random_generator(), compressed_certs_cache_,
-      *crypto_negotiated_params_, cached_network_params,
-      (session()->config()->HasReceivedConnectionOptions()
-           ? session()->config()->ReceivedConnectionOptions()
-           : QuicTagVector()),
-      std::move(cb));
-}
-
-QuicCryptoServerHandshaker::SendServerConfigUpdateCallback::
-    SendServerConfigUpdateCallback(QuicCryptoServerHandshaker* parent)
-    : parent_(parent) {}
-
-void QuicCryptoServerHandshaker::SendServerConfigUpdateCallback::Cancel() {
-  parent_ = nullptr;
-}
-
-// From BuildServerConfigUpdateMessageResultCallback
-void QuicCryptoServerHandshaker::SendServerConfigUpdateCallback::Run(
-    bool ok,
-    const CryptoHandshakeMessage& message) {
-  if (parent_ == nullptr) {
-    return;
-  }
-  parent_->FinishSendServerConfigUpdate(ok, message);
-}
-
-void QuicCryptoServerHandshaker::FinishSendServerConfigUpdate(
-    bool ok,
-    const CryptoHandshakeMessage& message) {
-  // Clear the callback that got us here.
-  DCHECK(send_server_config_update_cb_ != nullptr);
-  send_server_config_update_cb_ = nullptr;
-
-  if (!ok) {
-    QUIC_DVLOG(1) << "Server: Failed to build server config update (SCUP)!";
-    return;
-  }
-
-  QUIC_DVLOG(1) << "Server: Sending server config update: "
-                << message.DebugString(Perspective::IS_SERVER);
-  const QuicData& data = message.GetSerialized(Perspective::IS_SERVER);
-  stream_->WriteOrBufferData(QuicStringPiece(data.data(), data.length()), false,
-                             nullptr);
-
-  ++num_server_config_update_messages_sent_;
-}
-
-uint8_t QuicCryptoServerHandshaker::NumHandshakeMessages() const {
-  return num_handshake_messages_;
-}
-
-uint8_t QuicCryptoServerHandshaker::NumHandshakeMessagesWithServerNonces()
-    const {
-  return num_handshake_messages_with_server_nonces_;
-}
-
-int QuicCryptoServerHandshaker::NumServerConfigUpdateMessagesSent() const {
-  return num_server_config_update_messages_sent_;
-}
-
-const CachedNetworkParameters*
-QuicCryptoServerHandshaker::PreviousCachedNetworkParams() const {
-  return previous_cached_network_params_.get();
-}
-
-bool QuicCryptoServerHandshaker::UseStatelessRejectsIfPeerSupported() const {
-  return use_stateless_rejects_if_peer_supported_;
-}
-
-bool QuicCryptoServerHandshaker::PeerSupportsStatelessRejects() const {
-  return peer_supports_stateless_rejects_;
-}
-
-bool QuicCryptoServerHandshaker::ZeroRttAttempted() const {
-  return zero_rtt_attempted_;
-}
-
-void QuicCryptoServerHandshaker::SetPeerSupportsStatelessRejects(
-    bool peer_supports_stateless_rejects) {
-  peer_supports_stateless_rejects_ = peer_supports_stateless_rejects;
-}
-
-void QuicCryptoServerHandshaker::SetPreviousCachedNetworkParams(
-    CachedNetworkParameters cached_network_params) {
-  previous_cached_network_params_.reset(
-      new CachedNetworkParameters(cached_network_params));
-}
-
-bool QuicCryptoServerHandshaker::ShouldSendExpectCTHeader() const {
-  return signed_config_->proof.send_expect_ct_header;
-}
-
-bool QuicCryptoServerHandshaker::GetBase64SHA256ClientChannelID(
-    string* output) const {
-  if (!encryption_established() ||
-      crypto_negotiated_params_->channel_id.empty()) {
-    return false;
-  }
-
-  const string& channel_id(crypto_negotiated_params_->channel_id);
-  uint8_t digest[SHA256_DIGEST_LENGTH];
-  SHA256(reinterpret_cast<const uint8_t*>(channel_id.data()), channel_id.size(),
-         digest);
-
-  QuicTextUtils::Base64Encode(digest, arraysize(digest), output);
-  return true;
-}
-
-bool QuicCryptoServerHandshaker::encryption_established() const {
-  return encryption_established_;
-}
-
-bool QuicCryptoServerHandshaker::handshake_confirmed() const {
-  return handshake_confirmed_;
-}
-
-const QuicCryptoNegotiatedParameters&
-QuicCryptoServerHandshaker::crypto_negotiated_params() const {
-  return *crypto_negotiated_params_;
-}
-
-CryptoMessageParser* QuicCryptoServerHandshaker::crypto_message_parser() {
-  return QuicCryptoHandshaker::crypto_message_parser();
-}
-
-void QuicCryptoServerHandshaker::ProcessClientHello(
-    QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
-        result,
-    std::unique_ptr<ProofSource::Details> proof_source_details,
-    std::unique_ptr<ProcessClientHelloResultCallback> done_cb) {
-  const CryptoHandshakeMessage& message = result->client_hello;
-  string error_details;
-  if (!helper_->CanAcceptClientHello(
-          message, session()->connection()->self_address(), &error_details)) {
-    done_cb->Run(QUIC_HANDSHAKE_FAILED, error_details, nullptr, nullptr,
-                 nullptr);
-    return;
-  }
-  if (!result->info.server_nonce.empty()) {
-    ++num_handshake_messages_with_server_nonces_;
-  }
-
-  if (num_handshake_messages_ == 1) {
-    // Client attempts zero RTT handshake by sending a non-inchoate CHLO.
-    QuicStringPiece public_value;
-    zero_rtt_attempted_ = message.GetStringPiece(kPUBS, &public_value);
-  }
-
-  // Store the bandwidth estimate from the client.
-  if (result->cached_network_params.bandwidth_estimate_bytes_per_second() > 0) {
-    previous_cached_network_params_.reset(
-        new CachedNetworkParameters(result->cached_network_params));
-  }
-  previous_source_address_tokens_ = result->info.source_address_tokens;
-
-  const bool use_stateless_rejects_in_crypto_config =
-      use_stateless_rejects_if_peer_supported_ &&
-      peer_supports_stateless_rejects_;
-  QuicConnection* connection = session()->connection();
-  const QuicConnectionId server_designated_connection_id =
-      GenerateConnectionIdForReject(use_stateless_rejects_in_crypto_config);
-  crypto_config_->ProcessClientHello(
-      result, /*reject_only=*/false, connection->connection_id(),
-      connection->self_address(), GetClientAddress(), version(),
-      connection->supported_versions(), use_stateless_rejects_in_crypto_config,
-      server_designated_connection_id, connection->clock(),
-      connection->random_generator(), compressed_certs_cache_,
-      crypto_negotiated_params_, signed_config_,
-      QuicCryptoStream::CryptoMessageFramingOverhead(version()),
-      chlo_packet_size_, std::move(done_cb));
-}
-
-void QuicCryptoServerHandshaker::OverrideQuicConfigDefaults(
-    QuicConfig* config) {}
-
-QuicCryptoServerHandshaker::ValidateCallback::ValidateCallback(
-    QuicCryptoServerHandshaker* parent)
-    : parent_(parent) {}
-
-void QuicCryptoServerHandshaker::ValidateCallback::Cancel() {
-  parent_ = nullptr;
-}
-
-void QuicCryptoServerHandshaker::ValidateCallback::Run(
-    QuicReferenceCountedPointer<Result> result,
-    std::unique_ptr<ProofSource::Details> details) {
-  if (parent_ != nullptr) {
-    parent_->FinishProcessingHandshakeMessage(std::move(result),
-                                              std::move(details));
-  }
-}
-
-QuicConnectionId QuicCryptoServerHandshaker::GenerateConnectionIdForReject(
-    bool use_stateless_rejects) {
-  if (!use_stateless_rejects) {
-    return 0;
-  }
-  return helper_->GenerateConnectionIdForReject(
-      session()->connection()->connection_id());
-}
-
-const QuicSocketAddress QuicCryptoServerHandshaker::GetClientAddress() {
-  return session()->connection()->peer_address();
-}
-
 }  // namespace net
diff --git a/net/quic/core/quic_crypto_server_stream.h b/net/quic/core/quic_crypto_server_stream.h
index 29271e48..d777293 100644
--- a/net/quic/core/quic_crypto_server_stream.h
+++ b/net/quic/core/quic_crypto_server_stream.h
@@ -15,6 +15,7 @@
 #include "net/quic/core/crypto/quic_crypto_server_config.h"
 #include "net/quic/core/proto/source_address_token.pb.h"
 #include "net/quic/core/quic_config.h"
+#include "net/quic/core/quic_crypto_handshaker.h"
 #include "net/quic/core/quic_crypto_stream.h"
 #include "net/quic/core/quic_session.h"
 #include "net/quic/platform/api/quic_export.h"
@@ -26,10 +27,6 @@
 class QuicCryptoServerConfig;
 class QuicCryptoServerStreamBase;
 
-namespace test {
-class QuicCryptoServerStreamPeer;
-}  // namespace test
-
 // TODO(alyssar) see what can be moved out of QuicCryptoServerStream with
 // various code and test refactoring.
 class QUIC_EXPORT_PRIVATE QuicCryptoServerStreamBase : public QuicCryptoStream {
@@ -205,225 +202,6 @@
   DISALLOW_COPY_AND_ASSIGN(QuicCryptoServerStream);
 };
 
-class QUIC_EXPORT_PRIVATE QuicCryptoServerHandshaker
-    : public QuicCryptoServerStream::HandshakerDelegate,
-      public QuicCryptoHandshaker {
- public:
-  // |crypto_config| must outlive the stream.
-  // |session| must outlive the stream.
-  // |helper| must outlive the stream.
-  QuicCryptoServerHandshaker(const QuicCryptoServerConfig* crypto_config,
-                             QuicCryptoServerStream* stream,
-                             QuicCompressedCertsCache* compressed_certs_cache,
-                             bool use_stateless_rejects_if_peer_supported,
-                             QuicSession* session,
-                             QuicCryptoServerStream::Helper* helper);
-
-  ~QuicCryptoServerHandshaker() override;
-
-  // From HandshakerDelegate
-  void CancelOutstandingCallbacks() override;
-  bool GetBase64SHA256ClientChannelID(std::string* output) const override;
-  void SendServerConfigUpdate(
-      const CachedNetworkParameters* cached_network_params) override;
-  uint8_t NumHandshakeMessages() const override;
-  uint8_t NumHandshakeMessagesWithServerNonces() const override;
-  int NumServerConfigUpdateMessagesSent() const override;
-  const CachedNetworkParameters* PreviousCachedNetworkParams() const override;
-  bool UseStatelessRejectsIfPeerSupported() const override;
-  bool PeerSupportsStatelessRejects() const override;
-  bool ZeroRttAttempted() const override;
-  void SetPeerSupportsStatelessRejects(
-      bool peer_supports_stateless_rejects) override;
-  void SetPreviousCachedNetworkParams(
-      CachedNetworkParameters cached_network_params) override;
-  bool ShouldSendExpectCTHeader() const override;
-
-  // From QuicCryptoStream
-  bool encryption_established() const override;
-  bool handshake_confirmed() const override;
-  const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
-      const override;
-  CryptoMessageParser* crypto_message_parser() override;
-
-  // From QuicCryptoHandshaker
-  void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
-
- protected:
-  virtual void ProcessClientHello(
-      QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
-          result,
-      std::unique_ptr<ProofSource::Details> proof_source_details,
-      std::unique_ptr<ProcessClientHelloResultCallback> done_cb);
-
-  // Hook that allows the server to set QuicConfig defaults just
-  // before going through the parameter negotiation step.
-  virtual void OverrideQuicConfigDefaults(QuicConfig* config);
-
-  // Returns client address used to generate and validate source address token.
-  virtual const QuicSocketAddress GetClientAddress();
-
- private:
-  friend class test::QuicCryptoServerStreamPeer;
-
-  class ValidateCallback : public ValidateClientHelloResultCallback {
-   public:
-    explicit ValidateCallback(QuicCryptoServerHandshaker* parent);
-    // To allow the parent to detach itself from the callback before deletion.
-    void Cancel();
-
-    // From ValidateClientHelloResultCallback
-    void Run(QuicReferenceCountedPointer<Result> result,
-             std::unique_ptr<ProofSource::Details> details) override;
-
-   private:
-    QuicCryptoServerHandshaker* parent_;
-
-    DISALLOW_COPY_AND_ASSIGN(ValidateCallback);
-  };
-
-  class SendServerConfigUpdateCallback
-      : public BuildServerConfigUpdateMessageResultCallback {
-   public:
-    explicit SendServerConfigUpdateCallback(QuicCryptoServerHandshaker* parent);
-    SendServerConfigUpdateCallback(const SendServerConfigUpdateCallback&) =
-        delete;
-    void operator=(const SendServerConfigUpdateCallback&) = delete;
-
-    // To allow the parent to detach itself from the callback before deletion.
-    void Cancel();
-
-    // From BuildServerConfigUpdateMessageResultCallback
-    void Run(bool ok, const CryptoHandshakeMessage& message) override;
-
-   private:
-    QuicCryptoServerHandshaker* parent_;
-  };
-
-  // Invoked by ValidateCallback::RunImpl once initial validation of
-  // the client hello is complete.  Finishes processing of the client
-  // hello message and handles handshake success/failure.
-  void FinishProcessingHandshakeMessage(
-      QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
-          result,
-      std::unique_ptr<ProofSource::Details> details);
-
-  class ProcessClientHelloCallback;
-  friend class ProcessClientHelloCallback;
-
-  // Portion of FinishProcessingHandshakeMessage which executes after
-  // ProcessClientHello has been called.
-  void FinishProcessingHandshakeMessageAfterProcessClientHello(
-      const ValidateClientHelloResultCallback::Result& result,
-      QuicErrorCode error,
-      const std::string& error_details,
-      std::unique_ptr<CryptoHandshakeMessage> reply,
-      std::unique_ptr<DiversificationNonce> diversification_nonce,
-      std::unique_ptr<ProofSource::Details> proof_source_details);
-
-  // Invoked by SendServerConfigUpdateCallback::RunImpl once the proof has been
-  // received.  |ok| indicates whether or not the proof was successfully
-  // acquired, and |message| holds the partially-constructed message from
-  // SendServerConfigUpdate.
-  void FinishSendServerConfigUpdate(bool ok,
-                                    const CryptoHandshakeMessage& message);
-
-  // Returns a new ConnectionId to be used for statelessly rejected connections
-  // if |use_stateless_rejects| is true. Returns 0 otherwise.
-  QuicConnectionId GenerateConnectionIdForReject(bool use_stateless_rejects);
-
-  // Returns the QuicSession that this stream belongs to.
-  QuicSession* session() const { return session_; }
-
-  // Returns the QuicVersion of the connection.
-  QuicVersion version() const { return session_->connection()->version(); }
-
-  QuicCryptoServerStream* stream_;
-
-  QuicSession* session_;
-
-  // crypto_config_ contains crypto parameters for the handshake.
-  const QuicCryptoServerConfig* crypto_config_;
-
-  // compressed_certs_cache_ contains a set of most recently compressed certs.
-  // Owned by QuicDispatcher.
-  QuicCompressedCertsCache* compressed_certs_cache_;
-
-  // Server's certificate chain and signature of the server config, as provided
-  // by ProofSource::GetProof.
-  QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
-
-  // Hash of the last received CHLO message which can be used for generating
-  // server config update messages.
-  std::string chlo_hash_;
-
-  // Pointer to the helper for this crypto stream. Must outlive this stream.
-  QuicCryptoServerStream::Helper* helper_;
-
-  // Number of handshake messages received by this stream.
-  uint8_t num_handshake_messages_;
-
-  // Number of handshake messages received by this stream that contain
-  // server nonces (indicating that this is a non-zero-RTT handshake
-  // attempt).
-  uint8_t num_handshake_messages_with_server_nonces_;
-
-  // Pointer to the active callback that will receive the result of
-  // BuildServerConfigUpdateMessage and forward it to
-  // FinishSendServerConfigUpdate.  nullptr if no update message is currently
-  // being built.
-  SendServerConfigUpdateCallback* send_server_config_update_cb_;
-
-  // Number of server config update (SCUP) messages sent by this stream.
-  int num_server_config_update_messages_sent_;
-
-  // If the client provides CachedNetworkParameters in the STK in the CHLO, then
-  // store here, and send back in future STKs if we have no better bandwidth
-  // estimate to send.
-  std::unique_ptr<CachedNetworkParameters> previous_cached_network_params_;
-
-  // Contains any source address tokens which were present in the CHLO.
-  SourceAddressTokens previous_source_address_tokens_;
-
-  // If true, the server should use stateless rejects, so long as the
-  // client supports them, as indicated by
-  // peer_supports_stateless_rejects_.
-  bool use_stateless_rejects_if_peer_supported_;
-
-  // Set to true, once the server has received information from the
-  // client that it supports stateless reject.
-  //  TODO(jokulik): Remove once client stateless reject support
-  // becomes the default.
-  bool peer_supports_stateless_rejects_;
-
-  // True if client attempts 0-rtt handshake (which can succeed or fail). If
-  // stateless rejects are used, this variable will be false for the stateless
-  // rejected connection and true for subsequent connections.
-  bool zero_rtt_attempted_;
-
-  // Size of the packet containing the most recently received CHLO.
-  QuicByteCount chlo_packet_size_;
-
-  // Pointer to the active callback that will receive the result of the client
-  // hello validation request and forward it to FinishProcessingHandshakeMessage
-  // for processing.  nullptr if no handshake message is being validated.  Note
-  // that this field is mutually exclusive with process_client_hello_cb_.
-  ValidateCallback* validate_client_hello_cb_;
-
-  // Pointer to the active callback which will receive the results of
-  // ProcessClientHello and forward it to
-  // FinishProcessingHandshakeMessageAfterProcessClientHello.  Note that this
-  // field is mutually exclusive with validate_client_hello_cb_.
-  ProcessClientHelloCallback* process_client_hello_cb_;
-
-  bool encryption_established_;
-  bool handshake_confirmed_;
-  QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters>
-      crypto_negotiated_params_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicCryptoServerHandshaker);
-};
-
 }  // namespace net
 
 #endif  // NET_QUIC_CORE_QUIC_CRYPTO_SERVER_STREAM_H_
diff --git a/net/quic/core/quic_crypto_stream.cc b/net/quic/core/quic_crypto_stream.cc
index 3af89889..6d5b4e6 100644
--- a/net/quic/core/quic_crypto_stream.cc
+++ b/net/quic/core/quic_crypto_stream.cc
@@ -94,39 +94,4 @@
       /* context= */ "", 32, result);
 }
 
-QuicCryptoHandshaker::QuicCryptoHandshaker(QuicCryptoStream* stream,
-                                           QuicSession* session)
-    : stream_(stream), session_(session) {
-  crypto_framer_.set_visitor(this);
-}
-
-QuicCryptoHandshaker::~QuicCryptoHandshaker() {}
-
-void QuicCryptoHandshaker::SendHandshakeMessage(
-    const CryptoHandshakeMessage& message) {
-  QUIC_DVLOG(1) << ENDPOINT << "Sending "
-                << message.DebugString(session()->perspective());
-  session()->connection()->NeuterUnencryptedPackets();
-  session()->OnCryptoHandshakeMessageSent(message);
-  const QuicData& data = message.GetSerialized(session()->perspective());
-  stream_->WriteOrBufferData(QuicStringPiece(data.data(), data.length()), false,
-                             nullptr);
-}
-
-void QuicCryptoHandshaker::OnError(CryptoFramer* framer) {
-  QUIC_DLOG(WARNING) << "Error processing crypto data: "
-                     << QuicErrorCodeToString(framer->error());
-}
-
-void QuicCryptoHandshaker::OnHandshakeMessage(
-    const CryptoHandshakeMessage& message) {
-  QUIC_DVLOG(1) << ENDPOINT << "Received "
-                << message.DebugString(session()->perspective());
-  session()->OnCryptoHandshakeMessageReceived(message);
-}
-
-CryptoMessageParser* QuicCryptoHandshaker::crypto_message_parser() {
-  return &crypto_framer_;
-}
-
 }  // namespace net
diff --git a/net/quic/core/quic_crypto_stream.h b/net/quic/core/quic_crypto_stream.h
index fdbf4dc0..8c3a548d 100644
--- a/net/quic/core/quic_crypto_stream.h
+++ b/net/quic/core/quic_crypto_stream.h
@@ -18,7 +18,6 @@
 
 namespace net {
 
-class CryptoHandshakeMessage;
 class QuicSession;
 
 // Crypto handshake messages in QUIC take place over a reserved stream with the
@@ -80,33 +79,6 @@
   DISALLOW_COPY_AND_ASSIGN(QuicCryptoStream);
 };
 
-class QUIC_EXPORT_PRIVATE QuicCryptoHandshaker
-    : public CryptoFramerVisitorInterface {
- public:
-  QuicCryptoHandshaker(QuicCryptoStream* stream, QuicSession* session);
-
-  ~QuicCryptoHandshaker() override;
-
-  // Sends |message| to the peer.
-  // TODO(wtc): return a success/failure status.
-  void SendHandshakeMessage(const CryptoHandshakeMessage& message);
-
-  void OnError(CryptoFramer* framer) override;
-  void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
-
-  CryptoMessageParser* crypto_message_parser();
-
- private:
-  QuicSession* session() { return session_; }
-
-  QuicCryptoStream* stream_;
-  QuicSession* session_;
-
-  CryptoFramer crypto_framer_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicCryptoHandshaker);
-};
-
 }  // namespace net
 
 #endif  // NET_QUIC_CORE_QUIC_CRYPTO_STREAM_H_
diff --git a/net/quic/core/quic_flags_list.h b/net/quic/core/quic_flags_list.h
index a5617f3..1af29cd 100644
--- a/net/quic/core/quic_flags_list.h
+++ b/net/quic/core/quic_flags_list.h
@@ -61,11 +61,6 @@
           FLAGS_quic_reloadable_flag_quic_limit_num_new_sessions_per_epoll_loop,
           true)
 
-// If true, QUIC server push will enabled by default.
-QUIC_FLAG(bool,
-          FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default,
-          true)
-
 // If true, release QuicCryptoStream\'s read buffer when stream are less
 // frequently used.
 QUIC_FLAG(bool,
@@ -76,9 +71,6 @@
 // public flag.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_remove_v33_hacks2, false)
 
-// Enable QUIC force HOL blocking experiment.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_force_hol_blocking, true)
-
 // If true, allows packets to be buffered in anticipation of a future CHLO, and
 // allow CHLO packets to be buffered until next iteration of the event loop.
 QUIC_FLAG(bool, FLAGS_quic_allow_chlo_buffering, true)
@@ -122,12 +114,6 @@
 // compressed for QUIC version >= 38.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_random_padding, true)
 
-// If true, update state if trailing headers with a :final-offset key are
-// received for a previously closed QUIC stream.
-QUIC_FLAG(bool,
-          FLAGS_quic_reloadable_flag_quic_final_offset_from_trailers,
-          true)
-
 // If enabled, use refactored stream creation methods.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_refactor_stream_creation, false)
 
@@ -196,3 +182,18 @@
 
 // When enabled, ack frame uses a deque internally instead of a set.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_frames_deque, false)
+
+// If true, server supported versions is updated before SelectMutualVersion.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_to_backend_multi_version, true)
+
+// If true, QUIC packet creator passes a stack allocated SerializedPacket to the
+// connection.
+QUIC_FLAG(bool,
+          FLAGS_quic_reloadable_flag_quic_clear_packet_before_handed_over,
+          false)
+
+// If true, enable QUIC v41.
+QUIC_FLAG(bool, FLAGS_quic_enable_version_41, false)
+
+// Small optimization for QuicSentPacketManager::HandleAckForSentPackets.
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_handle_acks, false)
diff --git a/net/quic/core/quic_framer.cc b/net/quic/core/quic_framer.cc
index b2f2912..868a882 100644
--- a/net/quic/core/quic_framer.cc
+++ b/net/quic/core/quic_framer.cc
@@ -1145,6 +1145,14 @@
 
   frame->fin = (stream_flags & kQuicStreamFinMask) == kQuicStreamFinShift;
 
+  uint16_t data_len = 0;
+  if (has_data_length && quic_version_ > QUIC_VERSION_39) {
+    if (!reader->ReadUInt16(&data_len)) {
+      set_detailed_error("Unable to read data length.");
+      return false;
+    }
+  }
+
   uint64_t stream_id = 0;
   if (!reader->ReadBytesToUInt64(stream_id_length, &stream_id)) {
     set_detailed_error("Unable to read stream_id.");
@@ -1161,9 +1169,16 @@
   // TODO(ianswett): Don't use QuicStringPiece as an intermediary.
   QuicStringPiece data;
   if (has_data_length) {
-    if (!reader->ReadStringPiece16(&data)) {
-      set_detailed_error("Unable to read frame data.");
-      return false;
+    if (quic_version_ > QUIC_VERSION_39) {
+      if (!reader->ReadStringPiece(&data, data_len)) {
+        set_detailed_error("Unable to read frame data.");
+        return false;
+      }
+    } else {
+      if (!reader->ReadStringPiece16(&data)) {
+        set_detailed_error("Unable to read frame data.");
+        return false;
+      }
     }
   } else {
     if (!reader->ReadStringPiece(&data, reader->BytesRemaining())) {
@@ -1334,9 +1349,11 @@
     return false;
   }
 
-  if (!reader->ReadUInt64(&frame->byte_offset)) {
-    set_detailed_error("Unable to read rst stream sent byte offset.");
-    return false;
+  if (quic_version_ <= QUIC_VERSION_39) {
+    if (!reader->ReadUInt64(&frame->byte_offset)) {
+      set_detailed_error("Unable to read rst stream sent byte offset.");
+      return false;
+    }
   }
 
   uint32_t error_code;
@@ -1351,6 +1368,14 @@
   }
 
   frame->error_code = static_cast<QuicRstStreamErrorCode>(error_code);
+
+  if (quic_version_ > QUIC_VERSION_39) {
+    if (!reader->ReadUInt64(&frame->byte_offset)) {
+      set_detailed_error("Unable to read rst stream sent byte offset.");
+      return false;
+    }
+  }
+
   return true;
 }
 
@@ -1794,6 +1819,13 @@
 bool QuicFramer::AppendStreamFrame(const QuicStreamFrame& frame,
                                    bool no_stream_frame_length,
                                    QuicDataWriter* writer) {
+  if (!no_stream_frame_length && quic_version_ > QUIC_VERSION_39) {
+    if ((frame.data_length > std::numeric_limits<uint16_t>::max()) ||
+        !writer->WriteUInt16(static_cast<uint16_t>(frame.data_length))) {
+      QUIC_BUG << "Writing stream frame length failed";
+      return false;
+    }
+  }
   if (!AppendStreamId(GetStreamIdSize(frame.stream_id), frame.stream_id,
                       writer)) {
     QUIC_BUG << "Writing stream id size failed.";
@@ -1804,7 +1836,7 @@
     QUIC_BUG << "Writing offset size failed.";
     return false;
   }
-  if (!no_stream_frame_length) {
+  if (!no_stream_frame_length && quic_version_ <= QUIC_VERSION_39) {
     if ((frame.data_length > std::numeric_limits<uint16_t>::max()) ||
         !writer->WriteUInt16(static_cast<uint16_t>(frame.data_length))) {
       QUIC_BUG << "Writing stream frame length failed";
@@ -2081,8 +2113,10 @@
     return false;
   }
 
-  if (!writer->WriteUInt64(frame.byte_offset)) {
-    return false;
+  if (quic_version_ <= QUIC_VERSION_39) {
+    if (!writer->WriteUInt64(frame.byte_offset)) {
+      return false;
+    }
   }
 
   uint32_t error_code = static_cast<uint32_t>(frame.error_code);
@@ -2090,6 +2124,12 @@
     return false;
   }
 
+  if (quic_version_ > QUIC_VERSION_39) {
+    if (!writer->WriteUInt64(frame.byte_offset)) {
+      return false;
+    }
+  }
+
   return true;
 }
 
diff --git a/net/quic/core/quic_framer_test.cc b/net/quic/core/quic_framer_test.cc
index 34337fa..c7018db0 100644
--- a/net/quic/core/quic_framer_test.cc
+++ b/net/quic/core/quic_framer_test.cc
@@ -397,13 +397,27 @@
     // Now test framing boundaries.
     for (size_t i = kQuicFrameTypeSize; i < GetMinStreamFrameSize(); ++i) {
       string expected_error;
-      if (i < kQuicFrameTypeSize + stream_id_size) {
-        expected_error = "Unable to read stream_id.";
-      } else if (i < kQuicFrameTypeSize + stream_id_size +
-                         kQuicMaxStreamOffsetSize) {
-        expected_error = "Unable to read offset.";
+      if (framer_.version() <= QUIC_VERSION_39) {
+        if (i < kQuicFrameTypeSize + stream_id_size) {
+          expected_error = "Unable to read stream_id.";
+        } else if (i < kQuicFrameTypeSize + stream_id_size +
+                           kQuicMaxStreamOffsetSize) {
+          expected_error = "Unable to read offset.";
+        } else {
+          expected_error = "Unable to read frame data.";
+        }
       } else {
-        expected_error = "Unable to read frame data.";
+        const size_t kQuicDataLenSize = sizeof(uint16_t);
+        if (i < kQuicFrameTypeSize + kQuicDataLenSize) {
+          expected_error = "Unable to read data length.";
+        } else if (i < kQuicFrameTypeSize + kQuicDataLenSize + stream_id_size) {
+          expected_error = "Unable to read stream_id.";
+        } else if (i < kQuicFrameTypeSize + kQuicDataLenSize + stream_id_size +
+                           kQuicMaxStreamOffsetSize) {
+          expected_error = "Unable to read offset.";
+        } else {
+          expected_error = "Unable to read frame data.";
+        }
       }
       CheckProcessingFails(
           packet, i + GetPacketHeaderSize(
@@ -1176,15 +1190,47 @@
     // paddings
     0x00, 0x00,
   };
+
+  unsigned char packet40[] = {
+    // public flags (8 byte connection_id)
+    0x38,
+    // connection_id
+    0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+    // packet number
+    0x12, 0x34, 0x56, 0x78,
+    0x9A, 0xBC,
+
+    // paddings
+    0x00, 0x00,
+    // frame type (stream frame with fin)
+    0xFF,
+    // data length
+    0x00, 0x0c,
+    // stream id
+    0x01, 0x02, 0x03, 0x04,
+    // offset
+    0xBA, 0x98, 0xFE, 0xDC,
+    0x32, 0x10, 0x76, 0x54,
+    // data
+    'h',  'e',  'l',  'l',
+    'o',  ' ',  'w',  'o',
+    'r',  'l',  'd',  '!',
+    // paddings
+    0x00, 0x00,
+  };
   // clang-format on
 
   if (framer_.version() <= QUIC_VERSION_37) {
     return;
   }
 
-  QuicEncryptedPacket encrypted(
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
-      arraysize(packet), false);
+  unsigned char* p = packet;
+  if (framer_.version() > QUIC_VERSION_39) {
+    p = packet40;
+  } else if (framer_.version() > QUIC_VERSION_38) {
+    p = packet39;
+  }
+  QuicEncryptedPacket encrypted(AsChars(p), arraysize(packet), false);
   EXPECT_TRUE(framer_.ProcessPacket(encrypted));
   EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
   ASSERT_TRUE(visitor_.header_.get());
@@ -1251,11 +1297,39 @@
       'o',  ' ',  'w',  'o',
       'r',  'l',  'd',  '!',
   };
+
+  unsigned char packet40[] = {
+      // public flags (8 byte connection_id)
+      0x38,
+      // connection_id
+      0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+      // packet number
+      0x12, 0x34, 0x56, 0x78,
+      0x9A, 0xBC,
+
+      // frame type (stream frame with fin)
+      0xFF,
+      // data length
+      0x00, 0x0c,
+      // stream id
+      0x01, 0x02, 0x03, 0x04,
+      // offset
+      0xBA, 0x98, 0xFE, 0xDC,
+      0x32, 0x10, 0x76, 0x54,
+      // data
+      'h',  'e',  'l',  'l',
+      'o',  ' ',  'w',  'o',
+      'r',  'l',  'd',  '!',
+  };
   // clang-format on
 
-  QuicEncryptedPacket encrypted(
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
-      arraysize(packet), false);
+  unsigned char* p = packet;
+  if (framer_.version() > QUIC_VERSION_39) {
+    p = packet40;
+  } else if (framer_.version() > QUIC_VERSION_38) {
+    p = packet39;
+  }
+  QuicEncryptedPacket encrypted(AsChars(p), arraysize(packet), false);
   EXPECT_TRUE(framer_.ProcessPacket(encrypted));
 
   EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
@@ -1389,11 +1463,39 @@
     'o',  ' ',  'w',  'o',
     'r',  'l',  'd',  '!',
   };
+
+  unsigned char packet40[] = {
+    // public flags (8 byte connection_id)
+    0x38,
+    // connection_id
+    0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
+    // packet number
+    0x12, 0x34, 0x56, 0x78,
+    0x9A, 0xBC,
+
+    // frame type (stream frame with fin)
+    0xFE,
+    // data length
+    0x00, 0x0c,
+    // stream id
+    0x02, 0x03, 0x04,
+    // offset
+    0xBA, 0x98, 0xFE, 0xDC,
+    0x32, 0x10, 0x76, 0x54,
+    // data
+    'h',  'e',  'l',  'l',
+    'o',  ' ',  'w',  'o',
+    'r',  'l',  'd',  '!',
+  };
   // clang-format on
 
-  QuicEncryptedPacket encrypted(
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
-      arraysize(packet), false);
+  unsigned char* p = packet;
+  if (framer_.version() > QUIC_VERSION_39) {
+    p = packet40;
+  } else if (framer_.version() > QUIC_VERSION_38) {
+    p = packet39;
+  }
+  QuicEncryptedPacket encrypted(AsChars(p), arraysize(packet), false);
   EXPECT_TRUE(framer_.ProcessPacket(encrypted));
 
   EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
@@ -1442,34 +1544,62 @@
     'r',  'l',  'd',  '!',
   };
 
-    unsigned char packet39[] = {
-      // public flags (8 byte connection_id)
-      0x38,
-      // connection_id
-      0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
-      // packet number
-      0x12, 0x34, 0x56, 0x78,
-      0x9A, 0xBC,
+  unsigned char packet39[] = {
+    // public flags (8 byte connection_id)
+    0x38,
+    // connection_id
+    0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+    // packet number
+    0x12, 0x34, 0x56, 0x78,
+    0x9A, 0xBC,
 
-      // frame type (stream frame with fin)
-      0xFD,
-      // stream id
-      0x03, 0x04,
-      // offset
-      0xBA, 0x98, 0xFE, 0xDC,
-      0x32, 0x10, 0x76, 0x54,
-      // data length
-      0x00, 0x0c,
-      // data
-      'h',  'e',  'l',  'l',
-      'o',  ' ',  'w',  'o',
-      'r',  'l',  'd',  '!',
-    };
+    // frame type (stream frame with fin)
+    0xFD,
+    // stream id
+    0x03, 0x04,
+    // offset
+    0xBA, 0x98, 0xFE, 0xDC,
+    0x32, 0x10, 0x76, 0x54,
+    // data length
+    0x00, 0x0c,
+    // data
+    'h',  'e',  'l',  'l',
+    'o',  ' ',  'w',  'o',
+    'r',  'l',  'd',  '!',
+  };
+
+  unsigned char packet40[] = {
+    // public flags (8 byte connection_id)
+    0x38,
+    // connection_id
+    0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+    // packet number
+    0x12, 0x34, 0x56, 0x78,
+    0x9A, 0xBC,
+
+    // frame type (stream frame with fin)
+    0xFD,
+    // data length
+    0x00, 0x0c,
+    // stream id
+    0x03, 0x04,
+    // offset
+    0xBA, 0x98, 0xFE, 0xDC,
+    0x32, 0x10, 0x76, 0x54,
+    // data
+    'h',  'e',  'l',  'l',
+    'o',  ' ',  'w',  'o',
+    'r',  'l',  'd',  '!',
+  };
   // clang-format on
 
-  QuicEncryptedPacket encrypted(
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
-      arraysize(packet), false);
+  unsigned char* p = packet;
+  if (framer_.version() > QUIC_VERSION_39) {
+    p = packet40;
+  } else if (framer_.version() > QUIC_VERSION_38) {
+    p = packet39;
+  }
+  QuicEncryptedPacket encrypted(AsChars(p), arraysize(packet), false);
   EXPECT_TRUE(framer_.ProcessPacket(encrypted));
 
   EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
@@ -1518,34 +1648,62 @@
     'r',  'l',  'd',  '!',
   };
 
-    unsigned char packet39[] = {
-      // public flags (8 byte connection_id)
-      0x38,
-      // connection_id
-      0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
-      // packet number
-      0x12, 0x34, 0x56, 0x78,
-      0x9A, 0xBC,
+  unsigned char packet39[] = {
+    // public flags (8 byte connection_id)
+    0x38,
+    // connection_id
+    0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+    // packet number
+    0x12, 0x34, 0x56, 0x78,
+    0x9A, 0xBC,
 
-      // frame type (stream frame with fin)
-      0xFC,
-      // stream id
-      0x04,
-      // offset
-      0xBA, 0x98, 0xFE, 0xDC,
-      0x32, 0x10, 0x76, 0x54,
-      // data length
-      0x00, 0x0c,
-      // data
-      'h',  'e',  'l',  'l',
-      'o',  ' ',  'w',  'o',
-      'r',  'l',  'd',  '!',
-    };
+    // frame type (stream frame with fin)
+    0xFC,
+    // stream id
+    0x04,
+    // offset
+    0xBA, 0x98, 0xFE, 0xDC,
+    0x32, 0x10, 0x76, 0x54,
+    // data length
+    0x00, 0x0c,
+    // data
+    'h',  'e',  'l',  'l',
+    'o',  ' ',  'w',  'o',
+    'r',  'l',  'd',  '!',
+  };
+
+  unsigned char packet40[] = {
+    // public flags (8 byte connection_id)
+    0x38,
+    // connection_id
+    0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+    // packet number
+    0x12, 0x34, 0x56, 0x78,
+    0x9A, 0xBC,
+
+    // frame type (stream frame with fin)
+    0xFC,
+    // data length
+    0x00, 0x0c,
+    // stream id
+    0x04,
+    // offset
+    0xBA, 0x98, 0xFE, 0xDC,
+    0x32, 0x10, 0x76, 0x54,
+    // data
+    'h',  'e',  'l',  'l',
+    'o',  ' ',  'w',  'o',
+    'r',  'l',  'd',  '!',
+  };
   // clang-format on
 
-  QuicEncryptedPacket encrypted(
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
-      arraysize(packet), false);
+  unsigned char* p = packet;
+  if (framer_.version() > QUIC_VERSION_39) {
+    p = packet40;
+  } else if (framer_.version() > QUIC_VERSION_38) {
+    p = packet39;
+  }
+  QuicEncryptedPacket encrypted(AsChars(p), arraysize(packet), false);
   EXPECT_TRUE(framer_.ProcessPacket(encrypted));
 
   EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
@@ -1596,36 +1754,66 @@
     'r',  'l',  'd',  '!',
   };
 
-    unsigned char packet39[] = {
-      // public flags (version, 8 byte connection_id)
-      0x39,
-      // connection_id
-      0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
-      // version tag
-      'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(),
-      // packet number
-      0x12, 0x34, 0x56, 0x78,
-      0x9A, 0xBC,
+  unsigned char packet39[] = {
+    // public flags (version, 8 byte connection_id)
+    0x39,
+    // connection_id
+    0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+    // version tag
+    'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(),
+    // packet number
+    0x12, 0x34, 0x56, 0x78,
+    0x9A, 0xBC,
 
-      // frame type (stream frame with fin)
-      0xFF,
-      // stream id
-      0x01, 0x02, 0x03, 0x04,
-      // offset
-      0xBA, 0x98, 0xFE, 0xDC,
-      0x32, 0x10, 0x76, 0x54,
-      // data length
-      0x00, 0x0c,
-      // data
-      'h',  'e',  'l',  'l',
-      'o',  ' ',  'w',  'o',
-      'r',  'l',  'd',  '!',
-    };
+    // frame type (stream frame with fin)
+    0xFF,
+    // stream id
+    0x01, 0x02, 0x03, 0x04,
+    // offset
+    0xBA, 0x98, 0xFE, 0xDC,
+    0x32, 0x10, 0x76, 0x54,
+    // data length
+    0x00, 0x0c,
+    // data
+    'h',  'e',  'l',  'l',
+    'o',  ' ',  'w',  'o',
+    'r',  'l',  'd',  '!',
+  };
+
+  unsigned char packet40[] = {
+    // public flags (version, 8 byte connection_id)
+    0x39,
+    // connection_id
+    0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+    // version tag
+    'Q', '0', GetQuicVersionDigitTens(), GetQuicVersionDigitOnes(),
+    // packet number
+    0x12, 0x34, 0x56, 0x78,
+    0x9A, 0xBC,
+
+    // frame type (stream frame with fin)
+    0xFF,
+    // data length
+    0x00, 0x0c,
+    // stream id
+    0x01, 0x02, 0x03, 0x04,
+    // offset
+    0xBA, 0x98, 0xFE, 0xDC,
+    0x32, 0x10, 0x76, 0x54,
+    // data
+    'h',  'e',  'l',  'l',
+    'o',  ' ',  'w',  'o',
+    'r',  'l',  'd',  '!',
+  };
   // clang-format on
 
-  QuicEncryptedPacket encrypted(
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
-      arraysize(packet), false);
+  unsigned char* p = packet;
+  if (framer_.version() > QUIC_VERSION_39) {
+    p = packet40;
+  } else if (framer_.version() > QUIC_VERSION_38) {
+    p = packet39;
+  }
+  QuicEncryptedPacket encrypted(AsChars(p), arraysize(packet), false);
   EXPECT_TRUE(framer_.ProcessPacket(encrypted));
 
   EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
@@ -2165,11 +2353,37 @@
     // error code
     0x00, 0x00, 0x00, 0x01,
   };
+
+  unsigned char packet40[] = {
+    // public flags (8 byte connection_id)
+    0x38,
+    // connection_id
+    0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+    // packet number
+    0x12, 0x34, 0x56, 0x78,
+    0x9A, 0xBC,
+
+    // frame type (rst stream frame)
+    0x01,
+    // stream id
+    0x01, 0x02, 0x03, 0x04,
+
+    // error code
+    0x00, 0x00, 0x00, 0x01,
+
+    // sent byte offset
+    0xBA, 0x98, 0xFE, 0xDC,
+    0x32, 0x10, 0x76, 0x54,
+  };
   // clang-format on
 
-  QuicEncryptedPacket encrypted(
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
-      arraysize(packet), false);
+  unsigned char* p = packet;
+  if (framer_.version() > QUIC_VERSION_39) {
+    p = packet40;
+  } else if (framer_.version() > QUIC_VERSION_38) {
+    p = packet39;
+  }
+  QuicEncryptedPacket encrypted(AsChars(p), arraysize(packet), false);
   EXPECT_TRUE(framer_.ProcessPacket(encrypted));
 
   EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
@@ -2185,17 +2399,29 @@
   for (size_t i = kQuicFrameTypeSize; i < QuicFramer::GetRstStreamFrameSize();
        ++i) {
     string expected_error;
-    if (i < kQuicFrameTypeSize + kQuicMaxStreamIdSize) {
-      expected_error = "Unable to read stream_id.";
-    } else if (i < kQuicFrameTypeSize + kQuicMaxStreamIdSize +
-                       kQuicMaxStreamOffsetSize) {
-      expected_error = "Unable to read rst stream sent byte offset.";
-    } else if (i < kQuicFrameTypeSize + kQuicMaxStreamIdSize +
-                       kQuicMaxStreamOffsetSize + kQuicErrorCodeSize) {
-      expected_error = "Unable to read rst stream error code.";
+    if (framer_.version() <= QUIC_VERSION_39) {
+      if (i < kQuicFrameTypeSize + kQuicMaxStreamIdSize) {
+        expected_error = "Unable to read stream_id.";
+      } else if (i < kQuicFrameTypeSize + kQuicMaxStreamIdSize +
+                         kQuicMaxStreamOffsetSize) {
+        expected_error = "Unable to read rst stream sent byte offset.";
+      } else if (i < kQuicFrameTypeSize + kQuicMaxStreamIdSize +
+                         kQuicMaxStreamOffsetSize + kQuicErrorCodeSize) {
+        expected_error = "Unable to read rst stream error code.";
+      }
+    } else {
+      if (i < kQuicFrameTypeSize + kQuicMaxStreamIdSize) {
+        expected_error = "Unable to read stream_id.";
+      } else if (i < kQuicFrameTypeSize + kQuicMaxStreamIdSize +
+                         kQuicErrorCodeSize) {
+        expected_error = "Unable to read rst stream error code.";
+      } else if (i < kQuicFrameTypeSize + kQuicMaxStreamIdSize +
+                         kQuicMaxStreamOffsetSize + kQuicMaxStreamOffsetSize) {
+        expected_error = "Unable to read rst stream sent byte offset.";
+      }
     }
     CheckProcessingFails(
-        framer_.version() <= QUIC_VERSION_38 ? packet : packet39,
+        p,
         i + GetPacketHeaderSize(framer_.version(), PACKET_8BYTE_CONNECTION_ID,
                                 !kIncludeVersion, !kIncludeDiversificationNonce,
                                 PACKET_6BYTE_PACKET_NUMBER),
@@ -2975,15 +3201,50 @@
     // paddings
     0x00, 0x00,
   };
+
+  unsigned char packet40[] = {
+    // public flags (8 byte connection_id)
+    0x38,
+    // connection_id
+    0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+    // packet number
+    0x12, 0x34, 0x56, 0x78,
+    0x9A, 0xBC,
+
+    // paddings
+    0x00, 0x00,
+    // frame type (stream frame with fin)
+    0xFF,
+    // data length
+    0x00, 0x0c,
+    // stream id
+    0x01, 0x02, 0x03, 0x04,
+    // offset
+    0xBA, 0x98, 0xFE, 0xDC,
+    0x32, 0x10, 0x76, 0x54,
+    // data
+    'h',  'e',  'l',  'l',
+    'o',  ' ',  'w',  'o',
+    'r',  'l',  'd',  '!',
+    // paddings
+    0x00, 0x00,
+  };
   // clang-format on
 
   std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_TRUE(data != nullptr);
 
-  test::CompareCharArraysWithHexError(
-      "constructed packet", data->data(), data->length(),
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
-      arraysize(packet));
+  unsigned char* p = packet;
+  if (framer_.version() > QUIC_VERSION_39) {
+    p = packet40;
+  } else if (framer_.version() > QUIC_VERSION_38) {
+    p = packet39;
+  }
+  QuicEncryptedPacket encrypted(AsChars(p), arraysize(packet), false);
+
+  test::CompareCharArraysWithHexError("constructed packet", data->data(),
+                                      data->length(), AsChars(p),
+                                      arraysize(packet));
 }
 
 TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) {
@@ -3781,6 +4042,26 @@
     // error code
     0x05, 0x06, 0x07, 0x08,
   };
+
+  unsigned char packet40[] = {
+    // public flags (8 byte connection_id)
+    0x38,
+    // connection_id
+    0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+    // packet number
+    0x12, 0x34, 0x56, 0x78,
+    0x9A, 0xBC,
+
+    // frame type (rst stream frame)
+    0x01,
+    // stream id
+    0x01, 0x02, 0x03, 0x04,
+    // error code
+    0x05, 0x06, 0x07, 0x08,
+    // sent byte offset
+    0x08, 0x07, 0x06, 0x05,
+    0x04, 0x03, 0x02, 0x01,
+  };
   // clang-format on
 
   QuicFrames frames = {QuicFrame(&rst_frame)};
@@ -3788,10 +4069,17 @@
   std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_TRUE(data != nullptr);
 
-  test::CompareCharArraysWithHexError(
-      "constructed packet", data->data(), data->length(),
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
-      arraysize(packet));
+  unsigned char* p = packet;
+  if (framer_.version() > QUIC_VERSION_39) {
+    p = packet40;
+  } else if (framer_.version() > QUIC_VERSION_38) {
+    p = packet39;
+  }
+  QuicEncryptedPacket encrypted(AsChars(p), arraysize(packet), false);
+
+  test::CompareCharArraysWithHexError("constructed packet", data->data(),
+                                      data->length(), AsChars(p),
+                                      arraysize(packet));
 }
 
 TEST_P(QuicFramerTest, BuildCloseFramePacket) {
@@ -4542,6 +4830,44 @@
     0x12, 0x34, 0x56, 0x78,
     0x9A, 0xBE,
   };
+
+  unsigned char packet40[] = {
+    // public flags (8 byte connection_id)
+    0x38,
+    // connection_id
+    0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+    // packet number
+    0x12, 0x34, 0x56, 0x78,
+    0x9A, 0xBC,
+
+    // frame type (stream frame with fin)
+    0xFF,
+    // data length
+    0x00, 0x0c,
+    // stream id
+    0x01, 0x02, 0x03, 0x04,
+    // offset
+    0xBA, 0x98, 0xFE, 0xDC,
+    0x32, 0x10, 0x76, 0x54,
+    // data
+    'h',  'e',  'l',  'l',
+    'o',  ' ',  'w',  'o',
+    'r',  'l',  'd',  '!',
+
+    // frame type (ack frame)
+    0x40,
+    // least packet number awaiting an ack
+    0x12, 0x34, 0x56, 0x78,
+    0x9A, 0xA0,
+    // largest observed packet number
+    0x12, 0x34, 0x56, 0x78,
+    0x9A, 0xBF,
+    // num missing packets
+    0x01,
+    // missing packet
+    0x12, 0x34, 0x56, 0x78,
+    0x9A, 0xBE,
+  };
   // clang-format on
 
   MockFramerVisitor visitor;
@@ -4555,9 +4881,13 @@
   EXPECT_CALL(visitor, OnUnauthenticatedHeader(_)).WillOnce(Return(true));
   EXPECT_CALL(visitor, OnDecryptedPacket(_));
 
-  QuicEncryptedPacket encrypted(
-      AsChars(framer_.version() <= QUIC_VERSION_38 ? packet : packet39),
-      arraysize(packet), false);
+  unsigned char* p = packet;
+  if (framer_.version() > QUIC_VERSION_39) {
+    p = packet40;
+  } else if (framer_.version() > QUIC_VERSION_38) {
+    p = packet39;
+  }
+  QuicEncryptedPacket encrypted(AsChars(p), arraysize(packet), false);
   EXPECT_TRUE(framer_.ProcessPacket(encrypted));
   EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
 }
diff --git a/net/quic/core/quic_headers_stream_test.cc b/net/quic/core/quic_headers_stream_test.cc
index 888b6da..3d52e0a 100644
--- a/net/quic/core/quic_headers_stream_test.cc
+++ b/net/quic/core/quic_headers_stream_test.cc
@@ -473,7 +473,6 @@
 
 TEST_P(QuicHeadersStreamTest, ProcessPushPromiseDisabledSetting) {
   FLAGS_quic_reloadable_flag_quic_respect_http2_settings_frame = true;
-  FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default = true;
   session_.OnConfigNegotiated();
   SpdySettingsIR data;
   // Respect supported settings frames SETTINGS_ENABLE_PUSH.
@@ -723,8 +722,7 @@
                       QuicStrCat("Unsupported field of HTTP/2 SETTINGS frame: ",
                                  SETTINGS_INITIAL_WINDOW_SIZE),
                       _));
-  if (!FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default ||
-      session_.perspective() == Perspective::IS_CLIENT) {
+  if (session_.perspective() == Perspective::IS_CLIENT) {
     EXPECT_CALL(*connection_,
                 CloseConnection(
                     QUIC_INVALID_HEADERS_STREAM_DATA,
diff --git a/net/quic/core/quic_packet_creator.cc b/net/quic/core/quic_packet_creator.cc
index b21e85ea..cba3a8f7 100644
--- a/net/quic/core/quic_packet_creator.cc
+++ b/net/quic/core/quic_packet_creator.cc
@@ -285,8 +285,15 @@
     return;
   }
 
-  delegate_->OnSerializedPacket(&packet_);
+  if (!FLAGS_quic_reloadable_flag_quic_clear_packet_before_handed_over) {
+    delegate_->OnSerializedPacket(&packet_);
+    ClearPacket();
+    return;
+  }
+  QUIC_FLAG_COUNT(quic_reloadable_flag_quic_clear_packet_before_handed_over);
+  SerializedPacket packet(std::move(packet_));
   ClearPacket();
+  delegate_->OnSerializedPacket(&packet);
 }
 
 void QuicPacketCreator::ClearPacket() {
diff --git a/net/quic/core/quic_packets.cc b/net/quic/core/quic_packets.cc
index 579aa8c..16720b7 100644
--- a/net/quic/core/quic_packets.cc
+++ b/net/quic/core/quic_packets.cc
@@ -216,6 +216,26 @@
 
 SerializedPacket::SerializedPacket(const SerializedPacket& other) = default;
 
+SerializedPacket& SerializedPacket::operator=(const SerializedPacket& other) =
+    default;
+
+SerializedPacket::SerializedPacket(SerializedPacket&& other)
+    : encrypted_buffer(other.encrypted_buffer),
+      encrypted_length(other.encrypted_length),
+      has_crypto_handshake(other.has_crypto_handshake),
+      num_padding_bytes(other.num_padding_bytes),
+      packet_number(other.packet_number),
+      packet_number_length(other.packet_number_length),
+      encryption_level(other.encryption_level),
+      has_ack(other.has_ack),
+      has_stop_waiting(other.has_stop_waiting),
+      transmission_type(other.transmission_type),
+      original_packet_number(other.original_packet_number),
+      largest_acked(other.largest_acked) {
+  retransmittable_frames.swap(other.retransmittable_frames);
+  listeners.swap(other.listeners);
+}
+
 SerializedPacket::~SerializedPacket() {}
 
 void ClearSerializedPacket(SerializedPacket* serialized_packet) {
diff --git a/net/quic/core/quic_packets.h b/net/quic/core/quic_packets.h
index d097a0c..f552f0d 100644
--- a/net/quic/core/quic_packets.h
+++ b/net/quic/core/quic_packets.h
@@ -214,6 +214,8 @@
                    bool has_ack,
                    bool has_stop_waiting);
   SerializedPacket(const SerializedPacket& other);
+  SerializedPacket& operator=(const SerializedPacket& other);
+  SerializedPacket(SerializedPacket&& other);
   ~SerializedPacket();
 
   // Not owned.
diff --git a/net/quic/core/quic_sent_packet_manager.cc b/net/quic/core/quic_sent_packet_manager.cc
index 90eaad0..f6cb1cbd 100644
--- a/net/quic/core/quic_sent_packet_manager.cc
+++ b/net/quic/core/quic_sent_packet_manager.cc
@@ -15,6 +15,7 @@
 #include "net/quic/core/quic_connection_stats.h"
 #include "net/quic/core/quic_pending_retransmission.h"
 #include "net/quic/platform/api/quic_bug_tracker.h"
+#include "net/quic/platform/api/quic_flag_utils.h"
 #include "net/quic/platform/api/quic_flags.h"
 #include "net/quic/platform/api/quic_logging.h"
 #include "net/quic/platform/api/quic_map_util.h"
@@ -289,6 +290,8 @@
 
 void QuicSentPacketManager::HandleAckForSentPackets(
     const QuicAckFrame& ack_frame) {
+  const bool skip_unackable_packets_early =
+      FLAGS_quic_reloadable_flag_quic_handle_acks;
   // Go through the packets we have not received an ack for and see if this
   // incoming_ack shows they've been seen by the peer.
   QuicTime::Delta ack_delay_time = ack_frame.ack_delay_time;
@@ -299,7 +302,9 @@
       // These packets are still in flight.
       break;
     }
-
+    if (skip_unackable_packets_early && it->is_unackable) {
+      continue;
+    }
     if (!ack_frame.packets.Contains(packet_number)) {
       // Packet is still missing.
       continue;
@@ -314,7 +319,7 @@
     // packet, then inform the caller.
     if (it->in_flight) {
       packets_acked_.push_back(std::make_pair(packet_number, it->bytes_sent));
-    } else if (!it->is_unackable) {
+    } else if (skip_unackable_packets_early || !it->is_unackable) {
       // Packets are marked unackable after they've been acked once.
       largest_newly_acked_ = packet_number;
     }
diff --git a/net/quic/core/quic_server_session_base.cc b/net/quic/core/quic_server_session_base.cc
index 2524e5c..a7ba3ec6 100644
--- a/net/quic/core/quic_server_session_base.cc
+++ b/net/quic/core/quic_server_session_base.cc
@@ -55,8 +55,7 @@
   bandwidth_resumption_enabled_ =
       last_bandwidth_resumption || max_bandwidth_resumption;
 
-  if (!FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default ||
-      connection()->version() < QUIC_VERSION_35) {
+  if (connection()->version() < QUIC_VERSION_35) {
     set_server_push_enabled(
         ContainsQuicTag(config()->ReceivedConnectionOptions(), kSPSH));
   }
diff --git a/net/quic/core/quic_server_session_base_test.cc b/net/quic/core/quic_server_session_base_test.cc
index 8c1eb879..3758855 100644
--- a/net/quic/core/quic_server_session_base_test.cc
+++ b/net/quic/core/quic_server_session_base_test.cc
@@ -198,17 +198,6 @@
 INSTANTIATE_TEST_CASE_P(Tests,
                         QuicServerSessionBaseTest,
                         ::testing::ValuesIn(AllSupportedVersions()));
-TEST_P(QuicServerSessionBaseTest, ServerPushDisabledByDefault) {
-  FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default = true;
-  // Without the client explicitly sending kSPSH, server push will be disabled
-  // at the server, until version 35 when it is enabled by default.
-  EXPECT_FALSE(
-      session_->config()->HasReceivedConnectionOptions() &&
-      ContainsQuicTag(session_->config()->ReceivedConnectionOptions(), kSPSH));
-  session_->OnConfigNegotiated();
-  EXPECT_TRUE(session_->server_push_enabled());
-}
-
 TEST_P(QuicServerSessionBaseTest, CloseStreamDueToReset) {
   // Open a stream, then reset it.
   // Send two bytes of payload to open it.
@@ -358,19 +347,6 @@
       session_.get(), kLimitingStreamId + 2 * next_id));
 }
 
-// TODO(ckrasic): remove this when
-// FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default is
-// deprecated.
-TEST_P(QuicServerSessionBaseTest, EnableServerPushThroughConnectionOption) {
-  FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default = false;
-  // Assume server received server push connection option.
-  QuicTagVector copt;
-  copt.push_back(kSPSH);
-  QuicConfigPeer::SetReceivedConnectionOptions(session_->config(), copt);
-  session_->OnConfigNegotiated();
-  EXPECT_TRUE(session_->server_push_enabled());
-}
-
 TEST_P(QuicServerSessionBaseTest, GetEvenIncomingError) {
   // Incoming streams on the server session must be odd.
   EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID, _, _));
diff --git a/net/quic/core/quic_spdy_session.cc b/net/quic/core/quic_spdy_session.cc
index 95369471..82143059 100644
--- a/net/quic/core/quic_spdy_session.cc
+++ b/net/quic/core/quic_spdy_session.cc
@@ -178,8 +178,7 @@
         session_->UpdateHeaderEncoderTableSize(value);
         break;
       case SETTINGS_ENABLE_PUSH:
-        if (FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default &&
-            session_->perspective() == Perspective::IS_SERVER) {
+        if (session_->perspective() == Perspective::IS_SERVER) {
           // See rfc7540, Section 6.5.2.
           if (value > 1) {
             CloseConnection(
@@ -336,7 +335,7 @@
                                  const QuicConfig& config)
     : QuicSession(connection, visitor, config),
       force_hol_blocking_(false),
-      server_push_enabled_(false),
+      server_push_enabled_(true),
       stream_id_(kInvalidStreamId),
       promised_stream_id_(kInvalidStreamId),
       fin_(false),
@@ -396,31 +395,23 @@
                                          const QuicHeaderList& header_list) {
   QuicSpdyStream* stream = GetSpdyDataStream(stream_id);
   if (stream == nullptr) {
-    QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_final_offset_from_trailers, 1,
-                      3);
-    if (FLAGS_quic_reloadable_flag_quic_final_offset_from_trailers) {
-      QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_final_offset_from_trailers, 2,
-                        3);
-      // The stream no longer exists, but trailing headers may contain the final
-      // byte offset necessary for flow control and open stream accounting.
-      size_t final_byte_offset = 0;
-      for (const auto& header : header_list) {
-        const string& header_key = header.first;
-        const string& header_value = header.second;
-        if (header_key == kFinalOffsetHeaderKey) {
-          if (!QuicTextUtils::StringToSizeT(header_value, &final_byte_offset)) {
-            connection()->CloseConnection(
-                QUIC_INVALID_HEADERS_STREAM_DATA,
-                "Trailers are malformed (no final offset)",
-                ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
-            return;
-          }
-          DVLOG(1) << "Received final byte offset in trailers for stream "
-                   << stream_id << ", which no longer exists.";
-          OnFinalByteOffsetReceived(stream_id, final_byte_offset);
-          QUIC_FLAG_COUNT_N(
-              quic_reloadable_flag_quic_final_offset_from_trailers, 3, 3);
+    // The stream no longer exists, but trailing headers may contain the final
+    // byte offset necessary for flow control and open stream accounting.
+    size_t final_byte_offset = 0;
+    for (const auto& header : header_list) {
+      const string& header_key = header.first;
+      const string& header_value = header.second;
+      if (header_key == kFinalOffsetHeaderKey) {
+        if (!QuicTextUtils::StringToSizeT(header_value, &final_byte_offset)) {
+          connection()->CloseConnection(
+              QUIC_INVALID_HEADERS_STREAM_DATA,
+              "Trailers are malformed (no final offset)",
+              ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+          return;
         }
+        DVLOG(1) << "Received final byte offset in trailers for stream "
+                 << stream_id << ", which no longer exists.";
+        OnFinalByteOffsetReceived(stream_id, final_byte_offset);
       }
     }
 
@@ -626,7 +617,6 @@
   }
   const QuicVersion version = connection()->version();
   if (!use_stream_notifier() &&
-      FLAGS_quic_reloadable_flag_quic_enable_force_hol_blocking &&
       version == QUIC_VERSION_36 && config()->ForceHolBlocking(perspective())) {
     force_hol_blocking_ = true;
     // Since all streams are tunneled through the headers stream, it
@@ -639,9 +629,6 @@
     headers_stream_->flow_controller()->UpdateSendWindowOffset(
         kStreamReceiveWindowLimit);
   }
-
-  server_push_enabled_ =
-      FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default;
 }
 
 void QuicSpdySession::OnStreamFrameData(QuicStreamId stream_id,
diff --git a/net/quic/core/quic_stream.h b/net/quic/core/quic_stream.h
index a8bff46..e8d4377 100644
--- a/net/quic/core/quic_stream.h
+++ b/net/quic/core/quic_stream.h
@@ -239,6 +239,12 @@
   // Does not send a FIN.  May cause the stream to be closed.
   virtual void CloseWriteSide();
 
+  // Close the read side of the socket.  May cause the stream to be closed.
+  // Subclasses and consumers should use StopReading to terminate reading early
+  // if expecting a FIN. Can be used directly by subclasses if not expecting a
+  // FIN.
+  void CloseReadSide();
+
   bool fin_buffered() const { return fin_buffered_; }
 
   const QuicSession* session() const { return session_; }
@@ -260,10 +266,6 @@
   friend class test::QuicStreamPeer;
   friend class QuicStreamUtils;
 
-  // Close the read side of the socket.  May cause the stream to be closed.
-  // Subclasses and consumers should use StopReading to terminate reading early.
-  void CloseReadSide();
-
   // Subclasses and consumers should use reading_stopped.
   bool read_side_closed() const { return read_side_closed_; }
 
diff --git a/net/quic/core/quic_version_manager.cc b/net/quic/core/quic_version_manager.cc
index 201d8ae..15466d89c 100644
--- a/net/quic/core/quic_version_manager.cc
+++ b/net/quic/core/quic_version_manager.cc
@@ -10,7 +10,8 @@
 namespace net {
 
 QuicVersionManager::QuicVersionManager(QuicVersionVector supported_versions)
-    : enable_version_40_(GetQuicFlag(FLAGS_quic_enable_version_40)),
+    : enable_version_41_(GetQuicFlag(FLAGS_quic_enable_version_41)),
+      enable_version_40_(GetQuicFlag(FLAGS_quic_enable_version_40)),
       enable_version_39_(FLAGS_quic_reloadable_flag_quic_enable_version_39),
       enable_version_38_(FLAGS_quic_reloadable_flag_quic_enable_version_38),
       disable_version_36_(FLAGS_quic_reloadable_flag_quic_disable_version_36),
@@ -26,11 +27,13 @@
 }
 
 void QuicVersionManager::MaybeRefilterSupportedVersions() {
-  if (enable_version_40_ != GetQuicFlag(FLAGS_quic_enable_version_40) ||
+  if (enable_version_41_ != GetQuicFlag(FLAGS_quic_enable_version_41) ||
+      enable_version_40_ != GetQuicFlag(FLAGS_quic_enable_version_40) ||
       enable_version_39_ != FLAGS_quic_reloadable_flag_quic_enable_version_39 ||
       enable_version_38_ != FLAGS_quic_reloadable_flag_quic_enable_version_38 ||
       disable_version_36_ !=
           FLAGS_quic_reloadable_flag_quic_disable_version_36) {
+    enable_version_41_ = GetQuicFlag(FLAGS_quic_enable_version_41);
     enable_version_40_ = GetQuicFlag(FLAGS_quic_enable_version_40);
     enable_version_39_ = FLAGS_quic_reloadable_flag_quic_enable_version_39;
     enable_version_38_ = FLAGS_quic_reloadable_flag_quic_enable_version_38;
diff --git a/net/quic/core/quic_version_manager.h b/net/quic/core/quic_version_manager.h
index a9201da..55138f6f 100644
--- a/net/quic/core/quic_version_manager.h
+++ b/net/quic/core/quic_version_manager.h
@@ -31,6 +31,8 @@
   }
 
  private:
+  // FLAGS_quic_enable_version_41
+  bool enable_version_41_;
   // FLAGS_quic_enable_version_40
   bool enable_version_40_;
   // FLAGS_quic_reloadable_flag_quic_enable_version_39
diff --git a/net/quic/core/quic_version_manager_test.cc b/net/quic/core/quic_version_manager_test.cc
index 232e5cc..fb735894 100644
--- a/net/quic/core/quic_version_manager_test.cc
+++ b/net/quic/core/quic_version_manager_test.cc
@@ -16,6 +16,7 @@
 class QuicVersionManagerTest : public QuicTest {};
 
 TEST_F(QuicVersionManagerTest, QuicVersionManager) {
+  SetQuicFlag(&FLAGS_quic_enable_version_41, false);
   SetQuicFlag(&FLAGS_quic_enable_version_40, false);
   FLAGS_quic_reloadable_flag_quic_enable_version_39 = false;
   FLAGS_quic_reloadable_flag_quic_enable_version_38 = false;
@@ -56,14 +57,24 @@
   EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[3]);
   EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[4]);
 
+  SetQuicFlag(&FLAGS_quic_enable_version_41, true);
+  ASSERT_EQ(6u, manager.GetSupportedVersions().size());
+  EXPECT_EQ(QUIC_VERSION_41, manager.GetSupportedVersions()[0]);
+  EXPECT_EQ(QUIC_VERSION_40, manager.GetSupportedVersions()[1]);
+  EXPECT_EQ(QUIC_VERSION_39, manager.GetSupportedVersions()[2]);
+  EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedVersions()[3]);
+  EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[4]);
+  EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[5]);
+
   EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()),
             manager.GetSupportedVersions());
-  ASSERT_EQ(5u, manager.GetSupportedVersions().size());
-  EXPECT_EQ(QUIC_VERSION_40, manager.GetSupportedVersions()[0]);
-  EXPECT_EQ(QUIC_VERSION_39, manager.GetSupportedVersions()[1]);
-  EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedVersions()[2]);
-  EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[3]);
-  EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[4]);
+  ASSERT_EQ(6u, manager.GetSupportedVersions().size());
+  EXPECT_EQ(QUIC_VERSION_41, manager.GetSupportedVersions()[0]);
+  EXPECT_EQ(QUIC_VERSION_40, manager.GetSupportedVersions()[1]);
+  EXPECT_EQ(QUIC_VERSION_39, manager.GetSupportedVersions()[2]);
+  EXPECT_EQ(QUIC_VERSION_38, manager.GetSupportedVersions()[3]);
+  EXPECT_EQ(QUIC_VERSION_37, manager.GetSupportedVersions()[4]);
+  EXPECT_EQ(QUIC_VERSION_35, manager.GetSupportedVersions()[5]);
 }
 
 }  // namespace
diff --git a/net/quic/core/quic_versions.cc b/net/quic/core/quic_versions.cc
index ff4d7fe..13a363c 100644
--- a/net/quic/core/quic_versions.cc
+++ b/net/quic/core/quic_versions.cc
@@ -30,7 +30,14 @@
   QuicVersionVector filtered_versions(versions.size());
   filtered_versions.clear();  // Guaranteed by spec not to change capacity.
   for (QuicVersion version : versions) {
-    if (version == QUIC_VERSION_40) {
+    if (version == QUIC_VERSION_41) {
+      if (GetQuicFlag(FLAGS_quic_enable_version_41) &&
+          GetQuicFlag(FLAGS_quic_enable_version_40) &&
+          FLAGS_quic_reloadable_flag_quic_enable_version_39 &&
+          FLAGS_quic_reloadable_flag_quic_enable_version_38) {
+        filtered_versions.push_back(version);
+      }
+    } else if (version == QUIC_VERSION_40) {
       if (GetQuicFlag(FLAGS_quic_enable_version_40) &&
           FLAGS_quic_reloadable_flag_quic_enable_version_39 &&
           FLAGS_quic_reloadable_flag_quic_enable_version_38) {
@@ -81,6 +88,8 @@
       return MakeQuicTag('Q', '0', '3', '9');
     case QUIC_VERSION_40:
       return MakeQuicTag('Q', '0', '4', '0');
+    case QUIC_VERSION_41:
+      return MakeQuicTag('Q', '0', '4', '1');
     default:
       // This shold be an ERROR because we should never attempt to convert an
       // invalid QuicVersion to be written to the wire.
@@ -113,6 +122,7 @@
     RETURN_STRING_LITERAL(QUIC_VERSION_38);
     RETURN_STRING_LITERAL(QUIC_VERSION_39);
     RETURN_STRING_LITERAL(QUIC_VERSION_40);
+    RETURN_STRING_LITERAL(QUIC_VERSION_41);
     default:
       return "QUIC_VERSION_UNSUPPORTED";
   }
diff --git a/net/quic/core/quic_versions.h b/net/quic/core/quic_versions.h
index 1ddffe1..8e5989b 100644
--- a/net/quic/core/quic_versions.h
+++ b/net/quic/core/quic_versions.h
@@ -33,11 +33,8 @@
                          // endian. Dot not ack acks. Send a connection level
                          // WINDOW_UPDATE every 20 sent packets which do not
                          // contain retransmittable frames.
-  QUIC_VERSION_40 = 40,  // Initial packet number is randomly chosen from
-                         // [0:2^31], WINDOW_UPDATE for connection flow control
-                         // advertises value in 1024-byte units, WINDOW_UPDATE
-                         // splits into MAX_DATA and MAX_STREAM_DATA, BLOCKED
-                         // frame split into BLOCKED and STREAM_BLOCKED frames
+  QUIC_VERSION_40 = 40,  // RST_STREAM and STREAM_FRAME frame match IETF format.
+  QUIC_VERSION_41 = 41,  // Use IETF packet header format.
 
   // IMPORTANT: if you are adding to this list, follow the instructions at
   // http://sites/quic/adding-and-removing-versions
@@ -51,7 +48,7 @@
 // IMPORTANT: if you are adding to this list, follow the instructions at
 // http://sites/quic/adding-and-removing-versions
 static const QuicVersion kSupportedQuicVersions[] = {
-    QUIC_VERSION_40, QUIC_VERSION_39, QUIC_VERSION_38,
+    QUIC_VERSION_41, QUIC_VERSION_40, QUIC_VERSION_39, QUIC_VERSION_38,
     QUIC_VERSION_37, QUIC_VERSION_36, QUIC_VERSION_35};
 
 typedef std::vector<QuicVersion> QuicVersionVector;
diff --git a/net/quic/platform/api/quic_flag_utils.h b/net/quic/platform/api/quic_flag_utils.h
index 1689f68..da2f03b 100644
--- a/net/quic/platform/api/quic_flag_utils.h
+++ b/net/quic/platform/api/quic_flag_utils.h
@@ -10,4 +10,7 @@
 #define QUIC_FLAG_COUNT QUIC_FLAG_COUNT_IMPL
 #define QUIC_FLAG_COUNT_N QUIC_FLAG_COUNT_N_IMPL
 
+#define QUIC_CODE_COUNT QUIC_CODE_COUNT_IMPL
+#define QUIC_CODE_COUNT_N QUIC_CODE_COUNT_N_IMPL
+
 #endif  // NET_QUIC_PLATFORM_API_QUIC_FLAG_UTILS_H_
diff --git a/net/quic/platform/impl/quic_flag_utils_impl.h b/net/quic/platform/impl/quic_flag_utils_impl.h
index bd18794..38cfda1 100644
--- a/net/quic/platform/impl/quic_flag_utils_impl.h
+++ b/net/quic/platform/impl/quic_flag_utils_impl.h
@@ -9,4 +9,11 @@
   DVLOG(1) << "FLAG_" #flag ": " << FLAGS_##flag
 #define QUIC_FLAG_COUNT_N_IMPL(flag, instance, total) QUIC_FLAG_COUNT_IMPL(flag)
 
+#define QUIC_CODE_COUNT_IMPL(name) \
+  do {                             \
+  } while (0)
+#define QUIC_CODE_COUNT_N_IMPL(name, instance, total) \
+  do {                                                \
+  } while (0)
+
 #endif  // NET_QUIC_PLATFORM_IMPL_QUIC_FLAG_UTILS_IMPL_H_
diff --git a/net/quic/quartc/quartc_session.cc b/net/quic/quartc/quartc_session.cc
index 7e5c5af6..005f123 100644
--- a/net/quic/quartc/quartc_session.cc
+++ b/net/quic/quartc/quartc_session.cc
@@ -189,6 +189,14 @@
   }
 }
 
+QuartcSessionStats QuartcSession::GetStats() {
+  QuartcSessionStats stats;
+  const QuicConnectionStats& connection_stats = connection_->GetStats();
+  stats.bandwidth_estimate_bits_per_second =
+      connection_stats.estimated_bandwidth.ToBitsPerSecond();
+  return stats;
+}
+
 void QuartcSession::OnConnectionClosed(QuicErrorCode error,
                                        const string& error_details,
                                        ConnectionCloseSource source) {
@@ -308,11 +316,6 @@
       DCHECK(session_delegate_);
       // Incoming streams need to be registered with the session_delegate_.
       session_delegate_->OnIncomingStream(stream.get());
-      // Quartc doesn't send on incoming streams.
-      stream->set_fin_sent(true);
-    } else {
-      // Quartc doesn't receive on outgoing streams.
-      stream->set_fin_received(true);
     }
   }
   return stream;
diff --git a/net/quic/quartc/quartc_session.h b/net/quic/quartc/quartc_session.h
index ffb38fd..fb2eddb 100644
--- a/net/quic/quartc/quartc_session.h
+++ b/net/quic/quartc/quartc_session.h
@@ -72,6 +72,8 @@
 
   void CancelStream(QuicStreamId stream_id) override;
 
+  QuartcSessionStats GetStats() override;
+
   void SetDelegate(QuartcSessionInterface::Delegate* session_delegate) override;
 
   void OnTransportCanWrite() override;
diff --git a/net/quic/quartc/quartc_session_interface.h b/net/quic/quartc/quartc_session_interface.h
index f7dfeb8..8af6343 100644
--- a/net/quic/quartc/quartc_session_interface.h
+++ b/net/quic/quartc/quartc_session_interface.h
@@ -16,6 +16,12 @@
 
 namespace net {
 
+// Structure holding stats exported by a QuartcSession.
+struct QUIC_EXPORT_PRIVATE QuartcSessionStats {
+  // Bandwidth estimate in bits per second.
+  int64_t bandwidth_estimate_bits_per_second;
+};
+
 // Given a PacketTransport, provides a way to send and receive separate streams
 // of reliable, in-order, encrypted data. For example, this can build on top of
 // a WebRTC IceTransport for sending and receiving data over QUIC.
@@ -58,6 +64,9 @@
   // caller tries to cancel them, rendering the caller's pointers invalid.
   virtual void CancelStream(QuicStreamId stream_id) = 0;
 
+  // Gets stats associated with this Quartc session.
+  virtual QuartcSessionStats GetStats() = 0;
+
   // Send and receive packets, like a virtual UDP socket. For example, this
   // could be implemented by WebRTC's IceTransport.
   class PacketTransport {
diff --git a/net/quic/quartc/quartc_session_test.cc b/net/quic/quartc/quartc_session_test.cc
index a4fc6232..d126b96 100644
--- a/net/quic/quartc/quartc_session_test.cc
+++ b/net/quic/quartc/quartc_session_test.cc
@@ -336,7 +336,7 @@
 
   void OnClose(QuartcStreamInterface* stream) override {}
 
-  void OnBufferedAmountDecrease(QuartcStreamInterface* stream) override {}
+  void OnCanWrite(QuartcStreamInterface* stream) override {}
 
   string data() { return last_received_data_; }
 
@@ -636,6 +636,16 @@
   EXPECT_TRUE(client_peer_->IsClosedStream(id));
 }
 
+TEST_F(QuartcSessionTest, GetStats) {
+  CreateClientAndServerSessions();
+  StartHandshake();
+  ASSERT_TRUE(client_peer_->IsCryptoHandshakeConfirmed());
+  ASSERT_TRUE(server_peer_->IsCryptoHandshakeConfirmed());
+
+  QuartcSessionStats stats = client_peer_->GetStats();
+  EXPECT_GT(stats.bandwidth_estimate_bits_per_second, 0);
+}
+
 }  // namespace
 
 }  // namespace net
diff --git a/net/quic/quartc/quartc_stream.cc b/net/quic/quartc/quartc_stream.cc
index 2cae48d..c141b0c 100644
--- a/net/quic/quartc/quartc_stream.cc
+++ b/net/quic/quartc/quartc_stream.cc
@@ -24,6 +24,7 @@
   // Notify the delegate by calling the callback function one more time with
   // iov_len = 0.
   if (sequencer()->IsClosed()) {
+    OnFinRead();
     delegate_->OnReceived(this, reinterpret_cast<const char*>(iov.iov_base), 0);
   }
 }
@@ -37,15 +38,19 @@
 void QuartcStream::OnCanWrite() {
   QuicStream::OnCanWrite();
   DCHECK(delegate_);
-  delegate_->OnBufferedAmountDecrease(this);
+  // Don't call the delegate if the write-side is closed or a fin is buffered.
+  // It is already done with this stream.
+  if (!write_side_closed() && !fin_buffered()) {
+    delegate_->OnCanWrite(this);
+  }
 }
 
 uint32_t QuartcStream::stream_id() {
   return id();
 }
 
-uint64_t QuartcStream::buffered_amount() {
-  return queued_data_bytes();
+uint64_t QuartcStream::bytes_written() {
+  return stream_bytes_written();
 }
 
 bool QuartcStream::fin_sent() {
@@ -63,7 +68,16 @@
 void QuartcStream::Write(const char* data,
                          size_t size,
                          const WriteParameters& param) {
-  WriteOrBufferData(QuicStringPiece(data, size), param.fin, nullptr);
+  struct iovec iov = {const_cast<char*>(data), size};
+  WritevData(&iov, 1, param.fin, nullptr);
+}
+
+void QuartcStream::FinishWriting() {
+  WriteOrBufferData(QuicStringPiece(nullptr, 0), true, nullptr);
+}
+
+void QuartcStream::FinishReading() {
+  QuicStream::StopReading();
 }
 
 void QuartcStream::Close() {
diff --git a/net/quic/quartc/quartc_stream.h b/net/quic/quartc/quartc_stream.h
index 4c33f93..8b7a777 100644
--- a/net/quic/quartc/quartc_stream.h
+++ b/net/quic/quartc/quartc_stream.h
@@ -30,7 +30,7 @@
   // QuartcStreamInterface overrides.
   uint32_t stream_id() override;
 
-  uint64_t buffered_amount() override;
+  uint64_t bytes_written() override;
 
   bool fin_sent() override;
 
@@ -42,6 +42,10 @@
              size_t size,
              const WriteParameters& param) override;
 
+  void FinishWriting() override;
+
+  void FinishReading() override;
+
   void Close() override;
 
   void SetDelegate(QuartcStreamInterface::Delegate* delegate) override;
diff --git a/net/quic/quartc/quartc_stream_interface.h b/net/quic/quartc/quartc_stream_interface.h
index 354b4e50..304190aa 100644
--- a/net/quic/quartc/quartc_stream_interface.h
+++ b/net/quic/quartc/quartc_stream_interface.h
@@ -23,8 +23,8 @@
   // The QUIC stream ID.
   virtual uint32_t stream_id() = 0;
 
-  // The amount of data buffered by the QuicConnection.
-  virtual uint64_t buffered_amount() = 0;
+  // The amount of data sent on this stream.
+  virtual uint64_t bytes_written() = 0;
 
   // Return true if the FIN has been sent. Used by the outgoing streams to
   // determine if all the data has been sent
@@ -42,12 +42,24 @@
     bool fin;
   };
 
-  // Sends data reliably and in-order, buffering if necessary until Close() is
-  // called.
+  // Sends data reliably and in-order.  Returns the amount sent.
+  // Does not buffer data.
   virtual void Write(const char* data,
                      size_t size,
                      const WriteParameters& param) = 0;
 
+  // Marks this stream as finished writing.  Asynchronously sends a FIN and
+  // closes the write-side.  The stream will no longer call OnCanWrite().
+  // It is not necessary to call FinishWriting() if the last call to Write()
+  // sends a FIN.
+  virtual void FinishWriting() = 0;
+
+  // Marks this stream as finished reading.  Further incoming data is discarded.
+  // The stream will no longer call OnReceived().
+  // It is never necessary to call FinishReading().  The read-side closes when a
+  // FIN is received, regardless of whether FinishReading() has been called.
+  virtual void FinishReading() = 0;
+
   // Once Close is called, no more data can be sent, all buffered data will be
   // dropped and no data will be retransmitted.
   virtual void Close() = 0;
@@ -58,19 +70,21 @@
    public:
     virtual ~Delegate() {}
 
-    // Called when the stream receives the date.
+    // Called when the stream receives the data.  Called with |size| == 0 after
+    // all stream data has been delivered.
     virtual void OnReceived(QuartcStreamInterface* stream,
                             const char* data,
                             size_t size) = 0;
 
     // Called when the stream is closed, either locally or by the remote
-    // endpoint.
+    // endpoint.  Streams close when (a) fin bits are both sent and received,
+    // (b) Close() is called, or (c) the stream is reset.
     // TODO(zhihuang) Creates a map from the integer error_code to WebRTC native
     // error code.
     virtual void OnClose(QuartcStreamInterface* stream) = 0;
 
-    // Called when buffered_amount() decreases.
-    virtual void OnBufferedAmountDecrease(QuartcStreamInterface* stream) = 0;
+    // Called when more data may be written to a stream.
+    virtual void OnCanWrite(QuartcStreamInterface* stream) = 0;
   };
 
   // The |delegate| is not owned by QuartcStream.
diff --git a/net/quic/quartc/quartc_stream_test.cc b/net/quic/quartc/quartc_stream_test.cc
index 3302df6..072daca 100644
--- a/net/quic/quartc/quartc_stream_test.cc
+++ b/net/quic/quartc/quartc_stream_test.cc
@@ -126,8 +126,8 @@
   MockQuartcStreamDelegate(int id, std::string* read_buffer)
       : id_(id), read_buffer_(read_buffer) {}
 
-  void OnBufferedAmountDecrease(QuartcStreamInterface* stream) override {
-    queued_bytes_amount_ = stream->buffered_amount();
+  void OnCanWrite(QuartcStreamInterface* stream) override {
+    ++on_can_write_callbacks_;
   }
 
   void OnReceived(QuartcStreamInterface* stream,
@@ -141,7 +141,7 @@
 
   bool closed() { return closed_; }
 
-  int queued_bytes_amount() { return queued_bytes_amount_; }
+  int32_t on_can_write_callbacks() { return on_can_write_callbacks_; }
 
  protected:
   uint32_t id_;
@@ -149,7 +149,8 @@
   std::string* read_buffer_;
   // Whether the QuicStream is closed.
   bool closed_ = false;
-  int queued_bytes_amount_ = -1;
+  // How many times OnCanWrite has been called.
+  int32_t on_can_write_callbacks_ = 0;
 };
 
 class QuartcStreamTest : public ::testing::Test,
@@ -223,25 +224,49 @@
   EXPECT_EQ("Foo b", write_buffer_);
 }
 
-// Test that strings are buffered correctly.
-TEST_F(QuartcStreamTest, BufferData) {
+// Test that strings are not buffered.
+TEST_F(QuartcStreamTest, NoBuffer) {
   CreateReliableQuicStream();
 
   session_->set_writable(false);
   stream_->Write("Foo bar", 7, kDefaultParam);
-  // The data will be buffered.
+  // The data will not be buffered.
   EXPECT_EQ(0ul, write_buffer_.size());
-  EXPECT_TRUE(stream_->HasBufferedData());
-  EXPECT_EQ(-1, mock_stream_delegate_->queued_bytes_amount());
-  // The session is writable and the buffered data amount will change.
+  EXPECT_FALSE(stream_->HasBufferedData());
+  EXPECT_EQ(0u, stream_->bytes_written());
+  // The stream is writable, but there's nothing to send.
   session_->set_writable(true);
   stream_->OnCanWrite();
-  EXPECT_EQ(0, mock_stream_delegate_->queued_bytes_amount());
+  EXPECT_EQ(0u, stream_->bytes_written());
   EXPECT_FALSE(stream_->HasBufferedData());
-  EXPECT_EQ("Foo bar", write_buffer_);
+  EXPECT_EQ(0ul, write_buffer_.size());
 
+  // The stream threw away the previous data.  It only sends this.
   stream_->Write("xyzzy", 5, kDefaultParam);
-  EXPECT_EQ("Foo barxyzzy", write_buffer_);
+  EXPECT_EQ("xyzzy", write_buffer_);
+  EXPECT_EQ(5u, stream_->bytes_written());
+}
+
+// Finish writing to a stream.
+// The stream no longer calls OnCanWrite().  It delivers the fin bit and closes
+// the write-side as soon as possible.
+TEST_F(QuartcStreamTest, FinishWriting) {
+  CreateReliableQuicStream();
+
+  session_->set_writable(false);
+  stream_->FinishWriting();
+  EXPECT_FALSE(stream_->fin_sent());
+
+  // Fin is buffered, no callback to OnCanWrite.
+  stream_->OnCanWrite();
+  EXPECT_EQ(0, mock_stream_delegate_->on_can_write_callbacks());
+  EXPECT_FALSE(stream_->fin_sent());
+
+  // Fin is sent, no callback to OnCanWrite.
+  session_->set_writable(true);
+  stream_->OnCanWrite();
+  EXPECT_EQ(0, mock_stream_delegate_->on_can_write_callbacks());
+  EXPECT_TRUE(stream_->fin_sent());
 }
 
 // Read an entire string.
@@ -263,6 +288,23 @@
   EXPECT_EQ("Hello", read_buffer_);
 }
 
+// Streams do not call OnReceived() after FinishReading().
+TEST_F(QuartcStreamTest, FinishReading) {
+  CreateReliableQuicStream();
+  stream_->FinishReading();
+
+  QuicStreamFrame frame(kStreamId, false, 0, "Hello, World!");
+  stream_->OnStreamFrame(frame);
+
+  EXPECT_EQ(0ul, read_buffer_.size());
+
+  QuicStreamFrame frame2(kStreamId, true, 0, "Hello, World!");
+  stream_->OnStreamFrame(frame2);
+
+  EXPECT_EQ(0ul, read_buffer_.size());
+  EXPECT_TRUE(stream_->fin_received());
+}
+
 // Test that closing the stream results in a callback.
 TEST_F(QuartcStreamTest, CloseStream) {
   CreateReliableQuicStream();
@@ -271,6 +313,20 @@
   EXPECT_TRUE(mock_stream_delegate_->closed());
 }
 
+// Both sending and receiving fin automatically closes a stream.
+TEST_F(QuartcStreamTest, CloseOnFins) {
+  CreateReliableQuicStream();
+  QuicStreamFrame frame(kStreamId, true, 0, 0);
+  stream_->OnStreamFrame(frame);
+
+  QuartcStreamInterface::WriteParameters param;
+  param.fin = true;
+  stream_->Write(nullptr, 0, param);
+
+  // Check that the OnClose() callback occurred.
+  EXPECT_TRUE(mock_stream_delegate_->closed());
+}
+
 }  // namespace
 
 }  // namespace net
diff --git a/net/quic/test_tools/simulator/quic_endpoint_test.cc b/net/quic/test_tools/simulator/quic_endpoint_test.cc
index f402908..d739bfb 100644
--- a/net/quic/test_tools/simulator/quic_endpoint_test.cc
+++ b/net/quic/test_tools/simulator/quic_endpoint_test.cc
@@ -11,10 +11,9 @@
 #include "net/quic/test_tools/simulator/simulator.h"
 #include "net/quic/test_tools/simulator/switch.h"
 
-
-using ::testing::_;
 using ::testing::NiceMock;
 using ::testing::Return;
+using ::testing::_;
 
 namespace net {
 namespace simulator {
@@ -40,6 +39,15 @@
     return QuicMakeUnique<SymmetricLink>(a, b, kDefaultBandwidth,
                                          kDefaultPropagationDelay);
   }
+
+  std::unique_ptr<SymmetricLink> CustomLink(Endpoint* a,
+                                            Endpoint* b,
+                                            uint64_t extra_rtt_ms) {
+    return QuicMakeUnique<SymmetricLink>(
+        a, b, kDefaultBandwidth,
+        kDefaultPropagationDelay +
+            QuicTime::Delta::FromMilliseconds(extra_rtt_ms));
+  }
 };
 
 // Test transmission from one host to another.
@@ -159,9 +167,11 @@
       "Endpoint D",
       {endpoint_d_a.get(), endpoint_d_b.get(), endpoint_d_c.get()});
 
-  auto link_a = Link(endpoint_a.get(), switch_.port(1));
-  auto link_b = Link(endpoint_b.get(), switch_.port(2));
-  auto link_c = Link(endpoint_c.get(), switch_.port(3));
+  // Create links with slightly different RTTs in order to avoid pathological
+  // side-effects of packets entering the queue at the exactly same time.
+  auto link_a = CustomLink(endpoint_a.get(), switch_.port(1), 0);
+  auto link_b = CustomLink(endpoint_b.get(), switch_.port(2), 1);
+  auto link_c = CustomLink(endpoint_c.get(), switch_.port(3), 2);
   auto link_d = Link(&endpoint_d, switch_.port(4));
 
   endpoint_a->AddBytesToTransfer(2 * 1024 * 1024);
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc
index acaeea6..c9ef6ab 100644
--- a/net/tools/quic/end_to_end_test.cc
+++ b/net/tools/quic/end_to_end_test.cc
@@ -2848,43 +2848,6 @@
   EXPECT_EQ(12u, client_->num_responses());
 }
 
-// TODO(ckrasic) - remove this when deprecating
-// FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default.
-TEST_P(EndToEndTestServerPush, DisabledWithoutConnectionOption) {
-  FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default = false;
-  // Tests that server push won't be triggered when kSPSH is not set by client.
-  support_server_push_ = false;
-  ASSERT_TRUE(Initialize());
-
-  // Add a response with headers, body, and push resources.
-  const string kBody = "body content";
-  size_t const kNumResources = 4;
-  string push_urls[] = {
-      "https://example.com/font.woff", "https://example.com/script.js",
-      "https://fonts.example.com/font.woff",
-      "https://example.com/logo-hires.jpg",
-  };
-  AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody,
-                                      push_urls, kNumResources, 0);
-  client_->client()->set_response_listener(
-      std::unique_ptr<QuicClientBase::ResponseListener>(
-          new TestResponseListener));
-  EXPECT_EQ(kBody, client_->SendSynchronousRequest(
-                       "https://example.com/push_example"));
-
-  for (const string& url : push_urls) {
-    // Sending subsequent requests will trigger sending real requests because
-    // client doesn't support server push.
-    const string expected_body =
-        QuicStrCat("This is server push response body for ", url);
-    const string response_body = client_->SendSynchronousRequest(url);
-    EXPECT_EQ(expected_body, response_body);
-  }
-  // Same number of requests are sent as that of responses received.
-  EXPECT_EQ(1 + kNumResources, client_->num_requests());
-  EXPECT_EQ(1 + kNumResources, client_->num_responses());
-}
-
 // TODO(fayang): this test seems to cause net_unittests timeouts :|
 TEST_P(EndToEndTest, DISABLED_TestHugePostWithPacketLoss) {
   // This test tests a huge post with introduced packet loss from client to
diff --git a/net/tools/quic/quic_client_session_test.cc b/net/tools/quic/quic_client_session_test.cc
index b45312a..5b6cd71a 100644
--- a/net/tools/quic/quic_client_session_test.cc
+++ b/net/tools/quic/quic_client_session_test.cc
@@ -265,25 +265,16 @@
   trailers.OnHeaderBlockEnd(0, 0);
   session_->OnStreamHeaderList(stream_id, /*fin=*/false, 0, trailers);
 
-  if (FLAGS_quic_reloadable_flag_quic_final_offset_from_trailers) {
-    // The stream is now complete from the client's perspective, and it should
-    // be able to create a new outgoing stream.
-    EXPECT_EQ(0u, session_->GetNumOpenOutgoingStreams());
-    stream = session_->CreateOutgoingDynamicStream(kDefaultPriority);
-    EXPECT_NE(nullptr, stream);
-  } else {
-    // The old behavior: receiving trailers with final offset does not trigger
-    // cleanup of local stream state. New streams cannot be created.
-    EXPECT_EQ(1u, session_->GetNumOpenOutgoingStreams());
-    stream = session_->CreateOutgoingDynamicStream(kDefaultPriority);
-    EXPECT_EQ(nullptr, stream);
-  }
+  // The stream is now complete from the client's perspective, and it should
+  // be able to create a new outgoing stream.
+  EXPECT_EQ(0u, session_->GetNumOpenOutgoingStreams());
+  stream = session_->CreateOutgoingDynamicStream(kDefaultPriority);
+  EXPECT_NE(nullptr, stream);
 }
 
 TEST_P(QuicClientSessionTest, ReceivedMalformedTrailersAfterSendingRst) {
   // Tests the situation where the client has sent a RST to the server, and has
   // received trailing headers with a malformed final byte offset value.
-  FLAGS_quic_reloadable_flag_quic_final_offset_from_trailers = true;
   CompleteCryptoHandshake();
 
   QuicSpdyClientStream* stream =
diff --git a/net/tools/quic/quic_dispatcher_test.cc b/net/tools/quic/quic_dispatcher_test.cc
index 6491ebfc..5d4e9fd 100644
--- a/net/tools/quic/quic_dispatcher_test.cc
+++ b/net/tools/quic/quic_dispatcher_test.cc
@@ -548,11 +548,12 @@
 }
 
 TEST_F(QuicDispatcherTest, SupportedVersionsChangeInFlight) {
-  static_assert(arraysize(kSupportedQuicVersions) == 6u,
+  static_assert(arraysize(kSupportedQuicVersions) == 7u,
                 "Supported versions out of sync");
   FLAGS_quic_reloadable_flag_quic_enable_version_38 = true;
   FLAGS_quic_reloadable_flag_quic_enable_version_39 = true;
   SetQuicFlag(&FLAGS_quic_enable_version_40, true);
+  SetQuicFlag(&FLAGS_quic_enable_version_41, true);
   QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
   server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
   QuicConnectionId connection_id = 1;
@@ -597,6 +598,35 @@
   ProcessPacket(client_address, connection_id, true, QuicVersionMax(),
                 SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
                 PACKET_6BYTE_PACKET_NUMBER, 1);
+  // Turn off version 41.
+  SetQuicFlag(&FLAGS_quic_enable_version_41, false);
+  ++connection_id;
+  EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
+                                              QuicStringPiece("hq")))
+      .Times(0);
+  ProcessPacket(client_address, connection_id, true, QUIC_VERSION_41,
+                SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
+                PACKET_6BYTE_PACKET_NUMBER, 1);
+
+  // Turn on version 41.
+  SetQuicFlag(&FLAGS_quic_enable_version_41, true);
+  ++connection_id;
+  EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
+                                              QuicStringPiece("hq")))
+      .WillOnce(testing::Return(CreateSession(
+          dispatcher_.get(), config_, connection_id, client_address,
+          &mock_helper_, &mock_alarm_factory_, &crypto_config_,
+          QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+  EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+              ProcessUdpPacket(_, _, _))
+      .WillOnce(testing::WithArgs<2>(
+          Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket,
+                               base::Unretained(this), connection_id))));
+  EXPECT_CALL(*dispatcher_,
+              ShouldCreateOrBufferPacketForConnection(connection_id));
+  ProcessPacket(client_address, connection_id, true, QUIC_VERSION_41,
+                SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
+                PACKET_6BYTE_PACKET_NUMBER, 1);
   // Turn off version 40.
   SetQuicFlag(&FLAGS_quic_enable_version_40, false);
   ++connection_id;
diff --git a/services/device/generic_sensor/BUILD.gn b/services/device/generic_sensor/BUILD.gn
index 0e79734b..58f831cdc1 100644
--- a/services/device/generic_sensor/BUILD.gn
+++ b/services/device/generic_sensor/BUILD.gn
@@ -16,6 +16,8 @@
     "generic_sensor_consts.h",
     "linux/sensor_data_linux.cc",
     "linux/sensor_data_linux.h",
+    "orientation_quaternion_fusion_algorithm_using_euler_angles.cc",
+    "orientation_quaternion_fusion_algorithm_using_euler_angles.h",
     "platform_sensor.cc",
     "platform_sensor.h",
     "platform_sensor_accelerometer_mac.cc",
diff --git a/services/device/generic_sensor/README.md b/services/device/generic_sensor/README.md
index f60f783..c63ea5a 100644
--- a/services/device/generic_sensor/README.md
+++ b/services/device/generic_sensor/README.md
@@ -14,19 +14,19 @@
 table. An empty cell indicates that the sensor type is not supported on that
 platform.
 
-| SensorType                        | Android                   | Linux          | macOS              | Windows                                   |
-| --------------------------------- | ------------------------- | -------------- | ------------------ | ----------------------------------------- |
-| AMBIENT_LIGHT                     | TYPE_LIGHT                | in_illuminance | AppleLMUController | SENSOR_TYPE_AMBIENT_LIGHT                 |
-| PROXIMITY                         |                           |                |                    |                                           |
-| ACCELEROMETER                     | TYPE_ACCELEROMETER        | in_accel       | SMCMotionSensor    | SENSOR_TYPE_ACCELEROMETER_3D              |
-| LINEAR_ACCELEROMETER              | TYPE_LINEAR_ACCELEROMETER |                |                    |                                           |
-| GYROSCOPE                         | TYPE_GYROSCOPE            | in_anglvel     |                    | SENSOR_TYPE_GYROMETER_3D                  |
-| MAGNETOMETER                      | TYPE_MAGNETIC_FIELD       | in_magn        |                    | SENSOR_TYPE_COMPASS_3D                    |
-| PRESSURE                          |                           |                |                    |                                           |
-| ABSOLUTE_ORIENTATION_EULER_ANGLES |                           |                |                    | SENSOR_TYPE_INCLINOMETER_3D               |
-| ABSOLUTE_ORIENTATION_QUATERNION   | TYPE_ROTATION_VECTOR      |                |                    | SENSOR_TYPE_AGGREGATED_DEVICE_ORIENTATION |
-| RELATIVE_ORIENTATION_EULER_ANGLES |                           |                | ACCELEROMETER (*)  |                                           |
-| RELATIVE_ORIENTATION_QUATERNION   | TYPE_GAME_ROTATION_VECTOR |                |                    |                                           |
+| SensorType                        | Android                   | Linux          | macOS                                 | Windows                                   |
+| --------------------------------- | ------------------------- | -------------- | ------------------------------------- | ----------------------------------------- |
+| AMBIENT_LIGHT                     | TYPE_LIGHT                | in_illuminance | AppleLMUController                    | SENSOR_TYPE_AMBIENT_LIGHT                 |
+| PROXIMITY                         |                           |                |                                       |                                           |
+| ACCELEROMETER                     | TYPE_ACCELEROMETER        | in_accel       | SMCMotionSensor                       | SENSOR_TYPE_ACCELEROMETER_3D              |
+| LINEAR_ACCELEROMETER              | TYPE_LINEAR_ACCELEROMETER |                |                                       |                                           |
+| GYROSCOPE                         | TYPE_GYROSCOPE            | in_anglvel     |                                       | SENSOR_TYPE_GYROMETER_3D                  |
+| MAGNETOMETER                      | TYPE_MAGNETIC_FIELD       | in_magn        |                                       | SENSOR_TYPE_COMPASS_3D                    |
+| PRESSURE                          |                           |                |                                       |                                           |
+| ABSOLUTE_ORIENTATION_EULER_ANGLES |                           |                |                                       | SENSOR_TYPE_INCLINOMETER_3D               |
+| ABSOLUTE_ORIENTATION_QUATERNION   | TYPE_ROTATION_VECTOR      |                |                                       | SENSOR_TYPE_AGGREGATED_DEVICE_ORIENTATION |
+| RELATIVE_ORIENTATION_EULER_ANGLES |                           |                | ACCELEROMETER (*)                     |                                           |
+| RELATIVE_ORIENTATION_QUATERNION   | TYPE_GAME_ROTATION_VECTOR |                | RELATIVE_ORIENTATION_EULER_ANGLES (*) |                                           |
 
 (Note: "*" means the sensor type is provided by sensor fusion.)
 
@@ -50,7 +50,9 @@
 type is provided by interpreting the value that can be read from the LMU. The
 ACCELEROMETER sensor type is provided by interpreting the value that can be read
 from the SMCMotionSensor. The RELATIVE_ORIENTATION_EULER_ANGLES sensor type is
-provided by interpreting the value that can be read from the ACCELEROMETER.
+provided by interpreting the value that can be read from the ACCELEROMETER. The
+RELATIVE_ORIENTATION_QUATERNION sensor type is provided by interpreting the
+value that can be read from the RELATIVE_ORIENTATION_EULER_ANGLES.
 
 ### Windows
 
diff --git a/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.cc b/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.cc
new file mode 100644
index 0000000..68d9f26d
--- /dev/null
+++ b/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.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 "services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.h"
+
+#include <cmath>
+
+#include "services/device/generic_sensor/generic_sensor_consts.h"
+
+namespace {
+
+void ComputeQuaternionFromEulerAngles(double alpha,
+                                      double beta,
+                                      double gamma,
+                                      double* x,
+                                      double* y,
+                                      double* z,
+                                      double* w) {
+  double cx = std::cos(beta / 2);
+  double cy = std::cos(gamma / 2);
+  double cz = std::cos(alpha / 2);
+  double sx = std::sin(beta / 2);
+  double sy = std::sin(gamma / 2);
+  double sz = std::sin(alpha / 2);
+
+  *x = sx * cy * cz - cx * sy * sz;
+  *y = cx * sy * cz + sx * cy * sz;
+  *z = cx * cy * sz + sx * sy * cz;
+  *w = cx * cy * cz - sx * sy * sz;
+}
+
+}  // namespace
+
+namespace device {
+
+OrientationQuaternionFusionAlgorithmUsingEulerAngles::
+    OrientationQuaternionFusionAlgorithmUsingEulerAngles() {}
+
+OrientationQuaternionFusionAlgorithmUsingEulerAngles::
+    ~OrientationQuaternionFusionAlgorithmUsingEulerAngles() = default;
+
+void OrientationQuaternionFusionAlgorithmUsingEulerAngles::GetFusedData(
+    const std::vector<SensorReading>& readings,
+    SensorReading* fused_reading) {
+  // Transform the *_ORIENTATION_EULER_ANGLES values to
+  // *_ORIENTATION_QUATERNION.
+  DCHECK(readings.size() == 1);
+
+  double beta = readings[0].values[0].value();
+  double gamma = readings[0].values[1].value();
+  double alpha = readings[0].values[2].value();
+  double x, y, z, w;
+  ComputeQuaternionFromEulerAngles(alpha, beta, gamma, &x, &y, &z, &w);
+  fused_reading->values[0].value() = x;
+  fused_reading->values[1].value() = y;
+  fused_reading->values[2].value() = z;
+  fused_reading->values[3].value() = w;
+}
+
+}  // namespace device
diff --git a/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.h b/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.h
new file mode 100644
index 0000000..2b571c3
--- /dev/null
+++ b/services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.h
@@ -0,0 +1,31 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_DEVICE_ORIENTATION_QUATERNION_FUSION_ALGORITHM_USING_EULER_ANGLES_H_
+#define SERVICES_DEVICE_ORIENTATION_QUATERNION_FUSION_ALGORITHM_USING_EULER_ANGLES_H_
+
+#include "base/macros.h"
+#include "services/device/generic_sensor/platform_sensor_fusion_algorithm.h"
+
+namespace device {
+
+// Sensor fusion algorithm for implementing *_ORIENTATION_QUATERNION
+// using *_ORIENTATION_EULER_ANGLES.
+class OrientationQuaternionFusionAlgorithmUsingEulerAngles
+    : public PlatformSensorFusionAlgorithm {
+ public:
+  OrientationQuaternionFusionAlgorithmUsingEulerAngles();
+  ~OrientationQuaternionFusionAlgorithmUsingEulerAngles() override;
+
+  void GetFusedData(const std::vector<SensorReading>& readings,
+                    SensorReading* fused_reading) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(
+      OrientationQuaternionFusionAlgorithmUsingEulerAngles);
+};
+
+}  // namespace device
+
+#endif  // SERVICES_DEVICE_ORIENTATION_QUATERNION_FUSION_ALGORITHM_USING_EULER_ANGLES_H_
diff --git a/services/device/generic_sensor/platform_sensor_provider_mac.cc b/services/device/generic_sensor/platform_sensor_provider_mac.cc
index 3c34b3d..ffd7540 100644
--- a/services/device/generic_sensor/platform_sensor_provider_mac.cc
+++ b/services/device/generic_sensor/platform_sensor_provider_mac.cc
@@ -6,6 +6,7 @@
 
 #include "base/memory/ptr_util.h"
 #include "base/memory/singleton.h"
+#include "services/device/generic_sensor/orientation_quaternion_fusion_algorithm_using_euler_angles.h"
 #include "services/device/generic_sensor/platform_sensor_accelerometer_mac.h"
 #include "services/device/generic_sensor/platform_sensor_ambient_light_mac.h"
 #include "services/device/generic_sensor/platform_sensor_fusion.h"
@@ -47,6 +48,8 @@
       auto relative_orientation_euler_angles_fusion_algorithm_using_accelerometer =
           base::MakeUnique<
               RelativeOrientationEulerAnglesFusionAlgorithmUsingAccelerometer>();
+      // If a PlatformSensorFusion object is created successfully, the caller
+      // of this function holds the reference to the object.
       base::MakeRefCounted<PlatformSensorFusion>(
           std::move(mapping), this, callback, source_sensor_types,
           mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES,
@@ -54,6 +57,21 @@
               relative_orientation_euler_angles_fusion_algorithm_using_accelerometer));
       break;
     }
+    case mojom::SensorType::RELATIVE_ORIENTATION_QUATERNION: {
+      std::vector<mojom::SensorType> source_sensor_types = {
+          mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES};
+      auto orientation_quaternion_fusion_algorithm_using_euler_angles =
+          base::MakeUnique<
+              OrientationQuaternionFusionAlgorithmUsingEulerAngles>();
+      // If a PlatformSensorFusion object is created successfully, the caller
+      // of this function holds the reference to the object.
+      base::MakeRefCounted<PlatformSensorFusion>(
+          std::move(mapping), this, callback, source_sensor_types,
+          mojom::SensorType::RELATIVE_ORIENTATION_QUATERNION,
+          std::move(
+              orientation_quaternion_fusion_algorithm_using_euler_angles));
+      break;
+    }
     default:
       NOTIMPLEMENTED();
       callback.Run(nullptr);
diff --git a/services/shape_detection/DEPS b/services/shape_detection/DEPS
index 09ca6e8..dd63880 100644
--- a/services/shape_detection/DEPS
+++ b/services/shape_detection/DEPS
@@ -1,5 +1,5 @@
 include_rules = [
-  "+media/capture/video/scoped_result_callback.h",
+  "+media/base/scoped_callback_runner.h",
   "+jni",
   "+skia/ext/skia_utils_mac.h",
   "+third_party/skia/include",
diff --git a/services/shape_detection/barcode_detection_impl_mac.mm b/services/shape_detection/barcode_detection_impl_mac.mm
index 77521cf..1c198b8 100644
--- a/services/shape_detection/barcode_detection_impl_mac.mm
+++ b/services/shape_detection/barcode_detection_impl_mac.mm
@@ -8,22 +8,13 @@
 #include "base/mac/scoped_cftyperef.h"
 #include "base/mac/sdk_forward_declarations.h"
 #include "base/strings/sys_string_conversions.h"
-#include "media/capture/video/scoped_result_callback.h"
+#include "media/base/scoped_callback_runner.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/shape_detection/barcode_detection_impl.h"
 #include "services/shape_detection/detection_utils_mac.h"
 
 namespace shape_detection {
 
-namespace {
-
-void RunCallbackWithNoBarcodes(
-    shape_detection::mojom::BarcodeDetection::DetectCallback callback) {
-  std::move(callback).Run({});
-}
-
-}  // anonymous namespace
-
 // static
 void BarcodeDetectionImpl::Create(
     shape_detection::mojom::BarcodeDetectionRequest request) {
@@ -45,8 +36,8 @@
 
 void BarcodeDetectionImplMac::Detect(const SkBitmap& bitmap,
                                      DetectCallback callback) {
-  media::ScopedResultCallback<DetectCallback> scoped_callback(
-      std::move(callback), base::Bind(&RunCallbackWithNoBarcodes));
+  DetectCallback scoped_callback = media::ScopedCallbackRunner(
+      std::move(callback), std::vector<mojom::BarcodeDetectionResultPtr>());
 
   base::scoped_nsobject<CIImage> ci_image = CreateCIImageFromSkBitmap(bitmap);
   if (!ci_image)
@@ -78,7 +69,7 @@
     result->raw_value = base::SysNSStringToUTF8(f.messageString);
     results.push_back(std::move(result));
   }
-  scoped_callback.Run(std::move(results));
+  std::move(scoped_callback).Run(std::move(results));
 }
 
 }  // namespace shape_detection
diff --git a/services/shape_detection/face_detection_impl_mac.mm b/services/shape_detection/face_detection_impl_mac.mm
index 29648c3..ddf076f5 100644
--- a/services/shape_detection/face_detection_impl_mac.mm
+++ b/services/shape_detection/face_detection_impl_mac.mm
@@ -5,22 +5,13 @@
 #include "services/shape_detection/face_detection_impl_mac.h"
 
 #include "base/mac/scoped_cftyperef.h"
-#include "media/capture/video/scoped_result_callback.h"
+#include "media/base/scoped_callback_runner.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/shape_detection/detection_utils_mac.h"
 #include "services/shape_detection/face_detection_provider_impl.h"
 
 namespace shape_detection {
 
-namespace {
-
-void RunCallbackWithNoFaces(
-    shape_detection::mojom::FaceDetection::DetectCallback callback) {
-  std::move(callback).Run({});
-}
-
-}  // anonymous namespace
-
 void FaceDetectionProviderImpl::CreateFaceDetection(
     shape_detection::mojom::FaceDetectionRequest request,
     shape_detection::mojom::FaceDetectorOptionsPtr options) {
@@ -43,8 +34,8 @@
 
 void FaceDetectionImplMac::Detect(const SkBitmap& bitmap,
                                   DetectCallback callback) {
-  media::ScopedResultCallback<DetectCallback> scoped_callback(
-      std::move(callback), base::Bind(&RunCallbackWithNoFaces));
+  DetectCallback scoped_callback = media::ScopedCallbackRunner(
+      std::move(callback), std::vector<mojom::FaceDetectionResultPtr>());
 
   base::scoped_nsobject<CIImage> ci_image = CreateCIImageFromSkBitmap(bitmap);
   if (!ci_image)
@@ -89,7 +80,7 @@
 
     results.push_back(std::move(face));
   }
-  scoped_callback.Run(std::move(results));
+  std::move(scoped_callback).Run(std::move(results));
 }
 
 }  // namespace shape_detection
diff --git a/services/shape_detection/text_detection_impl_mac.mm b/services/shape_detection/text_detection_impl_mac.mm
index 9532fb1..1c98cf3 100644
--- a/services/shape_detection/text_detection_impl_mac.mm
+++ b/services/shape_detection/text_detection_impl_mac.mm
@@ -8,21 +8,13 @@
 #include "base/mac/scoped_cftyperef.h"
 #include "base/mac/sdk_forward_declarations.h"
 #include "base/strings/sys_string_conversions.h"
-#include "media/capture/video/scoped_result_callback.h"
+#include "media/base/scoped_callback_runner.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/shape_detection/detection_utils_mac.h"
 #include "services/shape_detection/text_detection_impl.h"
 
 namespace shape_detection {
 
-namespace {
-
-void RunCallbackWithNoResults(mojom::TextDetection::DetectCallback callback) {
-  std::move(callback).Run({});
-}
-
-}  // anonymous namespace
-
 // static
 void TextDetectionImpl::Create(mojom::TextDetectionRequest request) {
   // Text detection needs at least MAC OS X 10.11.
@@ -44,8 +36,8 @@
 void TextDetectionImplMac::Detect(const SkBitmap& bitmap,
                                   DetectCallback callback) {
   DCHECK(base::mac::IsAtLeastOS10_11());
-  media::ScopedResultCallback<DetectCallback> scoped_callback(
-      std::move(callback), base::Bind(&RunCallbackWithNoResults));
+  DetectCallback scoped_callback = media::ScopedCallbackRunner(
+      std::move(callback), std::vector<mojom::TextDetectionResultPtr>());
 
   base::scoped_nsobject<CIImage> ci_image = CreateCIImageFromSkBitmap(bitmap);
   if (!ci_image)
@@ -67,7 +59,7 @@
     result->bounding_box = std::move(boundingbox);
     results.push_back(std::move(result));
   }
-  scoped_callback.Run(std::move(results));
+  std::move(scoped_callback).Run(std::move(results));
 }
 
 }  // namespace shape_detection
diff --git a/services/video_capture/device_media_to_mojo_adapter.cc b/services/video_capture/device_media_to_mojo_adapter.cc
index fdacea4..a287a56 100644
--- a/services/video_capture/device_media_to_mojo_adapter.cc
+++ b/services/video_capture/device_media_to_mojo_adapter.cc
@@ -7,6 +7,7 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "media/base/bind_to_current_loop.h"
+#include "media/base/scoped_callback_runner.h"
 #include "media/capture/video/video_capture_buffer_pool_impl.h"
 #include "media/capture/video/video_capture_buffer_tracker_factory_impl.h"
 #include "media/capture/video/video_capture_jpeg_decoder.h"
@@ -19,20 +20,6 @@
 // those frames get dropped.
 static const int kMaxBufferCount = 3;
 
-void RunFailedGetPhotoStateCallback(
-    base::OnceCallback<void(media::mojom::PhotoStatePtr)> cb) {
-  std::move(cb).Run(nullptr);
-}
-
-void RunFailedSetOptionsCallback(base::OnceCallback<void(bool)> cb) {
-  std::move(cb).Run(false);
-}
-
-void RunFailedTakePhotoCallback(
-    base::OnceCallback<void(media::mojom::BlobPtr blob)> cb) {
-  std::move(cb).Run(nullptr);
-}
-
 }  // anonymous namespace
 
 namespace video_capture {
@@ -113,28 +100,25 @@
 }
 
 void DeviceMediaToMojoAdapter::GetPhotoState(GetPhotoStateCallback callback) {
-  media::VideoCaptureDevice::GetPhotoStateCallback scoped_callback(
-      media::BindToCurrentLoop(std::move(callback)),
-      media::BindToCurrentLoop(
-          base::BindOnce(&RunFailedGetPhotoStateCallback)));
+  media::VideoCaptureDevice::GetPhotoStateCallback scoped_callback =
+      media::ScopedCallbackRunner(media::BindToCurrentLoop(std::move(callback)),
+                                  nullptr);
   device_->GetPhotoState(std::move(scoped_callback));
 }
 
 void DeviceMediaToMojoAdapter::SetPhotoOptions(
     media::mojom::PhotoSettingsPtr settings,
     SetPhotoOptionsCallback callback) {
-  media::ScopedResultCallback<media::mojom::ImageCapture::SetOptionsCallback>
-      scoped_callback(media::BindToCurrentLoop(std::move(callback)),
-                      media::BindToCurrentLoop(
-                          base::BindOnce(&RunFailedSetOptionsCallback)));
+  media::mojom::ImageCapture::SetOptionsCallback scoped_callback =
+      media::ScopedCallbackRunner(media::BindToCurrentLoop(std::move(callback)),
+                                  false);
   device_->SetPhotoOptions(std::move(settings), std::move(scoped_callback));
 }
 
 void DeviceMediaToMojoAdapter::TakePhoto(TakePhotoCallback callback) {
-  media::ScopedResultCallback<media::mojom::ImageCapture::TakePhotoCallback>
-      scoped_callback(media::BindToCurrentLoop(std::move(callback)),
-                      media::BindToCurrentLoop(
-                          base::BindOnce(&RunFailedTakePhotoCallback)));
+  media::mojom::ImageCapture::TakePhotoCallback scoped_callback =
+      media::ScopedCallbackRunner(media::BindToCurrentLoop(std::move(callback)),
+                                  nullptr);
   device_->TakePhoto(std::move(scoped_callback));
 }
 
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index 4fe7805d..3a2e095 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -208,6 +208,10 @@
 #define SK_DISABLE_DEFERRED_PROXIES
 #endif
 
+#ifndef SK_SUPPORT_LEGACY_GRADIENT_MATRIX_MATH
+#define SK_SUPPORT_LEGACY_GRADIENT_MATRIX_MATH
+#endif
+
 ///////////////////////// Imported from BUILD.gn and skia_common.gypi
 
 /* In some places Skia can use static initializers for global initialization,
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index 28e5532..5dba6df 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -12331,27 +12331,19 @@
 crbug.com/591099 http/tests/inspector/search/source-frame-search.html [ Failure ]
 crbug.com/591099 http/tests/inspector/search/sources-search-scope-in-files.html [ Failure ]
 crbug.com/591099 http/tests/inspector/search/sources-search-scope-many-projects.html [ Failure ]
-crbug.com/591099 http/tests/inspector/security/active-and-passive-subresources-with-cert-errors.html [ Failure Timeout ]
-crbug.com/591099 http/tests/inspector/security/active-subresource-with-cert-errors.html [ Failure ]
 crbug.com/591099 http/tests/inspector/security/blank-origins-not-shown.html [ Failure Timeout ]
-crbug.com/591099 http/tests/inspector/security/blocked-mixed-content-and-subresources-with-cert-errors.html [ Failure ]
 crbug.com/591099 http/tests/inspector/security/failed-request.html [ Failure ]
 crbug.com/591099 http/tests/inspector/security/interstitial-sidebar.html [ Failure ]
 crbug.com/591099 http/tests/inspector/security/main-origin-assigned-despite-request-missing.html [ Failure Timeout ]
 crbug.com/591099 http/tests/inspector/security/mixed-content-active-and-passive-reload.html [ Failure ]
-crbug.com/591099 http/tests/inspector/security/mixed-content-and-subresources-with-cert-errors.html [ Failure ]
 crbug.com/591099 http/tests/inspector/security/mixed-content-reload.html [ Failure ]
-crbug.com/591099 http/tests/inspector/security/mixed-form.html [ Failure ]
 crbug.com/591099 http/tests/inspector/security/origin-group-names-unique.html [ Failure ]
 crbug.com/591099 http/tests/inspector/security/origin-view-then-interstitial.html [ Failure ]
-crbug.com/591099 http/tests/inspector/security/passive-subresource-with-cert-errors.html [ Failure ]
-crbug.com/591099 http/tests/inspector/security/security-all-resources-secure.html [ Failure ]
-crbug.com/591099 http/tests/inspector/security/security-blocked-mixed-content-and-malicious.html [ Failure ]
 crbug.com/591099 http/tests/inspector/security/security-blocked-mixed-content.html [ Failure ]
 crbug.com/591099 http/tests/inspector/security/security-details-updated-with-security-state.html [ Failure ]
 crbug.com/591099 http/tests/inspector/security/security-explanation-ordering.html [ Failure ]
-crbug.com/591099 http/tests/inspector/security/security-secure-but-malicious.html [ Failure ]
 crbug.com/591099 http/tests/inspector/security/security-state-comparator.html [ Failure ]
+crbug.com/591099 http/tests/inspector/security/security-summary.html [ Failure ]
 crbug.com/591099 http/tests/inspector/security/security-unknown-resource.html [ Failure Timeout ]
 crbug.com/591099 http/tests/inspector/service-workers/lazy-addeventlisteners.html [ Failure ]
 crbug.com/591099 http/tests/inspector/service-workers/service-worker-agents.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls b/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls
index 4e23d43..fff5208 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls
@@ -26,9 +26,6 @@
 crbug.com/417782 compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow.html [ Failure Pass ]
 crbug.com/417782 compositing/filters/sw-shadow-overlaps-hw-layer.html [ Failure Pass ]
 crbug.com/417782 compositing/filters/sw-shadow-overlaps-hw-shadow.html [ Failure Pass ]
-crbug.com/417782 compositing/fixed-background-after-style-recalc.html [ Failure Pass ]
-crbug.com/417782 compositing/fixed-background-composited-html.html [ Failure Pass ]
-crbug.com/417782 compositing/fixed-background-negative-z-index-fixed.html [ Failure Pass ]
 crbug.com/417782 compositing/fixed-body-background-positioned.html [ Failure Pass ]
 crbug.com/417782 compositing/fixed-position-changed-to-absolute.html [ Failure Pass ]
 crbug.com/417782 compositing/force-compositing-mode/force-composite-empty.html [ Failure Pass ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 213db32d..39960fb 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -733,6 +733,8 @@
 crbug.com/520611 [ Debug ] fast/filesystem/workers/file-writer-events-shared-worker.html [ Failure Pass ]
 crbug.com/520194 http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-worker-overridesexpires.html [ Failure Pass ]
 
+crbug.com/233303 [ Win7 Debug ] inspector/sources/debugger-breakpoints/dom-breakpoints.html [ Pass Failure Timeout ]
+
 crbug.com/410974 fast/scroll-behavior/scroll-customization/scrollstate-basic.html [ Pass Failure ]
 crbug.com/410974 fast/scroll-behavior/scroll-customization/scrollstate-consume-deltas.html [ Pass Failure ]
 crbug.com/410974 fast/scroll-behavior/scroll-customization/scrollstate-consume-deltas-throw.html [ Pass Failure ]
diff --git a/third_party/WebKit/LayoutTests/compositing/dont-composite-select-elements.html b/third_party/WebKit/LayoutTests/compositing/dont-composite-select-elements.html
new file mode 100644
index 0000000..351b0460
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/compositing/dont-composite-select-elements.html
@@ -0,0 +1,18 @@
+<!doctype HTML>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<select size="2">
+  <option> value 1</option>
+  <option> value 2</option>
+  <option> value 3</option>
+  <option> value 4</option>
+</select>
+<script>
+if (window.internals)
+  window.internals.settings.setPreferCompositingToLCDTextEnabled(true);
+test(function() {
+    var json = JSON.parse(window.internals.layerTreeAsText(document));
+    // The <select> element's scroller should be painted into the root layer.
+    assert_equals(json["layers"].length, 1);
+    }, "test");
+</script>
diff --git a/third_party/WebKit/LayoutTests/compositing/dont-composite-text-input-elements.html b/third_party/WebKit/LayoutTests/compositing/dont-composite-text-input-elements.html
new file mode 100644
index 0000000..04456a4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/compositing/dont-composite-text-input-elements.html
@@ -0,0 +1,13 @@
+<!doctype HTML>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<input width=10 value="This is a long truncated text entry" style="font-size:40pt;"/>
+<script>
+if (window.internals)
+  window.internals.settings.setPreferCompositingToLCDTextEnabled(true);
+test(function() {
+    var json = JSON.parse(window.internals.layerTreeAsText(document));
+    // The <input> element's scroller should be painted into the root layer.
+    assert_equals(json["layers"].length, 1);
+    }, "test");
+</script>
diff --git a/third_party/WebKit/LayoutTests/css3/font-weight-expected.txt b/third_party/WebKit/LayoutTests/css3/font-weight-expected.txt
index 7c84fb9..6212a32 100644
--- a/third_party/WebKit/LayoutTests/css3/font-weight-expected.txt
+++ b/third_party/WebKit/LayoutTests/css3/font-weight-expected.txt
@@ -4,38 +4,38 @@
 
 
 PASS getComputedStyle(outer).fontWeight is "100"
-PASS getComputedStyle(bolder).fontWeight is "normal"
+PASS getComputedStyle(bolder).fontWeight is "400"
 PASS getComputedStyle(lighter).fontWeight is "100"
 PASS getComputedStyle(outer).fontWeight is "200"
-PASS getComputedStyle(bolder).fontWeight is "normal"
+PASS getComputedStyle(bolder).fontWeight is "400"
 PASS getComputedStyle(lighter).fontWeight is "100"
 PASS getComputedStyle(outer).fontWeight is "300"
-PASS getComputedStyle(bolder).fontWeight is "normal"
+PASS getComputedStyle(bolder).fontWeight is "400"
 PASS getComputedStyle(lighter).fontWeight is "100"
-PASS getComputedStyle(outer).fontWeight is "normal"
-PASS getComputedStyle(bolder).fontWeight is "bold"
+PASS getComputedStyle(outer).fontWeight is "400"
+PASS getComputedStyle(bolder).fontWeight is "700"
 PASS getComputedStyle(lighter).fontWeight is "100"
-PASS getComputedStyle(outer).fontWeight is "normal"
-PASS getComputedStyle(bolder).fontWeight is "bold"
+PASS getComputedStyle(outer).fontWeight is "400"
+PASS getComputedStyle(bolder).fontWeight is "700"
 PASS getComputedStyle(lighter).fontWeight is "100"
 PASS getComputedStyle(outer).fontWeight is "500"
-PASS getComputedStyle(bolder).fontWeight is "bold"
+PASS getComputedStyle(bolder).fontWeight is "700"
 PASS getComputedStyle(lighter).fontWeight is "100"
 PASS getComputedStyle(outer).fontWeight is "600"
 PASS getComputedStyle(bolder).fontWeight is "900"
-PASS getComputedStyle(lighter).fontWeight is "normal"
-PASS getComputedStyle(outer).fontWeight is "bold"
+PASS getComputedStyle(lighter).fontWeight is "400"
+PASS getComputedStyle(outer).fontWeight is "700"
 PASS getComputedStyle(bolder).fontWeight is "900"
-PASS getComputedStyle(lighter).fontWeight is "normal"
-PASS getComputedStyle(outer).fontWeight is "bold"
+PASS getComputedStyle(lighter).fontWeight is "400"
+PASS getComputedStyle(outer).fontWeight is "700"
 PASS getComputedStyle(bolder).fontWeight is "900"
-PASS getComputedStyle(lighter).fontWeight is "normal"
+PASS getComputedStyle(lighter).fontWeight is "400"
 PASS getComputedStyle(outer).fontWeight is "800"
 PASS getComputedStyle(bolder).fontWeight is "900"
-PASS getComputedStyle(lighter).fontWeight is "bold"
+PASS getComputedStyle(lighter).fontWeight is "700"
 PASS getComputedStyle(outer).fontWeight is "900"
 PASS getComputedStyle(bolder).fontWeight is "900"
-PASS getComputedStyle(lighter).fontWeight is "bold"
+PASS getComputedStyle(lighter).fontWeight is "700"
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/css3/font-weight-multiple-selectors-expected.txt b/third_party/WebKit/LayoutTests/css3/font-weight-multiple-selectors-expected.txt
index 5afce7e..43751d0a 100644
--- a/third_party/WebKit/LayoutTests/css3/font-weight-multiple-selectors-expected.txt
+++ b/third_party/WebKit/LayoutTests/css3/font-weight-multiple-selectors-expected.txt
@@ -4,38 +4,38 @@
 
 
 PASS getComputedStyle(outer).fontWeight is "100"
-PASS getComputedStyle(bolder).fontWeight is "normal"
+PASS getComputedStyle(bolder).fontWeight is "400"
 PASS getComputedStyle(lighter).fontWeight is "100"
 PASS getComputedStyle(outer).fontWeight is "200"
-PASS getComputedStyle(bolder).fontWeight is "normal"
+PASS getComputedStyle(bolder).fontWeight is "400"
 PASS getComputedStyle(lighter).fontWeight is "100"
 PASS getComputedStyle(outer).fontWeight is "300"
-PASS getComputedStyle(bolder).fontWeight is "normal"
+PASS getComputedStyle(bolder).fontWeight is "400"
 PASS getComputedStyle(lighter).fontWeight is "100"
-PASS getComputedStyle(outer).fontWeight is "normal"
-PASS getComputedStyle(bolder).fontWeight is "bold"
+PASS getComputedStyle(outer).fontWeight is "400"
+PASS getComputedStyle(bolder).fontWeight is "700"
 PASS getComputedStyle(lighter).fontWeight is "100"
-PASS getComputedStyle(outer).fontWeight is "normal"
-PASS getComputedStyle(bolder).fontWeight is "bold"
+PASS getComputedStyle(outer).fontWeight is "400"
+PASS getComputedStyle(bolder).fontWeight is "700"
 PASS getComputedStyle(lighter).fontWeight is "100"
 PASS getComputedStyle(outer).fontWeight is "500"
-PASS getComputedStyle(bolder).fontWeight is "bold"
+PASS getComputedStyle(bolder).fontWeight is "700"
 PASS getComputedStyle(lighter).fontWeight is "100"
 PASS getComputedStyle(outer).fontWeight is "600"
 PASS getComputedStyle(bolder).fontWeight is "900"
-PASS getComputedStyle(lighter).fontWeight is "normal"
-PASS getComputedStyle(outer).fontWeight is "bold"
+PASS getComputedStyle(lighter).fontWeight is "400"
+PASS getComputedStyle(outer).fontWeight is "700"
 PASS getComputedStyle(bolder).fontWeight is "900"
-PASS getComputedStyle(lighter).fontWeight is "normal"
-PASS getComputedStyle(outer).fontWeight is "bold"
+PASS getComputedStyle(lighter).fontWeight is "400"
+PASS getComputedStyle(outer).fontWeight is "700"
 PASS getComputedStyle(bolder).fontWeight is "900"
-PASS getComputedStyle(lighter).fontWeight is "normal"
+PASS getComputedStyle(lighter).fontWeight is "400"
 PASS getComputedStyle(outer).fontWeight is "800"
 PASS getComputedStyle(bolder).fontWeight is "900"
-PASS getComputedStyle(lighter).fontWeight is "bold"
+PASS getComputedStyle(lighter).fontWeight is "700"
 PASS getComputedStyle(outer).fontWeight is "900"
 PASS getComputedStyle(bolder).fontWeight is "900"
-PASS getComputedStyle(lighter).fontWeight is "bold"
+PASS getComputedStyle(lighter).fontWeight is "700"
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/css3/font-weight-multiple-selectors.html b/third_party/WebKit/LayoutTests/css3/font-weight-multiple-selectors.html
index 67aeeaf..4a3b196b 100644
--- a/third_party/WebKit/LayoutTests/css3/font-weight-multiple-selectors.html
+++ b/third_party/WebKit/LayoutTests/css3/font-weight-multiple-selectors.html
@@ -17,17 +17,17 @@
 description('Test that font-weight: bolder and font-weight: lighter are not cumulative when multiple selectors apply.');
 
 table = [
-["100"   , "100"   , "normal", "100"],
-["200"   , "200"   , "normal", "100"],
-["300"   , "300"   , "normal", "100"],
-["400"   , "normal", "bold"  , "100"],
-["normal", "normal", "bold"  , "100"],
-["500"   , "500"   , "bold"  , "100"],
-["600"   , "600"   , "900"   , "normal"],
-["700"   , "bold"  , "900"   , "normal"],
-["bold"  , "bold"  , "900"   , "normal"],
-["800"   , "800"   , "900"   , "bold"],
-["900"   , "900"   , "900"   , "bold"],
+["100"   , "100"   , "400", "100"],
+["200"   , "200"   , "400", "100"],
+["300"   , "300"   , "400", "100"],
+["400"   , "400", "700"  , "100"],
+["normal", "400", "700"  , "100"],
+["500"   , "500"   , "700"  , "100"],
+["600"   , "600"   , "900"   , "400"],
+["700"   , "700"  , "900"   , "400"],
+["bold"  , "700"  , "900"   , "400"],
+["800"   , "800"   , "900"   , "700"],
+["900"   , "900"   , "900"   , "700"],
 ];
 
 var outer = document.getElementById("outer");
diff --git a/third_party/WebKit/LayoutTests/css3/font-weight.html b/third_party/WebKit/LayoutTests/css3/font-weight.html
index 6c83be88..b4ceacf5 100644
--- a/third_party/WebKit/LayoutTests/css3/font-weight.html
+++ b/third_party/WebKit/LayoutTests/css3/font-weight.html
@@ -16,17 +16,17 @@
 description('Test that font-weight: bolder and font-weight: lighter behave according to spec.');
 
 table = [
-["100"   , "100"   , "normal", "100"],
-["200"   , "200"   , "normal", "100"],
-["300"   , "300"   , "normal", "100"],
-["400"   , "normal", "bold"  , "100"],
-["normal", "normal", "bold"  , "100"],
-["500"   , "500"   , "bold"  , "100"],
-["600"   , "600"   , "900"   , "normal"],
-["700"   , "bold"  , "900"   , "normal"],
-["bold"  , "bold"  , "900"   , "normal"],
-["800"   , "800"   , "900"   , "bold"],
-["900"   , "900"   , "900"   , "bold"],
+["100"   , "100"   , "400", "100"],
+["200"   , "200"   , "400", "100"],
+["300"   , "300"   , "400", "100"],
+["400"   , "400", "700"  , "100"],
+["normal", "400", "700"  , "100"],
+["500"   , "500"   , "700"  , "100"],
+["600"   , "600"   , "900"   , "400"],
+["700"   , "700"  , "900"   , "400"],
+["bold"  , "700"  , "900"   , "400"],
+["800"   , "800"   , "900"   , "700"],
+["900"   , "900"   , "900"   , "700"],
 ];
 
 var outer = document.getElementById("outer");
diff --git a/third_party/WebKit/LayoutTests/editing/pasteboard/dragstart-contains-default-content-expected.txt b/third_party/WebKit/LayoutTests/editing/pasteboard/dragstart-contains-default-content-expected.txt
index d7f3e48..ebdc0777 100644
--- a/third_party/WebKit/LayoutTests/editing/pasteboard/dragstart-contains-default-content-expected.txt
+++ b/third_party/WebKit/LayoutTests/editing/pasteboard/dragstart-contains-default-content-expected.txt
@@ -9,7 +9,7 @@
 Test ID: selectionTest
 text/plain: Select some text in this box and drag it.
 text/url: 
-text/html: <span style="color: rgb(0, 0, 0); font-family: serif; font-size: medium; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">Select some text in this box and drag it.</span>
+text/html: <span style="color: rgb(0, 0, 0); font-family: serif; font-size: medium; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">Select some text in this box and drag it.</span>
 Test ID: imageTest
 text/plain: 
 text/url: 
diff --git a/third_party/WebKit/LayoutTests/editing/pasteboard/onpaste-text-html-expected.txt b/third_party/WebKit/LayoutTests/editing/pasteboard/onpaste-text-html-expected.txt
index 64b01dc..2d67684 100644
--- a/third_party/WebKit/LayoutTests/editing/pasteboard/onpaste-text-html-expected.txt
+++ b/third_party/WebKit/LayoutTests/editing/pasteboard/onpaste-text-html-expected.txt
@@ -1,5 +1,5 @@
 CONSOLE MESSAGE: line 21: text/plain: This test verifies that we can get text/html from the clipboard during an onpaste event. 
-CONSOLE MESSAGE: line 23: text/html: <span style="color: rgb(0, 0, 0); font-size: medium; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">This test verifies that we can get text/html from the clipboard during an onpaste event.<span> </span></span>
+CONSOLE MESSAGE: line 23: text/html: <span style="color: rgb(0, 0, 0); font-size: medium; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">This test verifies that we can get text/html from the clipboard during an onpaste event.<span> </span></span>
 This test verifies that we can get text/html from the clipboard during an onpaste event. This test requires DRT.
 Paste content in this div.This test verifies that we can get text/html from the clipboard during an onpaste event. 
 PASS
diff --git a/third_party/WebKit/LayoutTests/editing/pasteboard/paste-text-with-style-4-expected.txt b/third_party/WebKit/LayoutTests/editing/pasteboard/paste-text-with-style-4-expected.txt
index 7df4ab74..27cab07 100644
--- a/third_party/WebKit/LayoutTests/editing/pasteboard/paste-text-with-style-4-expected.txt
+++ b/third_party/WebKit/LayoutTests/editing/pasteboard/paste-text-with-style-4-expected.txt
@@ -10,6 +10,6 @@
 | <b>
 |   style="border: solid 5px blue;padding: 5px;"
 |   <i>
-|     style="font-weight: normal;"
+|     style="font-weight: 400;"
 |     "hello<#selection-caret>"
 |   <br>
diff --git a/third_party/WebKit/LayoutTests/editing/selection/mouse/overidden_user_select_in_dom_tree.html b/third_party/WebKit/LayoutTests/editing/selection/mouse/overidden_user_select_in_dom_tree.html
new file mode 100644
index 0000000..983165d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/editing/selection/mouse/overidden_user_select_in_dom_tree.html
@@ -0,0 +1,33 @@
+<!doctype HTML>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+
+<div style="user-select: none; -moz-user-select: none">
+<span id="foo">foo</span><span id="bar" style="user-select: text; -moz-user-select: text">bar</span>
+</div>
+
+<script>
+test(function() {
+  assert_not_equals(window.eventSender, undefined, 'This test requires window.eventSender');
+
+  let selection = window.getSelection();
+  function moveAndDoubleClick(element) {
+    eventSender.mouseMoveTo(element.offsetLeft + element.offsetWidth / 2, element.offsetTop + element.offsetHeight / 2);
+    eventSender.mouseDown();
+    eventSender.mouseUp();
+    eventSender.leapForward(1);
+    eventSender.mouseDown();
+    eventSender.mouseUp();
+    eventSender.leapForward(1);
+  }
+
+  // 'foo' cannot be selected.
+  moveAndDoubleClick(foo);
+  assert_equals(selection.toString(), '', 'selection.toString');
+
+  // 'bar' can be selected even though its parent cannot be selected.
+  moveAndDoubleClick(bar);
+  assert_equals(selection.toString(), 'bar', 'selection.toString');
+});
+</script>
+
diff --git a/third_party/WebKit/LayoutTests/editing/selection/mouse/overriden_user_select_in_shadow_tree.html b/third_party/WebKit/LayoutTests/editing/selection/mouse/overriden_user_select_in_shadow_tree.html
new file mode 100644
index 0000000..b49c513b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/editing/selection/mouse/overriden_user_select_in_shadow_tree.html
@@ -0,0 +1,43 @@
+<!doctype HTML>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+
+<div id="shadow_host" style="user-select: none; -moz-user-select: none; background: orange; padding: 20%;" slot="hereplz">foo</div>
+
+<script>
+test(function() {
+  assert_not_equals(window.eventSender, undefined, 'This test requires window.eventSender');
+
+  let selection = window.getSelection();
+  function moveAndDoubleClick(element) {
+    eventSender.mouseMoveTo(element.offsetLeft + element.offsetWidth / 2, element.offsetTop + element.offsetHeight / 2);
+    eventSender.mouseDown();
+    eventSender.mouseUp();
+    eventSender.leapForward(1);
+    eventSender.mouseDown();
+    eventSender.mouseUp();
+    eventSender.leapForward(1);
+  }
+
+  selection.removeAllRanges();
+  moveAndDoubleClick(document.getElementById("shadow_host"));
+  // 'foo' is under user-select: none.
+  assert_equals(selection.toString(), '', 'selection.toString');
+
+  // Make sure the shadow tree's style overrides the style
+  // of the shadow host.
+  let shadow_host = document.getElementById("shadow_host");
+  let shadow_root = shadow_host.attachShadow({mode: 'open'});
+  let slot = document.createElement('slot');
+  slot.name = 'hereplz';
+  let shadow_span = document.createElement('span');
+  shadow_span.textContent = 'shadowbar';
+  shadow_span.style.userSelect = 'text';
+  slot.appendChild(shadow_span);
+  shadow_root.appendChild(slot);
+
+  // 'shadowbar' comes from the shadow tree and overrides the style of its host.
+  moveAndDoubleClick(shadow_span);
+  assert_equals(selection.toString(), 'shadowbar', 'selection.toString');
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/editing/run/multitest-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/editing/run/multitest-expected.txt
index 82f80aa..e5a1c3be 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/editing/run/multitest-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/editing/run/multitest-expected.txt
@@ -8145,7 +8145,7 @@
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar]</b>baz": execCommand("delete", false, "") return value 
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar]</b>baz": execCommand("inserttext", false, "a") return value 
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar]</b>baz" checks for modifications to non-editable content 
-FAIL [["delete",""],["inserttext","a"]] "foo<b>[bar]</b>baz" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "foo<b>a</b>baz" but got "foo<span style=\"font-weight:bold\">a</span>baz"
+FAIL [["delete",""],["inserttext","a"]] "foo<b>[bar]</b>baz" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "foo<b>a</b>baz" but got "foo<span style=\"font-weight:700\">a</span>baz"
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar]</b>baz" queryCommandIndeterm("delete") before 
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar]</b>baz" queryCommandState("delete") before 
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar]</b>baz" queryCommandValue("delete") before 
@@ -8849,7 +8849,7 @@
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar</b>baz]": execCommand("delete", false, "") return value 
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar</b>baz]": execCommand("inserttext", false, "a") return value 
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar</b>baz]" checks for modifications to non-editable content 
-FAIL [["delete",""],["inserttext","a"]] "foo<b>[bar</b>baz]" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "foo<b>a</b>" but got "foo<span style=\"font-weight:bold\">a</span>"
+FAIL [["delete",""],["inserttext","a"]] "foo<b>[bar</b>baz]" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "foo<b>a</b>" but got "foo<span style=\"font-weight:700\">a</span>"
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar</b>baz]" queryCommandIndeterm("delete") before 
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar</b>baz]" queryCommandState("delete") before 
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar</b>baz]" queryCommandValue("delete") before 
diff --git a/third_party/WebKit/LayoutTests/fast/css/atapply/at-apply-shorthands.html b/third_party/WebKit/LayoutTests/fast/css/atapply/at-apply-shorthands.html
index 9054dd3..43400bc 100644
--- a/third_party/WebKit/LayoutTests/fast/css/atapply/at-apply-shorthands.html
+++ b/third_party/WebKit/LayoutTests/fast/css/atapply/at-apply-shorthands.html
@@ -15,6 +15,6 @@
 <script>
 test(function(){
     assert_equals(getComputedStyle(e).border, "10px solid rgb(0, 128, 0)");
-    assert_equals(getComputedStyle(e).font, "normal normal normal normal 20px / normal serif");
+    assert_equals(getComputedStyle(e).font, "normal normal 400 normal 20px / normal serif");
 }, "Basic usage of @apply with shorthand properties");
 </script>
diff --git a/third_party/WebKit/LayoutTests/fast/css/child-selector-implicit-tbody.html b/third_party/WebKit/LayoutTests/fast/css/child-selector-implicit-tbody.html
index 0f46248..f364fbe 100644
--- a/third_party/WebKit/LayoutTests/fast/css/child-selector-implicit-tbody.html
+++ b/third_party/WebKit/LayoutTests/fast/css/child-selector-implicit-tbody.html
@@ -6,8 +6,8 @@
     if (window.testRunner)
         testRunner.dumpAsText();
     result = "TEST FAILED";
-    if (getComputedStyle(document.getElementById("cell1")).fontWeight == "normal")
-        if (getComputedStyle(document.getElementById("cell2")).fontWeight == "bold")
+    if (getComputedStyle(document.getElementById("cell1")).fontWeight == "400")
+        if (getComputedStyle(document.getElementById("cell2")).fontWeight == "700")
             result = "TEST PASSED: Child rule did not affect the table.";
     document.getElementById("result").firstChild.data = result;
 }
diff --git a/third_party/WebKit/LayoutTests/fast/css/css-properties-case-insensitive.html b/third_party/WebKit/LayoutTests/fast/css/css-properties-case-insensitive.html
index 9f55fe6..05700883b 100644
--- a/third_party/WebKit/LayoutTests/fast/css/css-properties-case-insensitive.html
+++ b/third_party/WebKit/LayoutTests/fast/css/css-properties-case-insensitive.html
@@ -29,7 +29,7 @@
             test.style.setProperty("font-weight", "bold", null);
             test.style.removeProperty("FONT-WEIGHT");
             lowerValue = document.defaultView.getComputedStyle(test, "").getPropertyValue("font-weight");
-            log("removeProperty: " + (lowerValue == "normal" ? "PASS" : "FAIL"));
+            log("removeProperty: " + (lowerValue == "400" ? "PASS" : "FAIL"));
         }
     </script>
 </head>
diff --git a/third_party/WebKit/LayoutTests/fast/css/font-shorthand-from-longhands-expected.txt b/third_party/WebKit/LayoutTests/fast/css/font-shorthand-from-longhands-expected.txt
index 595f9c2..a9f29cb9 100644
--- a/third_party/WebKit/LayoutTests/fast/css/font-shorthand-from-longhands-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css/font-shorthand-from-longhands-expected.txt
@@ -4,37 +4,37 @@
 
 
 PASS style.font is ''
-PASS computedStyle.font is 'normal normal normal normal 20px / normal foobar'
+PASS computedStyle.font is 'normal normal 400 normal 20px / normal foobar'
 PASS computedStyle.fontSize is '20px'
 PASS checkFontStyleValue() is true
 PASS style.font is ''
-PASS computedStyle.font is 'normal normal normal normal 20px / normal sans-serif'
+PASS computedStyle.font is 'normal normal 400 normal 20px / normal sans-serif'
 PASS computedStyle.fontFamily is 'sans-serif'
 PASS style.font is ''
-PASS computedStyle.font is 'italic normal normal normal 20px / normal sans-serif'
+PASS computedStyle.font is 'italic normal 400 normal 20px / normal sans-serif'
 PASS computedStyle.fontStyle is 'italic'
 PASS style.font is ''
-PASS computedStyle.font is 'italic small-caps normal normal 20px / normal sans-serif'
+PASS computedStyle.font is 'italic small-caps 400 normal 20px / normal sans-serif'
 PASS computedStyle.fontVariant is 'small-caps'
 PASS style.font is ''
-PASS computedStyle.font is 'italic small-caps bold normal 20px / normal sans-serif'
-PASS computedStyle.fontWeight is 'bold'
+PASS computedStyle.font is 'italic small-caps 700 normal 20px / normal sans-serif'
+FAIL computedStyle.fontWeight should be bold. Was 700.
 PASS style.font is ''
-PASS computedStyle.font is 'italic small-caps bold normal 20px / 40px sans-serif'
+PASS computedStyle.font is 'italic small-caps 700 normal 20px / 40px sans-serif'
 PASS computedStyle.lineHeight is '40px'
 PASS style.font is 'italic small-caps bold ultra-expanded 20px/40px sans-serif'
-PASS computedStyle.font is 'italic small-caps bold ultra-expanded 20px / 40px sans-serif'
+PASS computedStyle.font is 'italic small-caps 700 ultra-expanded 20px / 40px sans-serif'
 PASS checkFontStyleValue() is true
 PASS style.font is ''
 PASS computedStyle.font is ''
 PASS style.font is 'italic small-caps bold ultra-expanded 20px/40px sans-serif'
-PASS computedStyle.font is 'italic small-caps bold ultra-expanded 20px / 40px sans-serif'
+PASS computedStyle.font is 'italic small-caps 700 ultra-expanded 20px / 40px sans-serif'
 PASS style.font is ''
 PASS computedStyle.font is ''
 PASS style.font is 'italic small-caps bold ultra-expanded 20px/40px sans-serif'
-PASS computedStyle.font is 'italic small-caps bold ultra-expanded 20px / 40px sans-serif'
+PASS computedStyle.font is 'italic small-caps 700 ultra-expanded 20px / 40px sans-serif'
 PASS style.font is ''
-PASS computedStyle.font is 'normal normal normal normal 16px / normal foobar'
+PASS computedStyle.font is 'normal normal 400 normal 16px / normal foobar'
 PASS checkFontStyleValue() is true
 PASS style.fontVariantCaps is 'all-small-caps'
 PASS computedStyle.font is ''
diff --git a/third_party/WebKit/LayoutTests/fast/css/font-shorthand-from-longhands.html b/third_party/WebKit/LayoutTests/fast/css/font-shorthand-from-longhands.html
index 7830808..0345aa339 100644
--- a/third_party/WebKit/LayoutTests/fast/css/font-shorthand-from-longhands.html
+++ b/third_party/WebKit/LayoutTests/fast/css/font-shorthand-from-longhands.html
@@ -36,40 +36,40 @@
 style.fontSize = "20px";
 // We need all font longhands to build the shorthand.
 shouldBe("style.font", "''");
-shouldBe("computedStyle.font", "'normal normal normal normal 20px / normal foobar'");
+shouldBe("computedStyle.font", "'normal normal 400 normal 20px / normal foobar'");
 shouldBe("computedStyle.fontSize", "'20px'");
 shouldBe("checkFontStyleValue()", "true");
 
 style.fontSize = "20px";
 style.fontFamily = "sans-serif";
 shouldBe("style.font", "''");
-shouldBe("computedStyle.font", "'normal normal normal normal 20px / normal sans-serif'");
+shouldBe("computedStyle.font", "'normal normal 400 normal 20px / normal sans-serif'");
 shouldBe("computedStyle.fontFamily", "'sans-serif'");
 
 style.fontStyle = "italic";
 shouldBe("style.font", "''");
-shouldBe("computedStyle.font", "'italic normal normal normal 20px / normal sans-serif'");
+shouldBe("computedStyle.font", "'italic normal 400 normal 20px / normal sans-serif'");
 shouldBe("computedStyle.fontStyle", "'italic'");
 
 style.fontVariant = "small-caps";
 shouldBe("style.font", "''");
-shouldBe("computedStyle.font", "'italic small-caps normal normal 20px / normal sans-serif'");
+shouldBe("computedStyle.font", "'italic small-caps 400 normal 20px / normal sans-serif'");
 shouldBe("computedStyle.fontVariant", "'small-caps'");
 
 style.fontWeight = "bold";
 shouldBe("style.font", "''");
-shouldBe("computedStyle.font", "'italic small-caps bold normal 20px / normal sans-serif'");
+shouldBe("computedStyle.font", "'italic small-caps 700 normal 20px / normal sans-serif'");
 shouldBe("computedStyle.fontWeight", "'bold'");
 
 style.lineHeight = "40px";
 shouldBe("style.font", "''");
-shouldBe("computedStyle.font", "'italic small-caps bold normal 20px / 40px sans-serif'");
+shouldBe("computedStyle.font", "'italic small-caps 700 normal 20px / 40px sans-serif'");
 shouldBe("computedStyle.lineHeight", "'40px'");
 
 style.fontStretch = "ultra-expanded";
 // All font longhands are set, therefore shorthand is built
 shouldBe("style.font", "'italic small-caps bold ultra-expanded 20px/40px sans-serif'");
-shouldBe("computedStyle.font", "'italic small-caps bold ultra-expanded 20px / 40px sans-serif'");
+shouldBe("computedStyle.font", "'italic small-caps 700 ultra-expanded 20px / 40px sans-serif'");
 shouldBe("checkFontStyleValue()", "true");
 
 style.fontVariantLigatures = "discretionary-ligatures";
@@ -79,7 +79,7 @@
 // Reset for next test.
 style.fontVariantLigatures = "normal";
 shouldBe("style.font", "'italic small-caps bold ultra-expanded 20px/40px sans-serif'");
-shouldBe("computedStyle.font", "'italic small-caps bold ultra-expanded 20px / 40px sans-serif'");
+shouldBe("computedStyle.font", "'italic small-caps 700 ultra-expanded 20px / 40px sans-serif'");
 
 style.fontVariantNumeric = "lining-nums";
 // Shorthand cannot be built because of non-normal numeric value.
@@ -88,11 +88,11 @@
 // Reset for next test.
 style.fontVariantNumeric = "normal";
 shouldBe("style.font", "'italic small-caps bold ultra-expanded 20px/40px sans-serif'");
-shouldBe("computedStyle.font", "'italic small-caps bold ultra-expanded 20px / 40px sans-serif'");
+shouldBe("computedStyle.font", "'italic small-caps 700 ultra-expanded 20px / 40px sans-serif'");
 
 style.font = "";
 shouldBe("style.font", "''");
-shouldBe("computedStyle.font", "'normal normal normal normal 16px / normal foobar'");
+shouldBe("computedStyle.font", "'normal normal 400 normal 16px / normal foobar'");
 shouldBe("checkFontStyleValue()", "true");
 
 style.fontVariantCaps = "all-small-caps";
diff --git a/third_party/WebKit/LayoutTests/fast/css/font-weight-1.html b/third_party/WebKit/LayoutTests/fast/css/font-weight-1.html
index 4b9bf2aa..ccdb566 100644
--- a/third_party/WebKit/LayoutTests/fast/css/font-weight-1.html
+++ b/third_party/WebKit/LayoutTests/fast/css/font-weight-1.html
@@ -48,7 +48,7 @@
       src:  url('../../resources/WebKitWeightWatcher900.ttf');
     }
     div { font-family: 'WebKit WeightWatcher'; font-size: 48px; }
-    .w1 { font-weight: 100; font-weight: 500.4; font-weight: 500px; font-weigth: 500.4px; }
+    .w1 { font-weight: 100; font-weight: 1001; font-weight: 0; font-weight: 500px; font-weigth: 500.4px; }
     .w2 { font-weight: 200; }
     .w3 { font-weight: 300; }
     .w4 { font-weight: 400; }
diff --git a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-empty-font-family-expected.txt b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-empty-font-family-expected.txt
index 8cdc322..e0b950ce 100644
--- a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-empty-font-family-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-empty-font-family-expected.txt
@@ -10,5 +10,5 @@
 font-variant-ligatures: normal;
 font-variant-caps: normal;
 font-variant-numeric: normal;
-font-weight: normal;
+font-weight: 400;
 
diff --git a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-font-expected.txt b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-font-expected.txt
index de3f552..866ea81 100644
--- a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-font-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-font-expected.txt
@@ -3,34 +3,34 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS computedFont('10px sans-serif') is 'normal normal normal normal 10px / normal sans-serif'
-PASS computedFont('10px sans-serif') is 'normal normal normal normal 10px / normal sans-serif'
-PASS computedFont('10px SANS-SERIF') is 'normal normal normal normal 10px / normal sans-serif'
-PASS computedFont('12px sans-serif') is 'normal normal normal normal 12px / normal sans-serif'
-PASS computedFont('12px  sans-serif') is 'normal normal normal normal 12px / normal sans-serif'
-PASS computedFont('10px sans-serif, sans-serif') is 'normal normal normal normal 10px / normal sans-serif, sans-serif'
-PASS computedFont('10px sans-serif, serif') is 'normal normal normal normal 10px / normal sans-serif, serif'
-PASS computedFont('12px ahem') is 'normal normal normal normal 12px / normal ahem'
-PASS computedFont('12px unlikely-font-name') is 'normal normal normal normal 12px / normal unlikely-font-name'
+PASS computedFont('10px sans-serif') is 'normal normal 400 normal 10px / normal sans-serif'
+PASS computedFont('10px sans-serif') is 'normal normal 400 normal 10px / normal sans-serif'
+PASS computedFont('10px SANS-SERIF') is 'normal normal 400 normal 10px / normal sans-serif'
+PASS computedFont('12px sans-serif') is 'normal normal 400 normal 12px / normal sans-serif'
+PASS computedFont('12px  sans-serif') is 'normal normal 400 normal 12px / normal sans-serif'
+PASS computedFont('10px sans-serif, sans-serif') is 'normal normal 400 normal 10px / normal sans-serif, sans-serif'
+PASS computedFont('10px sans-serif, serif') is 'normal normal 400 normal 10px / normal sans-serif, serif'
+PASS computedFont('12px ahem') is 'normal normal 400 normal 12px / normal ahem'
+PASS computedFont('12px unlikely-font-name') is 'normal normal 400 normal 12px / normal unlikely-font-name'
 PASS computedFont('100 10px sans-serif') is 'normal normal 100 normal 10px / normal sans-serif'
 PASS computedFont('200 10px sans-serif') is 'normal normal 200 normal 10px / normal sans-serif'
 PASS computedFont('300 10px sans-serif') is 'normal normal 300 normal 10px / normal sans-serif'
-PASS computedFont('400 10px sans-serif') is 'normal normal normal normal 10px / normal sans-serif'
-PASS computedFont('normal 10px sans-serif') is 'normal normal normal normal 10px / normal sans-serif'
+PASS computedFont('400 10px sans-serif') is 'normal normal 400 normal 10px / normal sans-serif'
+PASS computedFont('normal 10px sans-serif') is 'normal normal 400 normal 10px / normal sans-serif'
 PASS computedFont('500 10px sans-serif') is 'normal normal 500 normal 10px / normal sans-serif'
 PASS computedFont('600 10px sans-serif') is 'normal normal 600 normal 10px / normal sans-serif'
-PASS computedFont('700 10px sans-serif') is 'normal normal bold normal 10px / normal sans-serif'
-PASS computedFont('bold 10px sans-serif') is 'normal normal bold normal 10px / normal sans-serif'
+FAIL computedFont('700 10px sans-serif') should be normal normal bold normal 10px / normal sans-serif. Was normal normal 700 normal 10px / normal sans-serif.
+FAIL computedFont('bold 10px sans-serif') should be normal normal bold normal 10px / normal sans-serif. Was normal normal 700 normal 10px / normal sans-serif.
 PASS computedFont('800 10px sans-serif') is 'normal normal 800 normal 10px / normal sans-serif'
 PASS computedFont('900 10px sans-serif') is 'normal normal 900 normal 10px / normal sans-serif'
-PASS computedFont('italic 10px sans-serif') is 'italic normal normal normal 10px / normal sans-serif'
-PASS computedFont('small-caps 10px sans-serif') is 'normal small-caps normal normal 10px / normal sans-serif'
-PASS computedFont('italic small-caps 10px sans-serif') is 'italic small-caps normal normal 10px / normal sans-serif'
-PASS computedFont('italic small-caps bold 10px sans-serif') is 'italic small-caps bold normal 10px / normal sans-serif'
-PASS computedFont('10px/100% sans-serif') is 'normal normal normal normal 10px / 10px sans-serif'
-PASS computedFont('10px/100px sans-serif') is 'normal normal normal normal 10px / 100px sans-serif'
-PASS computedFont('10px/normal sans-serif') is 'normal normal normal normal 10px / normal sans-serif'
-PASS computedFont('10px/normal sans-serif') is 'normal normal normal normal 10px / normal sans-serif'
+PASS computedFont('italic 10px sans-serif') is 'italic normal 400 normal 10px / normal sans-serif'
+PASS computedFont('small-caps 10px sans-serif') is 'normal small-caps 400 normal 10px / normal sans-serif'
+PASS computedFont('italic small-caps 10px sans-serif') is 'italic small-caps 400 normal 10px / normal sans-serif'
+PASS computedFont('italic small-caps bold 10px sans-serif') is 'italic small-caps 700 normal 10px / normal sans-serif'
+PASS computedFont('10px/100% sans-serif') is 'normal normal 400 normal 10px / 10px sans-serif'
+PASS computedFont('10px/100px sans-serif') is 'normal normal 400 normal 10px / 100px sans-serif'
+PASS computedFont('10px/normal sans-serif') is 'normal normal 400 normal 10px / normal sans-serif'
+PASS computedFont('10px/normal sans-serif') is 'normal normal 400 normal 10px / normal sans-serif'
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-font-family-expected.txt b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-font-family-expected.txt
index 8debc38..38014d29 100644
--- a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-font-family-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-font-family-expected.txt
@@ -10,5 +10,5 @@
 font-variant-ligatures: normal;
 font-variant-caps: normal;
 font-variant-numeric: normal;
-font-weight: normal;
+font-weight: 400;
 
diff --git a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-listing-expected.txt b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-listing-expected.txt
index d651bbc..17eb5de 100644
--- a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-listing-expected.txt
@@ -161,7 +161,7 @@
 font-variant-caps: normal
 font-variant-ligatures: normal
 font-variant-numeric: normal
-font-weight: normal
+font-weight: 400
 grid-auto-columns: auto
 grid-auto-flow: row
 grid-auto-rows: auto
@@ -286,7 +286,7 @@
 transition-timing-function: ease
 translate: none
 unicode-bidi: normal
-user-select: text
+user-select: auto
 vector-effect: none
 vertical-align: baseline
 visibility: visible
diff --git a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
index e5a7c17..872aabb5 100644
--- a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
@@ -161,7 +161,7 @@
 font-variant-caps: normal
 font-variant-ligatures: normal
 font-variant-numeric: normal
-font-weight: normal
+font-weight: 400
 grid-auto-columns: auto
 grid-auto-flow: row
 grid-auto-rows: auto
@@ -286,7 +286,7 @@
 transition-timing-function: ease
 translate: none
 unicode-bidi: normal
-user-select: text
+user-select: auto
 vector-effect: none
 vertical-align: baseline
 visibility: visible
diff --git a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/script-tests/computed-style-font.js b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/script-tests/computed-style-font.js
index f4e139a..d5b6343 100644
--- a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/script-tests/computed-style-font.js
+++ b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/script-tests/computed-style-font.js
@@ -9,31 +9,31 @@
     return window.getComputedStyle(testDiv).getPropertyValue('font');
 }
 
-shouldBe("computedFont('10px sans-serif')", "'normal normal normal normal 10px / normal sans-serif'");
-shouldBe("computedFont('10px sans-serif')", "'normal normal normal normal 10px / normal sans-serif'");
-shouldBe("computedFont('10px SANS-SERIF')", "'normal normal normal normal 10px / normal sans-serif'");
-shouldBe("computedFont('12px sans-serif')", "'normal normal normal normal 12px / normal sans-serif'");
-shouldBe("computedFont('12px  sans-serif')", "'normal normal normal normal 12px / normal sans-serif'");
-shouldBe("computedFont('10px sans-serif, sans-serif')", "'normal normal normal normal 10px / normal sans-serif, sans-serif'");
-shouldBe("computedFont('10px sans-serif, serif')", "'normal normal normal normal 10px / normal sans-serif, serif'");
-shouldBe("computedFont('12px ahem')", "'normal normal normal normal 12px / normal ahem'");
-shouldBe("computedFont('12px unlikely-font-name')", "'normal normal normal normal 12px / normal unlikely-font-name'");
+shouldBe("computedFont('10px sans-serif')", "'normal normal 400 normal 10px / normal sans-serif'");
+shouldBe("computedFont('10px sans-serif')", "'normal normal 400 normal 10px / normal sans-serif'");
+shouldBe("computedFont('10px SANS-SERIF')", "'normal normal 400 normal 10px / normal sans-serif'");
+shouldBe("computedFont('12px sans-serif')", "'normal normal 400 normal 12px / normal sans-serif'");
+shouldBe("computedFont('12px  sans-serif')", "'normal normal 400 normal 12px / normal sans-serif'");
+shouldBe("computedFont('10px sans-serif, sans-serif')", "'normal normal 400 normal 10px / normal sans-serif, sans-serif'");
+shouldBe("computedFont('10px sans-serif, serif')", "'normal normal 400 normal 10px / normal sans-serif, serif'");
+shouldBe("computedFont('12px ahem')", "'normal normal 400 normal 12px / normal ahem'");
+shouldBe("computedFont('12px unlikely-font-name')", "'normal normal 400 normal 12px / normal unlikely-font-name'");
 shouldBe("computedFont('100 10px sans-serif')", "'normal normal 100 normal 10px / normal sans-serif'");
 shouldBe("computedFont('200 10px sans-serif')", "'normal normal 200 normal 10px / normal sans-serif'");
 shouldBe("computedFont('300 10px sans-serif')", "'normal normal 300 normal 10px / normal sans-serif'");
-shouldBe("computedFont('400 10px sans-serif')", "'normal normal normal normal 10px / normal sans-serif'");
-shouldBe("computedFont('normal 10px sans-serif')", "'normal normal normal normal 10px / normal sans-serif'");
+shouldBe("computedFont('400 10px sans-serif')", "'normal normal 400 normal 10px / normal sans-serif'");
+shouldBe("computedFont('normal 10px sans-serif')", "'normal normal 400 normal 10px / normal sans-serif'");
 shouldBe("computedFont('500 10px sans-serif')", "'normal normal 500 normal 10px / normal sans-serif'");
 shouldBe("computedFont('600 10px sans-serif')", "'normal normal 600 normal 10px / normal sans-serif'");
 shouldBe("computedFont('700 10px sans-serif')", "'normal normal bold normal 10px / normal sans-serif'");
 shouldBe("computedFont('bold 10px sans-serif')", "'normal normal bold normal 10px / normal sans-serif'");
 shouldBe("computedFont('800 10px sans-serif')", "'normal normal 800 normal 10px / normal sans-serif'");
 shouldBe("computedFont('900 10px sans-serif')", "'normal normal 900 normal 10px / normal sans-serif'");
-shouldBe("computedFont('italic 10px sans-serif')", "'italic normal normal normal 10px / normal sans-serif'");
-shouldBe("computedFont('small-caps 10px sans-serif')", "'normal small-caps normal normal 10px / normal sans-serif'");
-shouldBe("computedFont('italic small-caps 10px sans-serif')", "'italic small-caps normal normal 10px / normal sans-serif'");
-shouldBe("computedFont('italic small-caps bold 10px sans-serif')", "'italic small-caps bold normal 10px / normal sans-serif'");
-shouldBe("computedFont('10px/100% sans-serif')", "'normal normal normal normal 10px / 10px sans-serif'");
-shouldBe("computedFont('10px/100px sans-serif')", "'normal normal normal normal 10px / 100px sans-serif'");
-shouldBe("computedFont('10px/normal sans-serif')", "'normal normal normal normal 10px / normal sans-serif'");
-shouldBe("computedFont('10px/normal sans-serif')", "'normal normal normal normal 10px / normal sans-serif'");
+shouldBe("computedFont('italic 10px sans-serif')", "'italic normal 400 normal 10px / normal sans-serif'");
+shouldBe("computedFont('small-caps 10px sans-serif')", "'normal small-caps 400 normal 10px / normal sans-serif'");
+shouldBe("computedFont('italic small-caps 10px sans-serif')", "'italic small-caps 400 normal 10px / normal sans-serif'");
+shouldBe("computedFont('italic small-caps bold 10px sans-serif')", "'italic small-caps 700 normal 10px / normal sans-serif'");
+shouldBe("computedFont('10px/100% sans-serif')", "'normal normal 400 normal 10px / 10px sans-serif'");
+shouldBe("computedFont('10px/100px sans-serif')", "'normal normal 400 normal 10px / 100px sans-serif'");
+shouldBe("computedFont('10px/normal sans-serif')", "'normal normal 400 normal 10px / normal sans-serif'");
+shouldBe("computedFont('10px/normal sans-serif')", "'normal normal 400 normal 10px / normal sans-serif'");
diff --git a/third_party/WebKit/LayoutTests/fast/css/invalidation/non-independent-inheritance-identical-computed-styles.html b/third_party/WebKit/LayoutTests/fast/css/invalidation/non-independent-inheritance-identical-computed-styles.html
index 711924e..98e6ef8 100644
--- a/third_party/WebKit/LayoutTests/fast/css/invalidation/non-independent-inheritance-identical-computed-styles.html
+++ b/third_party/WebKit/LayoutTests/fast/css/invalidation/non-independent-inheritance-identical-computed-styles.html
@@ -51,24 +51,24 @@
     inner.offsetTop; // Force recalc.
     assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 0);
 
-    assert_equals(getComputedStyle(outer).fontWeight, "normal");
-    assert_equals(getComputedStyle(inner).fontWeight, "normal");
+    assert_equals(getComputedStyle(outer).fontWeight, "400");
+    assert_equals(getComputedStyle(inner).fontWeight, "400");
     assert_equals(getComputedStyle(innermost).fontWeight, "100");
 
     inner.offsetTop; // Force recalc.
     inner.style.fontWeight = 'bolder';
     assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 2);
 
-    assert_equals(getComputedStyle(outer).fontWeight, "normal");
-    assert_equals(getComputedStyle(inner).fontWeight, "bold");
-    assert_equals(getComputedStyle(innermost).fontWeight, "normal");
+    assert_equals(getComputedStyle(outer).fontWeight, "400");
+    assert_equals(getComputedStyle(inner).fontWeight, "700");
+    assert_equals(getComputedStyle(innermost).fontWeight, "400");
 
     inner.offsetTop; // Force recalc.
     outer.style.fontWeight = 'bold';
     assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 3);
 
-    assert_equals(getComputedStyle(outer).fontWeight, "bold");
+    assert_equals(getComputedStyle(outer).fontWeight, "700");
     assert_equals(getComputedStyle(inner).fontWeight, "900");
-    assert_equals(getComputedStyle(innermost).fontWeight, "bold");
+    assert_equals(getComputedStyle(innermost).fontWeight, "700");
 }, "Changing font-weight (a non-independent inherited property) in a way that results in an identical ComputedStyle still triggers a style recalc for its children.");
 </script>
diff --git a/third_party/WebKit/LayoutTests/fast/css/variables/longhand-pending-shorthand-substitution.html b/third_party/WebKit/LayoutTests/fast/css/variables/longhand-pending-shorthand-substitution.html
index 7b4b60f..5b536bc 100644
--- a/third_party/WebKit/LayoutTests/fast/css/variables/longhand-pending-shorthand-substitution.html
+++ b/third_party/WebKit/LayoutTests/fast/css/variables/longhand-pending-shorthand-substitution.html
@@ -24,7 +24,7 @@
   assert_equals(style.fontSize, '12px');
   assert_equals(style.lineHeight, '30px');
   assert_equals(style.fontStyle, 'italic');
-  assert_equals(style.fontWeight, 'bold');
+  assert_equals(style.fontWeight, '700');
   assert_equals(style.fontFamily, 'serif, sans-serif');
 }, "Test shorthand substitution in font.");
 
diff --git a/third_party/WebKit/LayoutTests/fast/events/ondrop-text-html-expected.txt b/third_party/WebKit/LayoutTests/fast/events/ondrop-text-html-expected.txt
index fdc7bd94..0f35ce8 100644
--- a/third_party/WebKit/LayoutTests/fast/events/ondrop-text-html-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/events/ondrop-text-html-expected.txt
@@ -1,4 +1,4 @@
 CONSOLE MESSAGE: line 21: text/plain: This test verifies that we can get text/html from the drag object during an ondrop event. 
-CONSOLE MESSAGE: line 23: text/html: <span style="color: rgb(0, 0, 0); font-size: medium; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">This test verifies that we can get text/html from the drag object during an ondrop event.<span> </span></span>
+CONSOLE MESSAGE: line 23: text/html: <span style="color: rgb(0, 0, 0); font-size: medium; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">This test verifies that we can get text/html from the drag object during an ondrop event.<span> </span></span>
 This test verifies that we can get text/html from the drag object during an ondrop event. This test requires DRT.
 PASS
diff --git a/third_party/WebKit/LayoutTests/html/grouping_content/figcaption-element-expected.txt b/third_party/WebKit/LayoutTests/html/grouping_content/figcaption-element-expected.txt
index 07d615b..9402231 100644
--- a/third_party/WebKit/LayoutTests/html/grouping_content/figcaption-element-expected.txt
+++ b/third_party/WebKit/LayoutTests/html/grouping_content/figcaption-element-expected.txt
@@ -13,8 +13,8 @@
 PASS figcaption3.parentNode.id is "figcaption2"
 PASS figcaption5.parentNode.id is "footer1"
 Residual style:
-PASS getStyleValue("figcaption4","font-weight") is "bold"
-PASS getStyleValue("span1","font-weight") is "bold"
+PASS getStyleValue("figcaption4","font-weight") is "700"
+PASS getStyleValue("span1","font-weight") is "700"
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/html/grouping_content/figcaption-element.html b/third_party/WebKit/LayoutTests/html/grouping_content/figcaption-element.html
index 0587b43..7a22bef1 100644
--- a/third_party/WebKit/LayoutTests/html/grouping_content/figcaption-element.html
+++ b/third_party/WebKit/LayoutTests/html/grouping_content/figcaption-element.html
@@ -39,8 +39,8 @@
 
 debug('Residual style:');
 testParent.innerHTML = '<b><figcaption id="figcaption4">This text should be bold.</figcaption> <span id="span1">This is also bold.</span></b>';
-shouldBe('getStyleValue("figcaption4","font-weight")', '"bold"');
-shouldBe('getStyleValue("span1","font-weight")', '"bold"');
+shouldBe('getStyleValue("figcaption4","font-weight")', '"700"');
+shouldBe('getStyleValue("span1","font-weight")', '"700"');
 document.body.removeChild(testParent);
 
 </script>
diff --git a/third_party/WebKit/LayoutTests/html/grouping_content/figure-element-expected.txt b/third_party/WebKit/LayoutTests/html/grouping_content/figure-element-expected.txt
index 28f383f8..0a60a79 100644
--- a/third_party/WebKit/LayoutTests/html/grouping_content/figure-element-expected.txt
+++ b/third_party/WebKit/LayoutTests/html/grouping_content/figure-element-expected.txt
@@ -17,8 +17,8 @@
 PASS figure3.parentNode.id is "figure2"
 PASS figure5.parentNode.id is "footer1"
 Residual style:
-PASS getStyleValue("figure4","font-weight") is "bold"
-PASS getStyleValue("span1","font-weight") is "bold"
+PASS getStyleValue("figure4","font-weight") is "700"
+PASS getStyleValue("span1","font-weight") is "700"
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/html/grouping_content/figure-element.html b/third_party/WebKit/LayoutTests/html/grouping_content/figure-element.html
index bd4d047..860f2f07 100644
--- a/third_party/WebKit/LayoutTests/html/grouping_content/figure-element.html
+++ b/third_party/WebKit/LayoutTests/html/grouping_content/figure-element.html
@@ -43,8 +43,8 @@
 
 debug('Residual style:');
 testParent.innerHTML = '<b><figure id="figure4">This text should be bold.</figure> <span id="span1">This is also bold.</span></b>';
-shouldBe('getStyleValue("figure4","font-weight")', '"bold"');
-shouldBe('getStyleValue("span1","font-weight")', '"bold"');
+shouldBe('getStyleValue("figure4","font-weight")', '"700"');
+shouldBe('getStyleValue("span1","font-weight")', '"700"');
 document.body.removeChild(testParent);
 
 </script>
diff --git a/third_party/WebKit/LayoutTests/html/grouping_content/main-element-expected.txt b/third_party/WebKit/LayoutTests/html/grouping_content/main-element-expected.txt
index 32e3e9f..44e917a 100644
--- a/third_party/WebKit/LayoutTests/html/grouping_content/main-element-expected.txt
+++ b/third_party/WebKit/LayoutTests/html/grouping_content/main-element-expected.txt
@@ -10,8 +10,8 @@
 <main> can be nested inside <main>:
 PASS main3.parentNode.id is "main2"
 Residual style:
-PASS getWeight("main4") is "bold"
-PASS getWeight("span1") is "bold"
+PASS getWeight("main4") is "700"
+PASS getWeight("span1") is "700"
 FormatBlock:
 PASS document.getElementById("span2").parentNode.nodeName is "MAIN"
 PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/html/grouping_content/main-element.html b/third_party/WebKit/LayoutTests/html/grouping_content/main-element.html
index 5d0b754..1023198 100644
--- a/third_party/WebKit/LayoutTests/html/grouping_content/main-element.html
+++ b/third_party/WebKit/LayoutTests/html/grouping_content/main-element.html
@@ -30,8 +30,8 @@
 function getWeight(id) {
     return document.defaultView.getComputedStyle(document.getElementById(id), null).getPropertyValue('font-weight');
 }
-shouldBe('getWeight("main4")', '"bold"');
-shouldBe('getWeight("span1")', '"bold"');
+shouldBe('getWeight("main4")', '"700"');
+shouldBe('getWeight("span1")', '"700"');
 document.body.removeChild(testParent);
 
 debug('FormatBlock:');
diff --git a/third_party/WebKit/LayoutTests/html/sections/article-element-expected.txt b/third_party/WebKit/LayoutTests/html/sections/article-element-expected.txt
index f60ac38..6a6ba99 100644
--- a/third_party/WebKit/LayoutTests/html/sections/article-element-expected.txt
+++ b/third_party/WebKit/LayoutTests/html/sections/article-element-expected.txt
@@ -10,8 +10,8 @@
 <article> can be nested inside <article>:
 PASS article3.parentNode.id is "article2"
 Residual style:
-PASS getWeight("article4") is "bold"
-PASS getWeight("span1") is "bold"
+PASS getWeight("article4") is "700"
+PASS getWeight("span1") is "700"
 FormatBlock:
 PASS document.getElementById("span2").parentNode.nodeName is "ARTICLE"
 PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/html/sections/article-element.html b/third_party/WebKit/LayoutTests/html/sections/article-element.html
index 6e87d1c..c1f6290 100644
--- a/third_party/WebKit/LayoutTests/html/sections/article-element.html
+++ b/third_party/WebKit/LayoutTests/html/sections/article-element.html
@@ -30,8 +30,8 @@
 function getWeight(id) {
     return document.defaultView.getComputedStyle(document.getElementById(id), null).getPropertyValue('font-weight');
 }
-shouldBe('getWeight("article4")', '"bold"');
-shouldBe('getWeight("span1")', '"bold"');
+shouldBe('getWeight("article4")', '"700"');
+shouldBe('getWeight("span1")', '"700"');
 document.body.removeChild(testParent);
 
 debug('FormatBlock:');
diff --git a/third_party/WebKit/LayoutTests/html/sections/aside-element-expected.txt b/third_party/WebKit/LayoutTests/html/sections/aside-element-expected.txt
index 5022e636..af08fa6 100644
--- a/third_party/WebKit/LayoutTests/html/sections/aside-element-expected.txt
+++ b/third_party/WebKit/LayoutTests/html/sections/aside-element-expected.txt
@@ -10,8 +10,8 @@
 <aside> can be nested inside <aside>:
 PASS aside3.parentNode.id is "aside2"
 Residual style:
-PASS getWeight("aside4") is "bold"
-PASS getWeight("span1") is "bold"
+PASS getWeight("aside4") is "700"
+PASS getWeight("span1") is "700"
 FormatBlock:
 PASS document.getElementById("span2").parentNode.nodeName is "ASIDE"
 PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/html/sections/aside-element.html b/third_party/WebKit/LayoutTests/html/sections/aside-element.html
index d621ead..30855bf 100644
--- a/third_party/WebKit/LayoutTests/html/sections/aside-element.html
+++ b/third_party/WebKit/LayoutTests/html/sections/aside-element.html
@@ -30,8 +30,8 @@
 function getWeight(id) {
     return document.defaultView.getComputedStyle(document.getElementById(id), null).getPropertyValue('font-weight');
 }
-shouldBe('getWeight("aside4")', '"bold"');
-shouldBe('getWeight("span1")', '"bold"');
+shouldBe('getWeight("aside4")', '"700"');
+shouldBe('getWeight("span1")', '"700"');
 document.body.removeChild(testParent);
 
 debug('FormatBlock:');
diff --git a/third_party/WebKit/LayoutTests/html/sections/footer-element-expected.txt b/third_party/WebKit/LayoutTests/html/sections/footer-element-expected.txt
index 933f1aa..e0ec8177 100644
--- a/third_party/WebKit/LayoutTests/html/sections/footer-element-expected.txt
+++ b/third_party/WebKit/LayoutTests/html/sections/footer-element-expected.txt
@@ -11,8 +11,8 @@
 PASS footer3.parentNode.id is "footer2"
 PASS footer5.parentNode.id is "header1"
 Residual style:
-PASS getWeight("footer4") is "bold"
-PASS getWeight("span1") is "bold"
+PASS getWeight("footer4") is "700"
+PASS getWeight("span1") is "700"
 FormatBlock:
 PASS document.getElementById("span2").parentNode.nodeName is "FOOTER"
 PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/html/sections/footer-element.html b/third_party/WebKit/LayoutTests/html/sections/footer-element.html
index 8d101b3..d3d5437 100644
--- a/third_party/WebKit/LayoutTests/html/sections/footer-element.html
+++ b/third_party/WebKit/LayoutTests/html/sections/footer-element.html
@@ -33,8 +33,8 @@
 function getWeight(id) {
     return document.defaultView.getComputedStyle(document.getElementById(id), null).getPropertyValue('font-weight');
 }
-shouldBe('getWeight("footer4")', '"bold"');
-shouldBe('getWeight("span1")', '"bold"');
+shouldBe('getWeight("footer4")', '"700"');
+shouldBe('getWeight("span1")', '"700"');
 document.body.removeChild(testParent);
 
 debug('FormatBlock:');
diff --git a/third_party/WebKit/LayoutTests/html/sections/header-element-expected.txt b/third_party/WebKit/LayoutTests/html/sections/header-element-expected.txt
index 6dcba54..692f3ef 100644
--- a/third_party/WebKit/LayoutTests/html/sections/header-element-expected.txt
+++ b/third_party/WebKit/LayoutTests/html/sections/header-element-expected.txt
@@ -11,8 +11,8 @@
 PASS header3.parentNode.id is "header2"
 PASS header5.parentNode.id is "footer1"
 Residual style:
-PASS getWeight("header4") is "bold"
-PASS getWeight("span1") is "bold"
+PASS getWeight("header4") is "700"
+PASS getWeight("span1") is "700"
 FormatBlock:
 PASS document.getElementById("span2").parentNode.nodeName is "HEADER"
 PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/html/sections/header-element.html b/third_party/WebKit/LayoutTests/html/sections/header-element.html
index dd76093..62c1be14 100644
--- a/third_party/WebKit/LayoutTests/html/sections/header-element.html
+++ b/third_party/WebKit/LayoutTests/html/sections/header-element.html
@@ -33,8 +33,8 @@
 function getWeight(id) {
     return document.defaultView.getComputedStyle(document.getElementById(id), null).getPropertyValue('font-weight');
 }
-shouldBe('getWeight("header4")', '"bold"');
-shouldBe('getWeight("span1")', '"bold"');
+shouldBe('getWeight("header4")', '"700"');
+shouldBe('getWeight("span1")', '"700"');
 document.body.removeChild(testParent);
 
 debug('FormatBlock:');
diff --git a/third_party/WebKit/LayoutTests/html/sections/hgroup-element-expected.txt b/third_party/WebKit/LayoutTests/html/sections/hgroup-element-expected.txt
index 9937f17..1c7abe4 100644
--- a/third_party/WebKit/LayoutTests/html/sections/hgroup-element-expected.txt
+++ b/third_party/WebKit/LayoutTests/html/sections/hgroup-element-expected.txt
@@ -10,8 +10,8 @@
 <hgroup> can be nested inside <hgroup>:
 PASS hgroup3.parentNode.id is "hgroup2"
 Residual style:
-PASS getWeight("hgroup4") is "bold"
-PASS getWeight("span1") is "bold"
+PASS getWeight("hgroup4") is "700"
+PASS getWeight("span1") is "700"
 FormatBlock:
 PASS document.getElementById("span2").parentNode.nodeName is "HGROUP"
 PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/html/sections/hgroup-element.html b/third_party/WebKit/LayoutTests/html/sections/hgroup-element.html
index f446732..5e5c70bf 100644
--- a/third_party/WebKit/LayoutTests/html/sections/hgroup-element.html
+++ b/third_party/WebKit/LayoutTests/html/sections/hgroup-element.html
@@ -31,8 +31,8 @@
 function getWeight(id) {
     return document.defaultView.getComputedStyle(document.getElementById(id), null).getPropertyValue('font-weight');
 }
-shouldBe('getWeight("hgroup4")', '"bold"');
-shouldBe('getWeight("span1")', '"bold"');
+shouldBe('getWeight("hgroup4")', '"700"');
+shouldBe('getWeight("span1")', '"700"');
 document.body.removeChild(testParent);
 
 debug('FormatBlock:');
diff --git a/third_party/WebKit/LayoutTests/html/sections/section-element-expected.txt b/third_party/WebKit/LayoutTests/html/sections/section-element-expected.txt
index c637cf1..3d719d8 100644
--- a/third_party/WebKit/LayoutTests/html/sections/section-element-expected.txt
+++ b/third_party/WebKit/LayoutTests/html/sections/section-element-expected.txt
@@ -10,8 +10,8 @@
 <section> can be nested inside <section>:
 PASS section3.parentNode.id is "section2"
 Residual style:
-PASS getWeight("section4") is "bold"
-PASS getWeight("span1") is "bold"
+PASS getWeight("section4") is "700"
+PASS getWeight("span1") is "700"
 FormatBlock:
 PASS document.getElementById("span2").parentNode.nodeName is "SECTION"
 PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/html/sections/section-element.html b/third_party/WebKit/LayoutTests/html/sections/section-element.html
index 7bd78ce8..0b5eb2b 100644
--- a/third_party/WebKit/LayoutTests/html/sections/section-element.html
+++ b/third_party/WebKit/LayoutTests/html/sections/section-element.html
@@ -30,8 +30,8 @@
 function getWeight(id) {
     return document.defaultView.getComputedStyle(document.getElementById(id), null).getPropertyValue('font-weight');
 }
-shouldBe('getWeight("section4")', '"bold"');
-shouldBe('getWeight("span1")', '"bold"');
+shouldBe('getWeight("section4")', '"700"');
+shouldBe('getWeight("span1")', '"700"');
 document.body.removeChild(testParent);
 
 debug('FormatBlock:');
diff --git a/third_party/WebKit/LayoutTests/html/text_level_semantics/mark-element-expected.txt b/third_party/WebKit/LayoutTests/html/text_level_semantics/mark-element-expected.txt
index fa302653..18d2705 100644
--- a/third_party/WebKit/LayoutTests/html/text_level_semantics/mark-element-expected.txt
+++ b/third_party/WebKit/LayoutTests/html/text_level_semantics/mark-element-expected.txt
@@ -8,8 +8,8 @@
 <b> does not close <mark>:
 PASS b1.parentNode.nodeName is "MARK"
 Residual style:
-PASS getWeight("mark2") is "bold"
-PASS getWeight("span1") is "bold"
+PASS getWeight("mark2") is "700"
+PASS getWeight("span1") is "700"
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/html/text_level_semantics/mark-element.html b/third_party/WebKit/LayoutTests/html/text_level_semantics/mark-element.html
index f0bd234..577e356 100644
--- a/third_party/WebKit/LayoutTests/html/text_level_semantics/mark-element.html
+++ b/third_party/WebKit/LayoutTests/html/text_level_semantics/mark-element.html
@@ -25,8 +25,8 @@
 function getWeight(id) {
     return document.defaultView.getComputedStyle(document.getElementById(id), null).getPropertyValue('font-weight');
 }
-shouldBe('getWeight("mark2")', '"bold"');
-shouldBe('getWeight("span1")', '"bold"');
+shouldBe('getWeight("mark2")', '"700"');
+shouldBe('getWeight("span1")', '"700"');
 document.body.removeChild(testParent);
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/active-and-passive-subresources-with-cert-errors-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/security/active-and-passive-subresources-with-cert-errors-expected.txt
deleted file mode 100644
index e4aa138c6..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/active-and-passive-subresources-with-cert-errors-expected.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-Tests addition of explanation when active and passive subresources were loaded with certificate errors.
-
-<DIV class=security-explanation security-explanation-insecure >
-    <DIV class=security-property security-property-insecure >
-    </DIV>
-    <DIV class=security-explanation-text >
-        <DIV class=security-explanation-title >
-Active content with certificate errors
-        </DIV>
-        <DIV >
-You have recently allowed content loaded with certificate errors (such as scripts or iframes) to run on this site.
-        </DIV>
-    </DIV>
-</DIV>
-<DIV class=security-explanation security-explanation-neutral >
-    <DIV class=security-property security-property-neutral >
-    </DIV>
-    <DIV class=security-explanation-text >
-        <DIV class=security-explanation-title >
-Content with certificate errors
-        </DIV>
-        <DIV >
-This site includes resources that were loaded with certificate errors.
-        </DIV>
-    </DIV>
-</DIV>
-
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/active-and-passive-subresources-with-cert-errors.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/active-and-passive-subresources-with-cert-errors.html
deleted file mode 100644
index 057c3dd..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/active-and-passive-subresources-with-cert-errors.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<html>
-<head>
-<script src="../inspector-test.js"></script>
-<script src="../security-test.js"></script>
-<script>
-function test()
-{
-    /** @type {!Protocol.Security.InsecureContentStatus} */
-    var insecureContentStatus = { ranMixedContent: false, displayedMixedContent: false, ranContentWithCertErrors: true, displayedContentWithCertErrors: true, ranInsecureContentStyle: Protocol.Security.SecurityState.Insecure, displayedInsecureContentStyle: Protocol.Security.SecurityState.Neutral };
-
-    InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Insecure, true, [], insecureContentStatus, null));
-
-    var request = new SDK.NetworkRequest(0, "http://foo.test", "https://foo.test", 0, 0, null);
-    InspectorTest.dispatchRequestFinished(request);
-
-    var explanations = Security.SecurityPanel._instance()._mainView.contentElement.getElementsByClassName("security-explanation");
-    for (var i = 0; i < explanations.length; i++)
-        InspectorTest.dumpDeepInnerHTML(explanations[i]);
-    InspectorTest.completeTest();
-}
-</script>
-</head>
-<body onload="runTest()">
-<p>Tests addition of explanation when active and passive subresources were loaded with certificate errors.</p>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/active-subresource-with-cert-errors-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/security/active-subresource-with-cert-errors-expected.txt
deleted file mode 100644
index d3e3a0e3..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/active-subresource-with-cert-errors-expected.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-Tests addition of explanation when an active subresource was loaded with certificate errors.
-
-<DIV class=security-explanation security-explanation-insecure >
-    <DIV class=security-property security-property-insecure >
-    </DIV>
-    <DIV class=security-explanation-text >
-        <DIV class=security-explanation-title >
-Active content with certificate errors
-        </DIV>
-        <DIV >
-You have recently allowed content loaded with certificate errors (such as scripts or iframes) to run on this site.
-        </DIV>
-    </DIV>
-</DIV>
-
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/active-subresource-with-cert-errors.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/active-subresource-with-cert-errors.html
deleted file mode 100644
index 5a505d7d..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/active-subresource-with-cert-errors.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<html>
-<head>
-<script src="../inspector-test.js"></script>
-<script src="../security-test.js"></script>
-<script>
-function test()
-{
-    /** @type {!Protocol.Security.InsecureContentStatus} */
-    var insecureContentStatus = { ranMixedContent: false, displayedMixedContent: false, ranContentWithCertErrors: true, displayedContentWithCertErrors: false, ranInsecureContentStyle: Protocol.Security.SecurityState.Insecure, displayedInsecureContentStyle: Protocol.Security.SecurityState.Neutral };
-
-    InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Insecure, true, [], insecureContentStatus, null));
-
-    var request = new SDK.NetworkRequest(0, "http://foo.test", "https://foo.test", 0, 0, null);
-    InspectorTest.dispatchRequestFinished(request);
-
-    var explanations = Security.SecurityPanel._instance()._mainView.contentElement.getElementsByClassName("security-explanation");
-    for (var i = 0; i < explanations.length; i++)
-        InspectorTest.dumpDeepInnerHTML(explanations[i]);
-    InspectorTest.completeTest();
-}
-</script>
-</head>
-<body onload="runTest()">
-<p>Tests addition of explanation when an active subresource was loaded with certificate errors.</p>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/blocked-mixed-content-and-subresources-with-cert-errors-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/security/blocked-mixed-content-and-subresources-with-cert-errors-expected.txt
deleted file mode 100644
index 76247f8..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/blocked-mixed-content-and-subresources-with-cert-errors-expected.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-Tests active mixed content blocking in the security panel, along with subresources with cert errors.
-
-<DIV class=security-explanation security-explanation-neutral >
-    <DIV class=security-property security-property-neutral >
-    </DIV>
-    <DIV class=security-explanation-text >
-        <DIV class=security-explanation-title >
-Content with certificate errors
-        </DIV>
-        <DIV >
-This site includes resources that were loaded with certificate errors.
-        </DIV>
-    </DIV>
-</DIV>
-<DIV class=security-explanation security-explanation-info >
-    <DIV class=security-property security-property-info >
-    </DIV>
-    <DIV class=security-explanation-text >
-        <DIV class=security-explanation-title >
-Blocked mixed content
-        </DIV>
-        <DIV >
-Your page requested non-secure resources that were blocked.
-        </DIV>
-        <DIV class=security-mixed-content link >
-View 1 request in Network Panel
-        </DIV>
-    </DIV>
-</DIV>
-
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/blocked-mixed-content-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/security/blocked-mixed-content-expected.txt
new file mode 100644
index 0000000..ced5f44
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/blocked-mixed-content-expected.txt
@@ -0,0 +1,18 @@
+Tests active mixed content blocking in the security panel.
+
+<DIV class=security-explanation security-explanation-info >
+    <DIV class=security-property security-property-info >
+    </DIV>
+    <DIV class=security-explanation-text >
+        <DIV class=security-explanation-title >
+Blocked mixed content
+        </DIV>
+        <DIV >
+Your page requested non-secure resources that were blocked.
+        </DIV>
+        <DIV class=security-mixed-content link >
+View 1 request in Network Panel
+        </DIV>
+    </DIV>
+</DIV>
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/blocked-mixed-content-and-subresources-with-cert-errors.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/blocked-mixed-content.html
similarity index 92%
rename from third_party/WebKit/LayoutTests/http/tests/inspector/security/blocked-mixed-content-and-subresources-with-cert-errors.html
rename to third_party/WebKit/LayoutTests/http/tests/inspector/security/blocked-mixed-content.html
index 3654078..3b2c1b1 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/blocked-mixed-content-and-subresources-with-cert-errors.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/blocked-mixed-content.html
@@ -23,6 +23,6 @@
 </script>
 </head>
 <body onload="runTest()">
-<p>Tests active mixed content blocking in the security panel, along with subresources with cert errors.</p>
+<p>Tests active mixed content blocking in the security panel.</p>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-active-and-passive-reload-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-active-and-passive-reload-expected.txt
index ca460ab..b34a37717 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-active-and-passive-reload-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-active-and-passive-reload-expected.txt
@@ -1,29 +1,16 @@
 Tests that the active and pasive mixed content explanations prompt the user to refresh when there are no recorded requests, and link to the network panel when there are recorded requests.
 
-<DIV class=security-explanation security-explanation-insecure >
-    <DIV class=security-property security-property-insecure >
-    </DIV>
-    <DIV class=security-explanation-text >
-        <DIV class=security-explanation-title >
-Active mixed content
-        </DIV>
-        <DIV >
-You have recently allowed non-secure content (such as scripts or iframes) to run on this site.
-        </DIV>
-        <DIV class=security-mixed-content >
-Reload the page to record requests for HTTP resources.
-        </DIV>
-    </DIV>
-</DIV>
+
+Before Refresh --------------
 <DIV class=security-explanation security-explanation-neutral >
     <DIV class=security-property security-property-neutral >
     </DIV>
     <DIV class=security-explanation-text >
         <DIV class=security-explanation-title >
-Mixed content
+Neutral Test Summary
         </DIV>
         <DIV >
-The site includes HTTP resources.
+Neutral Test Description
         </DIV>
         <DIV class=security-mixed-content >
 Reload the page to record requests for HTTP resources.
@@ -35,25 +22,42 @@
     </DIV>
     <DIV class=security-explanation-text >
         <DIV class=security-explanation-title >
-Active mixed content
+Insecure Test Summary
         </DIV>
         <DIV >
-You have recently allowed non-secure content (such as scripts or iframes) to run on this site.
+Insecure Test Description
+        </DIV>
+        <DIV class=security-mixed-content >
+Reload the page to record requests for HTTP resources.
+        </DIV>
+    </DIV>
+</DIV>
+
+Refresh --------------
+<DIV class=security-explanation security-explanation-neutral >
+    <DIV class=security-property security-property-neutral >
+    </DIV>
+    <DIV class=security-explanation-text >
+        <DIV class=security-explanation-title >
+Neutral Test Summary
+        </DIV>
+        <DIV >
+Neutral Test Description
         </DIV>
         <DIV class=security-mixed-content link >
 View 1 request in Network Panel
         </DIV>
     </DIV>
 </DIV>
-<DIV class=security-explanation security-explanation-neutral >
-    <DIV class=security-property security-property-neutral >
+<DIV class=security-explanation security-explanation-insecure >
+    <DIV class=security-property security-property-insecure >
     </DIV>
     <DIV class=security-explanation-text >
         <DIV class=security-explanation-title >
-Mixed content
+Insecure Test Summary
         </DIV>
         <DIV >
-The site includes HTTP resources.
+Insecure Test Description
         </DIV>
         <DIV class=security-mixed-content link >
 View 1 request in Network Panel
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-active-and-passive-reload.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-active-and-passive-reload.html
index 36ef3e3..c6d6a1b 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-active-and-passive-reload.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-active-and-passive-reload.html
@@ -8,16 +8,23 @@
     /** @type {!Protocol.Security.InsecureContentStatus} */
     var insecureContentStatus = { ranMixedContent: true, displayedMixedContent: true, ranContentWithCertErrors: false, displayedContentWithCertErrors: false, ranInsecureContentStyle: Protocol.Security.SecurityState.Insecure, displayedInsecureContentStyle: Protocol.Security.SecurityState.Neutral };
 
-    InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Neutral, true, [], insecureContentStatus, null));
+    InspectorTest.addResult("\nBefore Refresh --------------");
+
+    var mixedExplanations = [
+        /** @type {!Protocol.Security.SecurityStateExplanation} */ ({"securityState": Protocol.Security.SecurityState.Neutral, "summary": "Neutral Test Summary", "description": "Neutral Test Description", mixedContentType: Protocol.Security.MixedContentType.OptionallyBlockable}),
+        /** @type {!Protocol.Security.SecurityStateExplanation} */ ({"securityState": Protocol.Security.SecurityState.Insecure, "summary": "Insecure Test Summary", "description": "Insecure Test Description", mixedContentType: Protocol.Security.MixedContentType.Blockable})
+    ];
+    InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Neutral, true, mixedExplanations, insecureContentStatus, null));
 
     // At this point, the page has mixed content but no mixed requests have been recorded, so the user should be prompted to refresh.
     var explanations = Security.SecurityPanel._instance()._mainView.contentElement.getElementsByClassName("security-explanation");
     for (var i = 0; i < explanations.length; i++)
         InspectorTest.dumpDeepInnerHTML(explanations[i]);
 
-    // Now simulate a refresh.
+    InspectorTest.addResult("\nRefresh --------------");
 
-    InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Neutral, true, [], insecureContentStatus, null));
+    // Now simulate a refresh.
+    InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Neutral, true, mixedExplanations, insecureContentStatus, null));
 
     var passive = new SDK.NetworkRequest(0, "http://foo.test", "https://foo.test", 0, 0, null);
     passive.mixedContentType = "optionally-blockable";
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-and-subresources-with-cert-errors-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-and-subresources-with-cert-errors-expected.txt
deleted file mode 100644
index 401af7c..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-and-subresources-with-cert-errors-expected.txt
+++ /dev/null
@@ -1,57 +0,0 @@
-Tests addition of explanation when there was both mixed content and subresources were loaded with certificate errors.
-
-<DIV class=security-explanation security-explanation-insecure >
-    <DIV class=security-property security-property-insecure >
-    </DIV>
-    <DIV class=security-explanation-text >
-        <DIV class=security-explanation-title >
-Active mixed content
-        </DIV>
-        <DIV >
-You have recently allowed non-secure content (such as scripts or iframes) to run on this site.
-        </DIV>
-        <DIV class=security-mixed-content >
-Reload the page to record requests for HTTP resources.
-        </DIV>
-    </DIV>
-</DIV>
-<DIV class=security-explanation security-explanation-neutral >
-    <DIV class=security-property security-property-neutral >
-    </DIV>
-    <DIV class=security-explanation-text >
-        <DIV class=security-explanation-title >
-Mixed content
-        </DIV>
-        <DIV >
-The site includes HTTP resources.
-        </DIV>
-        <DIV class=security-mixed-content >
-Reload the page to record requests for HTTP resources.
-        </DIV>
-    </DIV>
-</DIV>
-<DIV class=security-explanation security-explanation-insecure >
-    <DIV class=security-property security-property-insecure >
-    </DIV>
-    <DIV class=security-explanation-text >
-        <DIV class=security-explanation-title >
-Active content with certificate errors
-        </DIV>
-        <DIV >
-You have recently allowed content loaded with certificate errors (such as scripts or iframes) to run on this site.
-        </DIV>
-    </DIV>
-</DIV>
-<DIV class=security-explanation security-explanation-neutral >
-    <DIV class=security-property security-property-neutral >
-    </DIV>
-    <DIV class=security-explanation-text >
-        <DIV class=security-explanation-title >
-Content with certificate errors
-        </DIV>
-        <DIV >
-This site includes resources that were loaded with certificate errors.
-        </DIV>
-    </DIV>
-</DIV>
-
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-and-subresources-with-cert-errors.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-and-subresources-with-cert-errors.html
deleted file mode 100644
index 11c03ff..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-and-subresources-with-cert-errors.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<html>
-<head>
-<script src="../inspector-test.js"></script>
-<script src="../security-test.js"></script>
-<script>
-function test()
-{
-    /** @type {!Protocol.Security.InsecureContentStatus} */
-    var insecureContentStatus = { ranMixedContent: true, displayedMixedContent: true, ranContentWithCertErrors: true, displayedContentWithCertErrors: true, ranInsecureContentStyle: Protocol.Security.SecurityState.Insecure, displayedInsecureContentStyle: Protocol.Security.SecurityState.Neutral };
-
-    InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Insecure, true, [], insecureContentStatus, null));
-
-    var request = new SDK.NetworkRequest(0, "http://foo.test", "https://foo.test", 0, 0, null);
-    InspectorTest.dispatchRequestFinished(request);
-
-    var explanations = Security.SecurityPanel._instance()._mainView.contentElement.getElementsByClassName("security-explanation");
-    for (var i = 0; i < explanations.length; i++)
-        InspectorTest.dumpDeepInnerHTML(explanations[i]);
-    InspectorTest.completeTest();
-}
-</script>
-</head>
-<body onload="runTest()">
-<p>Tests addition of explanation when there was both mixed content and subresources were loaded with certificate errors.</p>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-reload-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-reload-expected.txt
index 6e29661..c0dd7e2 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-reload-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-reload-expected.txt
@@ -1,29 +1,33 @@
 Tests that the mixed content explanation prompts the user to refresh when there are no recorded requests, and links to the network panel when there are recorded requests.
 
+
+Before Refresh --------------
 <DIV class=security-explanation security-explanation-neutral >
     <DIV class=security-property security-property-neutral >
     </DIV>
     <DIV class=security-explanation-text >
         <DIV class=security-explanation-title >
-Mixed content
+Neutral Test Summary
         </DIV>
         <DIV >
-The site includes HTTP resources.
+Neutral Test Description
         </DIV>
         <DIV class=security-mixed-content >
 Reload the page to record requests for HTTP resources.
         </DIV>
     </DIV>
 </DIV>
+
+Refresh --------------
 <DIV class=security-explanation security-explanation-neutral >
     <DIV class=security-property security-property-neutral >
     </DIV>
     <DIV class=security-explanation-text >
         <DIV class=security-explanation-title >
-Mixed content
+Neutral Test Summary
         </DIV>
         <DIV >
-The site includes HTTP resources.
+Neutral Test Description
         </DIV>
         <DIV class=security-mixed-content link >
 View 1 request in Network Panel
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-reload.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-reload.html
index 1f40be4..8200b6e 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-reload.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-content-reload.html
@@ -8,16 +8,22 @@
     /** @type {!Protocol.Security.InsecureContentStatus} */
     var insecureContentStatus = { ranMixedContent: false, displayedMixedContent: true, ranContentWithCertErrors: false, displayedContentWithCertErrors: false, ranInsecureContentStyle: Protocol.Security.SecurityState.Insecure, displayedInsecureContentStyle: Protocol.Security.SecurityState.Neutral };
 
-    InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Neutral, true, [], insecureContentStatus, null));
+    InspectorTest.addResult("\nBefore Refresh --------------");
+
+    var mixedExplanations = [
+        /** @type {!Protocol.Security.SecurityStateExplanation} */ ({"securityState": Protocol.Security.SecurityState.Neutral, "summary": "Neutral Test Summary", "description": "Neutral Test Description", mixedContentType: Protocol.Security.MixedContentType.OptionallyBlockable})
+    ];
+    InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Neutral, true, mixedExplanations, insecureContentStatus, null));
 
     // At this point, the page has mixed content but no mixed requests have been recorded, so the user should be prompted to refresh.
     var explanations = Security.SecurityPanel._instance()._mainView.contentElement.getElementsByClassName("security-explanation");
     for (var i = 0; i < explanations.length; i++)
         InspectorTest.dumpDeepInnerHTML(explanations[i]);
 
-    // Now simulate a refresh.
+    InspectorTest.addResult("\nRefresh --------------");
 
-    InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Neutral, true, [], insecureContentStatus, null));
+    // Now simulate a refresh.
+    InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Neutral, true, mixedExplanations, insecureContentStatus, null));
 
     var request = new SDK.NetworkRequest(0, "http://foo.test", "https://foo.test", 0, 0, null);
     request.mixedContentType = "optionally-blockable";
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-form-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-form-expected.txt
deleted file mode 100644
index add6e17..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-form-expected.txt
+++ /dev/null
@@ -1,58 +0,0 @@
-Tests that the mixed-form explanation appears correctly.
-
-
-Security Explanations (Mixed Form Only) --------------
-<DIV class=security-explanation security-explanation-neutral >
-    <DIV class=security-property security-property-neutral >
-    </DIV>
-    <DIV class=security-explanation-text >
-        <DIV class=security-explanation-title >
-Non-secure form
-        </DIV>
-        <DIV >
-The page includes a form with a non-secure "action" attribute.
-        </DIV>
-    </DIV>
-</DIV>
-<DIV class=security-explanation security-explanation-secure >
-    <DIV class=security-property security-property-secure >
-    </DIV>
-    <DIV class=security-explanation-text >
-        <DIV class=security-explanation-title >
-Secure resources
-        </DIV>
-        <DIV >
-All resources on this page are served securely.
-        </DIV>
-    </DIV>
-</DIV>
-
-Security Explanations (Mixed Form + Mixed Passive) --------------
-<DIV class=security-explanation security-explanation-neutral >
-    <DIV class=security-property security-property-neutral >
-    </DIV>
-    <DIV class=security-explanation-text >
-        <DIV class=security-explanation-title >
-Non-secure form
-        </DIV>
-        <DIV >
-The page includes a form with a non-secure "action" attribute.
-        </DIV>
-    </DIV>
-</DIV>
-<DIV class=security-explanation security-explanation-neutral >
-    <DIV class=security-property security-property-neutral >
-    </DIV>
-    <DIV class=security-explanation-text >
-        <DIV class=security-explanation-title >
-Mixed content
-        </DIV>
-        <DIV >
-The site includes HTTP resources.
-        </DIV>
-        <DIV class=security-mixed-content >
-Reload the page to record requests for HTTP resources.
-        </DIV>
-    </DIV>
-</DIV>
-
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-form.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-form.html
deleted file mode 100644
index f73db95..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/mixed-form.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<html>
-<head>
-<script src="../inspector-test.js"></script>
-<script src="../security-test.js"></script>
-<script>
-function test()
-{
-    function dumpExplanations() {
-      var explanations = Security.SecurityPanel._instance()._mainView.contentElement.getElementsByClassName("security-explanation");
-      for (var i = 0; i < explanations.length; i++)
-          InspectorTest.dumpDeepInnerHTML(explanations[i]);
-    }
-
-    /** @type {!Protocol.Security.InsecureContentStatus} */
-    var insecureContentStatus = { ranMixedContent: false, displayedMixedContent: false, containedMixedForm: true, ranContentWithCertErrors: false, displayedContentWithCertErrors: false, ranInsecureContentStyle: Protocol.Security.SecurityState.Insecure, displayedInsecureContentStyle: Protocol.Security.SecurityState.Neutral };
-
-    InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Neutral, true, [], insecureContentStatus, null));
-
-    InspectorTest.addResult("\nSecurity Explanations (Mixed Form Only) --------------");
-    dumpExplanations();
-
-    // Now simulate a state change that adds passive mixed content.
-    insecureContentStatus = { ranMixedContent: false, displayedMixedContent: true, containedMixedForm: true, ranContentWithCertErrors: false, displayedContentWithCertErrors: false, ranInsecureContentStyle: Protocol.Security.SecurityState.Insecure, displayedInsecureContentStyle: Protocol.Security.SecurityState.Neutral };
-    InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Neutral, true, [], insecureContentStatus, null));
-    InspectorTest.addResult("\nSecurity Explanations (Mixed Form + Mixed Passive) --------------");
-    dumpExplanations();
-
-    InspectorTest.completeTest();
-}
-</script>
-</head>
-<body onload="runTest()">
-<p>Tests that the mixed-form explanation appears correctly.</p>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/passive-subresource-with-cert-errors-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/security/passive-subresource-with-cert-errors-expected.txt
deleted file mode 100644
index 2f21e8c3..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/passive-subresource-with-cert-errors-expected.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-Tests addition of explanation when a passive subresource was loaded with certificate errors.
-
-<DIV class=security-explanation security-explanation-neutral >
-    <DIV class=security-property security-property-neutral >
-    </DIV>
-    <DIV class=security-explanation-text >
-        <DIV class=security-explanation-title >
-Content with certificate errors
-        </DIV>
-        <DIV >
-This site includes resources that were loaded with certificate errors.
-        </DIV>
-    </DIV>
-</DIV>
-
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/passive-subresource-with-cert-errors.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/passive-subresource-with-cert-errors.html
deleted file mode 100644
index ac26615..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/passive-subresource-with-cert-errors.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<html>
-<head>
-<script src="../inspector-test.js"></script>
-<script src="../security-test.js"></script>
-<script>
-function test()
-{
-    /** @type {!Protocol.Security.InsecureContentStatus} */
-    var insecureContentStatus = { ranMixedContent: false, displayedMixedContent: false, ranContentWithCertErrors: false, displayedContentWithCertErrors: true, ranInsecureContentStyle: Protocol.Security.SecurityState.Insecure, displayedInsecureContentStyle: Protocol.Security.SecurityState.Neutral };
-
-    InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.None, true, [], insecureContentStatus, null));
-
-    var request = new SDK.NetworkRequest(0, "http://foo.test", "https://foo.test", 0, 0, null);
-    InspectorTest.dispatchRequestFinished(request);
-
-    var explanations = Security.SecurityPanel._instance()._mainView.contentElement.getElementsByClassName("security-explanation");
-    for (var i = 0; i < explanations.length; i++)
-        InspectorTest.dumpDeepInnerHTML(explanations[i]);
-    InspectorTest.completeTest();
-}
-</script>
-</head>
-<body onload="runTest()">
-<p>Tests addition of explanation when a passive subresource was loaded with certificate errors.</p>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-all-resources-secure-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-all-resources-secure-expected.txt
deleted file mode 100644
index 1077fae..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-all-resources-secure-expected.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-Tests addition of explanation when all page resources are transferred securely (no-mixed-content).
-
-<DIV class=security-explanation security-explanation-secure >
-    <DIV class=security-property security-property-secure >
-    </DIV>
-    <DIV class=security-explanation-text >
-        <DIV class=security-explanation-title >
-Secure resources
-        </DIV>
-        <DIV >
-All resources on this page are served securely.
-        </DIV>
-    </DIV>
-</DIV>
-
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-all-resources-secure.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-all-resources-secure.html
deleted file mode 100644
index 36f61e2..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-all-resources-secure.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<html>
-<head>
-<script src="../inspector-test.js"></script>
-<script src="../security-test.js"></script>
-<script>
-function test()
-{
-    /** @type {!Protocol.Security.InsecureContentStatus} */
-    var insecureContentStatus = { ranMixedContent: false, displayedMixedContent: false, ranContentWithCertErrors: false, displayedContentWithCertErrors: false, ranInsecureContentStyle: Protocol.Security.SecurityState.Insecure, displayedInsecureContentStyle: Protocol.Security.SecurityState.Neutral };
-
-    InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Secure, true, [], insecureContentStatus, null));
-
-    var request = new SDK.NetworkRequest(0, "http://foo.test", "https://foo.test", 0, 0, null);
-    InspectorTest.dispatchRequestFinished(request);
-
-    var explanations = Security.SecurityPanel._instance()._mainView.contentElement.getElementsByClassName("security-explanation");
-    for (var i = 0; i < explanations.length; i++)
-        InspectorTest.dumpDeepInnerHTML(explanations[i]);
-    InspectorTest.completeTest();
-}
-</script>
-</head>
-<body onload="runTest()">
-<p>Tests addition of explanation when all page resources are transferred securely (no-mixed-content).</p>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-blocked-mixed-content-and-malicious-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-blocked-mixed-content-and-malicious-expected.txt
deleted file mode 100644
index 26392a61..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-blocked-mixed-content-and-malicious-expected.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-Tests active mixed content blocking in the security panel when page is classified as malicious.
-
-<DIV class=security-summary-text >
-Test: Summary Override Text
-</DIV>
-<DIV class=security-explanation security-explanation-secure >
-    <DIV class=security-property security-property-secure >
-    </DIV>
-    <DIV class=security-explanation-text >
-        <DIV class=security-explanation-title >
-Secure resources
-        </DIV>
-        <DIV >
-All resources on this page are served securely.
-        </DIV>
-    </DIV>
-</DIV>
-<DIV class=security-explanation security-explanation-info >
-    <DIV class=security-property security-property-info >
-    </DIV>
-    <DIV class=security-explanation-text >
-        <DIV class=security-explanation-title >
-Blocked mixed content
-        </DIV>
-        <DIV >
-Your page requested non-secure resources that were blocked.
-        </DIV>
-        <DIV class=security-mixed-content link >
-View 1 request in Network Panel
-        </DIV>
-    </DIV>
-</DIV>
-
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-blocked-mixed-content-and-malicious.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-blocked-mixed-content-and-malicious.html
deleted file mode 100644
index 9a1e0cf..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-blocked-mixed-content-and-malicious.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<html>
-<head>
-<script src="../inspector-test.js"></script>
-<script src="../security-test.js"></script>
-<script>
-function test()
-{
-    /** @type {!Protocol.Security.InsecureContentStatus} */
-    var insecureContentStatus = { ranMixedContent: false, displayedMixedContent: false, ranContentWithCertErrors: false, displayedContentWithCertErrors: false, ranInsecureContentStyle: Protocol.Security.SecurityState.Insecure, displayedInsecureContentStyle: Protocol.Security.SecurityState.Neutral };
-    InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Secure, true, [], insecureContentStatus, "Test: Summary Override Text"));
-
-    var request = new SDK.NetworkRequest(0, "http://foo.test", "https://foo.test", 0, 0, null);
-    request.setBlockedReason(Protocol.Network.BlockedReason.MixedContent);
-    request.mixedContentType = "blockable";
-    InspectorTest.dispatchRequestFinished(request);
-
-    InspectorTest.dumpDeepInnerHTML(Security.SecurityPanel._instance()._mainView.contentElement.getElementsByClassName("security-summary-text")[0]);
-
-    var explanations = Security.SecurityPanel._instance()._mainView.contentElement.getElementsByClassName("security-explanation");
-    for (var i = 0; i < explanations.length; i++)
-        InspectorTest.dumpDeepInnerHTML(explanations[i]);
-
-    InspectorTest.completeTest();
-}
-</script>
-</head>
-<body onload="runTest()">
-<p>Tests active mixed content blocking in the security panel when page is classified as malicious.</p>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-blocked-mixed-content-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-blocked-mixed-content-expected.txt
index 0135a44..ced5f44 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-blocked-mixed-content-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-blocked-mixed-content-expected.txt
@@ -1,17 +1,5 @@
 Tests active mixed content blocking in the security panel.
 
-<DIV class=security-explanation security-explanation-secure >
-    <DIV class=security-property security-property-secure >
-    </DIV>
-    <DIV class=security-explanation-text >
-        <DIV class=security-explanation-title >
-Secure resources
-        </DIV>
-        <DIV >
-All resources on this page are served securely.
-        </DIV>
-    </DIV>
-</DIV>
 <DIV class=security-explanation security-explanation-info >
     <DIV class=security-property security-property-info >
     </DIV>
@@ -27,16 +15,4 @@
         </DIV>
     </DIV>
 </DIV>
-<DIV class=security-explanation security-explanation-secure >
-    <DIV class=security-property security-property-secure >
-    </DIV>
-    <DIV class=security-explanation-text >
-        <DIV class=security-explanation-title >
-Secure resources
-        </DIV>
-        <DIV >
-All resources on this page are served securely.
-        </DIV>
-    </DIV>
-</DIV>
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-explanation-ordering.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-explanation-ordering.html
index f0deac5d..d6d27070 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-explanation-ordering.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-explanation-ordering.html
@@ -28,6 +28,11 @@
             "securityState": "secure",
             "summary": "Obsolete Connection Settings"
 
+        },
+        {
+            "description": "All resources on this page are served securely.",
+            "securityState": "secure",
+            "summary": "Secure resources"
         }
     ];
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-secure-but-malicious-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-secure-but-malicious-expected.txt
deleted file mode 100644
index cebc927..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-secure-but-malicious-expected.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-Tests summary and explanation when all page resources are transferred securely (no-mixed-content) but page is flagged by Google Safe Browsing.
-
-<DIV class=security-summary-text >
-Test: Summary Override Text
-</DIV>
-<DIV class=security-explanation security-explanation-secure >
-    <DIV class=security-property security-property-secure >
-    </DIV>
-    <DIV class=security-explanation-text >
-        <DIV class=security-explanation-title >
-Secure resources
-        </DIV>
-        <DIV >
-All resources on this page are served securely.
-        </DIV>
-    </DIV>
-</DIV>
-
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-summary-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-summary-expected.txt
new file mode 100644
index 0000000..24c6aac9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-summary-expected.txt
@@ -0,0 +1,6 @@
+Tests specifying a security summary for the Security panel overview.
+
+<DIV class=security-summary-text >
+Test: Summary Override Text
+</DIV>
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-secure-but-malicious.html b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-summary.html
similarity index 65%
rename from third_party/WebKit/LayoutTests/http/tests/inspector/security/security-secure-but-malicious.html
rename to third_party/WebKit/LayoutTests/http/tests/inspector/security/security-summary.html
index ef78e48..8d8ae5a 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-secure-but-malicious.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/security/security-summary.html
@@ -7,22 +7,15 @@
 {
     /** @type {!Protocol.Security.InsecureContentStatus} */
     var insecureContentStatus = { ranMixedContent: false, displayedMixedContent: false, ranContentWithCertErrors: false, displayedContentWithCertErrors: false, ranInsecureContentStyle: Protocol.Security.SecurityState.Insecure, displayedInsecureContentStyle: Protocol.Security.SecurityState.Neutral };
-
     InspectorTest.mainTarget.model(Security.SecurityModel).dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, new Security.PageSecurityState(Protocol.Security.SecurityState.Secure, true, [], insecureContentStatus, "Test: Summary Override Text"));
 
-    var request = new SDK.NetworkRequest(0, "http://foo.test", "https://foo.test", 0, 0, null);
-    InspectorTest.dispatchRequestFinished(request);
-
     InspectorTest.dumpDeepInnerHTML(Security.SecurityPanel._instance()._mainView.contentElement.getElementsByClassName("security-summary-text")[0]);
 
-    var explanations = Security.SecurityPanel._instance()._mainView.contentElement.getElementsByClassName("security-explanation");
-    for (var i = 0; i < explanations.length; i++)
-        InspectorTest.dumpDeepInnerHTML(explanations[i]);
     InspectorTest.completeTest();
 }
 </script>
 </head>
 <body onload="runTest()">
-<p>Tests summary and explanation when all page resources are transferred securely (no-mixed-content) but page is flagged by Google Safe Browsing.</p>
+<p>Tests specifying a security summary for the Security panel overview.</p>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/elements-panel-styles-expected.txt b/third_party/WebKit/LayoutTests/inspector/elements/elements-panel-styles-expected.txt
index ece92d68..b992643 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/elements-panel-styles-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/elements/elements-panel-styles-expected.txt
@@ -28,7 +28,7 @@
 font-style: italic;
     italic !important - #container .foo elements-panel-styles.css:17 -> elements-panel-styles.css:17:18
     OVERLOADED normal !important - .foo elements-panel-styles.css:21 -> elements-panel-styles.css:21:7
-font-weight: normal;
+font-weight: 400;
     normal !important - .foo elements-panel-styles.css:21 -> elements-panel-styles.css:21:7
 margin-bottom: 2px;
     2px - .foo elements-panel-styles.css:21 -> elements-panel-styles.css:21:7
diff --git a/third_party/WebKit/LayoutTests/media/track/track-css-matching-default.html b/third_party/WebKit/LayoutTests/media/track/track-css-matching-default.html
index b3984586..7742217 100644
--- a/third_party/WebKit/LayoutTests/media/track/track-css-matching-default.html
+++ b/third_party/WebKit/LayoutTests/media/track/track-css-matching-default.html
@@ -18,7 +18,7 @@
 
     video.onseeked = t.step_func_done(function() {
         var cueNode = textTrackCueElementByIndex(video, 0).firstChild.firstElementChild;
-        assert_equals(getComputedStyle(cueNode).fontWeight, 'bold');
+        assert_equals(getComputedStyle(cueNode).fontWeight, '700');
         cueNode = cueNode.nextElementSibling;
         assert_equals(getComputedStyle(cueNode).fontStyle, 'italic');
         cueNode = cueNode.nextElementSibling;
@@ -27,4 +27,4 @@
     
     video.currentTime = 0.1;
 });
-</script>
\ No newline at end of file
+</script>
diff --git a/third_party/WebKit/LayoutTests/paint/overflow/background-paint-into-scrolling-contents-layer-with-root-layer-scrolls-offset-expected.html b/third_party/WebKit/LayoutTests/paint/overflow/background-paint-into-scrolling-contents-layer-with-root-layer-scrolls-offset-expected.html
new file mode 100644
index 0000000..344764c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/overflow/background-paint-into-scrolling-contents-layer-with-root-layer-scrolls-offset-expected.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<style>
+ body {
+   margin: 0;
+ }
+
+ div {
+   position: absolute;
+   left: 0;
+   top: 0;
+   width: 100%;
+   height: 10000px;
+   background: url('../../images/resources/lenna.png');
+ }
+
+ p {
+   position: fixed;
+ }
+</style>
+  <div></div>
+  <p>This test verifies document backgrounds are painted at correct
+  location when scroll offset is present.</p>
+<script>
+window.scrollTo(0, 100);
+</script>
diff --git a/third_party/WebKit/LayoutTests/paint/overflow/background-paint-into-scrolling-contents-layer-with-root-layer-scrolls-offset.html b/third_party/WebKit/LayoutTests/paint/overflow/background-paint-into-scrolling-contents-layer-with-root-layer-scrolls-offset.html
new file mode 100644
index 0000000..e6aad73
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/overflow/background-paint-into-scrolling-contents-layer-with-root-layer-scrolls-offset.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<style>
+  body {
+    height: 10000px;
+    margin: 0;
+  }
+  p {
+    position: fixed;
+  }
+</style>
+
+<body>
+  <p>This test verifies document backgrounds are painted at correct
+  location when scroll offset is present.</p>
+</body>
+
+<script>
+window.scrollTo(0, 100);
+document.body.style.background = "url('../../images/resources/lenna.png')";
+</script>
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/css/css2-system-fonts-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/css/css2-system-fonts-expected.txt
index 85d22fb..8d1c411 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/css/css2-system-fonts-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/css/css2-system-fonts-expected.txt
@@ -1,7 +1,7 @@
 This tests platform specific system font styles. If any of the styles appear in monospace the test fails.
-caption: normal normal normal normal 16px / normal Arial
-icon: normal normal normal normal 16px / normal Arial
-menu: normal normal normal normal 16px / normal Arial
-message-box: normal normal normal normal 16px / normal Arial
-small-caption: normal normal normal normal 16px / normal Arial
-status-bar: normal normal normal normal 16px / normal Arial
+caption: normal normal 400 normal 16px / normal Arial
+icon: normal normal 400 normal 16px / normal Arial
+menu: normal normal 400 normal 16px / normal Arial
+message-box: normal normal 400 normal 16px / normal Arial
+small-caption: normal normal 400 normal 16px / normal Arial
+status-bar: normal normal 400 normal 16px / normal Arial
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
index f81e0e0..203026e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
@@ -22,47 +22,18 @@
           "object": "LayoutTextControl INPUT id='root'",
           "rect": [0, 0, 64, 22],
           "reason": "full"
-        }
-      ]
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [3, 3],
-      "bounds": [60, 18]
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='inner-editor'",
-      "position": [0, 1],
-      "bounds": [60, 16],
-      "shouldFlattenTransform": false,
-      "drawsContent": true
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [60, 16],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [75, 16],
-      "drawsContent": true,
-      "paintInvalidations": [
+        },
         {
           "object": "LayoutBlockFlow DIV id='inner-editor'",
-          "rect": [73, 0, 1, 16],
-          "reason": "caret"
+          "rect": [3, 4, 60, 16],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [3, 4, 60, 16],
+          "reason": "subtree"
         }
       ]
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "bounds": [60, 16]
-    },
-    {
-      "name": "Horizontal Scrollbar Layer",
-      "position": [0, 16],
-      "bounds": [60, 0],
-      "drawsContent": true
     }
   ],
   "objectPaintInvalidations": [
@@ -71,8 +42,28 @@
       "reason": "subtree"
     },
     {
+      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "reason": "subtree"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "subtree"
+    },
+    {
+      "object": "HorizontalScrollbar",
+      "reason": "scroll control"
+    },
+    {
       "object": "Caret",
       "reason": "caret"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "subtree"
+    },
+    {
+      "object": "InlineTextBox 'test test test'",
+      "reason": "subtree"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
index 56cb65c..26bf4d9 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
@@ -10,42 +10,18 @@
           "object": "LayoutTextControl INPUT id='target'",
           "rect": [7, 7, 66, 24],
           "reason": "subtree"
-        }
-      ]
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='inner-editor'",
-      "position": [10, 11],
-      "bounds": [60, 16],
-      "shouldFlattenTransform": false,
-      "drawsContent": true
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [60, 16],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [75, 16],
-      "drawsContent": true,
-      "paintInvalidations": [
+        },
+        {
+          "object": "LayoutBlockFlow DIV id='inner-editor'",
+          "rect": [10, 11, 60, 16],
+          "reason": "subtree"
+        },
         {
           "object": "LayoutText #text",
-          "rect": [26, 0, 26, 16],
-          "reason": "selection"
+          "rect": [10, 11, 60, 16],
+          "reason": "subtree"
         }
       ]
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "bounds": [60, 16]
-    },
-    {
-      "name": "Horizontal Scrollbar Layer",
-      "position": [0, 16],
-      "bounds": [60, 0],
-      "drawsContent": true
     }
   ],
   "objectPaintInvalidations": [
@@ -63,15 +39,23 @@
     },
     {
       "object": "LayoutBlockFlow DIV id='inner-editor'",
-      "reason": "selection"
+      "reason": "subtree"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "subtree"
+    },
+    {
+      "object": "HorizontalScrollbar",
+      "reason": "scroll control"
     },
     {
       "object": "LayoutText #text",
-      "reason": "selection"
+      "reason": "subtree"
     },
     {
       "object": "InlineTextBox 'test test test'",
-      "reason": "selection"
+      "reason": "subtree"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
deleted file mode 100644
index 2490106..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
+++ /dev/null
@@ -1,79 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "drawsContent": true
-    },
-    {
-      "name": "LayoutTextControl INPUT id='root'",
-      "position": [5, 5],
-      "bounds": [47, 25],
-      "drawsContent": true,
-      "backgroundColor": "#FFFFFF",
-      "paintInvalidations": [
-        {
-          "object": "LayoutTextControl INPUT id='root'",
-          "rect": [0, 0, 47, 25],
-          "reason": "subtree"
-        },
-        {
-          "object": "LayoutTextControl INPUT id='root'",
-          "rect": [0, 0, 41, 19],
-          "reason": "full"
-        }
-      ]
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [5, 5],
-      "bounds": [37, 15]
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='inner-editor'",
-      "position": [1, 1],
-      "bounds": [35, 13],
-      "shouldFlattenTransform": false,
-      "drawsContent": true
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [35, 13],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [63, 13],
-      "drawsContent": true,
-      "paintInvalidations": [
-        {
-          "object": "LayoutBlockFlow DIV id='inner-editor'",
-          "rect": [61, 0, 1, 13],
-          "reason": "caret"
-        }
-      ]
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "bounds": [35, 13]
-    },
-    {
-      "name": "Horizontal Scrollbar Layer",
-      "position": [0, 13],
-      "bounds": [35, 0],
-      "drawsContent": true
-    }
-  ],
-  "objectPaintInvalidations": [
-    {
-      "object": "LayoutTextControl INPUT id='root'",
-      "reason": "subtree"
-    },
-    {
-      "object": "Caret",
-      "reason": "caret"
-    }
-  ]
-}
-
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
deleted file mode 100644
index cc030eb9..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
+++ /dev/null
@@ -1,78 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "drawsContent": true,
-      "paintInvalidations": [
-        {
-          "object": "LayoutTextControl INPUT id='target'",
-          "rect": [5, 5, 47, 25],
-          "reason": "subtree"
-        }
-      ]
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='inner-editor'",
-      "position": [11, 11],
-      "bounds": [35, 13],
-      "shouldFlattenTransform": false,
-      "drawsContent": true
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [35, 13],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [63, 13],
-      "drawsContent": true,
-      "paintInvalidations": [
-        {
-          "object": "LayoutText #text",
-          "rect": [22, 0, 21, 13],
-          "reason": "selection"
-        }
-      ]
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "bounds": [35, 13]
-    },
-    {
-      "name": "Horizontal Scrollbar Layer",
-      "position": [0, 13],
-      "bounds": [35, 0],
-      "drawsContent": true
-    }
-  ],
-  "objectPaintInvalidations": [
-    {
-      "object": "LayoutBlockFlow HTML",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutBlockFlow BODY",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutTextControl INPUT id='target'",
-      "reason": "subtree"
-    },
-    {
-      "object": "LayoutBlockFlow DIV id='inner-editor'",
-      "reason": "selection"
-    },
-    {
-      "object": "LayoutText #text",
-      "reason": "selection"
-    },
-    {
-      "object": "InlineTextBox 'test test test'",
-      "reason": "selection"
-    }
-  ]
-}
-
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
index b3e9fda..049aa0d 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
@@ -22,47 +22,18 @@
           "object": "LayoutTextControl INPUT id='root'",
           "rect": [0, 0, 48, 19],
           "reason": "full"
-        }
-      ]
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [5, 5],
-      "bounds": [44, 15]
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='inner-editor'",
-      "position": [1, 1],
-      "bounds": [42, 13],
-      "shouldFlattenTransform": false,
-      "drawsContent": true
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [42, 13],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [68, 13],
-      "drawsContent": true,
-      "paintInvalidations": [
+        },
         {
           "object": "LayoutBlockFlow DIV id='inner-editor'",
-          "rect": [66, 0, 1, 13],
-          "reason": "caret"
+          "rect": [6, 6, 42, 13],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [6, 6, 42, 13],
+          "reason": "subtree"
         }
       ]
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "bounds": [42, 13]
-    },
-    {
-      "name": "Horizontal Scrollbar Layer",
-      "position": [0, 13],
-      "bounds": [42, 0],
-      "drawsContent": true
     }
   ],
   "objectPaintInvalidations": [
@@ -71,8 +42,28 @@
       "reason": "subtree"
     },
     {
+      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "reason": "subtree"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "subtree"
+    },
+    {
+      "object": "HorizontalScrollbar",
+      "reason": "scroll control"
+    },
+    {
       "object": "Caret",
       "reason": "caret"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "subtree"
+    },
+    {
+      "object": "InlineTextBox 'test test test'",
+      "reason": "subtree"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
index 568024f..e4815bf 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
@@ -10,42 +10,18 @@
           "object": "LayoutTextControl INPUT id='target'",
           "rect": [5, 5, 54, 25],
           "reason": "subtree"
-        }
-      ]
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='inner-editor'",
-      "position": [11, 11],
-      "bounds": [42, 13],
-      "shouldFlattenTransform": false,
-      "drawsContent": true
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [42, 13],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [68, 13],
-      "drawsContent": true,
-      "paintInvalidations": [
+        },
+        {
+          "object": "LayoutBlockFlow DIV id='inner-editor'",
+          "rect": [11, 11, 42, 13],
+          "reason": "subtree"
+        },
         {
           "object": "LayoutText #text",
-          "rect": [23, 0, 24, 13],
-          "reason": "selection"
+          "rect": [11, 11, 42, 13],
+          "reason": "subtree"
         }
       ]
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "bounds": [42, 13]
-    },
-    {
-      "name": "Horizontal Scrollbar Layer",
-      "position": [0, 13],
-      "bounds": [42, 0],
-      "drawsContent": true
     }
   ],
   "objectPaintInvalidations": [
@@ -63,15 +39,23 @@
     },
     {
       "object": "LayoutBlockFlow DIV id='inner-editor'",
-      "reason": "selection"
+      "reason": "subtree"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "subtree"
+    },
+    {
+      "object": "HorizontalScrollbar",
+      "reason": "scroll control"
     },
     {
       "object": "LayoutText #text",
-      "reason": "selection"
+      "reason": "subtree"
     },
     {
       "object": "InlineTextBox 'test test test'",
-      "reason": "selection"
+      "reason": "subtree"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/css/css2-system-fonts-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/css/css2-system-fonts-expected.txt
index 03519a1..dd54fe8 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/css/css2-system-fonts-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/css/css2-system-fonts-expected.txt
@@ -1,7 +1,7 @@
 This tests platform specific system font styles. If any of the styles appear in monospace the test fails.
-caption: normal normal normal normal 13px / normal system-ui
-icon: normal normal normal normal 13px / normal system-ui
-menu: normal normal normal normal 13px / normal system-ui
-message-box: normal normal normal normal 13px / normal system-ui
-small-caption: normal normal normal normal 11px / normal system-ui
-status-bar: normal normal normal normal 10px / normal system-ui
+caption: normal normal 400 normal 13px / normal system-ui
+icon: normal normal 400 normal 13px / normal system-ui
+menu: normal normal 400 normal 13px / normal system-ui
+message-box: normal normal 400 normal 13px / normal system-ui
+small-caption: normal normal 400 normal 11px / normal system-ui
+status-bar: normal normal 400 normal 10px / normal system-ui
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
index 461ce523..54051b3 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
@@ -22,47 +22,18 @@
           "object": "LayoutTextControl INPUT id='root'",
           "rect": [0, 0, 41, 19],
           "reason": "full"
-        }
-      ]
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [5, 5],
-      "bounds": [37, 15]
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='inner-editor'",
-      "position": [1, 1],
-      "bounds": [35, 13],
-      "shouldFlattenTransform": false,
-      "drawsContent": true
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [35, 13],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [67, 13],
-      "drawsContent": true,
-      "paintInvalidations": [
+        },
         {
           "object": "LayoutBlockFlow DIV id='inner-editor'",
-          "rect": [65, 0, 1, 13],
-          "reason": "caret"
+          "rect": [6, 6, 35, 13],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [6, 6, 35, 13],
+          "reason": "subtree"
         }
       ]
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "bounds": [35, 13]
-    },
-    {
-      "name": "Horizontal Scrollbar Layer",
-      "position": [0, 13],
-      "bounds": [35, 0],
-      "drawsContent": true
     }
   ],
   "objectPaintInvalidations": [
@@ -71,8 +42,28 @@
       "reason": "subtree"
     },
     {
+      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "reason": "subtree"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "subtree"
+    },
+    {
+      "object": "HorizontalScrollbar",
+      "reason": "scroll control"
+    },
+    {
       "object": "Caret",
       "reason": "caret"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "subtree"
+    },
+    {
+      "object": "InlineTextBox 'test test test'",
+      "reason": "subtree"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
index eb78545ec..7143be3 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
@@ -10,42 +10,18 @@
           "object": "LayoutTextControl INPUT id='target'",
           "rect": [5, 5, 47, 25],
           "reason": "subtree"
-        }
-      ]
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='inner-editor'",
-      "position": [11, 11],
-      "bounds": [35, 13],
-      "shouldFlattenTransform": false,
-      "drawsContent": true
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [35, 13],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [67, 13],
-      "drawsContent": true,
-      "paintInvalidations": [
+        },
+        {
+          "object": "LayoutBlockFlow DIV id='inner-editor'",
+          "rect": [11, 11, 35, 13],
+          "reason": "subtree"
+        },
         {
           "object": "LayoutText #text",
-          "rect": [23, 0, 23, 13],
-          "reason": "selection"
+          "rect": [11, 11, 35, 13],
+          "reason": "subtree"
         }
       ]
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "bounds": [35, 13]
-    },
-    {
-      "name": "Horizontal Scrollbar Layer",
-      "position": [0, 13],
-      "bounds": [35, 0],
-      "drawsContent": true
     }
   ],
   "objectPaintInvalidations": [
@@ -63,15 +39,23 @@
     },
     {
       "object": "LayoutBlockFlow DIV id='inner-editor'",
-      "reason": "selection"
+      "reason": "subtree"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "subtree"
+    },
+    {
+      "object": "HorizontalScrollbar",
+      "reason": "scroll control"
     },
     {
       "object": "LayoutText #text",
-      "reason": "selection"
+      "reason": "subtree"
     },
     {
       "object": "InlineTextBox 'test test test'",
-      "reason": "selection"
+      "reason": "subtree"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/css/css2-system-fonts-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/css/css2-system-fonts-expected.txt
index ddadcdb..9777159d 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/css/css2-system-fonts-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/css/css2-system-fonts-expected.txt
@@ -1,7 +1,7 @@
 This tests platform specific system font styles. If any of the styles appear in monospace the test fails.
-caption: normal normal normal normal 16px / normal Arial
-icon: normal normal normal normal 16px / normal Arial
-menu: normal normal normal normal 12px / normal "Segoe UI"
-message-box: normal normal normal normal 16px / normal Arial
-small-caption: normal normal normal normal 12px / normal "Segoe UI"
-status-bar: normal normal normal normal 12px / normal "Segoe UI"
+caption: normal normal 400 normal 16px / normal Arial
+icon: normal normal 400 normal 16px / normal Arial
+menu: normal normal 400 normal 12px / normal "Segoe UI"
+message-box: normal normal 400 normal 16px / normal Arial
+small-caption: normal normal 400 normal 12px / normal "Segoe UI"
+status-bar: normal normal 400 normal 12px / normal "Segoe UI"
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
index 0aae2c6e5..72994ca 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/invalidate-caret-in-composited-scrolling-container-expected.txt
@@ -22,47 +22,18 @@
           "object": "LayoutTextControl INPUT id='root'",
           "rect": [0, 0, 68, 22],
           "reason": "full"
-        }
-      ]
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [3, 3],
-      "bounds": [64, 18]
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='inner-editor'",
-      "position": [0, 1],
-      "bounds": [64, 16],
-      "shouldFlattenTransform": false,
-      "drawsContent": true
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [64, 16],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [75, 16],
-      "drawsContent": true,
-      "paintInvalidations": [
+        },
         {
           "object": "LayoutBlockFlow DIV id='inner-editor'",
-          "rect": [73, 0, 1, 16],
-          "reason": "caret"
+          "rect": [3, 4, 64, 16],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [3, 4, 64, 16],
+          "reason": "subtree"
         }
       ]
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "bounds": [64, 16]
-    },
-    {
-      "name": "Horizontal Scrollbar Layer",
-      "position": [0, 16],
-      "bounds": [64, 0],
-      "drawsContent": true
     }
   ],
   "objectPaintInvalidations": [
@@ -71,8 +42,28 @@
       "reason": "subtree"
     },
     {
+      "object": "LayoutBlockFlow DIV id='inner-editor'",
+      "reason": "subtree"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "subtree"
+    },
+    {
+      "object": "HorizontalScrollbar",
+      "reason": "scroll control"
+    },
+    {
       "object": "Caret",
       "reason": "caret"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "subtree"
+    },
+    {
+      "object": "InlineTextBox 'test test test'",
+      "reason": "subtree"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
index 90a2bd6..a81a817 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
@@ -10,42 +10,18 @@
           "object": "LayoutTextControl INPUT id='target'",
           "rect": [7, 7, 70, 24],
           "reason": "subtree"
-        }
-      ]
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='inner-editor'",
-      "position": [10, 11],
-      "bounds": [64, 16],
-      "shouldFlattenTransform": false,
-      "drawsContent": true
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [64, 16],
-      "shouldFlattenTransform": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [75, 16],
-      "drawsContent": true,
-      "paintInvalidations": [
+        },
+        {
+          "object": "LayoutBlockFlow DIV id='inner-editor'",
+          "rect": [10, 11, 64, 16],
+          "reason": "subtree"
+        },
         {
           "object": "LayoutText #text",
-          "rect": [26, 0, 26, 16],
-          "reason": "selection"
+          "rect": [10, 11, 64, 16],
+          "reason": "subtree"
         }
       ]
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "bounds": [64, 16]
-    },
-    {
-      "name": "Horizontal Scrollbar Layer",
-      "position": [0, 16],
-      "bounds": [64, 0],
-      "drawsContent": true
     }
   ],
   "objectPaintInvalidations": [
@@ -63,15 +39,23 @@
     },
     {
       "object": "LayoutBlockFlow DIV id='inner-editor'",
-      "reason": "selection"
+      "reason": "subtree"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "subtree"
+    },
+    {
+      "object": "HorizontalScrollbar",
+      "reason": "scroll control"
     },
     {
       "object": "LayoutText #text",
-      "reason": "selection"
+      "reason": "subtree"
     },
     {
       "object": "InlineTextBox 'test test test'",
-      "reason": "selection"
+      "reason": "subtree"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/svg/css/getComputedStyle-listing-expected.txt b/third_party/WebKit/LayoutTests/svg/css/getComputedStyle-listing-expected.txt
index 49c9a86..ef488dd 100644
--- a/third_party/WebKit/LayoutTests/svg/css/getComputedStyle-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/svg/css/getComputedStyle-listing-expected.txt
@@ -161,7 +161,7 @@
 font-variant-caps: normal
 font-variant-ligatures: normal
 font-variant-numeric: normal
-font-weight: normal
+font-weight: 400
 grid-auto-columns: auto
 grid-auto-flow: row
 grid-auto-rows: auto
@@ -286,7 +286,7 @@
 transition-timing-function: ease
 translate: none
 unicode-bidi: normal
-user-select: text
+user-select: auto
 vector-effect: none
 vertical-align: baseline
 visibility: visible
diff --git a/third_party/WebKit/LayoutTests/svg/parser/foreign-object-case-sensitivity-expected.txt b/third_party/WebKit/LayoutTests/svg/parser/foreign-object-case-sensitivity-expected.txt
index 824500a..5e50e1c9 100644
--- a/third_party/WebKit/LayoutTests/svg/parser/foreign-object-case-sensitivity-expected.txt
+++ b/third_party/WebKit/LayoutTests/svg/parser/foreign-object-case-sensitivity-expected.txt
@@ -39,13 +39,13 @@
 (Should have matched case-sensitively for svg elements according to the html spec).
 
 PASS getComputedStyle(fo1).color is "rgb(0, 128, 0)"
-PASS getComputedStyle(fo1).fontWeight is "bold"
+PASS getComputedStyle(fo1).fontWeight is "700"
 PASS getComputedStyle(fo2).color is "rgb(0, 128, 0)"
-PASS getComputedStyle(fo2).fontWeight is "bold"
+PASS getComputedStyle(fo2).fontWeight is "700"
 PASS getComputedStyle(fo3).color is "rgb(0, 128, 0)"
-PASS getComputedStyle(fo3).fontWeight is "bold"
+PASS getComputedStyle(fo3).fontWeight is "700"
 PASS getComputedStyle(fo4).color is "rgb(0, 128, 0)"
-PASS getComputedStyle(fo4).fontWeight is "bold"
+PASS getComputedStyle(fo4).fontWeight is "700"
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/svg/parser/foreign-object-case-sensitivity.html b/third_party/WebKit/LayoutTests/svg/parser/foreign-object-case-sensitivity.html
index f60f1266..73d64160 100644
--- a/third_party/WebKit/LayoutTests/svg/parser/foreign-object-case-sensitivity.html
+++ b/third_party/WebKit/LayoutTests/svg/parser/foreign-object-case-sensitivity.html
@@ -69,9 +69,9 @@
     shouldBeEqualToString("getComputedStyle("+id+").fontWeight", fontWeight);
 }
 
-testComputedStyle("fo1", "rgb(0, 128, 0)", "bold");
-testComputedStyle("fo2", "rgb(0, 128, 0)", "bold");
-testComputedStyle("fo3", "rgb(0, 128, 0)", "bold");
-testComputedStyle("fo4", "rgb(0, 128, 0)", "bold");
+testComputedStyle("fo1", "rgb(0, 128, 0)", "700");
+testComputedStyle("fo2", "rgb(0, 128, 0)", "700");
+testComputedStyle("fo3", "rgb(0, 128, 0)", "700");
+testComputedStyle("fo4", "rgb(0, 128, 0)", "700");
 
 </script>
diff --git a/third_party/WebKit/Source/core/animation/CSSFontWeightInterpolationType.cpp b/third_party/WebKit/Source/core/animation/CSSFontWeightInterpolationType.cpp
index c386ecb1..fdacbc0 100644
--- a/third_party/WebKit/Source/core/animation/CSSFontWeightInterpolationType.cpp
+++ b/third_party/WebKit/Source/core/animation/CSSFontWeightInterpolationType.cpp
@@ -65,15 +65,20 @@
     const CSSValue& value,
     const StyleResolverState* state,
     ConversionCheckers& conversion_checkers) const {
-  if (!value.IsIdentifierValue())
-    return nullptr;
+  if (value.IsPrimitiveValue()) {
+    return CreateFontWeightValue(
+        FontSelectionValue(ToCSSPrimitiveValue(value).GetFloatValue()));
+  }
 
+  CHECK(value.IsIdentifierValue());
   const CSSIdentifierValue& identifier_value = ToCSSIdentifierValue(value);
   CSSValueID keyword = identifier_value.GetValueID();
 
   switch (keyword) {
     case CSSValueInvalid:
       return nullptr;
+    case CSSValueNormal:
+      return CreateFontWeightValue(NormalWeightValue());
 
     case CSSValueBolder:
     case CSSValueLighter: {
@@ -82,15 +87,16 @@
           state->ParentStyle()->GetFontWeight();
       conversion_checkers.push_back(
           InheritedFontWeightChecker::Create(inherited_font_weight));
-      if (keyword == CSSValueBolder)
+      if (keyword == CSSValueBolder) {
         return CreateFontWeightValue(
             FontDescription::BolderWeight(inherited_font_weight));
+      }
       return CreateFontWeightValue(
           FontDescription::LighterWeight(inherited_font_weight));
     }
     default:
-      return CreateFontWeightValue(
-          identifier_value.ConvertTo<FontSelectionValueWeight>());
+      NOTREACHED();
+      return nullptr;
   }
 }
 
diff --git a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
index f0da176..d8b6042 100644
--- a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
+++ b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
@@ -941,81 +941,6 @@
 }
 
 template <>
-inline CSSIdentifierValue::CSSIdentifierValue(FontSelectionValueWeight weight)
-    : CSSValue(kIdentifierClass) {
-  if (weight == FontSelectionValue(900)) {
-    value_id_ = CSSValue900;
-    return;
-  }
-  if (weight == FontSelectionValue(800)) {
-    value_id_ = CSSValue800;
-    return;
-  }
-  if (weight == FontSelectionValue(700)) {
-    value_id_ = CSSValueBold;
-    return;
-  }
-  if (weight == FontSelectionValue(600)) {
-    value_id_ = CSSValue600;
-    return;
-  }
-  if (weight == FontSelectionValue(500)) {
-    value_id_ = CSSValue500;
-    return;
-  }
-  if (weight == FontSelectionValue(400)) {
-    value_id_ = CSSValueNormal;
-    return;
-  }
-  if (weight == FontSelectionValue(300)) {
-    value_id_ = CSSValue300;
-    return;
-  }
-  if (weight == FontSelectionValue(200)) {
-    value_id_ = CSSValue200;
-    return;
-  }
-  if (weight == FontSelectionValue(100)) {
-    value_id_ = CSSValue100;
-    return;
-  }
-
-  NOTREACHED();
-  value_id_ = CSSValueNormal;
-}
-
-template <>
-inline FontSelectionValueWeight CSSIdentifierValue::ConvertTo() const {
-  switch (value_id_) {
-    case CSSValue900:
-      return FontSelectionValueWeight(900);
-    case CSSValue800:
-      return FontSelectionValueWeight(800);
-    case CSSValueBold:
-    case CSSValue700:
-      return BoldWeightValue();
-    case CSSValue600:
-      return FontSelectionValueWeight(600);
-    case CSSValue500:
-      return FontSelectionValueWeight(500);
-    case CSSValue400:
-    case CSSValueNormal:
-      return NormalWeightValue();
-    case CSSValue300:
-      return FontSelectionValueWeight(300);
-    case CSSValue200:
-      return FontSelectionValueWeight(200);
-    case CSSValue100:
-      return FontSelectionValueWeight(100);
-    default:
-      break;
-  }
-
-  NOTREACHED();
-  return NormalWeightValue();
-}
-
-template <>
 inline CSSIdentifierValue::CSSIdentifierValue(FontSelectionValueStyle italic)
     : CSSValue(kIdentifierClass) {
   if (italic == NormalSlopeValue()) {
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.json5 b/third_party/WebKit/Source/core/css/CSSProperties.json5
index c02a816..b918f7f 100644
--- a/third_party/WebKit/Source/core/css/CSSProperties.json5
+++ b/third_party/WebKit/Source/core/css/CSSProperties.json5
@@ -525,7 +525,6 @@
       interpolable: true,
       name_for_methods: "Weight",
       priority: "High",
-      type_name: "FontSelectionValueWeight",
     },
     {
       name: "font-feature-settings",
@@ -3355,8 +3354,8 @@
       name: "user-select",
       inherited: true,
       field_template: "keyword",
-      keywords: ["none", "text", "all"],
-      default_value: "text",
+      keywords: ["auto", "none", "text", "all"],
+      default_value: "auto",
       field_group: "rare-inherited",
     },
     {
diff --git a/third_party/WebKit/Source/core/css/CSSValueIDMappings.h b/third_party/WebKit/Source/core/css/CSSValueIDMappings.h
index b063980..99a78346 100644
--- a/third_party/WebKit/Source/core/css/CSSValueIDMappings.h
+++ b/third_party/WebKit/Source/core/css/CSSValueIDMappings.h
@@ -122,7 +122,7 @@
 template <>
 inline EUserSelect CssValueIDToPlatformEnum(CSSValueID v) {
   if (v == CSSValueAuto)
-    return EUserSelect::kText;
+    return EUserSelect::kAuto;
   return detail::cssValueIDToPlatformEnumGenerated<EUserSelect>(v);
 }
 
diff --git a/third_party/WebKit/Source/core/css/CSSValueKeywords.json5 b/third_party/WebKit/Source/core/css/CSSValueKeywords.json5
index d562ab38..d52fccc6 100644
--- a/third_party/WebKit/Source/core/css/CSSValueKeywords.json5
+++ b/third_party/WebKit/Source/core/css/CSSValueKeywords.json5
@@ -95,15 +95,6 @@
     "bold",
     "bolder",
     "lighter",
-    "100",
-    "200",
-    "300",
-    "400",
-    "500",
-    "600",
-    "700",
-    "800",
-    "900",
 
     //
     // font-stretch
diff --git a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
index eb52947..b191c9b 100644
--- a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
+++ b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
@@ -766,9 +766,9 @@
       FontSelectionValueStyle(style.GetFontDescription().Style()));
 }
 
-static CSSIdentifierValue* ValueForFontWeight(const ComputedStyle& style) {
-  return CSSIdentifierValue::Create(
-      FontSelectionValueWeight(style.GetFontDescription().Weight()));
+static CSSPrimitiveValue* ValueForFontWeight(const ComputedStyle& style) {
+  return CSSPrimitiveValue::Create(style.GetFontDescription().Weight(),
+                                   CSSPrimitiveValue::UnitType::kNumber);
 }
 
 static CSSIdentifierValue* ValueForFontVariantCaps(const ComputedStyle& style) {
diff --git a/third_party/WebKit/Source/core/css/FontFace.cpp b/third_party/WebKit/Source/core/css/FontFace.cpp
index 6015032..10a41d49 100644
--- a/third_party/WebKit/Source/core/css/FontFace.cpp
+++ b/third_party/WebKit/Source/core/css/FontFace.cpp
@@ -584,44 +584,6 @@
   if (weight_) {
     if (weight_->IsIdentifierValue()) {
       switch (ToCSSIdentifierValue(weight_.Get())->GetValueID()) {
-        case CSSValue100:
-          capabilities.weight = {FontSelectionValue(100),
-                                 FontSelectionValue(100)};
-          break;
-        case CSSValue200:
-          capabilities.weight = {FontSelectionValue(200),
-                                 FontSelectionValue(200)};
-          break;
-        case CSSValue300:
-          capabilities.weight = {FontSelectionValue(300),
-                                 FontSelectionValue(300)};
-          break;
-        case CSSValueNormal:
-        case CSSValue400:
-          capabilities.weight = {FontSelectionValue(400),
-                                 FontSelectionValue(400)};
-          break;
-        case CSSValue500:
-          capabilities.weight = {FontSelectionValue(500),
-                                 FontSelectionValue(500)};
-          break;
-        case CSSValue600:
-          capabilities.weight = {FontSelectionValue(600),
-                                 FontSelectionValue(600)};
-          break;
-        case CSSValueBold:
-        case CSSValue700:
-          capabilities.weight = {FontSelectionValue(700),
-                                 FontSelectionValue(700)};
-          break;
-        case CSSValue800:
-          capabilities.weight = {FontSelectionValue(800),
-                                 FontSelectionValue(800)};
-          break;
-        case CSSValue900:
-          capabilities.weight = {FontSelectionValue(900),
-                                 FontSelectionValue(900)};
-          break;
         // Although 'lighter' and 'bolder' are valid keywords for
         // font-weights, they are invalid inside font-face rules so they are
         // ignored. Reference:
@@ -629,6 +591,12 @@
         case CSSValueLighter:
         case CSSValueBolder:
           break;
+        case CSSValueNormal:
+          capabilities.weight = {NormalWeightValue(), NormalWeightValue()};
+          break;
+        case CSSValueBold:
+          capabilities.weight = {BoldWeightValue(), BoldWeightValue()};
+          break;
         default:
           NOTREACHED();
           break;
diff --git a/third_party/WebKit/Source/core/css/FontFaceCacheTest.cpp b/third_party/WebKit/Source/core/css/FontFaceCacheTest.cpp
index fa9666d..e29eb90 100644
--- a/third_party/WebKit/Source/core/css/FontFaceCacheTest.cpp
+++ b/third_party/WebKit/Source/core/css/FontFaceCacheTest.cpp
@@ -27,9 +27,6 @@
   void SetUp() override;
 
   void ClearCache();
-  void AppendTestFaceForCapabilities(const CSSValueID& stretch,
-                                     const CSSValueID& style,
-                                     const CSSValueID& weight);
   void AppendTestFaceForCapabilities(const CSSValue& stretch,
                                      const CSSValue& style,
                                      const CSSValue& weight);
@@ -55,16 +52,6 @@
   cache_.ClearAll();
 }
 
-void FontFaceCacheTest::AppendTestFaceForCapabilities(
-    const CSSValueID& stretch,
-    const CSSValueID& style,
-    const CSSValueID& weight) {
-  CSSIdentifierValue* stretch_value = CSSIdentifierValue::Create(stretch);
-  CSSIdentifierValue* weight_value = CSSIdentifierValue::Create(style);
-  CSSIdentifierValue* style_value = CSSIdentifierValue::Create(weight);
-  AppendTestFaceForCapabilities(*stretch_value, *style_value, *weight_value);
-}
-
 void FontFaceCacheTest::AppendTestFaceForCapabilities(const CSSValue& stretch,
                                                       const CSSValue& style,
                                                       const CSSValue& weight) {
@@ -106,18 +93,33 @@
 }
 
 TEST_F(FontFaceCacheTest, Instantiate) {
-  AppendTestFaceForCapabilities(CSSValueUltraExpanded, CSSValueBold,
-                                CSSValueItalic);
-  AppendTestFaceForCapabilities(CSSValueCondensed, CSSValueBold,
-                                CSSValueItalic);
+  CSSIdentifierValue* stretch_value_expanded =
+      CSSIdentifierValue::Create(CSSValueUltraExpanded);
+  CSSIdentifierValue* stretch_value_condensed =
+      CSSIdentifierValue::Create(CSSValueCondensed);
+  CSSPrimitiveValue* weight_value = CSSPrimitiveValue::Create(
+      BoldWeightValue(), CSSPrimitiveValue::UnitType::kNumber);
+  CSSIdentifierValue* style_value = CSSIdentifierValue::Create(CSSValueItalic);
+
+  AppendTestFaceForCapabilities(*stretch_value_expanded, *style_value,
+                                *weight_value);
+  AppendTestFaceForCapabilities(*stretch_value_condensed, *style_value,
+                                *weight_value);
   ASSERT_EQ(cache_.GetNumSegmentedFacesForTesting(), 2ul);
 }
 
 TEST_F(FontFaceCacheTest, SimpleWidthMatch) {
-  AppendTestFaceForCapabilities(CSSValueUltraExpanded, CSSValueNormal,
-                                CSSValueNormal);
-  AppendTestFaceForCapabilities(CSSValueCondensed, CSSValueNormal,
-                                CSSValueNormal);
+  CSSIdentifierValue* stretch_value_expanded =
+      CSSIdentifierValue::Create(CSSValueUltraExpanded);
+  CSSIdentifierValue* stretch_value_condensed =
+      CSSIdentifierValue::Create(CSSValueCondensed);
+  CSSPrimitiveValue* weight_value = CSSPrimitiveValue::Create(
+      NormalWeightValue(), CSSPrimitiveValue::UnitType::kNumber);
+  CSSIdentifierValue* style_value = CSSIdentifierValue::Create(CSSValueNormal);
+  AppendTestFaceForCapabilities(*stretch_value_expanded, *style_value,
+                                *weight_value);
+  AppendTestFaceForCapabilities(*stretch_value_condensed, *style_value,
+                                *weight_value);
   ASSERT_EQ(cache_.GetNumSegmentedFacesForTesting(), 2ul);
 
   const FontDescription& description_condensed = FontDescriptionForRequest(
@@ -140,12 +142,12 @@
   CSSIdentifierValue* stretch_value =
       CSSIdentifierValue::Create(CSSValueNormal);
   CSSIdentifierValue* style_value = CSSIdentifierValue::Create(CSSValueNormal);
-  CSSIdentifierValue* weight_value_black =
-      CSSIdentifierValue::Create(CSSValue900);
+  CSSPrimitiveValue* weight_value_black =
+      CSSPrimitiveValue::Create(900, CSSPrimitiveValue::UnitType::kNumber);
   AppendTestFaceForCapabilities(*stretch_value, *style_value,
                                 *weight_value_black);
-  CSSIdentifierValue* weight_value_thin =
-      CSSIdentifierValue::Create(CSSValue100);
+  CSSPrimitiveValue* weight_value_thin =
+      CSSPrimitiveValue::Create(100, CSSPrimitiveValue::UnitType::kNumber);
   AppendTestFaceForCapabilities(*stretch_value, *style_value,
                                 *weight_value_thin);
   ASSERT_EQ(cache_.GetNumSegmentedFacesForTesting(), 2ul);
@@ -209,8 +211,9 @@
                         CSSIdentifierValue::Create(CSSValueExpanded)};
   CSSValue* slopes[] = {CSSIdentifierValue::Create(CSSValueNormal),
                         CSSIdentifierValue::Create(CSSValueItalic)};
-  CSSValue* weights[] = {CSSIdentifierValue::Create(CSSValue100),
-                         CSSIdentifierValue::Create(CSSValue900)};
+  CSSValue* weights[] = {
+      CSSPrimitiveValue::Create(100, CSSPrimitiveValue::UnitType::kNumber),
+      CSSPrimitiveValue::Create(900, CSSPrimitiveValue::UnitType::kNumber)};
 
   Vector<FontSelectionValue> width_choices = {CondensedWidthValue(),
                                               ExpandedWidthValue()};
diff --git a/third_party/WebKit/Source/core/css/html.css b/third_party/WebKit/Source/core/css/html.css
index 9e38e56..5a16e5d 100644
--- a/third_party/WebKit/Source/core/css/html.css
+++ b/third_party/WebKit/Source/core/css/html.css
@@ -423,7 +423,6 @@
     background-color: white;
     border: 2px inset;
     -webkit-rtl-ordering: logical;
-    -webkit-user-select: text;
     cursor: auto;
 }
 
@@ -475,7 +474,6 @@
     cursor: default;
     flex: none;
     align-self: stretch;
-    -webkit-user-select: none;
     -webkit-user-modify: read-only !important;
     opacity: 0;
     pointer-events: none;
@@ -495,7 +493,6 @@
     background-color: white;
     border: 1px solid;
     -webkit-rtl-ordering: logical;
-    -webkit-user-select: text;
     flex-direction: column;
     resize: auto;
     cursor: auto;
@@ -760,7 +757,6 @@
     overflow-x: hidden;
     overflow-y: scroll;
     vertical-align: text-bottom;
-    -webkit-user-select: none;
     white-space: nowrap;
 }
 
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.cpp
index e9b9c59..f88dac5 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.cpp
@@ -95,20 +95,18 @@
   return builder.ToString();
 }
 
-CSSIdentifierValue* CSSPropertyFontUtils::ConsumeFontWeight(
-    CSSParserTokenRange& range) {
+CSSValue* CSSPropertyFontUtils::ConsumeFontWeight(CSSParserTokenRange& range) {
   const CSSParserToken& token = range.Peek();
   if (token.Id() >= CSSValueNormal && token.Id() <= CSSValueLighter)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
-  if (token.GetType() != kNumberToken ||
-      token.GetNumericValueType() != kIntegerValueType)
+  if (token.GetType() != kNumberToken)
     return nullptr;
-  int weight = static_cast<int>(token.NumericValue());
-  if ((weight % 100) || weight < 100 || weight > 900)
+  float weight = token.NumericValue();
+  if (weight < 1 || weight > 1000)
     return nullptr;
   range.ConsumeIncludingWhitespace();
-  return CSSIdentifierValue::Create(
-      static_cast<CSSValueID>(CSSValue100 + weight / 100 - 1));
+  return CSSPrimitiveValue::Create(weight,
+                                   CSSPrimitiveValue::UnitType::kNumber);
 }
 
 // TODO(bugsnash): move this to the FontFeatureSettings API when it is no longer
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.h b/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.h
index 26fd14b0..b9f42166 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.h
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.h
@@ -33,7 +33,7 @@
   static CSSValue* ConsumeFamilyName(CSSParserTokenRange&);
   static String ConcatenateFamilyName(CSSParserTokenRange&);
 
-  static CSSIdentifierValue* ConsumeFontWeight(CSSParserTokenRange&);
+  static CSSValue* ConsumeFontWeight(CSSParserTokenRange&);
 
   static CSSValue* ConsumeFontFeatureSettings(CSSParserTokenRange&);
   static CSSFontFeatureValue* ConsumeFontFeatureTag(CSSParserTokenRange&);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIFont.cpp b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIFont.cpp
index 8bf0c5564..2b59188 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIFont.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIFont.cpp
@@ -28,7 +28,7 @@
     return false;
 
   FontSelectionValueStyle font_style = NormalSlopeValue();
-  FontSelectionValueWeight font_weight = NormalWeightValue();
+  FontSelectionValue font_weight = NormalWeightValue();
   float font_size = 0;
   AtomicString font_family;
   LayoutTheme::GetTheme().SystemFont(system_font_id, font_style, font_weight,
@@ -42,8 +42,10 @@
       properties);
   CSSPropertyParserHelpers::AddProperty(
       CSSPropertyFontWeight, CSSPropertyFont,
-      *CSSIdentifierValue::Create(font_weight), important,
-      CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
+      *CSSPrimitiveValue::Create(font_weight,
+                                 CSSPrimitiveValue::UnitType::kNumber),
+      important, CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit,
+      properties);
   CSSPropertyParserHelpers::AddProperty(
       CSSPropertyFontSize, CSSPropertyFont,
       *CSSPrimitiveValue::Create(font_size,
@@ -94,7 +96,7 @@
   // Optional font-style, font-variant, font-stretch and font-weight.
   CSSIdentifierValue* font_style = nullptr;
   CSSIdentifierValue* font_variant_caps = nullptr;
-  CSSIdentifierValue* font_weight = nullptr;
+  CSSValue* font_weight = nullptr;
   CSSIdentifierValue* font_stretch = nullptr;
   while (!range.AtEnd()) {
     CSSValueID id = range.Peek().Id();
diff --git a/third_party/WebKit/Source/core/css/resolver/FontBuilder.h b/third_party/WebKit/Source/core/css/resolver/FontBuilder.h
index 44bf60db..29142d7d 100644
--- a/third_party/WebKit/Source/core/css/resolver/FontBuilder.h
+++ b/third_party/WebKit/Source/core/css/resolver/FontBuilder.h
@@ -114,10 +114,8 @@
   static FontSelectionValueStretch InitialStretch() {
     return NormalWidthValue();
   }
-  static FontSelectionValueWeight InitialWeight() {
-    return NormalWeightValue();
-  }
   static FontSelectionValueStyle InitialStyle() { return NormalSlopeValue(); }
+  static FontSelectionValue InitialWeight() { return NormalWeightValue(); }
 
  private:
   void SetFamilyDescription(FontDescription&,
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
index b8c7dd20..8863426 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
@@ -384,23 +384,36 @@
   }
 }
 
-FontSelectionValueWeight StyleBuilderConverterBase::ConvertFontWeight(
+FontSelectionValue StyleBuilderConverterBase::ConvertFontWeight(
     const CSSValue& value,
     FontSelectionValue parent_weight) {
-  const CSSIdentifierValue& identifier_value = ToCSSIdentifierValue(value);
-  switch (identifier_value.GetValueID()) {
-    case CSSValueBolder:
-      return FontSelectionValueWeight(
-          FontDescription::BolderWeight(parent_weight));
-    case CSSValueLighter:
-      return FontSelectionValueWeight(
-          FontDescription::LighterWeight(parent_weight));
-    default:
-      return identifier_value.ConvertTo<FontSelectionValueWeight>();
+  if (value.IsPrimitiveValue()) {
+    const CSSPrimitiveValue& primitive_value = ToCSSPrimitiveValue(value);
+    if (primitive_value.IsNumber())
+      return clampTo<FontSelectionValue>(primitive_value.GetFloatValue());
   }
+
+  if (value.IsIdentifierValue()) {
+    const CSSIdentifierValue& identifier_value = ToCSSIdentifierValue(value);
+    switch (identifier_value.GetValueID()) {
+      case CSSValueNormal:
+        return NormalWeightValue();
+      case CSSValueBold:
+        return BoldWeightValue();
+      case CSSValueBolder:
+        return FontDescription::BolderWeight(parent_weight);
+      case CSSValueLighter:
+        return FontDescription::LighterWeight(parent_weight);
+      default:
+        NOTREACHED();
+        return NormalWeightValue();
+    }
+  }
+  NOTREACHED();
+  return NormalWeightValue();
 }
 
-FontSelectionValueWeight StyleBuilderConverter::ConvertFontWeight(
+FontSelectionValue StyleBuilderConverter::ConvertFontWeight(
     StyleResolverState& state,
     const CSSValue& value) {
   return StyleBuilderConverterBase::ConvertFontWeight(
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.h b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.h
index 0d96fd3..dfa0995 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.h
+++ b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.h
@@ -58,8 +58,8 @@
   STATIC_ONLY(StyleBuilderConverterBase);
 
  public:
-  static FontSelectionValueWeight ConvertFontWeight(const CSSValue&,
-                                                    FontSelectionValue);
+  static FontSelectionValue ConvertFontWeight(const CSSValue&,
+                                              FontSelectionValue);
   static FontDescription::FontVariantCaps ConvertFontVariantCaps(
       const CSSValue&);
   static FontDescription::FamilyDescription ConvertFontFamily(
@@ -106,8 +106,9 @@
   static FontDescription::Size ConvertFontSize(StyleResolverState&,
                                                const CSSValue&);
   static float ConvertFontSizeAdjust(StyleResolverState&, const CSSValue&);
-  static FontSelectionValueWeight ConvertFontWeight(StyleResolverState&,
-                                                    const CSSValue&);
+  static FontSelectionValue ConvertFontWeight(StyleResolverState&,
+                                              const CSSValue&);
+
   static FontDescription::FontVariantCaps ConvertFontVariantCaps(
       StyleResolverState&,
       const CSSValue&);
diff --git a/third_party/WebKit/Source/core/dom/Node.cpp b/third_party/WebKit/Source/core/dom/Node.cpp
index 7b60b68..837b7b7 100644
--- a/third_party/WebKit/Source/core/dom/Node.cpp
+++ b/third_party/WebKit/Source/core/dom/Node.cpp
@@ -1069,12 +1069,13 @@
 
   if (GetLayoutObject()) {
     const ComputedStyle& style = GetLayoutObject()->StyleRef();
-    // We allow selections to begin within an element that has
-    // -webkit-user-select: none set, but if the element is draggable then
-    // dragging should take priority over selection.
-    if (style.UserDrag() == EUserDrag::kElement &&
-        style.UserSelect() == EUserSelect::kNone)
+    if (style.UserSelect() == EUserSelect::kNone)
       return false;
+    // We allow selections to begin within |user-select: text| sub trees
+    // but not if the element is draggable.
+    if (style.UserDrag() != EUserDrag::kElement &&
+        style.UserSelect() == EUserSelect::kText)
+      return true;
   }
   ContainerNode* parent = FlatTreeTraversal::Parent(*this);
   return parent ? parent->CanStartSelection() : true;
diff --git a/third_party/WebKit/Source/core/editing/EditingStyle.cpp b/third_party/WebKit/Source/core/editing/EditingStyle.cpp
index d730017..f48186c 100644
--- a/third_party/WebKit/Source/core/editing/EditingStyle.cpp
+++ b/third_party/WebKit/Source/core/editing/EditingStyle.cpp
@@ -1550,12 +1550,28 @@
   }
 }
 
+static bool GetPrimitiveValueNumber(StylePropertySet* style,
+                                    CSSPropertyID property_id,
+                                    float& number) {
+  if (!style)
+    return false;
+  const CSSValue* value = style->GetPropertyCSSValue(property_id);
+  if (!value || !value->IsPrimitiveValue())
+    return false;
+  number = ToCSSPrimitiveValue(value)->GetFloatValue();
+  return true;
+}
+
 void StyleChange::ExtractTextStyles(Document* document,
                                     MutableStylePropertySet* style,
                                     bool is_monospace_font) {
   DCHECK(style);
 
-  if (GetIdentifierValue(style, CSSPropertyFontWeight) == CSSValueBold) {
+  float weight = 0;
+  bool is_number =
+      GetPrimitiveValueNumber(style, CSSPropertyFontWeight, weight);
+  if (GetIdentifierValue(style, CSSPropertyFontWeight) == CSSValueBold ||
+      (is_number && weight >= BoldThreshold())) {
     style->RemoveProperty(CSSPropertyFontWeight);
     apply_bold_ = true;
   }
@@ -1644,38 +1660,30 @@
 }
 
 static bool FontWeightIsBold(const CSSValue* font_weight) {
-  if (!font_weight->IsIdentifierValue())
-    return false;
+  if (font_weight->IsIdentifierValue()) {
+    // Because b tag can only bold text, there are only two states in plain
+    // html: bold and not bold. Collapse all other values to either one of these
+    // two states for editing purposes.
 
-  // Because b tag can only bold text, there are only two states in plain html:
-  // bold and not bold. Collapse all other values to either one of these two
-  // states for editing purposes.
-  switch (ToCSSIdentifierValue(font_weight)->GetValueID()) {
-    case CSSValue100:
-    case CSSValue200:
-    case CSSValue300:
-    case CSSValue400:
-    case CSSValue500:
-    case CSSValueNormal:
-      return false;
-    case CSSValueBold:
-    case CSSValue600:
-    case CSSValue700:
-    case CSSValue800:
-    case CSSValue900:
-      return true;
-    default:
-      break;
+    switch (ToCSSIdentifierValue(font_weight)->GetValueID()) {
+      case CSSValueNormal:
+        return false;
+      case CSSValueBold:
+        return true;
+      default:
+        break;
+    }
   }
 
-  NOTREACHED();  // For CSSValueBolder and CSSValueLighter
-  return false;
+  CHECK(font_weight->IsPrimitiveValue());
+  CHECK(ToCSSPrimitiveValue(font_weight)->IsNumber());
+  return ToCSSPrimitiveValue(font_weight)->GetFloatValue() >= BoldThreshold();
 }
 
 static bool FontWeightNeedsResolving(const CSSValue* font_weight) {
-  if (!font_weight->IsIdentifierValue())
-    return true;
-
+  if (font_weight->IsPrimitiveValue())
+    return false;
+  CHECK(font_weight->IsIdentifierValue());
   const CSSValueID value = ToCSSIdentifierValue(font_weight)->GetValueID();
   return value == CSSValueLighter || value == CSSValueBolder;
 }
diff --git a/third_party/WebKit/Source/core/editing/EditingTestBase.h b/third_party/WebKit/Source/core/editing/EditingTestBase.h
index 1dfc3e0b..6d11ecb 100644
--- a/third_party/WebKit/Source/core/editing/EditingTestBase.h
+++ b/third_party/WebKit/Source/core/editing/EditingTestBase.h
@@ -20,6 +20,12 @@
 class EditingTestBase : public ::testing::Test {
   USING_FAST_MALLOC(EditingTestBase);
 
+ public:
+  static ShadowRoot* CreateShadowRootForElementWithIDAndSetInnerHTML(
+      TreeScope&,
+      const char* host_element_id,
+      const char* shadow_root_content);
+
  protected:
   EditingTestBase();
   ~EditingTestBase() override;
@@ -33,11 +39,6 @@
   LocalFrame& GetFrame() const;
   FrameSelection& Selection() const;
 
-  static ShadowRoot* CreateShadowRootForElementWithIDAndSetInnerHTML(
-      TreeScope&,
-      const char* host_element_id,
-      const char* shadow_root_content);
-
   void SetBodyContent(const std::string&);
   ShadowRoot* SetShadowContent(const char* shadow_content,
                                const char* shadow_host_id);
diff --git a/third_party/WebKit/Source/core/editing/OWNERS b/third_party/WebKit/Source/core/editing/OWNERS
index 3b26aa1f1..aebb74d 100644
--- a/third_party/WebKit/Source/core/editing/OWNERS
+++ b/third_party/WebKit/Source/core/editing/OWNERS
@@ -1,3 +1,4 @@
+changwan@chromium.org # for IME related changes
 ojan@chromium.org
 yosin@chromium.org
 xiaochengh@chromium.org
diff --git a/third_party/WebKit/Source/core/exported/WebViewTest.cpp b/third_party/WebKit/Source/core/exported/WebViewTest.cpp
index 6800708..f1d2fbb 100644
--- a/third_party/WebKit/Source/core/exported/WebViewTest.cpp
+++ b/third_party/WebKit/Source/core/exported/WebViewTest.cpp
@@ -3087,7 +3087,7 @@
       "solid skyblue; float: left; width: 190px; height: 30px; "
       "color: rgb(0, 0, 0); font-family: myahem; font-size: 8px; font-style: "
       "normal; font-variant-ligatures: normal; font-variant-caps: normal; "
-      "font-weight: normal; letter-spacing: "
+      "font-weight: 400; letter-spacing: "
       "normal; orphans: 2; text-align: start; "
       "text-indent: 0px; text-transform: none; white-space: normal; widows: "
       "2; word-spacing: 0px; -webkit-text-stroke-width: 0px; "
@@ -3096,7 +3096,7 @@
       "border: 2px solid skyblue; float: left; width: 190px; height: 30px; "
       "color: rgb(0, 0, 0); font-family: myahem; font-size: 8px; font-style: "
       "normal; font-variant-ligatures: normal; font-variant-caps: normal; "
-      "font-weight: normal; letter-spacing: normal; orphans: 2; text-align: "
+      "font-weight: 400; letter-spacing: normal; orphans: 2; text-align: "
       "start; text-indent: 0px; text-transform: none; white-space: normal; "
       "widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; "
       "text-decoration-style: initial; text-decoration-color: initial;\">Price "
@@ -3123,7 +3123,7 @@
       "solid skyblue; float: left; width: 190px; height: 30px; "
       "color: rgb(0, 0, 0); font-family: myahem; font-size: 8px; font-style: "
       "normal; font-variant-ligatures: normal; font-variant-caps: normal; "
-      "font-weight: normal; letter-spacing: "
+      "font-weight: 400; letter-spacing: "
       "normal; orphans: 2; text-align: start; "
       "text-indent: 0px; text-transform: none; white-space: normal; widows: "
       "2; word-spacing: 0px; -webkit-text-stroke-width: 0px; "
@@ -3132,7 +3132,7 @@
       "border: 2px solid skyblue; float: left; width: 190px; height: 30px; "
       "color: rgb(0, 0, 0); font-family: myahem; font-size: 8px; font-style: "
       "normal; font-variant-ligatures: normal; font-variant-caps: normal; "
-      "font-weight: normal; letter-spacing: normal; orphans: 2; text-align: "
+      "font-weight: 400; letter-spacing: normal; orphans: 2; text-align: "
       "start; text-indent: 0px; text-transform: none; white-space: normal; "
       "widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; "
       "text-decoration-style: initial; text-decoration-color: initial;\">Price "
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
index 5c41078..c8b5fce 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
@@ -1656,8 +1656,7 @@
       // we wont perform a layout. If we have a fixed background image however,
       // the background layer needs to get resized so we should request a layout
       // explicitly.
-      PaintLayer* layer = GetLayoutView()->Layer();
-      if (GetLayoutView()->Compositor()->NeedsFixedRootBackgroundLayer(layer)) {
+      if (GetLayoutView()->Compositor()->NeedsFixedRootBackgroundLayer()) {
         SetNeedsLayout();
       } else {
         // If root layer scrolls is on, we've already issued a full invalidation
diff --git a/third_party/WebKit/Source/core/frame/VisualViewportTest.cpp b/third_party/WebKit/Source/core/frame/VisualViewportTest.cpp
index 03d2e69..37bbb86 100644
--- a/third_party/WebKit/Source/core/frame/VisualViewportTest.cpp
+++ b/third_party/WebKit/Source/core/frame/VisualViewportTest.cpp
@@ -18,6 +18,7 @@
 #include "core/input/EventHandler.h"
 #include "core/layout/LayoutObject.h"
 #include "core/layout/api/LayoutViewItem.h"
+#include "core/layout/compositing/CompositedLayerMapping.h"
 #include "core/layout/compositing/PaintLayerCompositor.h"
 #include "core/loader/DocumentLoader.h"
 #include "core/page/Page.h"
@@ -2118,13 +2119,21 @@
       ToLocalFrame(web_view_impl->GetPage()->MainFrame())->GetDocument();
   PaintLayerCompositor* compositor = document->GetLayoutView()->Compositor();
 
-  ASSERT_TRUE(compositor->NeedsFixedRootBackgroundLayer(
-      document->GetLayoutView()->Layer()));
-  ASSERT_TRUE(compositor->FixedRootBackgroundLayer());
+  GraphicsLayer* backgroundLayer = nullptr;
+  if (RuntimeEnabledFeatures::RootLayerScrollingEnabled()) {
+    ASSERT_FALSE(compositor->NeedsFixedRootBackgroundLayer());
+    backgroundLayer = document->GetLayoutView()
+                          ->Layer()
+                          ->GetCompositedLayerMapping()
+                          ->MainGraphicsLayer();
+  } else {
+    ASSERT_TRUE(compositor->NeedsFixedRootBackgroundLayer());
+    backgroundLayer = compositor->FixedRootBackgroundLayer();
+  }
+  ASSERT_TRUE(backgroundLayer);
 
-  ASSERT_EQ(page_width, compositor->FixedRootBackgroundLayer()->Size().Width());
-  ASSERT_EQ(page_height,
-            compositor->FixedRootBackgroundLayer()->Size().Height());
+  ASSERT_EQ(page_width, backgroundLayer->Size().Width());
+  ASSERT_EQ(page_height, backgroundLayer->Size().Height());
   ASSERT_EQ(page_width, document->View()->GetLayoutSize().Width());
   ASSERT_EQ(smallest_height, document->View()->GetLayoutSize().Height());
 
@@ -2136,17 +2145,15 @@
   ASSERT_EQ(smallest_height, document->View()->GetLayoutSize().Height());
 
   // The background layer's size should have changed though.
-  EXPECT_EQ(page_width, compositor->FixedRootBackgroundLayer()->Size().Width());
-  EXPECT_EQ(smallest_height,
-            compositor->FixedRootBackgroundLayer()->Size().Height());
+  EXPECT_EQ(page_width, backgroundLayer->Size().Width());
+  EXPECT_EQ(smallest_height, backgroundLayer->Size().Height());
 
   web_view_impl->ResizeWithBrowserControls(WebSize(page_width, page_height),
                                            browser_controls_height, 0, true);
 
   // The background layer's size should change again.
-  EXPECT_EQ(page_width, compositor->FixedRootBackgroundLayer()->Size().Width());
-  EXPECT_EQ(page_height,
-            compositor->FixedRootBackgroundLayer()->Size().Height());
+  EXPECT_EQ(page_width, backgroundLayer->Size().Width());
+  EXPECT_EQ(page_height, backgroundLayer->Size().Height());
 }
 
 static void configureAndroidNonCompositing(WebSettings* settings) {
@@ -2195,8 +2202,7 @@
       ToLocalFrame(web_view_impl->GetPage()->MainFrame())->GetDocument();
   PaintLayerCompositor* compositor = document->GetLayoutView()->Compositor();
 
-  ASSERT_FALSE(compositor->NeedsFixedRootBackgroundLayer(
-      document->GetLayoutView()->Layer()));
+  ASSERT_FALSE(compositor->NeedsFixedRootBackgroundLayer());
   ASSERT_FALSE(compositor->FixedRootBackgroundLayer());
 
   document->View()->SetTracksPaintInvalidations(true);
diff --git a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
index 2362ce59..4569815 100644
--- a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
@@ -1566,8 +1566,10 @@
                  static_cast<short>(WebPointerProperties::Button::kLeft) &&
              GetLayoutObject()) {
     if (GetDocument().GetPage() &&
-        GetDocument().GetPage()->GetAutoscrollController().AutoscrollInProgress(
-            ToLayoutBox(GetLayoutObject())))
+        GetDocument()
+            .GetPage()
+            ->GetAutoscrollController()
+            .AutoscrollInProgressFor(ToLayoutBox(GetLayoutObject())))
       GetDocument().GetPage()->GetAutoscrollController().StopAutoscroll();
     else
       HandleMouseRelease();
diff --git a/third_party/WebKit/Source/core/html/media/MediaRemotingElements.cpp b/third_party/WebKit/Source/core/html/media/MediaRemotingElements.cpp
index e8c8b73..8c1f4c2 100644
--- a/third_party/WebKit/Source/core/html/media/MediaRemotingElements.cpp
+++ b/third_party/WebKit/Source/core/html/media/MediaRemotingElements.cpp
@@ -5,7 +5,7 @@
 #include "core/html/media/MediaRemotingElements.h"
 
 #include "core/dom/ShadowRoot.h"
-#include "core/events/PointerEvent.h"
+#include "core/events/MouseEvent.h"
 #include "core/geometry/DOMRect.h"
 #include "core/html/HTMLVideoElement.h"
 #include "core/input/EventHandler.h"
@@ -18,10 +18,10 @@
 
 // ----------------------------
 
-class MediaRemotingExitButtonElement::PointerEventsListener final
+class MediaRemotingExitButtonElement::MouseEventsListener final
     : public EventListener {
  public:
-  explicit PointerEventsListener(MediaRemotingExitButtonElement& element)
+  explicit MouseEventsListener(MediaRemotingExitButtonElement& element)
       : EventListener(kCPPEventListenerType), element_(element) {}
 
   bool operator==(const EventListener& other) const override {
@@ -37,10 +37,10 @@
   void handleEvent(ExecutionContext* context, Event* event) override {
     DCHECK_EQ(event->type(), EventTypeNames::click);
 
-    PointerEvent* pointer_event = ToPointerEvent(event);
+    MouseEvent* mouse_event = ToMouseEvent(event);
     DOMRect* client_rect = element_->getBoundingClientRect();
-    const double x = pointer_event->x();
-    const double y = pointer_event->y();
+    const double x = mouse_event->x();
+    const double y = mouse_event->y();
     if (x < client_rect->left() || x > client_rect->right() ||
         y < client_rect->top() || y > client_rect->bottom())
       return;
@@ -56,7 +56,7 @@
 MediaRemotingExitButtonElement::MediaRemotingExitButtonElement(
     MediaRemotingInterstitial& interstitial)
     : HTMLDivElement(interstitial.GetDocument()), interstitial_(interstitial) {
-  listener_ = new PointerEventsListener(*this);
+  listener_ = new MouseEventsListener(*this);
   SetShadowPseudoId(AtomicString("-internal-media-remoting-disable-button"));
   setInnerText(interstitial.GetVideoElement().GetLocale().QueryString(
                    WebLocalizedString::kMediaRemotingDisableText),
diff --git a/third_party/WebKit/Source/core/html/media/MediaRemotingElements.h b/third_party/WebKit/Source/core/html/media/MediaRemotingElements.h
index e13a1bc..45ac577b8 100644
--- a/third_party/WebKit/Source/core/html/media/MediaRemotingElements.h
+++ b/third_party/WebKit/Source/core/html/media/MediaRemotingElements.h
@@ -22,14 +22,14 @@
   DECLARE_VIRTUAL_TRACE();
 
  private:
-  class PointerEventsListener;
+  class MouseEventsListener;
 
   Member<MediaRemotingInterstitial> interstitial_;
   // A document event listener to listen to the mouse clicking events while
   // media remoting is ongoing. This listener is used instead of the
   // DefaultEventHandler() to avoid other web sites stopping propagating the
   // events. It will be removed once media remoting stops.
-  Member<PointerEventsListener> listener_;
+  Member<MouseEventsListener> listener_;
 };
 
 // A text message shown to indicate media remoting is ongoing.
diff --git a/third_party/WebKit/Source/core/input/EventHandler.h b/third_party/WebKit/Source/core/input/EventHandler.h
index f125aa2..1c4380c 100644
--- a/third_party/WebKit/Source/core/input/EventHandler.h
+++ b/third_party/WebKit/Source/core/input/EventHandler.h
@@ -265,6 +265,10 @@
 
   bool IsTouchPointerIdActiveOnFrame(int, LocalFrame*) const;
 
+  // Clears drag target and related states. It is called when drag is done or
+  // canceled.
+  void ClearDragState();
+
  private:
   WebInputEventResult HandleMouseMoveOrLeaveEvent(
       const WebMouseEvent&,
@@ -317,10 +321,6 @@
       const WebMouseEvent&,
       const Vector<WebMouseEvent>& coalesced_events);
 
-  // Clears drag target and related states. It is called when drag is done or
-  // canceled.
-  void ClearDragState();
-
   WebInputEventResult PassMousePressEventToSubframe(
       MouseEventWithHitTestResults&,
       LocalFrame* subframe);
@@ -396,8 +396,19 @@
   // firing for the current gesture sequence (i.e. until next GestureTapDown).
   bool suppress_mouse_events_from_gestures_;
 
+  // ShouldShowIBeamForNode's unit tests:
   FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, HitOnNothingDoesNotShowIBeam);
   FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, HitOnTextShowsIBeam);
+  FRIEND_TEST_ALL_PREFIXES(EventHandlerTest,
+                           HitOnUserSelectNoneDoesNotShowIBeam);
+  FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, ChildCanOverrideUserSelectNone);
+  FRIEND_TEST_ALL_PREFIXES(EventHandlerTest,
+                           ShadowChildCanOverrideUserSelectNone);
+  FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, ChildCanOverrideUserSelectText);
+  FRIEND_TEST_ALL_PREFIXES(EventHandlerTest,
+                           ShadowChildCanOverrideUserSelectText);
+  FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, InputFieldsCanStartSelection);
+  FRIEND_TEST_ALL_PREFIXES(EventHandlerTest, ImagesCannotStartSelection);
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/input/EventHandlerTest.cpp b/third_party/WebKit/Source/core/input/EventHandlerTest.cpp
index 5ee46bf..3142106 100644
--- a/third_party/WebKit/Source/core/input/EventHandlerTest.cpp
+++ b/third_party/WebKit/Source/core/input/EventHandlerTest.cpp
@@ -7,6 +7,7 @@
 #include <memory>
 #include "core/dom/Document.h"
 #include "core/dom/Range.h"
+#include "core/editing/EditingTestBase.h"
 #include "core/editing/Editor.h"
 #include "core/editing/FrameSelection.h"
 #include "core/editing/SelectionController.h"
@@ -32,6 +33,7 @@
     return GetDocument().GetFrame()->Selection();
   }
   void SetHtmlInnerHTML(const char* html_content);
+  ShadowRoot* SetShadowContent(const char* shadow_content, const char* host);
 
  protected:
   std::unique_ptr<DummyPageHolder> dummy_page_holder_;
@@ -91,6 +93,14 @@
   GetDocument().View()->UpdateAllLifecyclePhases();
 }
 
+ShadowRoot* EventHandlerTest::SetShadowContent(const char* shadow_content,
+                                               const char* host) {
+  ShadowRoot* shadow_root =
+      EditingTestBase::CreateShadowRootForElementWithIDAndSetInnerHTML(
+          GetDocument(), host, shadow_content);
+  return shadow_root;
+}
+
 TEST_F(EventHandlerTest, dragSelectionAfterScroll) {
   SetHtmlInnerHTML(
       "<style> body { margin: 0px; } .upper { width: 300px; height: 400px; }"
@@ -331,16 +341,123 @@
 
 TEST_F(EventHandlerTest, HitOnTextShowsIBeam) {
   SetHtmlInnerHTML("blabla");
-  Node* text = GetDocument().body()->firstChild();
+  Node* const text = GetDocument().body()->firstChild();
   LayoutPoint location = text->GetLayoutObject()->VisualRect().Center();
   HitTestResult hit =
       GetDocument().GetFrame()->GetEventHandler().HitTestResultAtPoint(
           location);
+  EXPECT_TRUE(text->CanStartSelection());
   EXPECT_TRUE(
       GetDocument().GetFrame()->GetEventHandler().ShouldShowIBeamForNode(text,
                                                                          hit));
 }
 
+TEST_F(EventHandlerTest, HitOnUserSelectNoneDoesNotShowIBeam) {
+  SetHtmlInnerHTML("<span style='user-select: none'>blabla</span>");
+  Node* const text = GetDocument().body()->firstChild()->firstChild();
+  LayoutPoint location = text->GetLayoutObject()->VisualRect().Center();
+  HitTestResult hit =
+      GetDocument().GetFrame()->GetEventHandler().HitTestResultAtPoint(
+          location);
+  EXPECT_FALSE(text->CanStartSelection());
+  EXPECT_FALSE(
+      GetDocument().GetFrame()->GetEventHandler().ShouldShowIBeamForNode(text,
+                                                                         hit));
+}
+
+TEST_F(EventHandlerTest, ChildCanOverrideUserSelectNone) {
+  SetHtmlInnerHTML(
+      "<div style='user-select: none'>"
+      "<span style='user-select: text'>blabla</span>"
+      "</div>");
+  Node* const text = GetDocument().body()->firstChild()->firstChild()->firstChild();
+  LayoutPoint location = text->GetLayoutObject()->VisualRect().Center();
+  HitTestResult hit =
+      GetDocument().GetFrame()->GetEventHandler().HitTestResultAtPoint(
+          location);
+  EXPECT_TRUE(text->CanStartSelection());
+  EXPECT_TRUE(
+      GetDocument().GetFrame()->GetEventHandler().ShouldShowIBeamForNode(text,
+                                                                         hit));
+}
+
+TEST_F(EventHandlerTest, ShadowChildCanOverrideUserSelectNone) {
+  SetHtmlInnerHTML("<p style='user-select: none' id='host'></p>");
+  ShadowRoot* const shadow_root = SetShadowContent(
+      "<span style='user-select: text' id='bla'>blabla</span>", "host");
+
+  Node* const text = shadow_root->getElementById("bla")->firstChild();
+  LayoutPoint location = text->GetLayoutObject()->VisualRect().Center();
+  HitTestResult hit =
+      GetDocument().GetFrame()->GetEventHandler().HitTestResultAtPoint(
+          location);
+  EXPECT_TRUE(text->CanStartSelection());
+  EXPECT_TRUE(
+      GetDocument().GetFrame()->GetEventHandler().ShouldShowIBeamForNode(text,
+                                                                         hit));
+}
+
+TEST_F(EventHandlerTest, ChildCanOverrideUserSelectText) {
+  SetHtmlInnerHTML(
+      "<div style='user-select: text'>"
+      "<span style='user-select: none'>blabla</span>"
+      "</div>");
+  Node* const text = GetDocument().body()->firstChild()->firstChild()->firstChild();
+  LayoutPoint location = text->GetLayoutObject()->VisualRect().Center();
+  HitTestResult hit =
+      GetDocument().GetFrame()->GetEventHandler().HitTestResultAtPoint(
+          location);
+  EXPECT_FALSE(text->CanStartSelection());
+  EXPECT_FALSE(
+      GetDocument().GetFrame()->GetEventHandler().ShouldShowIBeamForNode(text,
+                                                                         hit));
+}
+
+TEST_F(EventHandlerTest, ShadowChildCanOverrideUserSelectText) {
+  SetHtmlInnerHTML("<p style='user-select: text' id='host'></p>");
+  ShadowRoot* const shadow_root = SetShadowContent(
+      "<span style='user-select: none' id='bla'>blabla</span>", "host");
+
+  Node* const text = shadow_root->getElementById("bla")->firstChild();
+  LayoutPoint location = text->GetLayoutObject()->VisualRect().Center();
+  HitTestResult hit =
+      GetDocument().GetFrame()->GetEventHandler().HitTestResultAtPoint(
+          location);
+  EXPECT_FALSE(text->CanStartSelection());
+  EXPECT_FALSE(
+      GetDocument().GetFrame()->GetEventHandler().ShouldShowIBeamForNode(text,
+                                                                         hit));
+}
+
+TEST_F(EventHandlerTest, InputFieldsCanStartSelection) {
+  SetHtmlInnerHTML("<input value='blabla'>");
+  Element* const field = ToElement(GetDocument().body()->firstChild());
+  ShadowRoot* const shadow_root = field->UserAgentShadowRoot();
+
+  Element* const text = shadow_root->getElementById("inner-editor");
+  LayoutPoint location = text->GetLayoutObject()->VisualRect().Center();
+  HitTestResult hit =
+      GetDocument().GetFrame()->GetEventHandler().HitTestResultAtPoint(
+          location);
+  EXPECT_TRUE(text->CanStartSelection());
+  EXPECT_TRUE(
+      GetDocument().GetFrame()->GetEventHandler().ShouldShowIBeamForNode(text,
+                                                                         hit));
+}
+
+TEST_F(EventHandlerTest, ImagesCannotStartSelection) {
+  SetHtmlInnerHTML("<img>");
+  Element* const img = ToElement(GetDocument().body()->firstChild());
+  LayoutPoint location = img->GetLayoutObject()->VisualRect().Center();
+  HitTestResult hit =
+      GetDocument().GetFrame()->GetEventHandler().HitTestResultAtPoint(
+          location);
+  EXPECT_FALSE(img->CanStartSelection());
+  EXPECT_FALSE(
+      GetDocument().GetFrame()->GetEventHandler().ShouldShowIBeamForNode(img,
+                                                                         hit));
+}
+
 // Regression test for http://crbug.com/641403 to verify we use up-to-date
 // layout tree for dispatching "contextmenu" event.
 TEST_F(EventHandlerTest, sendContextMenuEventWithHover) {
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
index 1c95fe1d..e1cd1f5 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -366,16 +366,17 @@
     return;
 
   // An object needs to be repainted on frame scroll when it has background-
-  // attachment:fixed. LayoutView is responsible for painting root background,
-  // thus the root element (and the body element if html element has no
-  // background) skips painting backgrounds.
+  // attachment:fixed, unless the background will be separately composited.
+  // LayoutView is responsible for painting root background, thus the root
+  // element (and the body element if html element has no background) skips
+  // painting backgrounds.
   bool is_background_attachment_fixed_object =
       !IsDocumentElement() && !BackgroundStolenForBeingBody() &&
       StyleRef().HasFixedBackgroundImage();
   if (IsLayoutView() &&
-      View()->Compositor()->SupportsFixedRootBackgroundCompositing()) {
-    if (StyleRef().HasEntirelyFixedBackground())
-      is_background_attachment_fixed_object = false;
+      View()->Compositor()->PreferCompositingToLCDTextEnabled() &&
+      StyleRef().HasEntirelyFixedBackground()) {
+    is_background_attachment_fixed_object = false;
   }
 
   SetIsBackgroundAttachmentFixedObject(is_background_attachment_fixed_object);
@@ -643,13 +644,14 @@
   return false;
 }
 
-void LayoutBox::ScrollRectToVisible(const LayoutRect& rect,
-                                    const ScrollAlignment& align_x,
-                                    const ScrollAlignment& align_y,
-                                    ScrollType scroll_type,
-                                    bool make_visible_in_visual_viewport,
-                                    ScrollBehavior scroll_behavior,
-                                    bool is_for_scroll_sequence) {
+void LayoutBox::ScrollRectToVisibleRecursive(
+    const LayoutRect& rect,
+    const ScrollAlignment& align_x,
+    const ScrollAlignment& align_y,
+    ScrollType scroll_type,
+    bool make_visible_in_visual_viewport,
+    ScrollBehavior scroll_behavior,
+    bool is_for_scroll_sequence) {
   DCHECK(scroll_type == kProgrammaticScroll || scroll_type == kUserScroll);
   // Presumably the same issue as in setScrollTop. See crbug.com/343132.
   DisableCompositingQueryAsserts disabler;
@@ -738,9 +740,10 @@
     parent_box = EnclosingScrollableBox();
 
   if (parent_box) {
-    parent_box->ScrollRectToVisible(new_rect, align_x, align_y, scroll_type,
-                                    make_visible_in_visual_viewport,
-                                    scroll_behavior, is_for_scroll_sequence);
+    parent_box->ScrollRectToVisibleRecursive(
+        new_rect, align_x, align_y, scroll_type,
+        make_visible_in_visual_viewport, scroll_behavior,
+        is_for_scroll_sequence);
   }
 }
 
@@ -1053,9 +1056,10 @@
 
   IntPoint position_in_content =
       frame_view->RootFrameToContents(position_in_root_frame);
-  ScrollRectToVisible(LayoutRect(position_in_content, LayoutSize(1, 1)),
-                      ScrollAlignment::kAlignToEdgeIfNeeded,
-                      ScrollAlignment::kAlignToEdgeIfNeeded, kUserScroll);
+  ScrollRectToVisibleRecursive(
+      LayoutRect(position_in_content, LayoutSize(1, 1)),
+      ScrollAlignment::kAlignToEdgeIfNeeded,
+      ScrollAlignment::kAlignToEdgeIfNeeded, kUserScroll);
 }
 
 // There are two kinds of layoutObject that can autoscroll.
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.h b/third_party/WebKit/Source/core/layout/LayoutBox.h
index be61d46..22fa77c2 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.h
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.h
@@ -595,15 +595,13 @@
   void ScrollByRecursively(const ScrollOffset& delta);
   // If makeVisibleInVisualViewport is set, the visual viewport will be scrolled
   // if required to make the rect visible.
-  // TODO(sunyunjia): Rename this method to distinguish with the one in
-  // LayoutObject. crbug.com/738160
-  void ScrollRectToVisible(const LayoutRect&,
-                           const ScrollAlignment& align_x,
-                           const ScrollAlignment& align_y,
-                           ScrollType = kProgrammaticScroll,
-                           bool make_visible_in_visual_viewport = true,
-                           ScrollBehavior = kScrollBehaviorAuto,
-                           bool is_for_scroll_sequence = false);
+  void ScrollRectToVisibleRecursive(const LayoutRect&,
+                                    const ScrollAlignment& align_x,
+                                    const ScrollAlignment& align_y,
+                                    ScrollType = kProgrammaticScroll,
+                                    bool make_visible_in_visual_viewport = true,
+                                    ScrollBehavior = kScrollBehaviorAuto,
+                                    bool is_for_scroll_sequence = false);
 
   LayoutRectOutsets MarginBoxOutsets() const override {
     return margin_box_outsets_;
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
index d6c9f0e..f8ff9ae 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -635,9 +635,9 @@
     return false;
 
   GetDocument().GetPage()->GetSmoothScrollSequencer()->AbortAnimations();
-  enclosing_box->ScrollRectToVisible(rect, align_x, align_y, scroll_type,
-                                     make_visible_in_visual_viewport,
-                                     scroll_behavior, true);
+  enclosing_box->ScrollRectToVisibleRecursive(
+      rect, align_x, align_y, scroll_type, make_visible_in_visual_viewport,
+      scroll_behavior, true);
   GetDocument().GetPage()->GetSmoothScrollSequencer()->RunQueuedAnimations();
 
   return true;
diff --git a/third_party/WebKit/Source/core/layout/LayoutView.cpp b/third_party/WebKit/Source/core/layout/LayoutView.cpp
index 5d544c2..578d9b9 100644
--- a/third_party/WebKit/Source/core/layout/LayoutView.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutView.cpp
@@ -243,7 +243,7 @@
   // composited and needs full paint invalidation on background positioning area
   // resize.
   if (Style()->HasFixedBackgroundImage() &&
-      (!compositor_ || !compositor_->NeedsFixedRootBackgroundLayer(Layer()))) {
+      (!compositor_ || !compositor_->NeedsFixedRootBackgroundLayer())) {
     if ((width_changed && MustInvalidateFillLayersPaintOnWidthChange(
                               Style()->BackgroundLayers())) ||
         (height_changed && MustInvalidateFillLayersPaintOnHeightChange(
diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp
index b732813..df2fe64f9 100644
--- a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp
+++ b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp
@@ -610,7 +610,8 @@
 
   bool layer_config_changed = false;
   SetBackgroundLayerPaintsFixedRootBackground(
-      compositor->NeedsFixedRootBackgroundLayer(&owning_layer_));
+      layout_object.IsLayoutView() &&
+      compositor->NeedsFixedRootBackgroundLayer());
 
   // The background layer is currently only used for fixed root backgrounds.
   if (UpdateBackgroundLayer(background_layer_paints_fixed_root_background_))
diff --git a/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp b/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp
index eac55c0a..b1699d83 100644
--- a/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp
+++ b/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp
@@ -700,7 +700,7 @@
 }
 
 void PaintLayerCompositor::RootFixedBackgroundsChanged() {
-  if (!SupportsFixedRootBackgroundCompositing() || !container_layer_)
+  if (!container_layer_)
     return;
 
   // To avoid having to make the fixed root background layer fixed positioned to
@@ -981,18 +981,9 @@
   return nullptr;
 }
 
-bool PaintLayerCompositor::SupportsFixedRootBackgroundCompositing() const {
-  if (Settings* settings = layout_view_.GetDocument().GetSettings())
-    return settings->GetPreferCompositingToLCDTextEnabled();
-  return false;
-}
-
-bool PaintLayerCompositor::NeedsFixedRootBackgroundLayer(
-    const PaintLayer* layer) const {
-  if (layer != layout_view_.Layer())
-    return false;
-
-  return SupportsFixedRootBackgroundCompositing() &&
+bool PaintLayerCompositor::NeedsFixedRootBackgroundLayer() const {
+  return !RuntimeEnabledFeatures::RootLayerScrollingEnabled() &&
+         PreferCompositingToLCDTextEnabled() &&
          layout_view_.RootBackgroundIsEntirelyFixed();
 }
 
diff --git a/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.h b/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.h
index fe03ad67..07ef6f4 100644
--- a/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.h
+++ b/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.h
@@ -122,8 +122,7 @@
   // Whether the given layer needs an extra 'contents' layer.
   bool NeedsContentsCompositingLayer(const PaintLayer*) const;
 
-  bool SupportsFixedRootBackgroundCompositing() const;
-  bool NeedsFixedRootBackgroundLayer(const PaintLayer*) const;
+  bool NeedsFixedRootBackgroundLayer() const;
   GraphicsLayer* FixedRootBackgroundLayer() const;
   void SetNeedsUpdateFixedBackground() {
     needs_update_fixed_background_ = true;
diff --git a/third_party/WebKit/Source/core/loader/BaseFetchContext.cpp b/third_party/WebKit/Source/core/loader/BaseFetchContext.cpp
index 911d172..3d63595d 100644
--- a/third_party/WebKit/Source/core/loader/BaseFetchContext.cpp
+++ b/third_party/WebKit/Source/core/loader/BaseFetchContext.cpp
@@ -93,18 +93,18 @@
 }
 
 ResourceRequestBlockedReason BaseFetchContext::CheckCSPForRequest(
-    const ResourceRequest& resource_request,
+    WebURLRequest::RequestContext request_context,
     const KURL& url,
     const ResourceLoaderOptions& options,
     SecurityViolationReportingPolicy reporting_policy,
     ResourceRequest::RedirectStatus redirect_status) const {
   return CheckCSPForRequestInternal(
-      resource_request, url, options, reporting_policy, redirect_status,
+      request_context, url, options, reporting_policy, redirect_status,
       ContentSecurityPolicy::CheckHeaderType::kCheckReportOnly);
 }
 
 ResourceRequestBlockedReason BaseFetchContext::CheckCSPForRequestInternal(
-    const ResourceRequest& resource_request,
+    WebURLRequest::RequestContext request_context,
     const KURL& url,
     const ResourceLoaderOptions& options,
     SecurityViolationReportingPolicy reporting_policy,
@@ -116,11 +116,10 @@
   }
 
   const ContentSecurityPolicy* csp = GetContentSecurityPolicy();
-  if (csp && !csp->AllowRequest(resource_request.GetRequestContext(), url,
-                                options.content_security_policy_nonce,
-                                options.integrity_metadata,
-                                options.parser_disposition, redirect_status,
-                                reporting_policy, check_header_type)) {
+  if (csp && !csp->AllowRequest(
+                 request_context, url, options.content_security_policy_nonce,
+                 options.integrity_metadata, options.parser_disposition,
+                 redirect_status, reporting_policy, check_header_type)) {
     return ResourceRequestBlockedReason::kCSP;
   }
   return ResourceRequestBlockedReason::kNone;
@@ -193,7 +192,8 @@
   // populateResourceRequest). We check the enforced headers here to ensure we
   // block things we ought to block.
   if (CheckCSPForRequestInternal(
-          resource_request, url, options, reporting_policy, redirect_status,
+          resource_request.GetRequestContext(), url, options, reporting_policy,
+          redirect_status,
           ContentSecurityPolicy::CheckHeaderType::kCheckEnforce) ==
       ResourceRequestBlockedReason::kCSP) {
     return ResourceRequestBlockedReason::kCSP;
diff --git a/third_party/WebKit/Source/core/loader/BaseFetchContext.h b/third_party/WebKit/Source/core/loader/BaseFetchContext.h
index df44abb9..11439ac 100644
--- a/third_party/WebKit/Source/core/loader/BaseFetchContext.h
+++ b/third_party/WebKit/Source/core/loader/BaseFetchContext.h
@@ -37,7 +37,7 @@
       FetchParameters::OriginRestriction,
       ResourceRequest::RedirectStatus) const override;
   ResourceRequestBlockedReason CheckCSPForRequest(
-      const ResourceRequest&,
+      WebURLRequest::RequestContext,
       const KURL&,
       const ResourceLoaderOptions&,
       SecurityViolationReportingPolicy,
@@ -95,7 +95,7 @@
 
  private:
   ResourceRequestBlockedReason CheckCSPForRequestInternal(
-      const ResourceRequest&,
+      WebURLRequest::RequestContext,
       const KURL&,
       const ResourceLoaderOptions&,
       SecurityViolationReportingPolicy,
diff --git a/third_party/WebKit/Source/core/loader/BaseFetchContextTest.cpp b/third_party/WebKit/Source/core/loader/BaseFetchContextTest.cpp
index ba8bf6f4..22a0170 100644
--- a/third_party/WebKit/Source/core/loader/BaseFetchContextTest.cpp
+++ b/third_party/WebKit/Source/core/loader/BaseFetchContextTest.cpp
@@ -291,16 +291,12 @@
                            kContentSecurityPolicyHeaderSourceHTTP);
 
   KURL url(NullURL(), "http://baz.test");
-  ResourceRequest resource_request(url);
-  resource_request.SetRequestContext(WebURLRequest::kRequestContextScript);
-  resource_request.SetFetchCredentialsMode(
-      WebURLRequest::kFetchCredentialsModeOmit);
 
   ResourceLoaderOptions options;
 
   EXPECT_EQ(ResourceRequestBlockedReason::kNone,
             fetch_context_->CheckCSPForRequest(
-                resource_request, url, options,
+                WebURLRequest::kRequestContextScript, url, options,
                 SecurityViolationReportingPolicy::kReport,
                 ResourceRequest::RedirectStatus::kFollowedRedirect));
   EXPECT_EQ(1u, policy->violation_reports_sent_.size());
diff --git a/third_party/WebKit/Source/core/page/AutoscrollController.cpp b/third_party/WebKit/Source/core/page/AutoscrollController.cpp
index 0a17c9a5..9643a0b 100644
--- a/third_party/WebKit/Source/core/page/AutoscrollController.cpp
+++ b/third_party/WebKit/Source/core/page/AutoscrollController.cpp
@@ -91,7 +91,11 @@
   return autoscroll_type_ == kAutoscrollForSelection;
 }
 
-bool AutoscrollController::AutoscrollInProgress(
+bool AutoscrollController::AutoscrollInProgress() const {
+  return autoscroll_layout_object_;
+}
+
+bool AutoscrollController::AutoscrollInProgressFor(
     const LayoutBox* layout_object) const {
   return autoscroll_layout_object_ == layout_object;
 }
diff --git a/third_party/WebKit/Source/core/page/AutoscrollController.h b/third_party/WebKit/Source/core/page/AutoscrollController.h
index d4a34b6..8141e6d99 100644
--- a/third_party/WebKit/Source/core/page/AutoscrollController.h
+++ b/third_party/WebKit/Source/core/page/AutoscrollController.h
@@ -71,7 +71,8 @@
   // Selection and drag-and-drop autoscroll.
   void Animate(double monotonic_frame_begin_time);
   bool SelectionAutoscrollInProgress() const;
-  bool AutoscrollInProgress(const LayoutBox*) const;
+  bool AutoscrollInProgressFor(const LayoutBox*) const;
+  bool AutoscrollInProgress() const;
   void StartAutoscrollForSelection(LayoutObject*);
   void StopAutoscroll();
   void StopAutoscrollIfNeeded(LayoutObject*);
diff --git a/third_party/WebKit/Source/core/page/DragController.cpp b/third_party/WebKit/Source/core/page/DragController.cpp
index 0a7e42ab..ca494ec 100644
--- a/third_party/WebKit/Source/core/page/DragController.cpp
+++ b/third_party/WebKit/Source/core/page/DragController.cpp
@@ -241,7 +241,7 @@
   file_input_element_under_mouse_ = nullptr;
 }
 
-bool DragController::PerformDrag(DragData* drag_data, LocalFrame& local_root) {
+void DragController::PerformDrag(DragData* drag_data, LocalFrame& local_root) {
   DCHECK(drag_data);
   document_under_mouse_ =
       local_root.DocumentAtPoint(drag_data->ClientPosition());
@@ -277,26 +277,31 @@
     if (prevented_default) {
       document_under_mouse_ = nullptr;
       CancelDrag();
-      return true;
+      return;
     }
   }
 
   if ((drag_destination_action_ & kDragDestinationActionEdit) &&
       ConcludeEditDrag(drag_data)) {
     document_under_mouse_ = nullptr;
-    return true;
+    return;
   }
 
   document_under_mouse_ = nullptr;
 
-  if (OperationForLoad(drag_data, local_root) == kDragOperationNone)
-    return false;
+  if (OperationForLoad(drag_data, local_root) != kDragOperationNone) {
+    if (page_->GetSettings().GetNavigateOnDragDrop()) {
+      page_->MainFrame()->Navigate(
+          FrameLoadRequest(nullptr, ResourceRequest(drag_data->AsURL())));
+    }
 
-  if (page_->GetSettings().GetNavigateOnDragDrop()) {
-    page_->MainFrame()->Navigate(
-        FrameLoadRequest(nullptr, ResourceRequest(drag_data->AsURL())));
+    // TODO(bokan): This case happens when we end a URL drag inside a guest
+    // process which doesn't navigate. We assume that since we'll navigate the
+    // page in the general case we don't end up sending `dragleave` and
+    // `dragend` events but for plugins we wont navigate so it seems we should
+    // be sending these events. crbug.com/748243.
+    local_root.GetEventHandler().ClearDragState();
   }
-  return true;
 }
 
 void DragController::MouseMovedIntoDocument(Document* new_document) {
diff --git a/third_party/WebKit/Source/core/page/DragController.h b/third_party/WebKit/Source/core/page/DragController.h
index 7fb08d4d..d9a34f6 100644
--- a/third_party/WebKit/Source/core/page/DragController.h
+++ b/third_party/WebKit/Source/core/page/DragController.h
@@ -58,7 +58,7 @@
 
   DragSession DragEnteredOrUpdated(DragData*, LocalFrame& local_root);
   void DragExited(DragData*, LocalFrame& local_root);
-  bool PerformDrag(DragData*, LocalFrame& local_root);
+  void PerformDrag(DragData*, LocalFrame& local_root);
 
   enum SelectionDragPolicy {
     kImmediateSelectionDragResolution,
diff --git a/third_party/WebKit/Source/core/page/DragControllerTest.cpp b/third_party/WebKit/Source/core/page/DragControllerTest.cpp
index 73d8a6f..20568561 100644
--- a/third_party/WebKit/Source/core/page/DragControllerTest.cpp
+++ b/third_party/WebKit/Source/core/page/DragControllerTest.cpp
@@ -4,6 +4,7 @@
 
 #include "core/page/DragController.h"
 
+#include "core/clipboard/DataObject.h"
 #include "core/editing/FrameSelection.h"
 #include "core/frame/LocalFrame.h"
 #include "core/frame/LocalFrameView.h"
@@ -11,9 +12,17 @@
 #include "core/frame/VisualViewport.h"
 #include "core/html/HTMLElement.h"
 #include "core/layout/LayoutObject.h"
+#include "core/layout/LayoutView.h"
+#include "core/page/AutoscrollController.h"
+#include "core/page/DragData.h"
+#include "core/page/DragSession.h"
 #include "core/testing/DummyPageHolder.h"
+#include "core/testing/sim/SimDisplayItemList.h"
+#include "core/testing/sim/SimRequest.h"
+#include "core/testing/sim/SimTest.h"
 #include "core/timing/Performance.h"
 #include "platform/DragImage.h"
+#include "platform/testing/RuntimeEnabledFeaturesTestHelpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace blink {
@@ -66,4 +75,54 @@
   EXPECT_EQ(image1->Size().Width() * 2, image2->Size().Width());
   EXPECT_EQ(image1->Size().Height() * 2, image2->Size().Height());
 }
+
+class DragControllerSimTest : public ::testing::WithParamInterface<bool>,
+                              private ScopedRootLayerScrollingForTest,
+                              public SimTest {
+ public:
+  DragControllerSimTest() : ScopedRootLayerScrollingForTest(GetParam()) {}
+};
+
+INSTANTIATE_TEST_CASE_P(All, DragControllerSimTest, ::testing::Bool());
+
+// Tests that dragging a URL onto a WebWidget that doesn't navigate on Drag and
+// Drop clears out the Autoscroll state. Regression test for
+// https://crbug.com/733996.
+TEST_P(DragControllerSimTest, DropURLOnNonNavigatingClearsState) {
+  WebView().GetPage()->GetSettings().SetNavigateOnDragDrop(false);
+  WebView().Resize(WebSize(800, 600));
+  SimRequest main_resource("https://example.com/test.html", "text/html");
+
+  LoadURL("https://example.com/test.html");
+
+  // Page must be scrollable so that Autoscroll is engaged.
+  main_resource.Complete(
+      "<!DOCTYPE html>"
+      "<style>body,html { height: 1000px; width: 1000px; }</style>");
+
+  Compositor().BeginFrame();
+
+  DataObject* object = DataObject::Create();
+  object->SetURLAndTitle("https://www.example.com/index.html", "index");
+  DragData data(
+      object, IntPoint(10, 10), IntPoint(10, 10),
+      static_cast<DragOperation>(kDragOperationCopy | kDragOperationLink |
+                                 kDragOperationMove));
+
+  WebView().GetPage()->GetDragController().DragEnteredOrUpdated(
+      &data, *GetDocument().GetFrame());
+
+  // The page should tell the AutoscrollController about the drag.
+  EXPECT_TRUE(
+      WebView().GetPage()->GetAutoscrollController().AutoscrollInProgress());
+
+  WebView().GetPage()->GetDragController().PerformDrag(
+      &data, *GetDocument().GetFrame());
+
+  // Once we've "performed" the drag (in which nothing happens), the
+  // AutoscrollController should have been cleared.
+  EXPECT_FALSE(
+      WebView().GetPage()->GetAutoscrollController().AutoscrollInProgress());
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
index caf7dd5..9cbc1d2c 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
@@ -61,6 +61,7 @@
 #include "core/fullscreen/Fullscreen.h"
 #include "core/html/HTMLFrameOwnerElement.h"
 #include "core/html/HTMLSelectElement.h"
+#include "core/html/TextControlElement.h"
 #include "core/input/EventHandler.h"
 #include "core/layout/LayoutEmbeddedContent.h"
 #include "core/layout/LayoutFlexibleBox.h"
@@ -1904,6 +1905,20 @@
   return ScrollableArea::ShouldScrollOnMainThread();
 }
 
+static bool LayerNodeMayNeedCompositedScrolling(const PaintLayer* layer) {
+  // Don't force composite scroll for select or text input elements.
+  if (Node* node = layer->GetLayoutObject().GetNode()) {
+    if (isHTMLSelectElement(node))
+      return false;
+    if (TextControlElement* text_control = EnclosingTextControl(node)) {
+      if (isHTMLInputElement(text_control)) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
 bool PaintLayerScrollableArea::ComputeNeedsCompositedScrolling(
     const LCDTextMode mode,
     const PaintLayer* layer) {
@@ -1923,6 +1938,9 @@
   if (layer->size().IsEmpty())
     return false;
 
+  if (!LayerNodeMayNeedCompositedScrolling(layer))
+    return false;
+
   bool needs_composited_scrolling = true;
 
   // TODO(flackr): Allow integer transforms as long as all of the ancestor
diff --git a/third_party/WebKit/Source/core/paint/ViewPainter.cpp b/third_party/WebKit/Source/core/paint/ViewPainter.cpp
index 3b2645f..636efc8 100644
--- a/third_party/WebKit/Source/core/paint/ViewPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/ViewPainter.cpp
@@ -128,12 +128,21 @@
   // The strategy is to apply root element transform on the context and issue
   // draw commands in the local space, therefore we need to apply inverse
   // transform on the document rect to get to the root element space.
+  // Local / scroll positioned background images will be painted into scrolling
+  // contents layer with root layer scrolling. Therefore we need to switch both
+  // the background_rect and context to documentElement visual space.
   bool background_renderable = true;
   TransformationMatrix transform;
   IntRect paint_rect = background_rect;
   if (!root_object || !root_object->IsBox()) {
     background_renderable = false;
   } else if (root_object->HasLayer()) {
+    if (BoxModelObjectPainter::
+            IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
+                &layout_view_, paint_info)) {
+      transform.Translate(layout_view_.ScrolledContentOffset().Width(),
+                          layout_view_.ScrolledContentOffset().Height());
+    }
     const PaintLayer& root_layer =
         *ToLayoutBoxModelObject(root_object)->Layer();
     LayoutPoint offset;
diff --git a/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js b/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js
index d7f3bd7..3407caa 100644
--- a/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js
@@ -660,114 +660,45 @@
     this._securityExplanationsMain.removeChildren();
     this._securityExplanationsExtra.removeChildren();
     for (var explanation of this._explanations) {
-      if (explanation.securityState === Protocol.Security.SecurityState.Info)
+      if (explanation.securityState === Protocol.Security.SecurityState.Info) {
         this._addExplanation(this._securityExplanationsExtra, explanation);
-      else
-        this._addExplanation(this._securityExplanationsMain, explanation);
-    }
-
-    this._addMixedContentExplanations();
-    this._addContentWithCertErrorsExplanations();
-
-    // If all resources were served securely, add a Secure explanation.
-    if (this._schemeIsCryptographic && this._insecureContentStatus &&
-        (!this._insecureContentStatus.displayedMixedContent && !this._insecureContentStatus.ranMixedContent &&
-         !this._insecureContentStatus.displayedContentWithCertErrors &&
-         !this._insecureContentStatus.ranContentWithCertErrors)) {
-      this._addExplanation(this._securityExplanationsMain, /** @type {!Protocol.Security.SecurityStateExplanation} */ ({
-                             'securityState': Protocol.Security.SecurityState.Secure,
-                             'summary': Common.UIString('Secure resources'),
-                             'description': Common.UIString('All resources on this page are served securely.')
-                           }));
-    }
-  }
-
-  _addMixedContentExplanations() {
-    if (!this._schemeIsCryptographic)
-      return;
-
-    if (this._insecureContentStatus &&
-        (this._insecureContentStatus.ranMixedContent || this._insecureContentStatus.displayedMixedContent ||
-         this._insecureContentStatus.containedMixedForm)) {
-      if (this._insecureContentStatus.ranMixedContent) {
-        this._addMixedContentExplanation(
-            this._securityExplanationsMain, this._insecureContentStatus.ranInsecureContentStyle,
-            Common.UIString('Active mixed content'),
-            Common.UIString(
-                'You have recently allowed non-secure content (such as scripts or iframes) to run on this site.'),
-            Network.NetworkLogView.MixedContentFilterValues.BlockOverridden,
-            showBlockOverriddenMixedContentInNetworkPanel);
-      }
-      if (this._insecureContentStatus.containedMixedForm) {
-        this._addMixedFormExplanation(
-            // TODO(elawrence): Replace |displayedInsecureContentStyle| with |containedMixedFormStyle|. https://crbug.com/705003
-            this._securityExplanationsMain, this._insecureContentStatus.displayedInsecureContentStyle,
-            Common.UIString('Non-secure form'),
-            Common.UIString('The page includes a form with a non-secure "action" attribute.'));
-      }
-      if (this._insecureContentStatus.displayedMixedContent) {
-        this._addMixedContentExplanation(
-            this._securityExplanationsMain, this._insecureContentStatus.displayedInsecureContentStyle,
-            Common.UIString('Mixed content'), Common.UIString('The site includes HTTP resources.'),
-            Network.NetworkLogView.MixedContentFilterValues.Displayed, showDisplayedMixedContentInNetworkPanel);
+      } else {
+        switch (explanation.mixedContentType) {
+          case Protocol.Security.MixedContentType.Blockable:
+            this._addMixedContentExplanation(
+                this._securityExplanationsMain, explanation,
+                Network.NetworkLogView.MixedContentFilterValues.BlockOverridden);
+            break;
+          case Protocol.Security.MixedContentType.OptionallyBlockable:
+            this._addMixedContentExplanation(
+                this._securityExplanationsMain, explanation, Network.NetworkLogView.MixedContentFilterValues.Displayed);
+            break;
+          default:
+            this._addExplanation(this._securityExplanationsMain, explanation);
+            break;
+        }
       }
     }
 
     if (this._panel.filterRequestCount(Network.NetworkLogView.MixedContentFilterValues.Blocked) > 0) {
+      var explanation = /** @type {!Protocol.Security.SecurityStateExplanation} */ ({
+        'securityState': Protocol.Security.SecurityState.Info,
+        'summary': Common.UIString('Blocked mixed content'),
+        'description': Common.UIString('Your page requested non-secure resources that were blocked.'),
+        'mixedContentType': Protocol.Security.MixedContentType.Blockable
+      });
       this._addMixedContentExplanation(
-          this._securityExplanationsExtra, Protocol.Security.SecurityState.Info,
-          Common.UIString('Blocked mixed content'),
-          Common.UIString('Your page requested non-secure resources that were blocked.'),
-          Network.NetworkLogView.MixedContentFilterValues.Blocked, showBlockedMixedContentInNetworkPanel);
-    }
-
-    /**
-     * @param {!Event} e
-     */
-    function showDisplayedMixedContentInNetworkPanel(e) {
-      e.consume();
-      Network.NetworkPanel.revealAndFilter([{
-        filterType: Network.NetworkLogView.FilterType.MixedContent,
-        filterValue: Network.NetworkLogView.MixedContentFilterValues.Displayed
-      }]);
-    }
-
-    /**
-     * @param {!Event} e
-     */
-    function showBlockOverriddenMixedContentInNetworkPanel(e) {
-      e.consume();
-      Network.NetworkPanel.revealAndFilter([{
-        filterType: Network.NetworkLogView.FilterType.MixedContent,
-        filterValue: Network.NetworkLogView.MixedContentFilterValues.BlockOverridden
-      }]);
-    }
-
-    /**
-     * @param {!Event} e
-     */
-    function showBlockedMixedContentInNetworkPanel(e) {
-      e.consume();
-      Network.NetworkPanel.revealAndFilter([{
-        filterType: Network.NetworkLogView.FilterType.MixedContent,
-        filterValue: Network.NetworkLogView.MixedContentFilterValues.Blocked
-      }]);
+          this._securityExplanationsMain, explanation, Network.NetworkLogView.MixedContentFilterValues.Blocked);
     }
   }
 
   /**
    * @param {!Element} parent
-   * @param {!Protocol.Security.SecurityState} securityState
-   * @param {string} summary
-   * @param {string} description
+   * @param {!Protocol.Security.SecurityStateExplanation} explanation
    * @param {!Network.NetworkLogView.MixedContentFilterValues} filterKey
-   * @param {!Function} networkFilterFn
    */
-  _addMixedContentExplanation(parent, securityState, summary, description, filterKey, networkFilterFn) {
-    var mixedContentExplanation = /** @type {!Protocol.Security.SecurityStateExplanation} */ (
-        {'securityState': securityState, 'summary': summary, 'description': description});
-
-    var explanation = this._addExplanation(parent, mixedContentExplanation);
+  _addMixedContentExplanation(parent, explanation, filterKey) {
+    var element = this._addExplanation(parent, explanation);
 
     var filterRequestCount = this._panel.filterRequestCount(filterKey);
     if (!filterRequestCount) {
@@ -776,59 +707,29 @@
       // individual mixed requests at this point. Prompt them to refresh
       // instead of pointing them to the Network panel to get prompted
       // to refresh.
-      var refreshPrompt = explanation.createChild('div', 'security-mixed-content');
+      var refreshPrompt = element.createChild('div', 'security-mixed-content');
       refreshPrompt.textContent = Common.UIString('Reload the page to record requests for HTTP resources.');
       return;
     }
 
-    var requestsAnchor = explanation.createChild('div', 'security-mixed-content link');
+    var requestsAnchor = element.createChild('div', 'security-mixed-content link');
     if (filterRequestCount === 1)
       requestsAnchor.textContent = Common.UIString('View %d request in Network Panel', filterRequestCount);
     else
       requestsAnchor.textContent = Common.UIString('View %d requests in Network Panel', filterRequestCount);
 
     requestsAnchor.href = '';
-    requestsAnchor.addEventListener('click', networkFilterFn);
+    requestsAnchor.addEventListener('click', this.showNetworkFilter.bind(this, filterKey));
   }
 
   /**
-   * @param {!Element} parent
-   * @param {!Protocol.Security.SecurityState} securityState
-   * @param {string} summary
-   * @param {string} description
+   * @param {!Network.NetworkLogView.MixedContentFilterValues} filterKey
+   * @param {!Event} e
    */
-  _addMixedFormExplanation(parent, securityState, summary, description) {
-    var mixedContentExplanation = /** @type {!Protocol.Security.SecurityStateExplanation} */ (
-        {'securityState': securityState, 'summary': summary, 'description': description});
-
-    this._addExplanation(parent, mixedContentExplanation);
-  }
-
-  _addContentWithCertErrorsExplanations() {
-    if (!this._schemeIsCryptographic)
-      return;
-
-    if (!this._insecureContentStatus)
-      return;
-
-    if (this._insecureContentStatus.ranContentWithCertErrors) {
-      this._addExplanation(
-          this._securityExplanationsMain, /** @type {!Protocol.Security.SecurityStateExplanation} */ ({
-            'securityState': this._insecureContentStatus.ranInsecureContentStyle,
-            'summary': Common.UIString('Active content with certificate errors'),
-            'description': Common.UIString(
-                'You have recently allowed content loaded with certificate errors (such as scripts or iframes) to run on this site.')
-          }));
-    }
-
-    if (this._insecureContentStatus.displayedContentWithCertErrors) {
-      this._addExplanation(
-          this._securityExplanationsMain, /** @type {!Protocol.Security.SecurityStateExplanation} */ ({
-            'securityState': this._insecureContentStatus.displayedInsecureContentStyle,
-            'summary': Common.UIString('Content with certificate errors'),
-            'description': Common.UIString('This site includes resources that were loaded with certificate errors.')
-          }));
-    }
+  showNetworkFilter(filterKey, e) {
+    e.consume();
+    Network.NetworkPanel.revealAndFilter(
+        [{filterType: Network.NetworkLogView.FilterType.MixedContent, filterValue: filterKey}]);
   }
 };
 
diff --git a/third_party/WebKit/Source/platform/fonts/FontSelectionTypes.h b/third_party/WebKit/Source/platform/fonts/FontSelectionTypes.h
index 03207b4..8e3084b 100644
--- a/third_party/WebKit/Source/platform/fonts/FontSelectionTypes.h
+++ b/third_party/WebKit/Source/platform/fonts/FontSelectionTypes.h
@@ -105,10 +105,6 @@
 class FontSelectionValueStyle : public FontSelectionValue {
   using FontSelectionValue::FontSelectionValue;
 };
-class FontSelectionValueWeight : public FontSelectionValue {
-  using FontSelectionValue::FontSelectionValue;
-};
-
 inline FontSelectionValue FontSelectionValue::operator+(
     const FontSelectionValue other) const {
   return FontSelectionValue(backing_ + other.backing_, RawTag::RawTag);
@@ -195,27 +191,27 @@
   return italicValue;
 }
 
-static inline const FontSelectionValueWeight BoldThreshold() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValueWeight, boldThreshold,
+static inline const FontSelectionValue BoldThreshold() {
+  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValue, boldThreshold,
                                   (600));
   return boldThreshold;
 }
 
-static inline const FontSelectionValueWeight BoldWeightValue() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValueWeight,
-                                  boldWeightValue, (700));
+static inline const FontSelectionValue BoldWeightValue() {
+  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValue, boldWeightValue,
+                                  (700));
   return boldWeightValue;
 }
 
-static inline const FontSelectionValueWeight NormalWeightValue() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValueWeight,
-                                  normalWeightValue, (400));
+static inline const FontSelectionValue NormalWeightValue() {
+  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValue, normalWeightValue,
+                                  (400));
   return normalWeightValue;
 }
 
-static inline const FontSelectionValueWeight LightWeightValue() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValueWeight,
-                                  lightWeightValue, (200));
+static inline const FontSelectionValue LightWeightValue() {
+  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValue, lightWeightValue,
+                                  (200));
   return lightWeightValue;
 }
 
diff --git a/third_party/WebKit/Source/platform/loader/fetch/FetchContext.h b/third_party/WebKit/Source/platform/loader/fetch/FetchContext.h
index aed53c562..5dc1c165 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/FetchContext.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/FetchContext.h
@@ -46,6 +46,7 @@
 #include "public/platform/WebApplicationCacheHost.h"
 #include "public/platform/WebCachePolicy.h"
 #include "public/platform/WebURLLoader.h"
+#include "public/platform/WebURLRequest.h"
 
 namespace blink {
 
@@ -159,7 +160,7 @@
     return ResourceRequestBlockedReason::kOther;
   }
   virtual ResourceRequestBlockedReason CheckCSPForRequest(
-      const ResourceRequest&,
+      WebURLRequest::RequestContext,
       const KURL&,
       const ResourceLoaderOptions&,
       SecurityViolationReportingPolicy,
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
index 2f63089e..d0de7ff 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
@@ -551,7 +551,7 @@
   // allows site owners to learn about requests that are being modified
   // (e.g. mixed content that is being upgraded by upgrade-insecure-requests).
   Context().CheckCSPForRequest(
-      resource_request,
+      resource_request.GetRequestContext(),
       MemoryCache::RemoveFragmentIdentifierIfNeeded(params.Url()), options,
       reporting_policy, resource_request.GetRedirectStatus());
 
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp
index 1857cab..888218f 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp
@@ -221,7 +221,7 @@
     // CanRequest() checks only enforced CSP, so check report-only here to
     // ensure that violations are sent.
     Context().CheckCSPForRequest(
-        new_request, new_url, options, reporting_policy,
+        request.GetRequestContext(), new_url, options, reporting_policy,
         ResourceRequest::RedirectStatus::kFollowedRedirect);
 
     ResourceRequestBlockedReason blocked_reason = Context().CanRequest(
@@ -448,7 +448,7 @@
       // CanRequest() below only checks enforced policies: check report-only
       // here to ensure violations are sent.
       Context().CheckCSPForRequest(
-          request, original_url, options,
+          request.GetRequestContext(), original_url, options,
           SecurityViolationReportingPolicy::kReport,
           ResourceRequest::RedirectStatus::kFollowedRedirect);
 
diff --git a/third_party/WebKit/Source/platform/loader/testing/MockFetchContext.h b/third_party/WebKit/Source/platform/loader/testing/MockFetchContext.h
index 00a3054..d30afd3 100644
--- a/third_party/WebKit/Source/platform/loader/testing/MockFetchContext.h
+++ b/third_party/WebKit/Source/platform/loader/testing/MockFetchContext.h
@@ -62,7 +62,7 @@
     return ResourceRequestBlockedReason::kNone;
   }
   ResourceRequestBlockedReason CheckCSPForRequest(
-      const ResourceRequest& request,
+      WebURLRequest::RequestContext,
       const KURL& url,
       const ResourceLoaderOptions& options,
       SecurityViolationReportingPolicy reporting_policy,
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 42d9ef3..01608d0 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py
@@ -115,7 +115,6 @@
             _log.info('Done: no changes to import.')
             return 0
 
-        self.run(['git', 'commit', '--all', '-F', '-'], stdin=commit_message)
         self._commit_changes(commit_message)
         _log.info('Changes imported and committed.')
 
diff --git a/third_party/axe-core/README.chromium b/third_party/axe-core/README.chromium
index 6bd3e1bb..7ab4e2f 100644
--- a/third_party/axe-core/README.chromium
+++ b/third_party/axe-core/README.chromium
@@ -2,8 +2,8 @@
 Short Name: axe-core
 URL: https://github.com/dequelabs/axe-core/
 Version: 0
-Date: Sun Jun 18 19:21:36 2017 -0400
-Revision: 1986520cdca8ed0f208d2cbd918829b27266a374
+Date: Mon Jul 24 12:17:05 2017
+Revision: d02dba3223fefe525438330e40b5da5de81eeeb5
 License: MPL 2.0
 License File: LICENSE
 Security Critical: no
diff --git a/third_party/axe-core/axe.js b/third_party/axe-core/axe.js
index 19c2cbf..2e2c746b 100644
--- a/third_party/axe-core/axe.js
+++ b/third_party/axe-core/axe.js
@@ -1,4 +1,4 @@
-/*! aXe v2.3.1
+/*! aXe v3.0.0-alpha-1
  * Copyright (c) 2017 Deque Systems, Inc.
  *
  * Your use of this Source Code Form is subject to the terms of the Mozilla Public
@@ -19,7 +19,7 @@
     return obj && typeof Symbol === 'function' && obj.constructor === Symbol && obj !== Symbol.prototype ? 'symbol' : typeof obj;
   };
   var axe = axe || {};
-  axe.version = '2.3.1';
+  axe.version = '3.0.0-alpha-1';
   if (typeof define === 'function' && define.amd) {
     define([], function() {
       'use strict';
@@ -144,7 +144,7 @@
   Audit.prototype.run = function(context, options, resolve, reject) {
     'use strict';
     this.validateOptions(options);
-    axe._tree = axe.utils.getFlattenedTree(document.body);
+    axe._tree = axe.utils.getFlattenedTree(document.documentElement);
     var q = axe.utils.queue();
     this.rules.forEach(function(rule) {
       if (axe.utils.ruleShouldRun(rule, context, options)) {
@@ -166,7 +166,7 @@
                 result: axe.constants.CANTTELL,
                 description: 'An error occured while running this rule',
                 message: err.message,
-                help: err.stack || err.message,
+                stack: err.stack,
                 error: err
               });
               res(errResult);
@@ -543,7 +543,7 @@
     var nodes = void 0;
     try {
       nodes = this.gather(context).filter(function(node) {
-        return _this.matches(node.actualNode);
+        return _this.matches(node.actualNode, node);
       });
     } catch (error) {
       reject(new SupportError({
@@ -1012,7 +1012,13 @@
       });
     }
     q.defer(function(res, rej) {
-      audit.run(context, options, res, rej);
+      if (options.restoreScroll) {
+        var scrollState = axe.utils.getScrollState();
+        audit.run(context, options, res, rej);
+        axe.utils.setScrollState(scrollState);
+      } else {
+        audit.run(context, options, res, rej);
+      }
     });
     q.then(function(data) {
       try {
@@ -2372,9 +2378,11 @@
     }
     nodeName = node.nodeName.toLowerCase();
     if (node.shadowRoot && nodeName !== 'marquee') {
+      retVal = virtualDOMfromNode(node, shadowId);
       shadowId = 'a' + Math.random().toString().substring(2);
       realArray = Array.from(node.shadowRoot.childNodes);
-      return realArray.reduce(reduceShadowDOM, []);
+      retVal.children = realArray.reduce(reduceShadowDOM, []);
+      return [ retVal ];
     } else {
       if (nodeName === 'content') {
         realArray = Array.from(node.getDistributedNodes());
@@ -2407,6 +2415,9 @@
   };
   axe.utils.getNodeFromTree = function(vNode, node) {
     var found;
+    if (vNode.actualNode === node) {
+      return vNode;
+    }
     vNode.children.forEach(function(candidate) {
       var retVal;
       if (candidate.actualNode === node) {
@@ -2627,11 +2638,11 @@
   }
   var createSelector = {
     getElmId: function getElmId(elm) {
-      if (!elm.id) {
+      if (!elm.getAttribute('id')) {
         return;
       }
       var doc = elm.getRootNode && elm.getRootNode() || document;
-      var id = '#' + escapeSelector(elm.id || '');
+      var id = '#' + escapeSelector(elm.getAttribute('id') || '');
       if (!id.match(/player_uid_/) && doc.querySelectorAll(id).length === 1) {
         return id;
       }
@@ -2658,7 +2669,7 @@
       }
     },
     getElmNameProp: function getElmNameProp(elm) {
-      if (!elm.id && elm.name) {
+      if (!elm.hasAttribute('id') && elm.name) {
         return '[name="' + escapeSelector(elm.name) + '"]';
       }
     },
@@ -2814,7 +2825,8 @@
     if (node.nodeType === 1) {
       var element = {};
       element.str = node.nodeName.toLowerCase();
-      if (node.getAttribute && node.getAttribute('id') && node.ownerDocument.querySelectorAll('#' + axe.utils.escapeSelector(node.id)).length === 1) {
+      var id = node.getAttribute && axe.utils.escapeSelector(node.getAttribute('id'));
+      if (id && node.ownerDocument.querySelectorAll('#' + id).length === 1) {
         element.id = node.getAttribute('id');
       }
       if (count > 1) {
@@ -3773,6 +3785,56 @@
     }
   };
   'use strict';
+  function getScroll(elm) {
+    var style = window.getComputedStyle(elm);
+    var visibleOverflowY = style.getPropertyValue('overflow-y') === 'visible';
+    var visibleOverflowX = style.getPropertyValue('overflow-x') === 'visible';
+    if (!visibleOverflowY && elm.scrollHeight > elm.clientHeight || !visibleOverflowX && elm.scrollWidth > elm.clientWidth) {
+      return {
+        elm: elm,
+        top: elm.scrollTop,
+        left: elm.scrollLeft
+      };
+    }
+  }
+  function setScroll(elm, top, left) {
+    if (elm === window) {
+      return elm.scroll(top, left);
+    } else {
+      elm.scrollTop = top;
+      elm.scrollLeft = left;
+    }
+  }
+  function getElmScrollRecursive(root) {
+    return Array.from(root.children).reduce(function(scrolls, elm) {
+      var scroll = getScroll(elm);
+      if (scroll) {
+        scrolls.push(scroll);
+      }
+      return scrolls.concat(getElmScrollRecursive(elm));
+    }, []);
+  }
+  axe.utils.getScrollState = function getScrollState() {
+    var win = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : window;
+    var root = win.document.documentElement;
+    var windowScroll = [ win.pageXOffset !== undefined ? {
+      elm: win,
+      top: win.pageYOffset,
+      left: win.pageXOffset
+    } : {
+      elm: root,
+      top: root.scrollTop,
+      left: root.scrollLeft
+    } ];
+    return windowScroll.concat(getElmScrollRecursive(document.body));
+  };
+  axe.utils.setScrollState = function setScrollState(scrollState) {
+    scrollState.forEach(function(_ref) {
+      var elm = _ref.elm, top = _ref.top, left = _ref.left;
+      return setScroll(elm, top, left);
+    });
+  };
+  'use strict';
   function getDeepest(collection) {
     'use strict';
     return collection.sort(function(a, b) {
@@ -4176,7 +4238,7 @@
       },
       checks: {
         accesskeys: {
-          impact: 'critical',
+          impact: 'serious',
           messages: {
             pass: function anonymous(it) {
               var out = 'Accesskey attribute value is unique';
@@ -4202,7 +4264,7 @@
           }
         },
         'non-empty-title': {
-          impact: 'critical',
+          impact: 'serious',
           messages: {
             pass: function anonymous(it) {
               var out = 'Element has a title attribute';
@@ -4215,7 +4277,7 @@
           }
         },
         'aria-label': {
-          impact: 'critical',
+          impact: 'serious',
           messages: {
             pass: function anonymous(it) {
               var out = 'aria-label attribute exists and is not empty';
@@ -4228,7 +4290,7 @@
           }
         },
         'aria-labelledby': {
-          impact: 'critical',
+          impact: 'serious',
           messages: {
             pass: function anonymous(it) {
               var out = 'aria-labelledby attribute exists and references elements that are visible to screen readers';
@@ -4423,7 +4485,7 @@
           }
         },
         'is-on-screen': {
-          impact: 'minor',
+          impact: 'serious',
           messages: {
             pass: function anonymous(it) {
               var out = 'Element is not visible';
@@ -4480,7 +4542,7 @@
           }
         },
         'role-presentation': {
-          impact: 'moderate',
+          impact: 'minor',
           messages: {
             pass: function anonymous(it) {
               var out = 'Element\'s default semantics were overriden with role="presentation"';
@@ -4493,7 +4555,7 @@
           }
         },
         'role-none': {
-          impact: 'moderate',
+          impact: 'minor',
           messages: {
             pass: function anonymous(it) {
               var out = 'Element\'s default semantics were overriden with role="none"';
@@ -4519,7 +4581,7 @@
           }
         },
         'internal-link-present': {
-          impact: 'critical',
+          impact: 'serious',
           messages: {
             pass: function anonymous(it) {
               var out = 'Valid skip link found';
@@ -4532,7 +4594,7 @@
           }
         },
         'header-present': {
-          impact: 'moderate',
+          impact: 'serious',
           messages: {
             pass: function anonymous(it) {
               var out = 'Page has a header';
@@ -4660,7 +4722,7 @@
           }
         },
         'doc-has-title': {
-          impact: 'moderate',
+          impact: 'serious',
           messages: {
             pass: function anonymous(it) {
               var out = 'Document has a non-empty <title> element';
@@ -4686,7 +4748,7 @@
           }
         },
         'has-visible-text': {
-          impact: 'moderate',
+          impact: 'minor',
           messages: {
             pass: function anonymous(it) {
               var out = 'Element has text that is visible to screen readers';
@@ -4712,7 +4774,7 @@
           }
         },
         'heading-order': {
-          impact: 'minor',
+          impact: 'moderate',
           messages: {
             pass: function anonymous(it) {
               var out = 'Heading order valid';
@@ -4911,7 +4973,7 @@
           }
         },
         'link-in-text-block': {
-          impact: 'critical',
+          impact: 'serious',
           messages: {
             pass: function anonymous(it) {
               var out = 'Links can be distinguished from surrounding text in a way that does not rely on color';
@@ -4945,7 +5007,7 @@
           }
         },
         listitem: {
-          impact: 'critical',
+          impact: 'serious',
           messages: {
             pass: function anonymous(it) {
               var out = 'List item has a <ul>, <ol> or role="list" parent element';
@@ -4974,11 +5036,11 @@
           impact: 'minor',
           messages: {
             pass: function anonymous(it) {
-              var out = '<meta> tag does not prevent significant zooming';
+              var out = '<meta> tag does not prevent significant zooming on mobile devices';
               return out;
             },
             fail: function anonymous(it) {
-              var out = '<meta> tag limits zooming';
+              var out = '<meta> tag limits zooming on mobile devices';
               return out;
             }
           }
@@ -4987,17 +5049,17 @@
           impact: 'critical',
           messages: {
             pass: function anonymous(it) {
-              var out = '<meta> tag does not disable zooming';
+              var out = '<meta> tag does not disable zooming on mobile devices';
               return out;
             },
             fail: function anonymous(it) {
-              var out = '<meta> tag disables zooming';
+              var out = '<meta> tag disables zooming on mobile devices';
               return out;
             }
           }
         },
         'p-as-heading': {
-          impact: 'critical',
+          impact: 'serious',
           messages: {
             pass: function anonymous(it) {
               var out = '<p> elements are not styled as headings';
@@ -5023,7 +5085,7 @@
           }
         },
         'html5-scope': {
-          impact: 'serious',
+          impact: 'moderate',
           messages: {
             pass: function anonymous(it) {
               var out = 'Scope attribute is only used on table header elements (<th>)';
@@ -5062,7 +5124,7 @@
           }
         },
         'skip-link': {
-          impact: 'critical',
+          impact: 'moderate',
           messages: {
             pass: function anonymous(it) {
               var out = 'Valid skip link found';
@@ -5088,7 +5150,7 @@
           }
         },
         'same-caption-summary': {
-          impact: 'moderate',
+          impact: 'minor',
           messages: {
             pass: function anonymous(it) {
               var out = 'Content of summary attribute and <caption> are not duplicated';
@@ -5101,7 +5163,7 @@
           }
         },
         'caption-faked': {
-          impact: 'critical',
+          impact: 'serious',
           messages: {
             pass: function anonymous(it) {
               var out = 'The first row of a table is not used as a caption';
@@ -5140,7 +5202,7 @@
           }
         },
         'th-has-data-cells': {
-          impact: 'critical',
+          impact: 'serious',
           messages: {
             pass: function anonymous(it) {
               var out = 'All table header cells refer to data cells';
@@ -5157,7 +5219,7 @@
           }
         },
         description: {
-          impact: 'serious',
+          impact: 'critical',
           messages: {
             pass: function anonymous(it) {
               var out = 'The multimedia element has an audio description track';
@@ -5227,7 +5289,7 @@
       none: []
     }, {
       id: 'aria-allowed-attr',
-      matches: function matches(node) {
+      matches: function matches(node, virtualNode) {
         var role = node.getAttribute('role');
         if (!role) {
           role = axe.commons.aria.implicitRole(node);
@@ -5288,7 +5350,7 @@
       none: [ 'invalidrole', 'abstractrole' ]
     }, {
       id: 'aria-valid-attr-value',
-      matches: function matches(node) {
+      matches: function matches(node, virtualNode) {
         var aria = /^aria-/;
         if (node.hasAttributes()) {
           var attrs = node.attributes;
@@ -5309,7 +5371,7 @@
       none: []
     }, {
       id: 'aria-valid-attr',
-      matches: function matches(node) {
+      matches: function matches(node, virtualNode) {
         var aria = /^aria-/;
         if (node.hasAttributes()) {
           var attrs = node.attributes;
@@ -5355,7 +5417,7 @@
       id: 'bypass',
       selector: 'html',
       pageLevel: true,
-      matches: function matches(node) {
+      matches: function matches(node, virtualNode) {
         return !!node.querySelector('a[href]');
       },
       tags: [ 'cat.keyboard', 'wcag2a', 'wcag241', 'section508', 'section508.22.o' ],
@@ -5371,8 +5433,8 @@
       none: []
     }, {
       id: 'color-contrast',
-      matches: function matches(node) {
-        var nodeName = node.nodeName.toUpperCase(), nodeType = node.type, doc = document;
+      matches: function matches(node, virtualNode) {
+        var nodeName = node.nodeName.toUpperCase(), nodeType = node.type;
         if (node.getAttribute('aria-disabled') === 'true' || axe.commons.dom.findUp(node, '[aria-disabled="true"]')) {
           return false;
         }
@@ -5400,29 +5462,32 @@
           if (nodeParentLabel) {
             relevantNode = nodeParentLabel;
           }
+          var doc = axe.commons.dom.getRootNode(relevantNode);
           var candidate = relevantNode.htmlFor && doc.getElementById(relevantNode.htmlFor);
           if (candidate && candidate.disabled) {
             return false;
           }
-          var candidate = node.querySelector('input:not([type="hidden"]):not([type="image"])' + ':not([type="button"]):not([type="submit"]):not([type="reset"]), select, textarea');
+          var candidate = axe.utils.querySelectorAll(virtualNode, 'input:not([type="hidden"]):not([type="image"])' + ':not([type="button"]):not([type="submit"]):not([type="reset"]), select, textarea');
+          if (candidate.length && candidate[0].actualNode.disabled) {
+            return false;
+          }
+        }
+        if (node.getAttribute('id')) {
+          var id = axe.commons.utils.escapeSelector(node.getAttribute('id'));
+          var _doc = axe.commons.dom.getRootNode(node);
+          var candidate = _doc.querySelector('[aria-labelledby~=' + id + ']');
           if (candidate && candidate.disabled) {
             return false;
           }
         }
-        if (node.id) {
-          var candidate = doc.querySelector('[aria-labelledby~=' + axe.commons.utils.escapeSelector(node.id) + ']');
-          if (candidate && candidate.disabled) {
-            return false;
-          }
-        }
-        if (axe.commons.text.visible(node, false, true) === '') {
+        if (axe.commons.text.visible(virtualNode, false, true) === '') {
           return false;
         }
-        var range = document.createRange(), childNodes = node.childNodes, length = childNodes.length, child, index;
+        var range = document.createRange(), childNodes = virtualNode.children, length = childNodes.length, child, index;
         for (index = 0; index < length; index++) {
           child = childNodes[index];
-          if (child.nodeType === 3 && axe.commons.text.sanitize(child.nodeValue) !== '') {
-            range.selectNodeContents(child);
+          if (child.actualNode.nodeType === 3 && axe.commons.text.sanitize(child.actualNode.nodeValue) !== '') {
+            range.selectNodeContents(child.actualNode);
           }
         }
         var rects = range.getClientRects();
@@ -5445,7 +5510,7 @@
     }, {
       id: 'definition-list',
       selector: 'dl',
-      matches: function matches(node) {
+      matches: function matches(node, virtualNode) {
         return !node.getAttribute('role');
       },
       tags: [ 'cat.structure', 'wcag2a', 'wcag131' ],
@@ -5455,7 +5520,7 @@
     }, {
       id: 'dlitem',
       selector: 'dd, dt',
-      matches: function matches(node) {
+      matches: function matches(node, virtualNode) {
         return !node.getAttribute('role');
       },
       tags: [ 'cat.structure', 'wcag2a', 'wcag131' ],
@@ -5465,7 +5530,7 @@
     }, {
       id: 'document-title',
       selector: 'html',
-      matches: function matches(node) {
+      matches: function matches(node, virtualNode) {
         return node.ownerDocument.defaultView.self === node.ownerDocument.defaultView.top;
       },
       tags: [ 'cat.text-alternatives', 'wcag2a', 'wcag242' ],
@@ -5491,7 +5556,7 @@
     }, {
       id: 'frame-title-unique',
       selector: 'frame[title], iframe[title]',
-      matches: function matches(node) {
+      matches: function matches(node, virtualNode) {
         var title = node.getAttribute('title');
         return !!(title ? axe.commons.text.sanitize(title).trim() : '');
       },
@@ -5569,7 +5634,7 @@
     }, {
       id: 'label-title-only',
       selector: 'input, select, textarea',
-      matches: function matches(node) {
+      matches: function matches(node, virtualNode) {
         if (node.nodeName.toLowerCase() !== 'input') {
           return true;
         }
@@ -5587,7 +5652,7 @@
     }, {
       id: 'label',
       selector: 'input, select, textarea',
-      matches: function matches(node) {
+      matches: function matches(node, virtualNode) {
         if (node.nodeName.toLowerCase() !== 'input') {
           return true;
         }
@@ -5604,7 +5669,7 @@
     }, {
       id: 'layout-table',
       selector: 'table',
-      matches: function matches(node) {
+      matches: function matches(node, virtualNode) {
         return !axe.commons.table.isDataTable(node);
       },
       tags: [ 'cat.semantics', 'wcag2a', 'wcag131' ],
@@ -5614,7 +5679,7 @@
     }, {
       id: 'link-in-text-block',
       selector: 'a[href], *[role=link]',
-      matches: function matches(node) {
+      matches: function matches(node, virtualNode) {
         var text = axe.commons.text.sanitize(node.textContent);
         var role = node.getAttribute('role');
         if (role && role !== 'link') {
@@ -5636,17 +5701,17 @@
     }, {
       id: 'link-name',
       selector: 'a[href], [role=link][href]',
-      matches: function matches(node) {
+      matches: function matches(node, virtualNode) {
         return node.getAttribute('role') !== 'button';
       },
-      tags: [ 'cat.name-role-value', 'wcag2a', 'wcag111', 'wcag412', 'section508', 'section508.22.a' ],
+      tags: [ 'cat.name-role-value', 'wcag2a', 'wcag111', 'wcag412', 'wcag244', 'section508', 'section508.22.a' ],
       all: [],
       any: [ 'has-visible-text', 'aria-label', 'aria-labelledby', 'role-presentation', 'role-none' ],
       none: [ 'focusable-no-name' ]
     }, {
       id: 'list',
       selector: 'ul, ol',
-      matches: function matches(node) {
+      matches: function matches(node, virtualNode) {
         return !node.getAttribute('role');
       },
       tags: [ 'cat.structure', 'wcag2a', 'wcag131' ],
@@ -5656,7 +5721,7 @@
     }, {
       id: 'listitem',
       selector: 'li',
-      matches: function matches(node) {
+      matches: function matches(node, virtualNode) {
         return !node.getAttribute('role');
       },
       tags: [ 'cat.structure', 'wcag2a', 'wcag131' ],
@@ -5716,7 +5781,7 @@
     }, {
       id: 'p-as-heading',
       selector: 'p',
-      matches: function matches(node) {
+      matches: function matches(node, virtualNode) {
         var children = Array.from(node.parentNode.childNodes);
         var nodeText = node.textContent.trim();
         var isSentence = /[.!?:;](?![.!?:;])/g;
@@ -5805,7 +5870,7 @@
     }, {
       id: 'table-fake-caption',
       selector: 'table',
-      matches: function matches(node) {
+      matches: function matches(node, virtualNode) {
         return axe.commons.table.isDataTable(node);
       },
       tags: [ 'cat.tables', 'experimental', 'wcag2a', 'wcag131', 'section508', 'section508.22.g' ],
@@ -5815,7 +5880,7 @@
     }, {
       id: 'td-has-header',
       selector: 'table',
-      matches: function matches(node) {
+      matches: function matches(node, virtualNode) {
         if (axe.commons.table.isDataTable(node)) {
           var tableArray = axe.commons.table.toArray(node);
           return tableArray.length >= 3 && tableArray[0].length >= 3 && tableArray[1].length >= 3 && tableArray[2].length >= 3;
@@ -5836,7 +5901,7 @@
     }, {
       id: 'th-has-data-cells',
       selector: 'table',
-      matches: function matches(node) {
+      matches: function matches(node, virtualNode) {
         return axe.commons.table.isDataTable(node);
       },
       tags: [ 'cat.tables', 'wcag2a', 'wcag131', 'section508', 'section508.22.g' ],
@@ -5846,7 +5911,7 @@
     }, {
       id: 'valid-lang',
       selector: '[lang], [xml\\:lang]',
-      matches: function matches(node) {
+      matches: function matches(node, virtualNode) {
         return node.nodeName.toLowerCase() !== 'html';
       },
       tags: [ 'cat.language', 'wcag2aa', 'wcag312' ],
@@ -5872,12 +5937,12 @@
     } ],
     checks: [ {
       id: 'abstractrole',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         return axe.commons.aria.getRoleType(node.getAttribute('role')) === 'abstract';
       }
     }, {
       id: 'aria-allowed-attr',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var invalid = [];
         var attr, attrName, allowed, role = node.getAttribute('role'), attrs = node.attributes;
         if (!role) {
@@ -5901,17 +5966,17 @@
       }
     }, {
       id: 'aria-hidden-body',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         return node.getAttribute('aria-hidden') !== 'true';
       }
     }, {
       id: 'invalidrole',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         return !axe.commons.aria.isValidRole(node.getAttribute('role'));
       }
     }, {
       id: 'aria-required-attr',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var missing = [];
         if (node.hasAttributes()) {
           var attr, role = node.getAttribute('role'), required = axe.commons.aria.requiredAttr(role);
@@ -5932,9 +5997,9 @@
       }
     }, {
       id: 'aria-required-children',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var requiredOwned = axe.commons.aria.requiredOwned, implicitNodes = axe.commons.aria.implicitNodes, matchesSelector = axe.commons.utils.matchesSelector, idrefs = axe.commons.dom.idrefs;
-        function owns(node, role, ariaOwned) {
+        function owns(node, virtualTree, role, ariaOwned) {
           if (node === null) {
             return false;
           }
@@ -5943,7 +6008,7 @@
             selector = selector.concat(implicit);
           }
           selector = selector.join(',');
-          return ariaOwned ? matchesSelector(node, selector) || !!node.querySelector(selector) : !!node.querySelector(selector);
+          return ariaOwned ? matchesSelector(node, selector) || !!axe.utils.querySelectorAll(virtualTree, selector)[0] : !!axe.utils.querySelectorAll(virtualTree, selector)[0];
         }
         function ariaOwns(nodes, role) {
           var index, length;
@@ -5951,7 +6016,8 @@
             if (nodes[index] === null) {
               continue;
             }
-            if (owns(nodes[index], role, true)) {
+            var virtualTree = axe.utils.getNodeFromTree(axe._tree[0], nodes[index]);
+            if (owns(nodes[index], virtualTree, role, true)) {
               return true;
             }
           }
@@ -5961,7 +6027,7 @@
           var i, l = childRoles.length, missing = [], ownedElements = idrefs(node, 'aria-owns');
           for (i = 0; i < l; i++) {
             var r = childRoles[i];
-            if (owns(node, r) || ariaOwns(ownedElements, r)) {
+            if (owns(node, virtualNode, r) || ariaOwns(ownedElements, r)) {
               if (!all) {
                 return null;
               }
@@ -5999,7 +6065,7 @@
       }
     }, {
       id: 'aria-required-parent',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         function getSelector(role) {
           var impliedNative = axe.commons.aria.implicitNodes(role) || [];
           return impliedNative.concat('[role="' + role + '"]').join(',');
@@ -6027,13 +6093,15 @@
         function getAriaOwners(element) {
           var owners = [], o = null;
           while (element) {
-            if (element.id) {
-              o = document.querySelector('[aria-owns~=' + axe.commons.utils.escapeSelector(element.id) + ']');
+            if (element.getAttribute('id')) {
+              var id = axe.commons.utils.escapeSelector(element.getAttribute('id'));
+              var doc = axe.commons.dom.getRootNode(element);
+              o = doc.querySelector('[aria-owns~=' + id + ']');
               if (o) {
                 owners.push(o);
               }
             }
-            element = element.parentNode;
+            element = element.parentElement;
           }
           return owners.length ? owners : null;
         }
@@ -6055,7 +6123,7 @@
       }
     }, {
       id: 'aria-valid-attr-value',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         options = Array.isArray(options) ? options : [];
         var invalid = [], aria = /^aria-/;
         var attr, attrName, attrs = node.attributes;
@@ -6075,7 +6143,7 @@
       options: []
     }, {
       id: 'aria-valid-attr',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         options = Array.isArray(options) ? options : [];
         var invalid = [], aria = /^aria-/;
         var attr, attrs = node.attributes;
@@ -6094,7 +6162,7 @@
       options: []
     }, {
       id: 'color-contrast',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         if (!axe.commons.dom.isVisible(node, false)) {
           return true;
         }
@@ -6124,20 +6192,20 @@
           missingData: missing
         };
         this.data(data);
-        if (!cr.isValid || equalRatio) {
-          this.relatedNodes(bgNodes);
-        }
         if (fgColor === null || bgColor === null || equalRatio) {
           missing = null;
           axe.commons.color.incompleteData.clear();
+          this.relatedNodes(bgNodes);
           return undefined;
+        } else if (!cr.isValid) {
+          this.relatedNodes(bgNodes);
         }
         return cr.isValid;
       }
     }, {
       id: 'link-in-text-block',
-      evaluate: function evaluate(node, options) {
-        var color = axe.commons.color;
+      evaluate: function evaluate(node, options, virtualNode) {
+        var _axe$commons = axe.commons, color = _axe$commons.color, dom = _axe$commons.dom;
         function getContrast(color1, color2) {
           var c1lum = color1.getRelativeLuminance();
           var c2lum = color2.getRelativeLuminance();
@@ -6151,10 +6219,11 @@
         if (isBlock(node)) {
           return false;
         }
-        var parentBlock = node.parentNode;
+        var parentBlock = dom.getComposedParent(node);
         while (parentBlock.nodeType === 1 && !isBlock(parentBlock)) {
-          parentBlock = parentBlock.parentNode;
+          parentBlock = dom.getComposedParent(parentBlock);
         }
+        this.relatedNodes([ parentBlock ]);
         if (color.elementIsDistinct(node, parentBlock)) {
           return true;
         } else {
@@ -6196,7 +6265,7 @@
       }
     }, {
       id: 'fieldset',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var failureCode, self = this;
         function getUnrelatedElements(parent, name) {
           return axe.commons.utils.toArray(parent.querySelectorAll('select,textarea,button,input:not([name="' + name + '"]):not([type="hidden"])'));
@@ -6246,7 +6315,8 @@
         }
         function runCheck(element) {
           var name = axe.commons.utils.escapeSelector(node.name);
-          var matchingNodes = document.querySelectorAll('input[type="' + axe.commons.utils.escapeSelector(node.type) + '"][name="' + name + '"]');
+          var root = axe.commons.dom.getRootNode(node);
+          var matchingNodes = root.querySelectorAll('input[type="' + axe.commons.utils.escapeSelector(node.type) + '"][name="' + name + '"]');
           if (matchingNodes.length < 2) {
             return true;
           }
@@ -6256,8 +6326,11 @@
             failureCode = 'no-group';
             self.relatedNodes(spliceCurrentNode(matchingNodes, element));
             return false;
+          } else if (fieldset) {
+            return checkFieldset(fieldset, name);
+          } else {
+            return checkARIAGroup(group, name);
           }
-          return fieldset ? checkFieldset(fieldset, name) : checkARIAGroup(group, name);
         }
         var data = {
           name: node.getAttribute('name'),
@@ -6296,12 +6369,13 @@
       }
     }, {
       id: 'group-labelledby',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         this.data({
           name: node.getAttribute('name'),
           type: node.getAttribute('type')
         });
-        var matchingNodes = document.querySelectorAll('input[type="' + axe.commons.utils.escapeSelector(node.type) + '"][name="' + axe.commons.utils.escapeSelector(node.name) + '"]');
+        var doc = axe.commons.dom.getRootNode(node);
+        var matchingNodes = doc.querySelectorAll('input[type="' + axe.commons.utils.escapeSelector(node.type) + '"][name="' + axe.commons.utils.escapeSelector(node.name) + '"]');
         if (matchingNodes.length <= 1) {
           return true;
         }
@@ -6310,10 +6384,10 @@
           return l ? l.split(/\s+/) : [];
         }).reduce(function(prev, curr) {
           return prev.filter(function(n) {
-            return curr.indexOf(n) !== -1;
+            return curr.includes(n);
           });
         }).filter(function(n) {
-          var labelNode = document.getElementById(n);
+          var labelNode = doc.getElementById(n);
           return labelNode && axe.commons.text.accessibleText(labelNode);
         }).length !== 0;
       },
@@ -6333,7 +6407,7 @@
       }
     }, {
       id: 'accesskeys',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         if (axe.commons.dom.isVisible(node, false)) {
           this.data(node.getAttribute('accesskey'));
           this.relatedNodes([ node ]);
@@ -6361,7 +6435,7 @@
       }
     }, {
       id: 'focusable-no-name',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var tabIndex = node.getAttribute('tabindex'), isFocusable = axe.commons.dom.isFocusable(node) && tabIndex > -1;
         if (!isFocusable) {
           return false;
@@ -6370,31 +6444,31 @@
       }
     }, {
       id: 'tabindex',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         return node.tabIndex <= 0;
       }
     }, {
       id: 'duplicate-img-label',
-      evaluate: function evaluate(node, options) {
-        var imgs = node.querySelectorAll('img');
-        var text = axe.commons.text.visible(node, true).toLowerCase();
+      evaluate: function evaluate(node, options, virtualNode) {
+        var text = axe.commons.text.visible(virtualNode, true).toLowerCase();
         if (text === '') {
           return false;
         }
-        for (var i = 0, len = imgs.length; i < len; i++) {
-          var img = imgs[i];
-          var imgAlt = axe.commons.text.accessibleText(img).toLowerCase();
-          if (imgAlt === text && img.getAttribute('role') !== 'presentation' && axe.commons.dom.isVisible(img)) {
-            return true;
-          }
-        }
-        return false;
+        var images = axe.utils.querySelectorAll(virtualNode, 'img').filter(function(_ref) {
+          var actualNode = _ref.actualNode;
+          return axe.commons.dom.isVisible(actualNode) && ![ 'none', 'presentation' ].includes(actualNode.getAttribute('role'));
+        });
+        return images.some(function(img) {
+          return text === axe.commons.text.accessibleText(img).toLowerCase();
+        });
       }
     }, {
       id: 'explicit-label',
-      evaluate: function evaluate(node, options) {
-        if (node.id) {
-          var label = document.querySelector('label[for="' + axe.commons.utils.escapeSelector(node.id) + '"]');
+      evaluate: function evaluate(node, options, virtualNode) {
+        if (node.getAttribute('id')) {
+          var root = axe.commons.dom.getRootNode(node);
+          var id = axe.commons.utils.escapeSelector(node.getAttribute('id'));
+          var label = root.querySelector('label[for="' + id + '"]');
           if (label) {
             return !!axe.commons.text.accessibleText(label);
           }
@@ -6403,8 +6477,8 @@
       }
     }, {
       id: 'help-same-as-label',
-      evaluate: function evaluate(node, options) {
-        var labelText = axe.commons.text.label(node), check = node.getAttribute('title');
+      evaluate: function evaluate(node, options, virtualNode) {
+        var labelText = axe.commons.text.label(virtualNode), check = node.getAttribute('title');
         if (!labelText) {
           return false;
         }
@@ -6422,7 +6496,7 @@
       enabled: false
     }, {
       id: 'implicit-label',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var label = axe.commons.dom.findUp(node, 'label');
         if (label) {
           return !!axe.commons.text.accessibleText(label);
@@ -6431,8 +6505,10 @@
       }
     }, {
       id: 'multiple-label',
-      evaluate: function evaluate(node, options) {
-        var labels = [].slice.call(document.querySelectorAll('label[for="' + axe.commons.utils.escapeSelector(node.id) + '"]')), parent = node.parentNode;
+      evaluate: function evaluate(node, options, virtualNode) {
+        var id = axe.commons.utils.escapeSelector(node.getAttribute('id'));
+        var labels = Array.from(document.querySelectorAll('label[for="' + id + '"]'));
+        var parent = node.parentNode;
         if (labels.length) {
           labels = labels.filter(function(label, index) {
             if (index === 0 && !axe.commons.dom.isVisible(label, true) || axe.commons.dom.isVisible(label, true)) {
@@ -6451,18 +6527,18 @@
       }
     }, {
       id: 'title-only',
-      evaluate: function evaluate(node, options) {
-        var labelText = axe.commons.text.label(node);
+      evaluate: function evaluate(node, options, virtualNode) {
+        var labelText = axe.commons.text.label(virtualNode);
         return !labelText && !!(node.getAttribute('title') || node.getAttribute('aria-describedby'));
       }
     }, {
       id: 'has-lang',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         return !!(node.getAttribute('lang') || node.getAttribute('xml:lang') || '').trim();
       }
     }, {
       id: 'valid-lang',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         function getBaseLang(lang) {
           return lang.trim().split('-')[0].toLowerCase();
         }
@@ -6487,44 +6563,37 @@
       }
     }, {
       id: 'dlitem',
-      evaluate: function evaluate(node, options) {
-        return node.parentNode.tagName === 'DL';
+      evaluate: function evaluate(node, options, virtualNode) {
+        var parent = axe.commons.dom.getComposedParent(node);
+        return parent.nodeName.toUpperCase() === 'DL';
       }
     }, {
       id: 'has-listitem',
-      evaluate: function evaluate(node, options) {
-        var children = node.children;
-        if (children.length === 0) {
-          return true;
-        }
-        for (var i = 0; i < children.length; i++) {
-          if (children[i].nodeName.toUpperCase() === 'LI') {
-            return false;
-          }
-        }
-        return true;
+      evaluate: function evaluate(node, options, virtualNode) {
+        return virtualNode.children.every(function(_ref2) {
+          var actualNode = _ref2.actualNode;
+          return actualNode.nodeName.toUpperCase() !== 'LI';
+        });
       }
     }, {
       id: 'listitem',
-      evaluate: function evaluate(node, options) {
-        if ([ 'UL', 'OL' ].indexOf(node.parentNode.nodeName.toUpperCase()) !== -1) {
-          return true;
-        }
-        return node.parentNode.getAttribute('role') === 'list';
+      evaluate: function evaluate(node, options, virtualNode) {
+        var parent = axe.commons.dom.getComposedParent(node);
+        return [ 'UL', 'OL' ].includes(parent.nodeName.toUpperCase()) || (parent.getAttribute('role') || '').toLowerCase() === 'list';
       }
     }, {
       id: 'only-dlitems',
-      evaluate: function evaluate(node, options) {
-        var child, nodeName, bad = [], children = node.childNodes, permitted = [ 'STYLE', 'META', 'LINK', 'MAP', 'AREA', 'SCRIPT', 'DATALIST', 'TEMPLATE' ], hasNonEmptyTextNode = false;
-        for (var i = 0; i < children.length; i++) {
-          child = children[i];
-          var nodeName = child.nodeName.toUpperCase();
-          if (child.nodeType === 1 && nodeName !== 'DT' && nodeName !== 'DD' && permitted.indexOf(nodeName) === -1) {
-            bad.push(child);
-          } else if (child.nodeType === 3 && child.nodeValue.trim() !== '') {
+      evaluate: function evaluate(node, options, virtualNode) {
+        var bad = [], permitted = [ 'STYLE', 'META', 'LINK', 'MAP', 'AREA', 'SCRIPT', 'DATALIST', 'TEMPLATE' ], hasNonEmptyTextNode = false;
+        virtualNode.children.forEach(function(_ref3) {
+          var actualNode = _ref3.actualNode;
+          var nodeName = actualNode.nodeName.toUpperCase();
+          if (actualNode.nodeType === 1 && nodeName !== 'DT' && nodeName !== 'DD' && permitted.indexOf(nodeName) === -1) {
+            bad.push(actualNode);
+          } else if (actualNode.nodeType === 3 && actualNode.nodeValue.trim() !== '') {
             hasNonEmptyTextNode = true;
           }
-        }
+        });
         if (bad.length) {
           this.relatedNodes(bad);
         }
@@ -6533,17 +6602,17 @@
       }
     }, {
       id: 'only-listitems',
-      evaluate: function evaluate(node, options) {
-        var child, nodeName, bad = [], children = node.childNodes, permitted = [ 'STYLE', 'META', 'LINK', 'MAP', 'AREA', 'SCRIPT', 'DATALIST', 'TEMPLATE' ], hasNonEmptyTextNode = false;
-        for (var i = 0; i < children.length; i++) {
-          child = children[i];
-          nodeName = child.nodeName.toUpperCase();
-          if (child.nodeType === 1 && nodeName !== 'LI' && permitted.indexOf(nodeName) === -1) {
-            bad.push(child);
-          } else if (child.nodeType === 3 && child.nodeValue.trim() !== '') {
+      evaluate: function evaluate(node, options, virtualNode) {
+        var bad = [], permitted = [ 'STYLE', 'META', 'LINK', 'MAP', 'AREA', 'SCRIPT', 'DATALIST', 'TEMPLATE' ], hasNonEmptyTextNode = false;
+        virtualNode.children.forEach(function(_ref4) {
+          var actualNode = _ref4.actualNode;
+          var nodeName = actualNode.nodeName.toUpperCase();
+          if (actualNode.nodeType === 1 && nodeName !== 'LI' && permitted.indexOf(nodeName) === -1) {
+            bad.push(actualNode);
+          } else if (actualNode.nodeType === 3 && actualNode.nodeValue.trim() !== '') {
             hasNonEmptyTextNode = true;
           }
-        }
+        });
         if (bad.length) {
           this.relatedNodes(bad);
         }
@@ -6551,14 +6620,14 @@
       }
     }, {
       id: 'structured-dlitems',
-      evaluate: function evaluate(node, options) {
-        var children = node.children;
+      evaluate: function evaluate(node, options, virtualNode) {
+        var children = virtualNode.children;
         if (!children || !children.length) {
           return false;
         }
         var hasDt = false, hasDd = false, nodeName;
         for (var i = 0; i < children.length; i++) {
-          nodeName = children[i].nodeName.toUpperCase();
+          nodeName = children[i].actualNode.nodeName.toUpperCase();
           if (nodeName === 'DT') {
             hasDt = true;
           }
@@ -6573,37 +6642,35 @@
       }
     }, {
       id: 'caption',
-      evaluate: function evaluate(node, options) {
-        var tracks = node.querySelectorAll('track');
+      evaluate: function evaluate(node, options, virtualNode) {
+        var tracks = axe.utils.querySelectorAll(virtualNode, 'track');
         if (tracks.length) {
-          for (var i = 0; i < tracks.length; i++) {
-            var kind = tracks[i].getAttribute('kind');
-            if (kind && kind === 'captions') {
-              return false;
-            }
-          }
-          return true;
+          return !tracks.some(function(_ref5) {
+            var actualNode = _ref5.actualNode;
+            return (actualNode.getAttribute('kind') || '').toLowerCase() === 'captions';
+          });
         }
         return undefined;
       }
     }, {
       id: 'description',
-      evaluate: function evaluate(node, options) {
-        var tracks = node.querySelectorAll('track');
+      evaluate: function evaluate(node, options, virtualNode) {
+        var tracks = axe.utils.querySelectorAll(virtualNode, 'track');
         if (tracks.length) {
-          for (var i = 0; i < tracks.length; i++) {
-            var kind = tracks[i].getAttribute('kind');
-            if (kind && kind === 'descriptions') {
-              return false;
-            }
-          }
-          return true;
+          var out = !tracks.some(function(_ref6) {
+            var actualNode = _ref6.actualNode;
+            return (actualNode.getAttribute('kind') || '').toLowerCase() === 'descriptions';
+          });
+          axe.log(tracks.map(function(t) {
+            return t.actualNode.getAttribute('kind');
+          }), out);
+          return out;
         }
         return undefined;
       }
     }, {
       id: 'meta-viewport-large',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         options = options || {};
         var params, content = node.getAttribute('content') || '', parsedParams = content.split(/[;,]/), result = {}, minimum = options.scaleMinimum || 2, lowerBound = options.lowerBound || false;
         for (var i = 0, l = parsedParams.length; i < l; i++) {
@@ -6630,7 +6697,7 @@
       }
     }, {
       id: 'meta-viewport',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         options = options || {};
         var params, content = node.getAttribute('content') || '', parsedParams = content.split(/[;,]/), result = {}, minimum = options.scaleMinimum || 2, lowerBound = options.lowerBound || false;
         for (var i = 0, l = parsedParams.length; i < l; i++) {
@@ -6656,12 +6723,12 @@
       }
     }, {
       id: 'header-present',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         return !!node.querySelector('h1, h2, h3, h4, h5, h6, [role="heading"]');
       }
     }, {
       id: 'heading-order',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var ariaHeadingLevel = node.getAttribute('aria-level');
         if (ariaHeadingLevel !== null) {
           this.data(parseInt(ariaHeadingLevel, 10));
@@ -6689,7 +6756,7 @@
       }
     }, {
       id: 'href-no-hash',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var href = node.getAttribute('href');
         if (href === '#') {
           return false;
@@ -6698,23 +6765,23 @@
       }
     }, {
       id: 'internal-link-present',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         return !!node.querySelector('a[href^="#"]');
       }
     }, {
       id: 'landmark',
-      evaluate: function evaluate(node, options) {
-        return node.getElementsByTagName('main').length > 0 || !!node.querySelector('[role="main"]');
+      evaluate: function evaluate(node, options, virtualNode) {
+        return axe.utils.querySelectorAll(virtualNode, 'main, [role="main"]').length > 0;
       }
     }, {
       id: 'meta-refresh',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var content = node.getAttribute('content') || '', parsedParams = content.split(/[;,]/);
         return content === '' || parsedParams[0] === '0';
       }
     }, {
       id: 'p-as-heading',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var siblings = Array.from(node.parentNode.children);
         var currentIndex = siblings.indexOf(node);
         options = options || {};
@@ -6804,48 +6871,58 @@
       }
     }, {
       id: 'region',
-      evaluate: function evaluate(node, options) {
-        var landmarkRoles = axe.commons.aria.getRolesByType('landmark'), firstLink = node.querySelector('a[href]');
-        function isSkipLink(n) {
-          return firstLink && axe.commons.dom.isFocusable(axe.commons.dom.getElementByReference(firstLink, 'href')) && firstLink === n;
-        }
-        function isLandmark(n) {
-          var role = n.getAttribute('role');
-          return role && landmarkRoles.indexOf(role) !== -1;
-        }
-        function checkRegion(n) {
-          if (isLandmark(n)) {
-            return null;
+      evaluate: function evaluate(node, options, virtualNode) {
+        var _axe$commons2 = axe.commons, dom = _axe$commons2.dom, aria = _axe$commons2.aria;
+        function getSkiplink(virtualNode) {
+          var firstLink = axe.utils.querySelectorAll(virtualNode, 'a[href]')[0];
+          if (firstLink && axe.commons.dom.getElementByReference(firstLink.actualNode, 'href')) {
+            return firstLink.actualNode;
           }
-          if (isSkipLink(n)) {
-            return getViolatingChildren(n);
-          }
-          if (axe.commons.dom.isVisible(n, true) && (axe.commons.text.visible(n, true, true) || axe.commons.dom.isVisualContent(n))) {
-            return n;
-          }
-          return getViolatingChildren(n);
         }
-        function getViolatingChildren(n) {
-          var children = axe.commons.utils.toArray(n.children);
-          if (children.length === 0) {
+        var skipLink = getSkiplink(virtualNode);
+        var landmarkRoles = aria.getRolesByType('landmark');
+        var implicitLandmarks = landmarkRoles.reduce(function(arr, role) {
+          return arr.concat(aria.implicitNodes(role));
+        }, []).filter(function(r) {
+          return r !== null;
+        }).map(function(r) {
+          return r.toUpperCase();
+        });
+        function isSkipLink(node) {
+          return skipLink && skipLink === node;
+        }
+        function isLandmark(node) {
+          if (node.hasAttribute('role')) {
+            return landmarkRoles.includes(node.getAttribute('role').toLowerCase());
+          } else {
+            return implicitLandmarks.includes(node.nodeName.toUpperCase());
+          }
+        }
+        function findRegionlessElms(virtualNode) {
+          var node = virtualNode.actualNode;
+          if (isLandmark(node) || isSkipLink(node) || !dom.isVisible(node, true)) {
             return [];
+          } else if (dom.hasContent(node, true)) {
+            return [ node ];
+          } else {
+            return virtualNode.children.filter(function(_ref7) {
+              var actualNode = _ref7.actualNode;
+              return actualNode.nodeType === 1;
+            }).map(findRegionlessElms).reduce(function(a, b) {
+              return a.concat(b);
+            }, []);
           }
-          return children.map(checkRegion).filter(function(c) {
-            return c !== null;
-          }).reduce(function(a, b) {
-            return a.concat(b);
-          }, []);
         }
-        var v = getViolatingChildren(node);
-        this.relatedNodes(v);
-        return !v.length;
+        var regionlessNodes = findRegionlessElms(virtualNode);
+        this.relatedNodes(regionlessNodes);
+        return regionlessNodes.length === 0;
       },
       after: function after(results, options) {
         return [ results[0] ];
       }
     }, {
       id: 'skip-link',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         return axe.commons.dom.isFocusable(axe.commons.dom.getElementByReference(node, 'href'));
       },
       after: function after(results, options) {
@@ -6853,7 +6930,7 @@
       }
     }, {
       id: 'unique-frame-title',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var title = axe.commons.text.sanitize(node.title).trim().toLowerCase();
         this.data(title);
         return true;
@@ -6870,13 +6947,13 @@
       }
     }, {
       id: 'aria-label',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var label = node.getAttribute('aria-label');
         return !!(label ? axe.commons.text.sanitize(label).trim() : '');
       }
     }, {
       id: 'aria-labelledby',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var getIdRefs = axe.commons.dom.idrefs;
         return getIdRefs(node, 'aria-labelledby').some(function(elm) {
           return elm && axe.commons.text.accessibleText(elm, true);
@@ -6884,7 +6961,7 @@
       }
     }, {
       id: 'button-has-visible-text',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var nodeName = node.nodeName.toUpperCase();
         var role = node.getAttribute('role');
         var label = void 0;
@@ -6898,17 +6975,18 @@
       }
     }, {
       id: 'doc-has-title',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var title = document.title;
         return !!(title ? axe.commons.text.sanitize(title).trim() : '');
       }
     }, {
       id: 'duplicate-id',
-      evaluate: function evaluate(node, options) {
-        if (!node.id.trim()) {
+      evaluate: function evaluate(node, options, virtualNode) {
+        if (!node.getAttribute('id').trim()) {
           return true;
         }
-        var matchingNodes = document.querySelectorAll('[id="' + axe.commons.utils.escapeSelector(node.id) + '"]');
+        var id = axe.commons.utils.escapeSelector(node.getAttribute('id'));
+        var matchingNodes = document.querySelectorAll('[id="' + id + '"]');
         var related = [];
         for (var i = 0; i < matchingNodes.length; i++) {
           if (matchingNodes[i] !== node) {
@@ -6933,34 +7011,34 @@
       }
     }, {
       id: 'exists',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         return true;
       }
     }, {
       id: 'has-alt',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var nn = node.nodeName.toLowerCase();
         return node.hasAttribute('alt') && (nn === 'img' || nn === 'input' || nn === 'area');
       }
     }, {
       id: 'has-visible-text',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         return axe.commons.text.accessibleText(node).length > 0;
       }
     }, {
       id: 'is-on-screen',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         return axe.commons.dom.isVisible(node, false) && !axe.commons.dom.isOffscreen(node);
       }
     }, {
       id: 'non-empty-alt',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var label = node.getAttribute('alt');
         return !!(label ? axe.commons.text.sanitize(label).trim() : '');
       }
     }, {
       id: 'non-empty-if-present',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var nodeName = node.nodeName.toUpperCase();
         var type = (node.getAttribute('type') || '').toLowerCase();
         var label = node.getAttribute('value');
@@ -6972,29 +7050,29 @@
       }
     }, {
       id: 'non-empty-title',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var title = node.getAttribute('title');
         return !!(title ? axe.commons.text.sanitize(title).trim() : '');
       }
     }, {
       id: 'non-empty-value',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var label = node.getAttribute('value');
         return !!(label ? axe.commons.text.sanitize(label).trim() : '');
       }
     }, {
       id: 'role-none',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         return node.getAttribute('role') === 'none';
       }
     }, {
       id: 'role-presentation',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         return node.getAttribute('role') === 'presentation';
       }
     }, {
       id: 'caption-faked',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var table = axe.commons.table.toGrid(node);
         var firstRow = table[0];
         if (table.length <= 1 || firstRow.length <= 1 || node.rows.length <= 1) {
@@ -7006,17 +7084,17 @@
       }
     }, {
       id: 'has-caption',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         return !!node.caption;
       }
     }, {
       id: 'has-summary',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         return !!node.summary;
       }
     }, {
       id: 'has-th',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var row, cell, badCells = [];
         for (var rowIndex = 0, rowLength = node.rows.length; rowIndex < rowLength; rowIndex++) {
           row = node.rows[rowIndex];
@@ -7035,7 +7113,7 @@
       }
     }, {
       id: 'html5-scope',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         if (!axe.commons.dom.isHTML5(document)) {
           return true;
         }
@@ -7043,12 +7121,12 @@
       }
     }, {
       id: 'same-caption-summary',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         return !!(node.summary && node.caption) && node.summary === axe.commons.text.accessibleText(node.caption);
       }
     }, {
       id: 'scope-value',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         options = options || {};
         var value = node.getAttribute('scope').toLowerCase();
         var validVals = [ 'row', 'col', 'rowgroup', 'colgroup' ] || options.values;
@@ -7056,7 +7134,7 @@
       }
     }, {
       id: 'td-has-header',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var tableUtils = axe.commons.table;
         var badCells = [];
         var cells = tableUtils.getAllCells(node);
@@ -7079,7 +7157,7 @@
       }
     }, {
       id: 'td-headers-attr',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var cells = [];
         for (var rowIndex = 0, rowLength = node.rows.length; rowIndex < rowLength; rowIndex++) {
           var row = node.rows[rowIndex];
@@ -7088,8 +7166,8 @@
           }
         }
         var ids = cells.reduce(function(ids, cell) {
-          if (cell.id) {
-            ids.push(cell.id);
+          if (cell.getAttribute('id')) {
+            ids.push(cell.getAttribute('id'));
           }
           return ids;
         }, []);
@@ -7103,8 +7181,8 @@
             return headers;
           }, []);
           if (headers.length !== 0) {
-            if (cell.id) {
-              isSelf = headers.indexOf(cell.id.trim()) !== -1;
+            if (cell.getAttribute('id')) {
+              isSelf = headers.indexOf(cell.getAttribute('id').trim()) !== -1;
             }
             notOfTable = headers.reduce(function(fail, header) {
               return fail || ids.indexOf(header) === -1;
@@ -7124,7 +7202,7 @@
       }
     }, {
       id: 'th-has-data-cells',
-      evaluate: function evaluate(node, options) {
+      evaluate: function evaluate(node, options, virtualNode) {
         var tableUtils = axe.commons.table;
         var cells = tableUtils.getAllCells(node);
         var checkResult = this;
@@ -7147,7 +7225,7 @@
         });
         var tableGrid = tableUtils.toGrid(node);
         var out = headers.reduce(function(res, header) {
-          if (header.id && reffedHeaders.indexOf(header.id) !== -1) {
+          if (header.getAttribute('id') && reffedHeaders.includes(header.getAttribute('id'))) {
             return !res ? res : true;
           }
           var hasCell = false;
@@ -7171,16 +7249,15 @@
       }
     }, {
       id: 'hidden-content',
-      evaluate: function evaluate(node, options) {
-        var styles = window.getComputedStyle(node);
+      evaluate: function evaluate(node, options, virtualNode) {
         var whitelist = [ 'SCRIPT', 'HEAD', 'TITLE', 'NOSCRIPT', 'STYLE', 'TEMPLATE' ];
-        if (!whitelist.includes(node.tagName.toUpperCase()) && axe.commons.dom.hasContent(node)) {
+        if (!whitelist.includes(node.tagName.toUpperCase()) && axe.commons.dom.hasContent(virtualNode)) {
+          var styles = window.getComputedStyle(node);
           if (styles.getPropertyValue('display') === 'none') {
             return undefined;
           } else if (styles.getPropertyValue('visibility') === 'hidden') {
-            if (node.parentNode) {
-              var parentStyle = window.getComputedStyle(node.parentNode);
-            }
+            var parent = axe.commons.dom.getComposedParent(node);
+            var parentStyle = parent && window.getComputedStyle(parent);
             if (!parentStyle || parentStyle.getPropertyValue('visibility') !== 'hidden') {
               return undefined;
             }
@@ -8117,6 +8194,9 @@
       };
       aria.label = function(node) {
         var ref, candidate;
+        if (node.actualNode instanceof Node === false) {
+          node = axe.utils.getNodeFromTree(axe._tree[0], node);
+        }
         if (node.actualNode.getAttribute('aria-labelledby')) {
           ref = dom.idrefs(node.actualNode, 'aria-labelledby');
           candidate = ref.map(function(thing) {
@@ -8464,7 +8544,8 @@
         var bgElms = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
         var noScroll = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
         if (noScroll !== true) {
-          elm.scrollIntoView();
+          var alignToTop = elm.clientHeight - 2 >= window.innerHeight * 2;
+          elm.scrollIntoView(alignToTop);
         }
         var bgColors = [];
         var elmStack = color.getBackgroundStack(elm);
@@ -8548,22 +8629,27 @@
         }
         return finalElements;
       };
+      dom.findElmsInContext = function(_ref8) {
+        var context = _ref8.context, value = _ref8.value, attr = _ref8.attr, _ref8$elm = _ref8.elm, elm = _ref8$elm === undefined ? '' : _ref8$elm;
+        var root = void 0;
+        context = context.actualNode || context;
+        var escapedValue = axe.utils.escapeSelector(value);
+        if (context.nodeType === 9 || context.nodeType === 11) {
+          root = context;
+        } else {
+          root = dom.getRootNode(context);
+        }
+        return Array.from(root.querySelectorAll(elm + '[' + attr + '=' + escapedValue + ']'));
+      };
       dom.findUp = function(element, target) {
-        'use strict';
-        var parent, doc = axe.commons.dom.getRootNode(element), matches;
-        matches = doc.querySelectorAll(target);
-        matches = axe.utils.toArray(matches);
-        if (doc === document && !matches.length) {
-          return null;
-        }
-        parent = element.assignedSlot ? element.assignedSlot : element.parentNode;
-        if (parent.nodeType === 11) {
-          parent = parent.host;
-        }
-        while (parent && matches.indexOf(parent) === -1) {
+        var doc = void 0, matches = void 0, parent = element;
+        do {
           parent = parent.assignedSlot ? parent.assignedSlot : parent.parentNode;
           if (parent && parent.nodeType === 11) {
+            matches = null;
             parent = parent.host;
+          }
+          if (!matches) {
             doc = axe.commons.dom.getRootNode(parent);
             matches = doc.querySelectorAll(target);
             matches = axe.utils.toArray(matches);
@@ -8571,19 +8657,31 @@
               return null;
             }
           }
-        }
+        } while (parent && !matches.includes(parent));
         return parent;
       };
+      dom.getComposedParent = function getComposedParent(element) {
+        if (element.assignedSlot) {
+          return getComposedParent(element.assignedSlot);
+        } else if (element.parentNode) {
+          var parentNode = element.parentNode;
+          if (parentNode.nodeType === 1) {
+            return parentNode;
+          } else if (parentNode.host) {
+            return parentNode.host;
+          }
+        }
+        return null;
+      };
       dom.getElementByReference = function(node, attr) {
-        'use strict';
-        var candidate, fragment = node.getAttribute(attr), doc = document;
+        var fragment = node.getAttribute(attr);
         if (fragment && fragment.charAt(0) === '#') {
           fragment = fragment.substring(1);
-          candidate = doc.getElementById(fragment);
+          var candidate = document.getElementById(fragment);
           if (candidate) {
             return candidate;
           }
-          candidate = doc.getElementsByName(fragment);
+          candidate = document.getElementsByName(fragment);
           if (candidate.length) {
             return candidate[0];
           }
@@ -8647,17 +8745,22 @@
           height: body.clientHeight
         };
       };
-      dom.hasContent = function hasContent(elm) {
-        if (elm.actualNode.textContent.trim() || aria.label(elm)) {
-          return true;
+      var hiddenTextElms = [ 'HEAD', 'TITLE', 'TEMPLATE', 'SCRIPT', 'STYLE', 'IFRAME', 'OBJECT', 'VIDEO', 'AUDIO', 'NOSCRIPT' ];
+      function hasChildTextNodes(elm) {
+        if (!hiddenTextElms.includes(elm.actualNode.nodeName.toUpperCase())) {
+          return elm.children.some(function(_ref9) {
+            var actualNode = _ref9.actualNode;
+            return actualNode.nodeType === 3 && actualNode.nodeValue.trim();
+          });
         }
-        var contentElms = axe.utils.querySelectorAll(elm, '*');
-        for (var i = 0; i < contentElms.length; i++) {
-          if (aria.label(contentElms[i]) || dom.isVisualContent(contentElms[i].actualNode)) {
-            return true;
-          }
+      }
+      dom.hasContent = function hasContent(elm, noRecursion) {
+        if (!elm.actualNode) {
+          elm = axe.utils.getNodeFromTree(axe._tree[0], elm);
         }
-        return false;
+        return hasChildTextNodes(elm) || dom.isVisualContent(elm.actualNode) || !!aria.label(elm) || !noRecursion && elm.children.some(function(child) {
+          return child.actualNode.nodeType === 1 && dom.hasContent(child);
+        });
       };
       dom.idrefs = function(node, attr) {
         'use strict';
@@ -8706,35 +8809,33 @@
         return node.name === 'html' && !node.publicId && !node.systemId;
       };
       function walkDomNode(node, functor) {
-        'use strict';
-        var shouldWalk = functor(node);
-        node = node.firstChild;
-        while (node) {
-          if (shouldWalk !== false) {
-            walkDomNode(node, functor);
-          }
-          node = node.nextSibling;
+        if (functor(node.actualNode) !== false) {
+          node.children.forEach(function(child) {
+            return walkDomNode(child, functor);
+          });
         }
       }
       var blockLike = [ 'block', 'list-item', 'table', 'flex', 'grid', 'inline-block' ];
       function isBlock(elm) {
-        'use strict';
         var display = window.getComputedStyle(elm).getPropertyValue('display');
-        return blockLike.indexOf(display) !== -1 || display.substr(0, 6) === 'table-';
+        return blockLike.includes(display) || display.substr(0, 6) === 'table-';
+      }
+      function getBlockParent(node) {
+        var parentBlock = dom.getComposedParent(node);
+        while (parentBlock && !isBlock(parentBlock)) {
+          parentBlock = dom.getComposedParent(parentBlock);
+        }
+        return axe.utils.getNodeFromTree(axe._tree[0], parentBlock);
       }
       dom.isInTextBlock = function isInTextBlock(node) {
-        'use strict';
         if (isBlock(node)) {
           return false;
         }
-        var parentBlock = node.parentNode;
-        while (parentBlock.nodeType === 1 && !isBlock(parentBlock)) {
-          parentBlock = parentBlock.parentNode;
-        }
+        var virtualParent = getBlockParent(node);
         var parentText = '';
         var linkText = '';
         var inBrBlock = 0;
-        walkDomNode(parentBlock, function(currNode) {
+        walkDomNode(virtualParent, function(currNode) {
           if (inBrBlock === 2) {
             return false;
           }
@@ -8745,14 +8846,14 @@
             return;
           }
           var nodeName = (currNode.nodeName || '').toUpperCase();
-          if ([ 'BR', 'HR' ].indexOf(nodeName) !== -1) {
+          if ([ 'BR', 'HR' ].includes(nodeName)) {
             if (inBrBlock === 0) {
               parentText = '';
               linkText = '';
             } else {
               inBrBlock = 2;
             }
-          } else if (currNode.style.display === 'none' || currNode.style.overflow === 'hidden' || [ '', null, 'none' ].indexOf(currNode.style.float) === -1 || [ '', null, 'relative' ].indexOf(currNode.style.position) === -1) {
+          } else if (currNode.style.display === 'none' || currNode.style.overflow === 'hidden' || ![ '', null, 'none' ].includes(currNode.style.float) || ![ '', null, 'relative' ].includes(currNode.style.position)) {
             return false;
           } else if (nodeName === 'A' && currNode.href || (currNode.getAttribute('role') || '').toLowerCase() === 'link') {
             if (currNode === node) {
@@ -9099,8 +9200,9 @@
         if (table.isColumnHeader(cell) || table.isRowHeader(cell)) {
           return true;
         }
-        if (cell.id) {
-          return !!document.querySelector('[headers~="' + axe.utils.escapeSelector(cell.id) + '"]');
+        if (cell.getAttribute('id')) {
+          var id = axe.utils.escapeSelector(cell.getAttribute('id'));
+          return !!document.querySelector('[headers~="' + id + '"]');
         }
         return false;
       };
@@ -9202,40 +9304,49 @@
       };
       var inputTypes = [ 'text', 'search', 'tel', 'url', 'email', 'date', 'time', 'number', 'range', 'color' ];
       var phrasingElements = [ 'A', 'EM', 'STRONG', 'SMALL', 'MARK', 'ABBR', 'DFN', 'I', 'B', 'S', 'U', 'CODE', 'VAR', 'SAMP', 'KBD', 'SUP', 'SUB', 'Q', 'CITE', 'SPAN', 'BDO', 'BDI', 'BR', 'WBR', 'INS', 'DEL', 'IMG', 'EMBED', 'OBJECT', 'IFRAME', 'MAP', 'AREA', 'SCRIPT', 'NOSCRIPT', 'RUBY', 'VIDEO', 'AUDIO', 'INPUT', 'TEXTAREA', 'SELECT', 'BUTTON', 'LABEL', 'OUTPUT', 'DATALIST', 'KEYGEN', 'PROGRESS', 'COMMAND', 'CANVAS', 'TIME', 'METER' ];
-      function findLabel(element) {
-        var ref = null;
-        if (element.id) {
-          ref = document.querySelector('label[for="' + axe.utils.escapeSelector(element.id) + '"]');
-          if (ref) {
-            return ref;
-          }
+      function findLabel(_ref10) {
+        var actualNode = _ref10.actualNode;
+        var label = void 0;
+        if (actualNode.id) {
+          label = dom.findElmsInContext({
+            elm: 'label',
+            attr: 'for',
+            value: actualNode.id,
+            context: actualNode
+          })[0];
+        } else {
+          label = dom.findUp(actualNode, 'label');
         }
-        ref = dom.findUp(element, 'label');
-        return ref;
+        return axe.utils.getNodeFromTree(axe._tree[0], label);
       }
-      function isButton(element) {
-        return [ 'button', 'reset', 'submit' ].indexOf(element.type) !== -1;
+      function isButton(_ref11) {
+        var actualNode = _ref11.actualNode;
+        return [ 'button', 'reset', 'submit' ].includes(actualNode.type.toLowerCase());
       }
-      function isInput(element) {
-        var nodeName = element.nodeName.toUpperCase();
-        return nodeName === 'TEXTAREA' || nodeName === 'SELECT' || nodeName === 'INPUT' && element.type.toLowerCase() !== 'hidden';
+      function isInput(_ref12) {
+        var actualNode = _ref12.actualNode;
+        var nodeName = actualNode.nodeName.toUpperCase();
+        return nodeName === 'TEXTAREA' || nodeName === 'SELECT' || nodeName === 'INPUT' && actualNode.type.toLowerCase() !== 'hidden';
       }
-      function shouldCheckSubtree(element) {
-        return [ 'BUTTON', 'SUMMARY', 'A' ].indexOf(element.nodeName.toUpperCase()) !== -1;
+      function shouldCheckSubtree(_ref13) {
+        var actualNode = _ref13.actualNode;
+        return [ 'BUTTON', 'SUMMARY', 'A' ].includes(actualNode.nodeName.toUpperCase());
       }
-      function shouldNeverCheckSubtree(element) {
-        return [ 'TABLE', 'FIGURE' ].indexOf(element.nodeName.toUpperCase()) !== -1;
+      function shouldNeverCheckSubtree(_ref14) {
+        var actualNode = _ref14.actualNode;
+        return [ 'TABLE', 'FIGURE' ].includes(actualNode.nodeName.toUpperCase());
       }
-      function formValueText(element) {
-        var nodeName = element.nodeName.toUpperCase();
+      function formValueText(_ref15) {
+        var actualNode = _ref15.actualNode;
+        var nodeName = actualNode.nodeName.toUpperCase();
         if (nodeName === 'INPUT') {
-          if (!element.hasAttribute('type') || inputTypes.indexOf(element.getAttribute('type').toLowerCase()) !== -1 && element.value) {
-            return element.value;
+          if (!actualNode.hasAttribute('type') || inputTypes.includes(actualNode.type.toLowerCase())) {
+            return actualNode.value;
           }
           return '';
         }
         if (nodeName === 'SELECT') {
-          var opts = element.options;
+          var opts = actualNode.options;
           if (opts && opts.length) {
             var returnText = '';
             for (var i = 0; i < opts.length; i++) {
@@ -9247,64 +9358,68 @@
           }
           return '';
         }
-        if (nodeName === 'TEXTAREA' && element.value) {
-          return element.value;
+        if (nodeName === 'TEXTAREA' && actualNode.value) {
+          return actualNode.value;
         }
         return '';
       }
-      function checkDescendant(element, nodeName) {
-        var candidate = element.querySelector(nodeName.toLowerCase());
+      function checkDescendant(_ref16, nodeName) {
+        var actualNode = _ref16.actualNode;
+        var candidate = actualNode.querySelector(nodeName.toLowerCase());
         if (candidate) {
           return text.accessibleText(candidate);
         }
         return '';
       }
-      function isEmbeddedControl(e) {
-        if (!e) {
+      function isEmbeddedControl(elm) {
+        if (!elm) {
           return false;
         }
-        switch (e.nodeName.toUpperCase()) {
+        var actualNode = elm.actualNode;
+        switch (actualNode.nodeName.toUpperCase()) {
          case 'SELECT':
          case 'TEXTAREA':
           return true;
 
          case 'INPUT':
-          return !e.hasAttribute('type') || inputTypes.indexOf(e.getAttribute('type').toLowerCase()) !== -1;
+          return !actualNode.hasAttribute('type') || inputTypes.includes(actualNode.getAttribute('type').toLowerCase());
 
          default:
           return false;
         }
       }
-      function shouldCheckAlt(element) {
-        var nodeName = element.nodeName.toUpperCase();
-        return nodeName === 'INPUT' && element.type.toLowerCase() === 'image' || [ 'IMG', 'APPLET', 'AREA' ].indexOf(nodeName) !== -1;
+      function shouldCheckAlt(_ref17) {
+        var actualNode = _ref17.actualNode;
+        var nodeName = actualNode.nodeName.toUpperCase();
+        return [ 'IMG', 'APPLET', 'AREA' ].includes(nodeName) || nodeName === 'INPUT' && actualNode.type.toLowerCase() === 'image';
       }
       function nonEmptyText(t) {
         return !!text.sanitize(t);
       }
       text.accessibleText = function(element, inLabelledByContext) {
-        var accessibleNameComputation;
+        var accessibleNameComputation = void 0;
         var encounteredNodes = [];
+        if (element instanceof Node) {
+          element = axe.utils.getNodeFromTree(axe._tree[0], element);
+        }
         function getInnerText(element, inLabelledByContext, inControlContext) {
-          var nodes = element.childNodes;
-          var returnText = '';
-          var node;
-          for (var i = 0; i < nodes.length; i++) {
-            node = nodes[i];
-            if (node.nodeType === 3) {
-              returnText += node.textContent;
-            } else if (node.nodeType === 1) {
-              if (phrasingElements.indexOf(node.nodeName.toUpperCase()) === -1) {
+          return element.children.reduce(function(returnText, child) {
+            var actualNode = child.actualNode;
+            if (actualNode.nodeType === 3) {
+              returnText += actualNode.nodeValue;
+            } else if (actualNode.nodeType === 1) {
+              if (!phrasingElements.includes(actualNode.nodeName.toUpperCase())) {
                 returnText += ' ';
               }
-              returnText += accessibleNameComputation(nodes[i], inLabelledByContext, inControlContext);
+              returnText += accessibleNameComputation(child, inLabelledByContext, inControlContext);
             }
-          }
-          return returnText;
+            return returnText;
+          }, '');
         }
         function checkNative(element, inLabelledByContext, inControlContext) {
           var returnText = '';
-          var nodeName = element.nodeName.toUpperCase();
+          var actualNode = element.actualNode;
+          var nodeName = actualNode.nodeName.toUpperCase();
           if (shouldCheckSubtree(element)) {
             returnText = getInnerText(element, false, false) || '';
             if (nonEmptyText(returnText)) {
@@ -9322,17 +9437,17 @@
             if (nonEmptyText(returnText)) {
               return returnText;
             }
-            returnText = element.getAttribute('title') || element.getAttribute('summary') || '';
+            returnText = actualNode.getAttribute('title') || actualNode.getAttribute('summary') || '';
             if (nonEmptyText(returnText)) {
               return returnText;
             }
           }
           if (shouldCheckAlt(element)) {
-            return element.getAttribute('alt') || '';
+            return actualNode.getAttribute('alt') || '';
           }
           if (isInput(element) && !inControlContext) {
             if (isButton(element)) {
-              return element.value || element.title || defaultButtonValues[element.type] || '';
+              return actualNode.value || actualNode.title || defaultButtonValues[actualNode.type] || '';
             }
             var labelElement = findLabel(element);
             if (labelElement) {
@@ -9342,29 +9457,37 @@
           return '';
         }
         function checkARIA(element, inLabelledByContext, inControlContext) {
-          if (!inLabelledByContext && element.hasAttribute('aria-labelledby')) {
-            return text.sanitize(dom.idrefs(element, 'aria-labelledby').map(function(l) {
-              if (element === l) {
-                encounteredNodes.pop();
+          var returnText = '';
+          var actualNode = element.actualNode;
+          if (!inLabelledByContext && actualNode.hasAttribute('aria-labelledby')) {
+            returnText = text.sanitize(dom.idrefs(actualNode, 'aria-labelledby').map(function(label) {
+              if (label !== null) {
+                if (actualNode === label) {
+                  encounteredNodes.pop();
+                }
+                var vLabel = axe.utils.getNodeFromTree(axe._tree[0], label);
+                return accessibleNameComputation(vLabel, true, actualNode !== label);
+              } else {
+                return '';
               }
-              return accessibleNameComputation(l, true, element !== l);
             }).join(' '));
           }
-          if (!(inControlContext && isEmbeddedControl(element)) && element.hasAttribute('aria-label')) {
-            return text.sanitize(element.getAttribute('aria-label'));
+          if (!returnText && !(inControlContext && isEmbeddedControl(element)) && actualNode.hasAttribute('aria-label')) {
+            return text.sanitize(actualNode.getAttribute('aria-label'));
           }
-          return '';
+          return returnText;
         }
         accessibleNameComputation = function accessibleNameComputation(element, inLabelledByContext, inControlContext) {
-          'use strict';
-          var returnText;
-          if (element === null || encounteredNodes.indexOf(element) !== -1) {
+          var returnText = void 0;
+          if (!element || encounteredNodes.includes(element)) {
             return '';
-          } else if (!inLabelledByContext && !dom.isVisible(element, true)) {
+          } else if (element !== null && element.actualNode instanceof Node !== true) {
+            throw new Error('Invalid argument. Virtual Node must be provided');
+          } else if (!inLabelledByContext && !dom.isVisible(element.actualNode, true)) {
             return '';
           }
           encounteredNodes.push(element);
-          var role = element.getAttribute('role');
+          var role = element.actualNode.getAttribute('role');
           returnText = checkARIA(element, inLabelledByContext, inControlContext);
           if (nonEmptyText(returnText)) {
             return returnText;
@@ -9385,8 +9508,8 @@
               return returnText;
             }
           }
-          if (element.hasAttribute('title')) {
-            return element.getAttribute('title');
+          if (element.actualNode.hasAttribute('title')) {
+            return element.actualNode.getAttribute('title');
           }
           return '';
         };
@@ -9399,8 +9522,9 @@
           return candidate;
         }
         if (node.actualNode.id) {
+          var id = axe.commons.utils.escapeSelector(node.actualNode.getAttribute('id'));
           doc = axe.commons.dom.getRootNode(node.actualNode);
-          ref = doc.querySelector('label[for="' + axe.utils.escapeSelector(node.actualNode.id) + '"]');
+          ref = doc.querySelector('label[for="' + id + '"]');
           ref = axe.utils.getNodeFromTree(axe._tree[0], ref);
           candidate = ref && text.visible(ref, true);
           if (candidate) {
diff --git a/third_party/axe-core/axe.min.js b/third_party/axe-core/axe.min.js
index 1cb6219..a06be242 100644
--- a/third_party/axe-core/axe.min.js
+++ b/third_party/axe-core/axe.min.js
@@ -1,4 +1,4 @@
-/*! aXe v2.3.1
+/*! aXe v3.0.0-alpha-1
  * Copyright (c) 2017 Deque Systems, Inc.
  *
  * Your use of this Source Code Form is subject to the terms of the Mozilla Public
@@ -9,8 +9,8 @@
  * distribute or in any file that contains substantial portions of this source
  * code.
  */
-!function a(window){function b(a){this.name="SupportError",this.cause=a.cause,this.message="`"+a.cause+"` - feature unsupported in your environment.",a.ruleId&&(this.ruleId=a.ruleId,this.message+=" Skipping "+this.ruleId+" rule."),this.stack=(new Error).stack}function c(a){"use strict";var b;return a?(b=axe.utils.clone(a),b.commons=a.commons):b={},b.reporter=b.reporter||null,b.rules=b.rules||[],b.checks=b.checks||[],b.data=Object.assign({checks:{},rules:{}},b.data),b}function d(a,b,c){"use strict";var d,e;for(d=0,e=a.length;d<e;d++)b[c](a[d])}function e(a){this.brand="axe",this.application="axeAPI",this.tagExclude=["experimental"],this.defaultConfig=a,this._init()}function f(a,b,c){var d=a.brand,e=a.application;return axe.constants.helpUrlBase+d+"/"+(c||axe.version.substring(0,axe.version.lastIndexOf(".")))+"/"+b+"?application="+e}function g(a){"use strict";this.id=a.id,this.data=null,this.relatedNodes=[],this.result=null}function h(a){"use strict";return"string"==typeof a?new Function("return "+a+";")():a}function i(a){a&&(this.id=a.id,this.configure(a))}function j(a,b){"use strict";if(!axe.utils.isHidden(b)){axe.utils.findBy(a,"node",b)||a.push({node:b,include:[],exclude:[]})}}function k(a,b,c){"use strict";a.frames=a.frames||[];var d,e,f=document.querySelectorAll(c.shift());a:for(var g=0,h=f.length;g<h;g++){e=f[g];for(var i=0,j=a.frames.length;i<j;i++)if(a.frames[i].node===e){a.frames[i][b].push(c);break a}d={node:e,include:[],exclude:[]},c&&d[b].push(c),a.frames.push(d)}}function l(a){"use strict";if(a&&"object"===(void 0===a?"undefined":qa(a))||a instanceof NodeList){if(a instanceof Node)return{include:[a],exclude:[]};if(a.hasOwnProperty("include")||a.hasOwnProperty("exclude"))return{include:a.include&&+a.include.length?a.include:[document],exclude:a.exclude||[]};if(a.length===+a.length)return{include:a,exclude:[]}}return"string"==typeof a?{include:[a],exclude:[]}:{include:[document],exclude:[]}}function m(a,b){"use strict";for(var c,d,e=[],f=0,g=a[b].length;f<g;f++){if("string"==typeof(c=a[b][f])){d=Array.from(document.querySelectorAll(c)),e=e.concat(d.map(function(a){return axe.utils.getFlattenedTree(a)[0]}));break}!c||!c.length||c instanceof Node?c instanceof Node&&e.push(axe.utils.getFlattenedTree(c)[0]):c.length>1?k(a,b,c):(d=Array.from(document.querySelectorAll(c[0])),e=e.concat(d.map(function(a){return axe.utils.getFlattenedTree(a)[0]})))}return e.filter(function(a){return a})}function n(a){"use strict";if(0===a.include.length){if(0===a.frames.length){var b=axe.utils.respondable.isInFrame()?"frame":"page";return new Error("No elements found for include in "+b+" Context")}a.frames.forEach(function(a,b){if(0===a.include.length)return new Error("No elements found for include in Context of frame "+b)})}}function o(a){"use strict";var b=this;this.frames=[],this.initiator=!a||"boolean"!=typeof a.initiator||a.initiator,this.page=!1,a=l(a),this.exclude=a.exclude,this.include=a.include,this.include=m(this,"include"),this.exclude=m(this,"exclude"),axe.utils.select("frame, iframe",this).forEach(function(a){oa(a,b)&&j(b.frames,a.actualNode)}),1===this.include.length&&this.include[0].actualNode===document.documentElement&&(this.page=!0);var c=n(this);if(c instanceof Error)throw c}function p(a){"use strict";this.id=a.id,this.result=axe.constants.NA,this.pageLevel=a.pageLevel,this.impact=null,this.nodes=[]}function q(a,b){"use strict";this._audit=b,this.id=a.id,this.selector=a.selector||"*",this.excludeHidden="boolean"!=typeof a.excludeHidden||a.excludeHidden,this.enabled="boolean"!=typeof a.enabled||a.enabled,this.pageLevel="boolean"==typeof a.pageLevel&&a.pageLevel,this.any=a.any||[],this.all=a.all||[],this.none=a.none||[],this.tags=a.tags||[],a.matches&&(this.matches=h(a.matches))}function r(a){"use strict";return axe.utils.getAllChecks(a).map(function(b){var c=a._audit.checks[b.id||b];return c&&"function"==typeof c.after?c:null}).filter(Boolean)}function s(a,b){"use strict";var c=[];return a.forEach(function(a){axe.utils.getAllChecks(a).forEach(function(a){a.id===b&&c.push(a)})}),c}function t(a){"use strict";return a.filter(function(a){return!0!==a.filtered})}function u(a){"use strict";var b=["any","all","none"],c=a.nodes.filter(function(a){var c=0;return b.forEach(function(b){a[b]=t(a[b]),c+=a[b].length}),c>0});return a.pageLevel&&c.length&&(c=[c.reduce(function(a,c){if(a)return b.forEach(function(b){a[b].push.apply(a[b],c[b])}),a})]),c}function v(a,b){"use strict";if(!axe._audit)throw new Error("No audit configured");var c=axe.utils.queue(),d=[];Object.keys(axe.plugins).forEach(function(a){c.defer(function(b){var c=function(a){d.push(a),b()};try{axe.plugins[a].cleanup(b,c)}catch(a){c(a)}})}),axe.utils.toArray(document.querySelectorAll("frame, iframe")).forEach(function(a){c.defer(function(b,c){return axe.utils.sendCommandToFrame(a,{command:"cleanup-plugin"},b,c)})}),c.then(function(c){0===d.length?a(c):b(d)}).catch(b)}function w(a){"use strict";var b;if(!(b=axe._audit))throw new Error("No audit configured");a.reporter&&("function"==typeof a.reporter||ta[a.reporter])&&(b.reporter=a.reporter),a.checks&&a.checks.forEach(function(a){b.addCheck(a)}),a.rules&&a.rules.forEach(function(a){b.addRule(a)}),void 0!==a.branding?b.setBranding(a.branding):b._constructHelpUrls(),a.tagExclude&&(b.tagExclude=a.tagExclude)}function x(a,b,c){"use strict";var d=c,e=function(a){a instanceof Error==!1&&(a=new Error(a)),c(a)},f=a&&a.context||{};f.include&&!f.include.length&&(f.include=[document]);var g=a&&a.options||{};switch(a.command){case"rules":return A(f,g,d,e);case"cleanup-plugin":return v(d,e);default:if(axe._audit&&axe._audit.commands&&axe._audit.commands[a.command])return axe._audit.commands[a.command](a,c)}}function y(a){"use strict";this._run=a.run,this._collect=a.collect,this._registry={},a.commands.forEach(function(a){axe._audit.registerCommand(a)})}function z(){"use strict";var a=axe._audit;if(!a)throw new Error("No audit configured");a.resetRulesAndChecks()}function A(a,b,c,d){"use strict";try{a=new o(a)}catch(a){return d(a)}var e=axe.utils.queue(),f=axe._audit;b.performanceTimer&&axe.utils.performanceTimer.auditStart(),a.frames.length&&!1!==b.iframes&&e.defer(function(c,d){axe.utils.collectResultsFromFrames(a,b,"rules",null,c,d)}),e.defer(function(c,d){f.run(a,b,c,d)}),e.then(function(e){try{b.performanceTimer&&axe.utils.performanceTimer.auditEnd();var g=axe.utils.mergeResults(e.map(function(a){return{results:a}}));a.initiator&&(g=f.after(g,b),g.forEach(axe.utils.publishMetaData),g=g.map(axe.utils.finalizeRuleResult));try{c(g)}catch(a){axe.log(a)}}catch(a){d(a)}}).catch(d)}function B(a){"use strict";switch(!0){case"string"==typeof a:case Array.isArray(a):case Node&&a instanceof Node:case NodeList&&a instanceof NodeList:return!0;case"object"!==(void 0===a?"undefined":qa(a)):return!1;case void 0!==a.include:case void 0!==a.exclude:case"number"==typeof a.length:return!0;default:return!1}}function C(a,b,c){"use strict";var d=new TypeError("axe.run arguments are invalid");if(!B(a)){if(void 0!==c)throw d;c=b,b=a,a=document}if("object"!==(void 0===b?"undefined":qa(b))){if(void 0!==c)throw d;c=b,b={}}if("function"!=typeof c&&void 0!==c)throw d;return{context:a,options:b,callback:c||ua}}function D(a,b){"use strict";["any","all","none"].forEach(function(c){Array.isArray(a[c])&&a[c].filter(function(a){return Array.isArray(a.relatedNodes)}).forEach(function(a){a.relatedNodes=a.relatedNodes.map(function(a){var c={html:a.source};return b.elementRef&&!a.fromFrame&&(c.element=a.element),(!1!==b.selectors||a.fromFrame)&&(c.target=a.selector),b.xpath&&(c.xpath=a.xpath),c})})})}function E(a,b){return xa.reduce(function(c,d){return c[d]=(a[d]||[]).map(function(a){return b(a,d)}),c},{})}function F(a,b,c){var d=Object.assign({},b);d.nodes=(d[c]||[]).concat(),axe.constants.resultGroups.forEach(function(a){delete d[a]}),a[c].push(d)}function G(a,b,c){"use strict";var d=window.getComputedStyle(a,null),e=!1;return!!d&&(b.forEach(function(a){d.getPropertyValue(a.property)===a.value&&(e=!0)}),!!e||!(a.nodeName.toUpperCase()===c.toUpperCase()||!a.parentNode)&&G(a.parentNode,b,c))}function H(a,b){"use strict";return new Error(a+": "+axe.utils.getSelector(b))}function I(a,b,c,d,e,f){"use strict";var g=axe.utils.queue();a.frames.forEach(function(e){var f={options:b,command:c,parameter:d,context:{initiator:!1,page:a.page,include:e.include||[],exclude:e.exclude||[]}};g.defer(function(a,b){var c=e.node;axe.utils.sendCommandToFrame(c,f,function(b){if(b)return a({results:b,frameElement:c,frame:axe.utils.getSelector(c)});a(null)},b)})}),g.then(function(a){e(axe.utils.mergeResults(a,b))}).catch(f)}function J(a,b){if(b=b||300,a.length>b){var c=a.indexOf(">");a=a.substring(0,c+1)}return a}function K(a){var b=a.outerHTML;return b||"function"!=typeof XMLSerializer||(b=(new XMLSerializer).serializeToString(a)),J(b||"")}function L(a,b,c){this._fromFrame=!!c,this.spec=c||{},b&&b.absolutePaths&&(this._options={toRoot:!0}),this.source=void 0!==this.spec.source?this.spec.source:K(a),this._element=a}function M(a,b){return{shadowId:b,children:[],actualNode:a}}function N(a){var b=[];for(a=a.firstChild;a;)b.push(a),a=a.nextSibling;return b}function O(){var a=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";return 0!==a.length&&(a.match(/[0-9]/g)||"").length>=a.length/2}function P(a,b){return[a.substring(0,b),a.substring(b)]}function Q(a){var b=a,c="",d="",e="",f="",g="",h="";if(a.includes("#")){var i=P(a,a.indexOf("#")),j=ya(i,2);a=j[0],h=j[1]}if(a.includes("?")){var k=P(a,a.indexOf("?")),l=ya(k,2);a=l[0],g=l[1]}if(a.includes("://")){var m=a.split("://"),n=ya(m,2);c=n[0],a=n[1];var o=P(a,a.indexOf("/")),p=ya(o,2);d=p[0],a=p[1]}else if("//"===a.substr(0,2)){a=a.substr(2);var q=P(a,a.indexOf("/")),r=ya(q,2);d=r[0],a=r[1]}if("www."===d.substr(0,4)&&(d=d.substr(4)),d&&d.includes(":")){var s=P(d,d.indexOf(":")),t=ya(s,2);d=t[0],e=t[1]}return f=a,{original:b,protocol:c,domain:d,port:e,path:f,query:g,hash:h}}function R(a){if(Array.isArray(a)){for(var b=0,c=Array(a.length);b<a.length;b++)c[b]=a[b];return c}return Array.from(a)}function S(a){return!["focus","hover","hidden","visible","dirty","touched","valid","disable","enable","active","col-"].find(function(b){return a.includes(b)})}function T(a){return a.classList&&0!==a.classList.length?(a.parentNode&&Array.from(a.parentNode.children||"")||[]).reduce(function(b,c){return a===c?b:b.filter(function(a){return!c.classList.contains(a)})},Array.from(a.classList).filter(S)):[]}function U(a,b){var c=a.parentNode&&Array.from(a.parentNode.children||"")||[];if(c.find(function(c){return c!==a&&axe.utils.matchesSelector(c,b)}))return":nth-child("+(1+c.indexOf(a))+")";return""}function V(a,b){var c=a.nodeName.toLowerCase(),d=Array.from(a.classList)||[],e={nodeName:c,classList:d,isCustomElm:c.includes("-"),isCommonElm:Aa.includes(c),distinctClassList:T(a)};return[Ba.getCustomElm,Ba.getElmRoleProp,Ba.getUncommonElm,Ba.getElmNameProp,Ba.getDistinctClass,Ba.getFileRefProp,Ba.getCommonName].reduce(function(c,d){if(c.length===b)return c;var f=d(a,e);return f&&(f[0].match(/[a-z]/)?c.unshift(f):c.push(f)),c},[])}function W(a,b,c){var d=void 0,e=void 0,f=b.isUnique,g=void 0!==f&&f,h=Ba.getElmId(a),i=b.featureCount,j=void 0===i?2:i,k=b.minDepth,l=void 0===k?1:k,m=b.toRoot,n=void 0!==m&&m,o=b.childSelectors,p=void 0===o?[]:o;h?(d=h,g=!0):(d=V(a,j).join(""),d+=U(a,d),g=b.isUnique||1===c.querySelectorAll(d).length,g||a!==document.documentElement||(d+=":root"),e=0!==l||!g);var q=[d].concat(R(p));return a.parentElement&&11!==a.parentElement.nodeType&&(n||e)?W(a.parentNode,{toRoot:n,isUnique:g,childSelectors:q,featureCount:1,minDepth:l-1},c):q.join(" > ")}function X(a,b){var c,d;if(!a)return[];if(!b&&9===a.nodeType)return b=[{str:"html"}];if(b=b||[],a.parentNode&&a.parentNode!==a&&(b=X(a.parentNode,b)),a.previousSibling){d=1,c=a.previousSibling;do{1===c.nodeType&&c.nodeName===a.nodeName&&d++,c=c.previousSibling}while(c);1===d&&(d=null)}else if(a.nextSibling){c=a.nextSibling;do{1===c.nodeType&&c.nodeName===a.nodeName?(d=1,c=null):(d=null,c=c.previousSibling)}while(c)}if(1===a.nodeType){var e={};e.str=a.nodeName.toLowerCase(),a.getAttribute&&a.getAttribute("id")&&1===a.ownerDocument.querySelectorAll("#"+axe.utils.escapeSelector(a.id)).length&&(e.id=a.getAttribute("id")),d>1&&(e.count=d),b.push(e)}return b}function Y(a){return a.reduce(function(a,b){return b.id?"/"+b.str+"[@id='"+b.id+"']":a+"/"+b.str+(b.count>0?"["+b.count+"]":"")},"")}function Z(a){"use strict";if(Ca&&Ca.parentNode)return void 0===Ca.styleSheet?Ca.appendChild(document.createTextNode(a)):Ca.styleSheet.cssText+=a,Ca;if(a){var b=document.head||document.getElementsByTagName("head")[0];return Ca=document.createElement("style"),Ca.type="text/css",void 0===Ca.styleSheet?Ca.appendChild(document.createTextNode(a)):Ca.styleSheet.cssText=a,b.appendChild(Ca),Ca}}function $(a,b,c,d){"use strict";var e=axe.utils.getXpath(c),f={element:c,selector:d,xpath:e};a.forEach(function(a){a.node=axe.utils.DqElement.fromFrame(a.node,b,f);var c=axe.utils.getAllChecks(a);c.length&&c.forEach(function(a){a.relatedNodes=a.relatedNodes.map(function(a){return axe.utils.DqElement.fromFrame(a,b,f)})})})}function _(a,b){"use strict";for(var c,d,e=b[0].node,f=0,g=a.length;f<g;f++)if(d=a[f].node,(c=axe.utils.nodeSorter({actualNode:d.element},{actualNode:e.element}))>0||0===c&&e.selector.length<d.selector.length)return void a.splice.apply(a,[f,0].concat(b));a.push.apply(a,b)}function aa(a){"use strict";return a&&a.results?Array.isArray(a.results)?a.results.length?a.results:null:[a.results]:null}function ba(a,b){function c(a){return a.incomplete&&a.incomplete.default?a.incomplete.default:ra.incompleteFallbackMessage()}if(!a||!a.missingData)return c(b);try{var d=b.incomplete[a.missingData[0].reason];if(!d)throw new Error;return d}catch(d){return"string"==typeof a.missingData?b.incomplete[a.missingData]:c(b)}}function ca(a,b){"use strict";return function(c){var d=a[c.id]||{},e=d.messages||{},f=Object.assign({},d);delete f.messages,void 0===c.result?"object"===qa(e.incomplete)?f.message=function(){return ba(c.data,e)}:f.message=e.incomplete:f.message=c.result===b?e.pass:e.fail,axe.utils.extendMetaData(c,f)}}function da(a,b){return 1===a.nodeType&&("*"===b.tag||a.nodeName.toLowerCase()===b.tag)}function ea(a,b){return!b.classes||b.classes.reduce(function(b,c){return b&&a.className&&a.className.match(c.regexp)},!0)}function fa(a,b){return!b.attributes||b.attributes.reduce(function(b,c){var d=a.getAttribute(c.key);return b&&null!==d&&(!c.value||c.test(d))},!0)}function ga(a,b){return!b.id||a.id===b.id}function ha(a,b){return!(b.pseudos&&!b.pseudos.reduce(function(b,c){if("not"===c.name)return b&&!Ea([a],c.expressions,!1).length;throw new Error("the pseudo selector "+c.name+" has not yet been implemented")},!0))}function ia(a,b,c){var d=[];return a=Array.isArray(a)?a:[a],a.forEach(function(a){da(a.actualNode,b)&&ea(a.actualNode,b)&&fa(a.actualNode,b)&&ga(a.actualNode,b)&&ha(a,b)&&d.push(a),c&&(d=d.concat(ia(a.children.filter(function(c){return!b.id||c.shadowId===a.shadowId}),b,c)))}),d}function ja(a){/*! Credit Mootools Copyright Mootools, MIT License */
-if(a)return a.map(function(a){var b,c,d=a.name.replace(Ga,""),e=(a.value||"").replace(Ga,"");switch(a.operator){case"^=":c=new RegExp("^"+Fa(e));break;case"$=":c=new RegExp(Fa(e)+"$");break;case"~=":c=new RegExp("(^|\\s)"+Fa(e)+"(\\s|$)");break;case"|=":c=new RegExp("^"+Fa(e)+"(-|$)");break;case"=":b=function(a){return e===a};break;case"*=":b=function(a){return a&&a.indexOf(e)>-1};break;case"!=":b=function(a){return e!==a};break;default:b=function(a){return!!a}}return""===e&&/^[*$^]=$/.test(a.operator)&&(b=function(){return!1}),b||(b=function(a){return a&&c.test(a)}),{key:d,value:e,test:b}})}function ka(a){if(a)return a.map(function(a){return a=a.replace(Ga,""),{value:a,regexp:new RegExp("(^|\\s)"+Fa(a)+"(\\s|$)")}})}function la(a){if(a)return a.map(function(a){var b;return"not"===a.name&&(b=axe.utils.cssParser.parse(a.value),b=b.selectors?b.selectors:[b],b=Da(b)),{name:a.name,expressions:b,value:a.value}})}function ma(a,b){"use strict";var c,d,e=axe._audit&&axe._audit.tagExclude?axe._audit.tagExclude:[];return b.include||b.exclude?(c=b.include||[],c=Array.isArray(c)?c:[c],d=b.exclude||[],d=Array.isArray(d)?d:[d],d=d.concat(e.filter(function(a){return-1===c.indexOf(a)}))):(c=Array.isArray(b)?b:[b],d=e.filter(function(a){return-1===c.indexOf(a)})),!!(c.some(function(b){return-1!==a.tags.indexOf(b)})||0===c.length&&!1!==a.enabled)&&d.every(function(b){return-1===a.tags.indexOf(b)})}function na(a){"use strict";return a.sort(function(a,b){return axe.utils.contains(a,b)?1:-1})[0]}function oa(a,b){"use strict";var c=b.include&&na(b.include.filter(function(b){return axe.utils.contains(b,a)})),d=b.exclude&&na(b.exclude.filter(function(b){return axe.utils.contains(b,a)}));return!!(!d&&c||d&&axe.utils.contains(d,c))}function pa(a,b,c){"use strict";for(var d=0,e=b.length;d<e;d++)!a.find(function(a){return a.actualNode===b[d].actualNode})&&oa(b[d],c)&&a.push(b[d])}var document=window.document,qa="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a},axe=axe||{};axe.version="2.3.1","function"==typeof define&&define.amd&&define([],function(){"use strict";return axe}),"object"===("undefined"==typeof module?"undefined":qa(module))&&module.exports&&"function"==typeof a.toString&&(axe.source="("+a.toString()+')(typeof window === "object" ? window : this);',module.exports=axe),"function"==typeof window.getComputedStyle&&(window.axe=axe);var commons;b.prototype=Object.create(Error.prototype),b.prototype.constructor=b;var utils=axe.utils={},ra={},qa="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a};e.prototype._init=function(){var a=c(this.defaultConfig);axe.commons=commons=a.commons,this.reporter=a.reporter,this.commands={},this.rules=[],this.checks={},d(a.rules,this,"addRule"),d(a.checks,this,"addCheck"),this.data={},this.data.checks=a.data&&a.data.checks||{},this.data.rules=a.data&&a.data.rules||{},this.data.failureSummaries=a.data&&a.data.failureSummaries||{},this.data.incompleteFallbackMessage=a.data&&a.data.incompleteFallbackMessage||"",this._constructHelpUrls()},e.prototype.registerCommand=function(a){"use strict";this.commands[a.id]=a.callback},e.prototype.addRule=function(a){"use strict";a.metadata&&(this.data.rules[a.id]=a.metadata);var b=this.getRule(a.id);b?b.configure(a):this.rules.push(new q(a,this))},e.prototype.addCheck=function(a){"use strict";var b=a.metadata;"object"===(void 0===b?"undefined":qa(b))&&(this.data.checks[a.id]=b,"object"===qa(b.messages)&&Object.keys(b.messages).filter(function(a){return b.messages.hasOwnProperty(a)&&"string"==typeof b.messages[a]}).forEach(function(a){0===b.messages[a].indexOf("function")&&(b.messages[a]=new Function("return "+b.messages[a]+";")())})),this.checks[a.id]?this.checks[a.id].configure(a):this.checks[a.id]=new i(a)},e.prototype.run=function(a,b,c,d){"use strict";this.validateOptions(b),axe._tree=axe.utils.getFlattenedTree(document.body);var e=axe.utils.queue();this.rules.forEach(function(c){if(axe.utils.ruleShouldRun(c,a,b)){if(b.performanceTimer){var d="mark_rule_end_"+c.id,f="mark_rule_start_"+c.id;axe.utils.performanceTimer.mark(f)}e.defer(function(e,g){c.run(a,b,function(a){b.performanceTimer&&(axe.utils.performanceTimer.mark(d),axe.utils.performanceTimer.measure("rule_"+c.id,f,d)),e(a)},function(a){if(b.debug)g(a);else{var d=Object.assign(new p(c),{result:axe.constants.CANTTELL,description:"An error occured while running this rule",message:a.message,help:a.stack||a.message,error:a});e(d)}})})}}),e.then(function(a){axe._tree=void 0,c(a.filter(function(a){return!!a}))}).catch(d)},e.prototype.after=function(a,b){"use strict";var c=this.rules;return a.map(function(a){return axe.utils.findBy(c,"id",a.id).after(a,b)})},e.prototype.getRule=function(a){return this.rules.find(function(b){return b.id===a})},e.prototype.validateOptions=function(a){"use strict";var b=this;if("object"===qa(a.runOnly)){var c=a.runOnly;if("rule"===c.type&&Array.isArray(c.value))c.value.forEach(function(a){if(!b.getRule(a))throw new Error("unknown rule `"+a+"` in options.runOnly")});else if(Array.isArray(c.value)&&c.value.length>0){var d=[].concat(c.value);if(b.rules.forEach(function(a){var b,c,e;if(d)for(c=0,e=a.tags.length;c<e;c++)-1!==(b=d.indexOf(a.tags[c]))&&d.splice(b,1)}),0!==d.length)throw new Error("could not find tags `"+d.join("`, `")+"`")}}return"object"===qa(a.rules)&&Object.keys(a.rules).forEach(function(a){if(!b.getRule(a))throw new Error("unknown rule `"+a+"` in options.rules")}),a},e.prototype.setBranding=function(a){"use strict";var b={brand:this.brand,application:this.application};a&&a.hasOwnProperty("brand")&&a.brand&&"string"==typeof a.brand&&(this.brand=a.brand),a&&a.hasOwnProperty("application")&&a.application&&"string"==typeof a.application&&(this.application=a.application),this._constructHelpUrls(b)},e.prototype._constructHelpUrls=function(){var a=this,b=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,c=axe.version.substring(0,axe.version.lastIndexOf("."));this.rules.forEach(function(d){a.data.rules[d.id]||(a.data.rules[d.id]={});var e=a.data.rules[d.id];("string"!=typeof e.helpUrl||b&&e.helpUrl===f(b,d.id,c))&&(e.helpUrl=f(a,d.id,c))})},e.prototype.resetRulesAndChecks=function(){"use strict";this._init()},i.prototype.enabled=!0,i.prototype.run=function(a,b,c,d){"use strict";b=b||{};var e=b.hasOwnProperty("enabled")?b.enabled:this.enabled,f=b.options||this.options;if(e){var h,i=new g(this),j=axe.utils.checkHelper(i,b,c,d);try{h=this.evaluate.call(j,a.actualNode,f,a)}catch(a){return void d(a)}j.isAsync||(i.result=h,setTimeout(function(){c(i)},0))}else c(null)},i.prototype.configure=function(a){var b=this;["options","enabled"].filter(function(b){return a.hasOwnProperty(b)}).forEach(function(c){return b[c]=a[c]}),["evaluate","after"].filter(function(b){return a.hasOwnProperty(b)}).forEach(function(c){return b[c]=h(a[c])})};var qa="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a};q.prototype.matches=function(){"use strict";return!0},q.prototype.gather=function(a){"use strict";var b=axe.utils.select(this.selector,a);return this.excludeHidden?b.filter(function(a){return!axe.utils.isHidden(a.actualNode)}):b},q.prototype.runChecks=function(a,b,c,d,e){"use strict";var f=this,g=axe.utils.queue();this[a].forEach(function(a){var d=f._audit.checks[a.id||a],e=axe.utils.getCheckOption(d,f.id,c);g.defer(function(a,c){d.run(b,e,a,c)})}),g.then(function(b){b=b.filter(function(a){return a}),d({type:a,results:b})}).catch(e)},q.prototype.run=function(a,c,d,e){var f=this,g=axe.utils.queue(),h=new p(this),i=void 0;try{i=this.gather(a).filter(function(a){return f.matches(a.actualNode)})}catch(a){return void e(new b({cause:a,ruleId:this.id}))}c.performanceTimer&&axe.log("gather (",i.length,"):",axe.utils.performanceTimer.timeElapsed()+"ms"),i.forEach(function(a){g.defer(function(b,d){var e=axe.utils.queue();e.defer(function(b,d){f.runChecks("any",a,c,b,d)}),e.defer(function(b,d){f.runChecks("all",a,c,b,d)}),e.defer(function(b,d){f.runChecks("none",a,c,b,d)}),e.then(function(d){if(d.length){var e=!1,f={};d.forEach(function(a){var b=a.results.filter(function(a){return a});f[a.type]=b,b.length&&(e=!0)}),e&&(f.node=new axe.utils.DqElement(a.actualNode,c),h.nodes.push(f))}b()}).catch(function(a){return d(a)})})}),g.then(function(){return d(h)}).catch(function(a){return e(a)})},q.prototype.after=function(a,b){"use strict";var c=r(this),d=this.id;return c.forEach(function(c){var e=s(a.nodes,c.id),f=axe.utils.getCheckOption(c,d,b),g=c.after(e,f);e.forEach(function(a){-1===g.indexOf(a)&&(a.filtered=!0)})}),a.nodes=u(a),a},q.prototype.configure=function(a){"use strict";a.hasOwnProperty("selector")&&(this.selector=a.selector),a.hasOwnProperty("excludeHidden")&&(this.excludeHidden="boolean"!=typeof a.excludeHidden||a.excludeHidden),a.hasOwnProperty("enabled")&&(this.enabled="boolean"!=typeof a.enabled||a.enabled),a.hasOwnProperty("pageLevel")&&(this.pageLevel="boolean"==typeof a.pageLevel&&a.pageLevel),a.hasOwnProperty("any")&&(this.any=a.any),a.hasOwnProperty("all")&&(this.all=a.all),a.hasOwnProperty("none")&&(this.none=a.none),a.hasOwnProperty("tags")&&(this.tags=a.tags),a.hasOwnProperty("matches")&&("string"==typeof a.matches?this.matches=new Function("return "+a.matches+";")():this.matches=a.matches)},function(axe){var a=[{name:"NA",value:"inapplicable",priority:0,group:"inapplicable"},{name:"PASS",value:"passed",priority:1,group:"passes"},{name:"CANTTELL",value:"cantTell",priority:2,group:"incomplete"},{name:"FAIL",value:"failed",priority:3,group:"violations"}],b={helpUrlBase:"https://dequeuniversity.com/rules/",results:[],resultGroups:[],resultGroupMap:{},impact:Object.freeze(["minor","moderate","serious","critical"])};a.forEach(function(a){var c=a.name,d=a.value,e=a.priority,f=a.group;b[c]=d,b[c+"_PRIO"]=e,b[c+"_GROUP"]=f,b.results[e]=d,b.resultGroups[e]=f,b.resultGroupMap[d]=f}),Object.freeze(b.results),Object.freeze(b.resultGroups),Object.freeze(b.resultGroupMap),Object.freeze(b),Object.defineProperty(axe,"constants",{value:b,enumerable:!0,configurable:!1,writable:!1})}(axe);var qa="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a};axe.log=function(){"use strict";"object"===("undefined"==typeof console?"undefined":qa(console))&&console.log&&Function.prototype.apply.call(console.log,console,arguments)};var qa="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a};axe.a11yCheck=function(a,b,c){"use strict";"function"==typeof b&&(c=b,b={}),b&&"object"===(void 0===b?"undefined":qa(b))||(b={});var d=axe._audit;if(!d)throw new Error("No audit configured");b.reporter=b.reporter||d.reporter||"v2",b.performanceTimer&&axe.utils.performanceTimer.start();var e=axe.getReporter(b.reporter);axe._runRules(a,b,function(a){var d=e(a,b,c);void 0!==d&&(b.performanceTimer&&axe.utils.performanceTimer.end(),c(d))},axe.log)},axe.cleanup=v,axe.configure=w,axe.getRules=function(a){"use strict";a=a||[];var b=a.length?axe._audit.rules.filter(function(b){return!!a.filter(function(a){return-1!==b.tags.indexOf(a)}).length}):axe._audit.rules,c=axe._audit.data.rules||{};return b.map(function(a){var b=c[a.id]||{};return{ruleId:a.id,description:b.description,help:b.help,helpUrl:b.helpUrl,tags:a.tags}})},axe._load=function(a){"use strict";axe.utils.respondable.subscribe("axe.ping",function(a,b,c){c({axe:!0})}),axe.utils.respondable.subscribe("axe.start",x),axe._audit=new e(a)};var axe=axe||{};axe.plugins={},y.prototype.run=function(){"use strict";return this._run.apply(this,arguments)},y.prototype.collect=function(){"use strict";return this._collect.apply(this,arguments)},y.prototype.cleanup=function(a){"use strict";var b=axe.utils.queue(),c=this;Object.keys(this._registry).forEach(function(a){b.defer(function(b){c._registry[a].cleanup(b)})}),b.then(function(){a()})},y.prototype.add=function(a){"use strict";this._registry[a.id]=a},axe.registerPlugin=function(a){"use strict";axe.plugins[a.id]=new y(a)};var sa,ta={};axe.getReporter=function(a){"use strict";return"string"==typeof a&&ta[a]?ta[a]:"function"==typeof a?a:sa},axe.addReporter=function(a,b,c){"use strict";ta[a]=b,c&&(sa=b)},axe.reset=z,axe._runRules=A;var qa="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a},ua=function(){};axe.run=function(a,b,c){"use strict";if(!axe._audit)throw new Error("No audit configured");var d=C(a,b,c);a=d.context,b=d.options,c=d.callback,b.reporter=b.reporter||axe._audit.reporter||"v1",b.performanceTimer&&axe.utils.performanceTimer.start();var e=void 0,f=ua,g=ua;return window.Promise&&c===ua&&(e=new Promise(function(a,b){f=b,g=a})),axe._runRules(a,b,function(a){var d=function(a){try{c(null,a)}catch(a){axe.log(a)}g(a)};b.performanceTimer&&axe.utils.performanceTimer.end();try{var e=axe.getReporter(b.reporter),h=e(a,b,d);void 0!==h&&d(h)}catch(a){c(a),f(a)}},function(a){c(a),f(a)}),e},ra.failureSummary=function(a){"use strict";var b={};return b.none=a.none.concat(a.all),b.any=a.any,Object.keys(b).map(function(a){if(b[a].length){var c=axe._audit.data.failureSummaries[a];return c&&"function"==typeof c.failureMessage?c.failureMessage(b[a].map(function(a){return a.message||""})):void 0}}).filter(function(a){return void 0!==a}).join("\n\n")},ra.incompleteFallbackMessage=function(){"use strict";return axe._audit.data.incompleteFallbackMessage()};var qa="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a},va=axe.constants.resultGroups;ra.processAggregate=function(a,b){var c=axe.utils.aggregateResult(a);return c.timestamp=(new Date).toISOString(),c.url=window.location.href,va.forEach(function(a){c[a]=(c[a]||[]).map(function(a){return a=Object.assign({},a),Array.isArray(a.nodes)&&a.nodes.length>0&&(a.nodes=a.nodes.map(function(a){return"object"===qa(a.node)&&(a.html=a.node.source,b.elementRef&&!a.node.fromFrame&&(a.element=a.node.element),(!1!==b.selectors||a.node.fromFrame)&&(a.target=a.node.selector),b.xpath&&(a.xpath=a.node.xpath)),delete a.result,delete a.node,D(a,b),a})),va.forEach(function(b){return delete a[b]}),delete a.pageLevel,delete a.result,a})}),c},axe.addReporter("na",function(a,b,c){"use strict";"function"==typeof b&&(c=b,b={});var d=ra.processAggregate(a,b);c({violations:d.violations,passes:d.passes,incomplete:d.incomplete,inapplicable:d.inapplicable,timestamp:d.timestamp,url:d.url})}),axe.addReporter("no-passes",function(a,b,c){"use strict";"function"==typeof b&&(c=b,b={});var d=ra.processAggregate(a,b);c({violations:d.violations,timestamp:d.timestamp,url:d.url})}),axe.addReporter("raw",function(a,b,c){"use strict";"function"==typeof b&&(c=b,b={}),c(a)}),axe.addReporter("v1",function(a,b,c){"use strict";"function"==typeof b&&(c=b,b={});var d=ra.processAggregate(a,b);d.violations.forEach(function(a){return a.nodes.forEach(function(a){a.failureSummary=ra.failureSummary(a)})}),c({violations:d.violations,passes:d.passes,incomplete:d.incomplete,inapplicable:d.inapplicable,timestamp:d.timestamp,url:d.url})}),axe.addReporter("v2",function(a,b,c){"use strict";"function"==typeof b&&(c=b,b={});var d=ra.processAggregate(a,b);c({violations:d.violations,passes:d.passes,incomplete:d.incomplete,inapplicable:d.inapplicable,timestamp:d.timestamp,url:d.url})},!0),axe.utils.aggregate=function(a,b,c){b=b.slice(),c&&b.push(c);var d=b.map(function(b){return a.indexOf(b)}).sort();return a[d.pop()]};var wa=[];wa[axe.constants.PASS_PRIO]=!0,wa[axe.constants.CANTTELL_PRIO]=null,wa[axe.constants.FAIL_PRIO]=!1;var xa=["any","all","none"];axe.utils.aggregateChecks=function(a){var b=Object.assign({},a);E(b,function(a,b){var c=wa.indexOf(a.result);a.priority=-1!==c?c:axe.constants.CANTTELL_PRIO,"none"===b&&(a.priority=4-a.priority)});var c=E(b,function(a){return a.priority});b.priority=Math.max(c.all.reduce(function(a,b){return Math.max(a,b)},0),c.none.reduce(function(a,b){return Math.max(a,b)},0),c.any.reduce(function(a,b){return Math.min(a,b)},4)%4);var d=[];return xa.forEach(function(a){b[a]=b[a].filter(function(a){return a.priority===b.priority}),b[a].forEach(function(a){return d.push(a.impact)})}),b.priority===axe.constants.FAIL_PRIO?b.impact=axe.utils.aggregate(axe.constants.impact,d):b.impact=null,E(b,function(a){delete a.result,delete a.priority}),b.result=axe.constants.results[b.priority],delete b.priority,b},axe.utils.aggregateResult=function(a){var b={};return axe.constants.resultGroups.forEach(function(a){return b[a]=[]}),a.forEach(function(a){a.error?F(b,a,axe.constants.CANTTELL_GROUP):a.result===axe.constants.NA?F(b,a,axe.constants.NA_GROUP):axe.constants.resultGroups.forEach(function(c){Array.isArray(a[c])&&a[c].length>0&&F(b,a,c)})}),b},function(){axe.utils.aggregateRule=function(a){var b={};a=a.map(function(a){if(a.any&&a.all&&a.none)return axe.utils.aggregateChecks(a);if(Array.isArray(a.node))return axe.utils.finalizeRuleResult(a);throw new TypeError("Invalid Result type")});var c=a.map(function(a){return a.result});b.result=axe.utils.aggregate(axe.constants.results,c,b.result),axe.constants.resultGroups.forEach(function(a){return b[a]=[]}),a.forEach(function(a){var c=axe.constants.resultGroupMap[a.result];b[c].push(a)});var d=axe.constants.FAIL_GROUP;if(b[d].length>0){var e=b[d].map(function(a){return a.impact});b.impact=axe.utils.aggregate(axe.constants.impact,e)||null}else b.impact=null;return b}}(),axe.utils.areStylesSet=G,axe.utils.checkHelper=function(a,b,c,d){"use strict";return{isAsync:!1,async:function(){return this.isAsync=!0,function(b){b instanceof Error==!1?(a.value=b,c(a)):d(b)}},data:function(b){a.data=b},relatedNodes:function(c){c=c instanceof Node?[c]:axe.utils.toArray(c),a.relatedNodes=c.map(function(a){return new axe.utils.DqElement(a,b)})}}};var qa="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a};axe.utils.clone=function(a){"use strict";var b,c,d=a;if(null!==a&&"object"===(void 0===a?"undefined":qa(a)))if(Array.isArray(a))for(d=[],b=0,c=a.length;b<c;b++)d[b]=axe.utils.clone(a[b]);else{d={};for(b in a)d[b]=axe.utils.clone(a[b])}return d},axe.utils.sendCommandToFrame=function(a,b,c,d){"use strict";var e=a.contentWindow;if(!e)return axe.log("Frame does not have a content window",a),void c(null);var f=setTimeout(function(){f=setTimeout(function(){var e=H("No response from frame",a);b.debug?d(e):(axe.log(e),c(null))},0)},500);axe.utils.respondable(e,"axe.ping",null,void 0,function(){clearTimeout(f),f=setTimeout(function(){d(H("Axe in frame timed out",a))},3e4),axe.utils.respondable(e,"axe.start",b,void 0,function(a){clearTimeout(f),a instanceof Error==!1?c(a):d(a)})})},axe.utils.collectResultsFromFrames=I,axe.utils.contains=function(a,b){"use strict";function c(a,b){return a.shadowId===b.shadowId||!!a.children.find(function(a){return c(a,b)})}return a.shadowId||b.shadowId?c(a,b):"function"==typeof a.actualNode.contains?a.actualNode.contains(b.actualNode):!!(16&a.actualNode.compareDocumentPosition(b.actualNode))},function(axe){/*!
+!function a(window){function b(a){this.name="SupportError",this.cause=a.cause,this.message="`"+a.cause+"` - feature unsupported in your environment.",a.ruleId&&(this.ruleId=a.ruleId,this.message+=" Skipping "+this.ruleId+" rule."),this.stack=(new Error).stack}function c(a){"use strict";var b;return a?(b=axe.utils.clone(a),b.commons=a.commons):b={},b.reporter=b.reporter||null,b.rules=b.rules||[],b.checks=b.checks||[],b.data=Object.assign({checks:{},rules:{}},b.data),b}function d(a,b,c){"use strict";var d,e;for(d=0,e=a.length;d<e;d++)b[c](a[d])}function e(a){this.brand="axe",this.application="axeAPI",this.tagExclude=["experimental"],this.defaultConfig=a,this._init()}function f(a,b,c){var d=a.brand,e=a.application;return axe.constants.helpUrlBase+d+"/"+(c||axe.version.substring(0,axe.version.lastIndexOf(".")))+"/"+b+"?application="+e}function g(a){"use strict";this.id=a.id,this.data=null,this.relatedNodes=[],this.result=null}function h(a){"use strict";return"string"==typeof a?new Function("return "+a+";")():a}function i(a){a&&(this.id=a.id,this.configure(a))}function j(a,b){"use strict";if(!axe.utils.isHidden(b)){axe.utils.findBy(a,"node",b)||a.push({node:b,include:[],exclude:[]})}}function k(a,b,c){"use strict";a.frames=a.frames||[];var d,e,f=document.querySelectorAll(c.shift());a:for(var g=0,h=f.length;g<h;g++){e=f[g];for(var i=0,j=a.frames.length;i<j;i++)if(a.frames[i].node===e){a.frames[i][b].push(c);break a}d={node:e,include:[],exclude:[]},c&&d[b].push(c),a.frames.push(d)}}function l(a){"use strict";if(a&&"object"===(void 0===a?"undefined":ta(a))||a instanceof NodeList){if(a instanceof Node)return{include:[a],exclude:[]};if(a.hasOwnProperty("include")||a.hasOwnProperty("exclude"))return{include:a.include&&+a.include.length?a.include:[document],exclude:a.exclude||[]};if(a.length===+a.length)return{include:a,exclude:[]}}return"string"==typeof a?{include:[a],exclude:[]}:{include:[document],exclude:[]}}function m(a,b){"use strict";for(var c,d,e=[],f=0,g=a[b].length;f<g;f++){if("string"==typeof(c=a[b][f])){d=Array.from(document.querySelectorAll(c)),e=e.concat(d.map(function(a){return axe.utils.getFlattenedTree(a)[0]}));break}!c||!c.length||c instanceof Node?c instanceof Node&&e.push(axe.utils.getFlattenedTree(c)[0]):c.length>1?k(a,b,c):(d=Array.from(document.querySelectorAll(c[0])),e=e.concat(d.map(function(a){return axe.utils.getFlattenedTree(a)[0]})))}return e.filter(function(a){return a})}function n(a){"use strict";if(0===a.include.length){if(0===a.frames.length){var b=axe.utils.respondable.isInFrame()?"frame":"page";return new Error("No elements found for include in "+b+" Context")}a.frames.forEach(function(a,b){if(0===a.include.length)return new Error("No elements found for include in Context of frame "+b)})}}function o(a){"use strict";var b=this;this.frames=[],this.initiator=!a||"boolean"!=typeof a.initiator||a.initiator,this.page=!1,a=l(a),this.exclude=a.exclude,this.include=a.include,this.include=m(this,"include"),this.exclude=m(this,"exclude"),axe.utils.select("frame, iframe",this).forEach(function(a){ra(a,b)&&j(b.frames,a.actualNode)}),1===this.include.length&&this.include[0].actualNode===document.documentElement&&(this.page=!0);var c=n(this);if(c instanceof Error)throw c}function p(a){"use strict";this.id=a.id,this.result=axe.constants.NA,this.pageLevel=a.pageLevel,this.impact=null,this.nodes=[]}function q(a,b){"use strict";this._audit=b,this.id=a.id,this.selector=a.selector||"*",this.excludeHidden="boolean"!=typeof a.excludeHidden||a.excludeHidden,this.enabled="boolean"!=typeof a.enabled||a.enabled,this.pageLevel="boolean"==typeof a.pageLevel&&a.pageLevel,this.any=a.any||[],this.all=a.all||[],this.none=a.none||[],this.tags=a.tags||[],a.matches&&(this.matches=h(a.matches))}function r(a){"use strict";return axe.utils.getAllChecks(a).map(function(b){var c=a._audit.checks[b.id||b];return c&&"function"==typeof c.after?c:null}).filter(Boolean)}function s(a,b){"use strict";var c=[];return a.forEach(function(a){axe.utils.getAllChecks(a).forEach(function(a){a.id===b&&c.push(a)})}),c}function t(a){"use strict";return a.filter(function(a){return!0!==a.filtered})}function u(a){"use strict";var b=["any","all","none"],c=a.nodes.filter(function(a){var c=0;return b.forEach(function(b){a[b]=t(a[b]),c+=a[b].length}),c>0});return a.pageLevel&&c.length&&(c=[c.reduce(function(a,c){if(a)return b.forEach(function(b){a[b].push.apply(a[b],c[b])}),a})]),c}function v(a,b){"use strict";if(!axe._audit)throw new Error("No audit configured");var c=axe.utils.queue(),d=[];Object.keys(axe.plugins).forEach(function(a){c.defer(function(b){var c=function(a){d.push(a),b()};try{axe.plugins[a].cleanup(b,c)}catch(a){c(a)}})}),axe.utils.toArray(document.querySelectorAll("frame, iframe")).forEach(function(a){c.defer(function(b,c){return axe.utils.sendCommandToFrame(a,{command:"cleanup-plugin"},b,c)})}),c.then(function(c){0===d.length?a(c):b(d)}).catch(b)}function w(a){"use strict";var b;if(!(b=axe._audit))throw new Error("No audit configured");a.reporter&&("function"==typeof a.reporter||wa[a.reporter])&&(b.reporter=a.reporter),a.checks&&a.checks.forEach(function(a){b.addCheck(a)}),a.rules&&a.rules.forEach(function(a){b.addRule(a)}),void 0!==a.branding?b.setBranding(a.branding):b._constructHelpUrls(),a.tagExclude&&(b.tagExclude=a.tagExclude)}function x(a,b,c){"use strict";var d=c,e=function(a){a instanceof Error==!1&&(a=new Error(a)),c(a)},f=a&&a.context||{};f.include&&!f.include.length&&(f.include=[document]);var g=a&&a.options||{};switch(a.command){case"rules":return A(f,g,d,e);case"cleanup-plugin":return v(d,e);default:if(axe._audit&&axe._audit.commands&&axe._audit.commands[a.command])return axe._audit.commands[a.command](a,c)}}function y(a){"use strict";this._run=a.run,this._collect=a.collect,this._registry={},a.commands.forEach(function(a){axe._audit.registerCommand(a)})}function z(){"use strict";var a=axe._audit;if(!a)throw new Error("No audit configured");a.resetRulesAndChecks()}function A(a,b,c,d){"use strict";try{a=new o(a)}catch(a){return d(a)}var e=axe.utils.queue(),f=axe._audit;b.performanceTimer&&axe.utils.performanceTimer.auditStart(),a.frames.length&&!1!==b.iframes&&e.defer(function(c,d){axe.utils.collectResultsFromFrames(a,b,"rules",null,c,d)}),e.defer(function(c,d){if(b.restoreScroll){var e=axe.utils.getScrollState();f.run(a,b,c,d),axe.utils.setScrollState(e)}else f.run(a,b,c,d)}),e.then(function(e){try{b.performanceTimer&&axe.utils.performanceTimer.auditEnd();var g=axe.utils.mergeResults(e.map(function(a){return{results:a}}));a.initiator&&(g=f.after(g,b),g.forEach(axe.utils.publishMetaData),g=g.map(axe.utils.finalizeRuleResult));try{c(g)}catch(a){axe.log(a)}}catch(a){d(a)}}).catch(d)}function B(a){"use strict";switch(!0){case"string"==typeof a:case Array.isArray(a):case Node&&a instanceof Node:case NodeList&&a instanceof NodeList:return!0;case"object"!==(void 0===a?"undefined":ta(a)):return!1;case void 0!==a.include:case void 0!==a.exclude:case"number"==typeof a.length:return!0;default:return!1}}function C(a,b,c){"use strict";var d=new TypeError("axe.run arguments are invalid");if(!B(a)){if(void 0!==c)throw d;c=b,b=a,a=document}if("object"!==(void 0===b?"undefined":ta(b))){if(void 0!==c)throw d;c=b,b={}}if("function"!=typeof c&&void 0!==c)throw d;return{context:a,options:b,callback:c||xa}}function D(a,b){"use strict";["any","all","none"].forEach(function(c){Array.isArray(a[c])&&a[c].filter(function(a){return Array.isArray(a.relatedNodes)}).forEach(function(a){a.relatedNodes=a.relatedNodes.map(function(a){var c={html:a.source};return b.elementRef&&!a.fromFrame&&(c.element=a.element),(!1!==b.selectors||a.fromFrame)&&(c.target=a.selector),b.xpath&&(c.xpath=a.xpath),c})})})}function E(a,b){return Aa.reduce(function(c,d){return c[d]=(a[d]||[]).map(function(a){return b(a,d)}),c},{})}function F(a,b,c){var d=Object.assign({},b);d.nodes=(d[c]||[]).concat(),axe.constants.resultGroups.forEach(function(a){delete d[a]}),a[c].push(d)}function G(a,b,c){"use strict";var d=window.getComputedStyle(a,null),e=!1;return!!d&&(b.forEach(function(a){d.getPropertyValue(a.property)===a.value&&(e=!0)}),!!e||!(a.nodeName.toUpperCase()===c.toUpperCase()||!a.parentNode)&&G(a.parentNode,b,c))}function H(a,b){"use strict";return new Error(a+": "+axe.utils.getSelector(b))}function I(a,b,c,d,e,f){"use strict";var g=axe.utils.queue();a.frames.forEach(function(e){var f={options:b,command:c,parameter:d,context:{initiator:!1,page:a.page,include:e.include||[],exclude:e.exclude||[]}};g.defer(function(a,b){var c=e.node;axe.utils.sendCommandToFrame(c,f,function(b){if(b)return a({results:b,frameElement:c,frame:axe.utils.getSelector(c)});a(null)},b)})}),g.then(function(a){e(axe.utils.mergeResults(a,b))}).catch(f)}function J(a,b){if(b=b||300,a.length>b){var c=a.indexOf(">");a=a.substring(0,c+1)}return a}function K(a){var b=a.outerHTML;return b||"function"!=typeof XMLSerializer||(b=(new XMLSerializer).serializeToString(a)),J(b||"")}function L(a,b,c){this._fromFrame=!!c,this.spec=c||{},b&&b.absolutePaths&&(this._options={toRoot:!0}),this.source=void 0!==this.spec.source?this.spec.source:K(a),this._element=a}function M(a,b){return{shadowId:b,children:[],actualNode:a}}function N(a){var b=[];for(a=a.firstChild;a;)b.push(a),a=a.nextSibling;return b}function O(){var a=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";return 0!==a.length&&(a.match(/[0-9]/g)||"").length>=a.length/2}function P(a,b){return[a.substring(0,b),a.substring(b)]}function Q(a){var b=a,c="",d="",e="",f="",g="",h="";if(a.includes("#")){var i=P(a,a.indexOf("#")),j=Ba(i,2);a=j[0],h=j[1]}if(a.includes("?")){var k=P(a,a.indexOf("?")),l=Ba(k,2);a=l[0],g=l[1]}if(a.includes("://")){var m=a.split("://"),n=Ba(m,2);c=n[0],a=n[1];var o=P(a,a.indexOf("/")),p=Ba(o,2);d=p[0],a=p[1]}else if("//"===a.substr(0,2)){a=a.substr(2);var q=P(a,a.indexOf("/")),r=Ba(q,2);d=r[0],a=r[1]}if("www."===d.substr(0,4)&&(d=d.substr(4)),d&&d.includes(":")){var s=P(d,d.indexOf(":")),t=Ba(s,2);d=t[0],e=t[1]}return f=a,{original:b,protocol:c,domain:d,port:e,path:f,query:g,hash:h}}function R(a){if(Array.isArray(a)){for(var b=0,c=Array(a.length);b<a.length;b++)c[b]=a[b];return c}return Array.from(a)}function S(a){return!["focus","hover","hidden","visible","dirty","touched","valid","disable","enable","active","col-"].find(function(b){return a.includes(b)})}function T(a){return a.classList&&0!==a.classList.length?(a.parentNode&&Array.from(a.parentNode.children||"")||[]).reduce(function(b,c){return a===c?b:b.filter(function(a){return!c.classList.contains(a)})},Array.from(a.classList).filter(S)):[]}function U(a,b){var c=a.parentNode&&Array.from(a.parentNode.children||"")||[];if(c.find(function(c){return c!==a&&axe.utils.matchesSelector(c,b)}))return":nth-child("+(1+c.indexOf(a))+")";return""}function V(a,b){var c=a.nodeName.toLowerCase(),d=Array.from(a.classList)||[],e={nodeName:c,classList:d,isCustomElm:c.includes("-"),isCommonElm:Da.includes(c),distinctClassList:T(a)};return[Ea.getCustomElm,Ea.getElmRoleProp,Ea.getUncommonElm,Ea.getElmNameProp,Ea.getDistinctClass,Ea.getFileRefProp,Ea.getCommonName].reduce(function(c,d){if(c.length===b)return c;var f=d(a,e);return f&&(f[0].match(/[a-z]/)?c.unshift(f):c.push(f)),c},[])}function W(a,b,c){var d=void 0,e=void 0,f=b.isUnique,g=void 0!==f&&f,h=Ea.getElmId(a),i=b.featureCount,j=void 0===i?2:i,k=b.minDepth,l=void 0===k?1:k,m=b.toRoot,n=void 0!==m&&m,o=b.childSelectors,p=void 0===o?[]:o;h?(d=h,g=!0):(d=V(a,j).join(""),d+=U(a,d),g=b.isUnique||1===c.querySelectorAll(d).length,g||a!==document.documentElement||(d+=":root"),e=0!==l||!g);var q=[d].concat(R(p));return a.parentElement&&11!==a.parentElement.nodeType&&(n||e)?W(a.parentNode,{toRoot:n,isUnique:g,childSelectors:q,featureCount:1,minDepth:l-1},c):q.join(" > ")}function X(a,b){var c,d;if(!a)return[];if(!b&&9===a.nodeType)return b=[{str:"html"}];if(b=b||[],a.parentNode&&a.parentNode!==a&&(b=X(a.parentNode,b)),a.previousSibling){d=1,c=a.previousSibling;do{1===c.nodeType&&c.nodeName===a.nodeName&&d++,c=c.previousSibling}while(c);1===d&&(d=null)}else if(a.nextSibling){c=a.nextSibling;do{1===c.nodeType&&c.nodeName===a.nodeName?(d=1,c=null):(d=null,c=c.previousSibling)}while(c)}if(1===a.nodeType){var e={};e.str=a.nodeName.toLowerCase();var f=a.getAttribute&&axe.utils.escapeSelector(a.getAttribute("id"));f&&1===a.ownerDocument.querySelectorAll("#"+f).length&&(e.id=a.getAttribute("id")),d>1&&(e.count=d),b.push(e)}return b}function Y(a){return a.reduce(function(a,b){return b.id?"/"+b.str+"[@id='"+b.id+"']":a+"/"+b.str+(b.count>0?"["+b.count+"]":"")},"")}function Z(a){"use strict";if(Fa&&Fa.parentNode)return void 0===Fa.styleSheet?Fa.appendChild(document.createTextNode(a)):Fa.styleSheet.cssText+=a,Fa;if(a){var b=document.head||document.getElementsByTagName("head")[0];return Fa=document.createElement("style"),Fa.type="text/css",void 0===Fa.styleSheet?Fa.appendChild(document.createTextNode(a)):Fa.styleSheet.cssText=a,b.appendChild(Fa),Fa}}function $(a,b,c,d){"use strict";var e=axe.utils.getXpath(c),f={element:c,selector:d,xpath:e};a.forEach(function(a){a.node=axe.utils.DqElement.fromFrame(a.node,b,f);var c=axe.utils.getAllChecks(a);c.length&&c.forEach(function(a){a.relatedNodes=a.relatedNodes.map(function(a){return axe.utils.DqElement.fromFrame(a,b,f)})})})}function _(a,b){"use strict";for(var c,d,e=b[0].node,f=0,g=a.length;f<g;f++)if(d=a[f].node,(c=axe.utils.nodeSorter({actualNode:d.element},{actualNode:e.element}))>0||0===c&&e.selector.length<d.selector.length)return void a.splice.apply(a,[f,0].concat(b));a.push.apply(a,b)}function aa(a){"use strict";return a&&a.results?Array.isArray(a.results)?a.results.length?a.results:null:[a.results]:null}function ba(a,b){function c(a){return a.incomplete&&a.incomplete.default?a.incomplete.default:ua.incompleteFallbackMessage()}if(!a||!a.missingData)return c(b);try{var d=b.incomplete[a.missingData[0].reason];if(!d)throw new Error;return d}catch(d){return"string"==typeof a.missingData?b.incomplete[a.missingData]:c(b)}}function ca(a,b){"use strict";return function(c){var d=a[c.id]||{},e=d.messages||{},f=Object.assign({},d);delete f.messages,void 0===c.result?"object"===ta(e.incomplete)?f.message=function(){return ba(c.data,e)}:f.message=e.incomplete:f.message=c.result===b?e.pass:e.fail,axe.utils.extendMetaData(c,f)}}function da(a,b){return 1===a.nodeType&&("*"===b.tag||a.nodeName.toLowerCase()===b.tag)}function ea(a,b){return!b.classes||b.classes.reduce(function(b,c){return b&&a.className&&a.className.match(c.regexp)},!0)}function fa(a,b){return!b.attributes||b.attributes.reduce(function(b,c){var d=a.getAttribute(c.key);return b&&null!==d&&(!c.value||c.test(d))},!0)}function ga(a,b){return!b.id||a.id===b.id}function ha(a,b){return!(b.pseudos&&!b.pseudos.reduce(function(b,c){if("not"===c.name)return b&&!Ha([a],c.expressions,!1).length;throw new Error("the pseudo selector "+c.name+" has not yet been implemented")},!0))}function ia(a,b,c){var d=[];return a=Array.isArray(a)?a:[a],a.forEach(function(a){da(a.actualNode,b)&&ea(a.actualNode,b)&&fa(a.actualNode,b)&&ga(a.actualNode,b)&&ha(a,b)&&d.push(a),c&&(d=d.concat(ia(a.children.filter(function(c){return!b.id||c.shadowId===a.shadowId}),b,c)))}),d}function ja(a){/*! Credit Mootools Copyright Mootools, MIT License */
+if(a)return a.map(function(a){var b,c,d=a.name.replace(Ja,""),e=(a.value||"").replace(Ja,"");switch(a.operator){case"^=":c=new RegExp("^"+Ia(e));break;case"$=":c=new RegExp(Ia(e)+"$");break;case"~=":c=new RegExp("(^|\\s)"+Ia(e)+"(\\s|$)");break;case"|=":c=new RegExp("^"+Ia(e)+"(-|$)");break;case"=":b=function(a){return e===a};break;case"*=":b=function(a){return a&&a.indexOf(e)>-1};break;case"!=":b=function(a){return e!==a};break;default:b=function(a){return!!a}}return""===e&&/^[*$^]=$/.test(a.operator)&&(b=function(){return!1}),b||(b=function(a){return a&&c.test(a)}),{key:d,value:e,test:b}})}function ka(a){if(a)return a.map(function(a){return a=a.replace(Ja,""),{value:a,regexp:new RegExp("(^|\\s)"+Ia(a)+"(\\s|$)")}})}function la(a){if(a)return a.map(function(a){var b;return"not"===a.name&&(b=axe.utils.cssParser.parse(a.value),b=b.selectors?b.selectors:[b],b=Ga(b)),{name:a.name,expressions:b,value:a.value}})}function ma(a,b){"use strict";var c,d,e=axe._audit&&axe._audit.tagExclude?axe._audit.tagExclude:[];return b.include||b.exclude?(c=b.include||[],c=Array.isArray(c)?c:[c],d=b.exclude||[],d=Array.isArray(d)?d:[d],d=d.concat(e.filter(function(a){return-1===c.indexOf(a)}))):(c=Array.isArray(b)?b:[b],d=e.filter(function(a){return-1===c.indexOf(a)})),!!(c.some(function(b){return-1!==a.tags.indexOf(b)})||0===c.length&&!1!==a.enabled)&&d.every(function(b){return-1===a.tags.indexOf(b)})}function na(a){var b=window.getComputedStyle(a),c="visible"===b.getPropertyValue("overflow-y"),d="visible"===b.getPropertyValue("overflow-x");if(!c&&a.scrollHeight>a.clientHeight||!d&&a.scrollWidth>a.clientWidth)return{elm:a,top:a.scrollTop,left:a.scrollLeft}}function oa(a,b,c){if(a===window)return a.scroll(b,c);a.scrollTop=b,a.scrollLeft=c}function pa(a){return Array.from(a.children).reduce(function(a,b){var c=na(b);return c&&a.push(c),a.concat(pa(b))},[])}function qa(a){"use strict";return a.sort(function(a,b){return axe.utils.contains(a,b)?1:-1})[0]}function ra(a,b){"use strict";var c=b.include&&qa(b.include.filter(function(b){return axe.utils.contains(b,a)})),d=b.exclude&&qa(b.exclude.filter(function(b){return axe.utils.contains(b,a)}));return!!(!d&&c||d&&axe.utils.contains(d,c))}function sa(a,b,c){"use strict";for(var d=0,e=b.length;d<e;d++)!a.find(function(a){return a.actualNode===b[d].actualNode})&&ra(b[d],c)&&a.push(b[d])}var document=window.document,ta="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a},axe=axe||{};axe.version="3.0.0-alpha-1","function"==typeof define&&define.amd&&define([],function(){"use strict";return axe}),"object"===("undefined"==typeof module?"undefined":ta(module))&&module.exports&&"function"==typeof a.toString&&(axe.source="("+a.toString()+')(typeof window === "object" ? window : this);',module.exports=axe),"function"==typeof window.getComputedStyle&&(window.axe=axe);var commons;b.prototype=Object.create(Error.prototype),b.prototype.constructor=b;var utils=axe.utils={},ua={},ta="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a};e.prototype._init=function(){var a=c(this.defaultConfig);axe.commons=commons=a.commons,this.reporter=a.reporter,this.commands={},this.rules=[],this.checks={},d(a.rules,this,"addRule"),d(a.checks,this,"addCheck"),this.data={},this.data.checks=a.data&&a.data.checks||{},this.data.rules=a.data&&a.data.rules||{},this.data.failureSummaries=a.data&&a.data.failureSummaries||{},this.data.incompleteFallbackMessage=a.data&&a.data.incompleteFallbackMessage||"",this._constructHelpUrls()},e.prototype.registerCommand=function(a){"use strict";this.commands[a.id]=a.callback},e.prototype.addRule=function(a){"use strict";a.metadata&&(this.data.rules[a.id]=a.metadata);var b=this.getRule(a.id);b?b.configure(a):this.rules.push(new q(a,this))},e.prototype.addCheck=function(a){"use strict";var b=a.metadata;"object"===(void 0===b?"undefined":ta(b))&&(this.data.checks[a.id]=b,"object"===ta(b.messages)&&Object.keys(b.messages).filter(function(a){return b.messages.hasOwnProperty(a)&&"string"==typeof b.messages[a]}).forEach(function(a){0===b.messages[a].indexOf("function")&&(b.messages[a]=new Function("return "+b.messages[a]+";")())})),this.checks[a.id]?this.checks[a.id].configure(a):this.checks[a.id]=new i(a)},e.prototype.run=function(a,b,c,d){"use strict";this.validateOptions(b),axe._tree=axe.utils.getFlattenedTree(document.documentElement);var e=axe.utils.queue();this.rules.forEach(function(c){if(axe.utils.ruleShouldRun(c,a,b)){if(b.performanceTimer){var d="mark_rule_end_"+c.id,f="mark_rule_start_"+c.id;axe.utils.performanceTimer.mark(f)}e.defer(function(e,g){c.run(a,b,function(a){b.performanceTimer&&(axe.utils.performanceTimer.mark(d),axe.utils.performanceTimer.measure("rule_"+c.id,f,d)),e(a)},function(a){if(b.debug)g(a);else{var d=Object.assign(new p(c),{result:axe.constants.CANTTELL,description:"An error occured while running this rule",message:a.message,stack:a.stack,error:a});e(d)}})})}}),e.then(function(a){axe._tree=void 0,c(a.filter(function(a){return!!a}))}).catch(d)},e.prototype.after=function(a,b){"use strict";var c=this.rules;return a.map(function(a){return axe.utils.findBy(c,"id",a.id).after(a,b)})},e.prototype.getRule=function(a){return this.rules.find(function(b){return b.id===a})},e.prototype.validateOptions=function(a){"use strict";var b=this;if("object"===ta(a.runOnly)){var c=a.runOnly;if("rule"===c.type&&Array.isArray(c.value))c.value.forEach(function(a){if(!b.getRule(a))throw new Error("unknown rule `"+a+"` in options.runOnly")});else if(Array.isArray(c.value)&&c.value.length>0){var d=[].concat(c.value);if(b.rules.forEach(function(a){var b,c,e;if(d)for(c=0,e=a.tags.length;c<e;c++)-1!==(b=d.indexOf(a.tags[c]))&&d.splice(b,1)}),0!==d.length)throw new Error("could not find tags `"+d.join("`, `")+"`")}}return"object"===ta(a.rules)&&Object.keys(a.rules).forEach(function(a){if(!b.getRule(a))throw new Error("unknown rule `"+a+"` in options.rules")}),a},e.prototype.setBranding=function(a){"use strict";var b={brand:this.brand,application:this.application};a&&a.hasOwnProperty("brand")&&a.brand&&"string"==typeof a.brand&&(this.brand=a.brand),a&&a.hasOwnProperty("application")&&a.application&&"string"==typeof a.application&&(this.application=a.application),this._constructHelpUrls(b)},e.prototype._constructHelpUrls=function(){var a=this,b=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,c=axe.version.substring(0,axe.version.lastIndexOf("."));this.rules.forEach(function(d){a.data.rules[d.id]||(a.data.rules[d.id]={});var e=a.data.rules[d.id];("string"!=typeof e.helpUrl||b&&e.helpUrl===f(b,d.id,c))&&(e.helpUrl=f(a,d.id,c))})},e.prototype.resetRulesAndChecks=function(){"use strict";this._init()},i.prototype.enabled=!0,i.prototype.run=function(a,b,c,d){"use strict";b=b||{};var e=b.hasOwnProperty("enabled")?b.enabled:this.enabled,f=b.options||this.options;if(e){var h,i=new g(this),j=axe.utils.checkHelper(i,b,c,d);try{h=this.evaluate.call(j,a.actualNode,f,a)}catch(a){return void d(a)}j.isAsync||(i.result=h,setTimeout(function(){c(i)},0))}else c(null)},i.prototype.configure=function(a){var b=this;["options","enabled"].filter(function(b){return a.hasOwnProperty(b)}).forEach(function(c){return b[c]=a[c]}),["evaluate","after"].filter(function(b){return a.hasOwnProperty(b)}).forEach(function(c){return b[c]=h(a[c])})};var ta="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a};q.prototype.matches=function(){"use strict";return!0},q.prototype.gather=function(a){"use strict";var b=axe.utils.select(this.selector,a);return this.excludeHidden?b.filter(function(a){return!axe.utils.isHidden(a.actualNode)}):b},q.prototype.runChecks=function(a,b,c,d,e){"use strict";var f=this,g=axe.utils.queue();this[a].forEach(function(a){var d=f._audit.checks[a.id||a],e=axe.utils.getCheckOption(d,f.id,c);g.defer(function(a,c){d.run(b,e,a,c)})}),g.then(function(b){b=b.filter(function(a){return a}),d({type:a,results:b})}).catch(e)},q.prototype.run=function(a,c,d,e){var f=this,g=axe.utils.queue(),h=new p(this),i=void 0;try{i=this.gather(a).filter(function(a){return f.matches(a.actualNode,a)})}catch(a){return void e(new b({cause:a,ruleId:this.id}))}c.performanceTimer&&axe.log("gather (",i.length,"):",axe.utils.performanceTimer.timeElapsed()+"ms"),i.forEach(function(a){g.defer(function(b,d){var e=axe.utils.queue();e.defer(function(b,d){f.runChecks("any",a,c,b,d)}),e.defer(function(b,d){f.runChecks("all",a,c,b,d)}),e.defer(function(b,d){f.runChecks("none",a,c,b,d)}),e.then(function(d){if(d.length){var e=!1,f={};d.forEach(function(a){var b=a.results.filter(function(a){return a});f[a.type]=b,b.length&&(e=!0)}),e&&(f.node=new axe.utils.DqElement(a.actualNode,c),h.nodes.push(f))}b()}).catch(function(a){return d(a)})})}),g.then(function(){return d(h)}).catch(function(a){return e(a)})},q.prototype.after=function(a,b){"use strict";var c=r(this),d=this.id;return c.forEach(function(c){var e=s(a.nodes,c.id),f=axe.utils.getCheckOption(c,d,b),g=c.after(e,f);e.forEach(function(a){-1===g.indexOf(a)&&(a.filtered=!0)})}),a.nodes=u(a),a},q.prototype.configure=function(a){"use strict";a.hasOwnProperty("selector")&&(this.selector=a.selector),a.hasOwnProperty("excludeHidden")&&(this.excludeHidden="boolean"!=typeof a.excludeHidden||a.excludeHidden),a.hasOwnProperty("enabled")&&(this.enabled="boolean"!=typeof a.enabled||a.enabled),a.hasOwnProperty("pageLevel")&&(this.pageLevel="boolean"==typeof a.pageLevel&&a.pageLevel),a.hasOwnProperty("any")&&(this.any=a.any),a.hasOwnProperty("all")&&(this.all=a.all),a.hasOwnProperty("none")&&(this.none=a.none),a.hasOwnProperty("tags")&&(this.tags=a.tags),a.hasOwnProperty("matches")&&("string"==typeof a.matches?this.matches=new Function("return "+a.matches+";")():this.matches=a.matches)},function(axe){var a=[{name:"NA",value:"inapplicable",priority:0,group:"inapplicable"},{name:"PASS",value:"passed",priority:1,group:"passes"},{name:"CANTTELL",value:"cantTell",priority:2,group:"incomplete"},{name:"FAIL",value:"failed",priority:3,group:"violations"}],b={helpUrlBase:"https://dequeuniversity.com/rules/",results:[],resultGroups:[],resultGroupMap:{},impact:Object.freeze(["minor","moderate","serious","critical"])};a.forEach(function(a){var c=a.name,d=a.value,e=a.priority,f=a.group;b[c]=d,b[c+"_PRIO"]=e,b[c+"_GROUP"]=f,b.results[e]=d,b.resultGroups[e]=f,b.resultGroupMap[d]=f}),Object.freeze(b.results),Object.freeze(b.resultGroups),Object.freeze(b.resultGroupMap),Object.freeze(b),Object.defineProperty(axe,"constants",{value:b,enumerable:!0,configurable:!1,writable:!1})}(axe);var ta="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a};axe.log=function(){"use strict";"object"===("undefined"==typeof console?"undefined":ta(console))&&console.log&&Function.prototype.apply.call(console.log,console,arguments)};var ta="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a};axe.a11yCheck=function(a,b,c){"use strict";"function"==typeof b&&(c=b,b={}),b&&"object"===(void 0===b?"undefined":ta(b))||(b={});var d=axe._audit;if(!d)throw new Error("No audit configured");b.reporter=b.reporter||d.reporter||"v2",b.performanceTimer&&axe.utils.performanceTimer.start();var e=axe.getReporter(b.reporter);axe._runRules(a,b,function(a){var d=e(a,b,c);void 0!==d&&(b.performanceTimer&&axe.utils.performanceTimer.end(),c(d))},axe.log)},axe.cleanup=v,axe.configure=w,axe.getRules=function(a){"use strict";a=a||[];var b=a.length?axe._audit.rules.filter(function(b){return!!a.filter(function(a){return-1!==b.tags.indexOf(a)}).length}):axe._audit.rules,c=axe._audit.data.rules||{};return b.map(function(a){var b=c[a.id]||{};return{ruleId:a.id,description:b.description,help:b.help,helpUrl:b.helpUrl,tags:a.tags}})},axe._load=function(a){"use strict";axe.utils.respondable.subscribe("axe.ping",function(a,b,c){c({axe:!0})}),axe.utils.respondable.subscribe("axe.start",x),axe._audit=new e(a)};var axe=axe||{};axe.plugins={},y.prototype.run=function(){"use strict";return this._run.apply(this,arguments)},y.prototype.collect=function(){"use strict";return this._collect.apply(this,arguments)},y.prototype.cleanup=function(a){"use strict";var b=axe.utils.queue(),c=this;Object.keys(this._registry).forEach(function(a){b.defer(function(b){c._registry[a].cleanup(b)})}),b.then(function(){a()})},y.prototype.add=function(a){"use strict";this._registry[a.id]=a},axe.registerPlugin=function(a){"use strict";axe.plugins[a.id]=new y(a)};var va,wa={};axe.getReporter=function(a){"use strict";return"string"==typeof a&&wa[a]?wa[a]:"function"==typeof a?a:va},axe.addReporter=function(a,b,c){"use strict";wa[a]=b,c&&(va=b)},axe.reset=z,axe._runRules=A;var ta="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a},xa=function(){};axe.run=function(a,b,c){"use strict";if(!axe._audit)throw new Error("No audit configured");var d=C(a,b,c);a=d.context,b=d.options,c=d.callback,b.reporter=b.reporter||axe._audit.reporter||"v1",b.performanceTimer&&axe.utils.performanceTimer.start();var e=void 0,f=xa,g=xa;return window.Promise&&c===xa&&(e=new Promise(function(a,b){f=b,g=a})),axe._runRules(a,b,function(a){var d=function(a){try{c(null,a)}catch(a){axe.log(a)}g(a)};b.performanceTimer&&axe.utils.performanceTimer.end();try{var e=axe.getReporter(b.reporter),h=e(a,b,d);void 0!==h&&d(h)}catch(a){c(a),f(a)}},function(a){c(a),f(a)}),e},ua.failureSummary=function(a){"use strict";var b={};return b.none=a.none.concat(a.all),b.any=a.any,Object.keys(b).map(function(a){if(b[a].length){var c=axe._audit.data.failureSummaries[a];return c&&"function"==typeof c.failureMessage?c.failureMessage(b[a].map(function(a){return a.message||""})):void 0}}).filter(function(a){return void 0!==a}).join("\n\n")},ua.incompleteFallbackMessage=function(){"use strict";return axe._audit.data.incompleteFallbackMessage()};var ta="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a},ya=axe.constants.resultGroups;ua.processAggregate=function(a,b){var c=axe.utils.aggregateResult(a);return c.timestamp=(new Date).toISOString(),c.url=window.location.href,ya.forEach(function(a){c[a]=(c[a]||[]).map(function(a){return a=Object.assign({},a),Array.isArray(a.nodes)&&a.nodes.length>0&&(a.nodes=a.nodes.map(function(a){return"object"===ta(a.node)&&(a.html=a.node.source,b.elementRef&&!a.node.fromFrame&&(a.element=a.node.element),(!1!==b.selectors||a.node.fromFrame)&&(a.target=a.node.selector),b.xpath&&(a.xpath=a.node.xpath)),delete a.result,delete a.node,D(a,b),a})),ya.forEach(function(b){return delete a[b]}),delete a.pageLevel,delete a.result,a})}),c},axe.addReporter("na",function(a,b,c){"use strict";"function"==typeof b&&(c=b,b={});var d=ua.processAggregate(a,b);c({violations:d.violations,passes:d.passes,incomplete:d.incomplete,inapplicable:d.inapplicable,timestamp:d.timestamp,url:d.url})}),axe.addReporter("no-passes",function(a,b,c){"use strict";"function"==typeof b&&(c=b,b={});var d=ua.processAggregate(a,b);c({violations:d.violations,timestamp:d.timestamp,url:d.url})}),axe.addReporter("raw",function(a,b,c){"use strict";"function"==typeof b&&(c=b,b={}),c(a)}),axe.addReporter("v1",function(a,b,c){"use strict";"function"==typeof b&&(c=b,b={});var d=ua.processAggregate(a,b);d.violations.forEach(function(a){return a.nodes.forEach(function(a){a.failureSummary=ua.failureSummary(a)})}),c({violations:d.violations,passes:d.passes,incomplete:d.incomplete,inapplicable:d.inapplicable,timestamp:d.timestamp,url:d.url})}),axe.addReporter("v2",function(a,b,c){"use strict";"function"==typeof b&&(c=b,b={});var d=ua.processAggregate(a,b);c({violations:d.violations,passes:d.passes,incomplete:d.incomplete,inapplicable:d.inapplicable,timestamp:d.timestamp,url:d.url})},!0),axe.utils.aggregate=function(a,b,c){b=b.slice(),c&&b.push(c);var d=b.map(function(b){return a.indexOf(b)}).sort();return a[d.pop()]};var za=[];za[axe.constants.PASS_PRIO]=!0,za[axe.constants.CANTTELL_PRIO]=null,za[axe.constants.FAIL_PRIO]=!1;var Aa=["any","all","none"];axe.utils.aggregateChecks=function(a){var b=Object.assign({},a);E(b,function(a,b){var c=za.indexOf(a.result);a.priority=-1!==c?c:axe.constants.CANTTELL_PRIO,"none"===b&&(a.priority=4-a.priority)});var c=E(b,function(a){return a.priority});b.priority=Math.max(c.all.reduce(function(a,b){return Math.max(a,b)},0),c.none.reduce(function(a,b){return Math.max(a,b)},0),c.any.reduce(function(a,b){return Math.min(a,b)},4)%4);var d=[];return Aa.forEach(function(a){b[a]=b[a].filter(function(a){return a.priority===b.priority}),b[a].forEach(function(a){return d.push(a.impact)})}),b.priority===axe.constants.FAIL_PRIO?b.impact=axe.utils.aggregate(axe.constants.impact,d):b.impact=null,E(b,function(a){delete a.result,delete a.priority}),b.result=axe.constants.results[b.priority],delete b.priority,b},axe.utils.aggregateResult=function(a){var b={};return axe.constants.resultGroups.forEach(function(a){return b[a]=[]}),a.forEach(function(a){a.error?F(b,a,axe.constants.CANTTELL_GROUP):a.result===axe.constants.NA?F(b,a,axe.constants.NA_GROUP):axe.constants.resultGroups.forEach(function(c){Array.isArray(a[c])&&a[c].length>0&&F(b,a,c)})}),b},function(){axe.utils.aggregateRule=function(a){var b={};a=a.map(function(a){if(a.any&&a.all&&a.none)return axe.utils.aggregateChecks(a);if(Array.isArray(a.node))return axe.utils.finalizeRuleResult(a);throw new TypeError("Invalid Result type")});var c=a.map(function(a){return a.result});b.result=axe.utils.aggregate(axe.constants.results,c,b.result),axe.constants.resultGroups.forEach(function(a){return b[a]=[]}),a.forEach(function(a){var c=axe.constants.resultGroupMap[a.result];b[c].push(a)});var d=axe.constants.FAIL_GROUP;if(b[d].length>0){var e=b[d].map(function(a){return a.impact});b.impact=axe.utils.aggregate(axe.constants.impact,e)||null}else b.impact=null;return b}}(),axe.utils.areStylesSet=G,axe.utils.checkHelper=function(a,b,c,d){"use strict";return{isAsync:!1,async:function(){return this.isAsync=!0,function(b){b instanceof Error==!1?(a.value=b,c(a)):d(b)}},data:function(b){a.data=b},relatedNodes:function(c){c=c instanceof Node?[c]:axe.utils.toArray(c),a.relatedNodes=c.map(function(a){return new axe.utils.DqElement(a,b)})}}};var ta="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a};axe.utils.clone=function(a){"use strict";var b,c,d=a;if(null!==a&&"object"===(void 0===a?"undefined":ta(a)))if(Array.isArray(a))for(d=[],b=0,c=a.length;b<c;b++)d[b]=axe.utils.clone(a[b]);else{d={};for(b in a)d[b]=axe.utils.clone(a[b])}return d},axe.utils.sendCommandToFrame=function(a,b,c,d){"use strict";var e=a.contentWindow;if(!e)return axe.log("Frame does not have a content window",a),void c(null);var f=setTimeout(function(){f=setTimeout(function(){var e=H("No response from frame",a);b.debug?d(e):(axe.log(e),c(null))},0)},500);axe.utils.respondable(e,"axe.ping",null,void 0,function(){clearTimeout(f),f=setTimeout(function(){d(H("Axe in frame timed out",a))},3e4),axe.utils.respondable(e,"axe.start",b,void 0,function(a){clearTimeout(f),a instanceof Error==!1?c(a):d(a)})})},axe.utils.collectResultsFromFrames=I,axe.utils.contains=function(a,b){"use strict";function c(a,b){return a.shadowId===b.shadowId||!!a.children.find(function(a){return c(a,b)})}return a.shadowId||b.shadowId?c(a,b):"function"==typeof a.actualNode.contains?a.actualNode.contains(b.actualNode):!!(16&a.actualNode.compareDocumentPosition(b.actualNode))},function(axe){/*!
   * The copyright below covers the code within this function block only
   *
   * Copyright (c) 2013 Dulin Marat
@@ -33,10 +33,10 @@
   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   * THE SOFTWARE.
   */
-function a(){this.pseudos={},this.attrEqualityMods={},this.ruleNestingOperators={},this.substitutesEnabled=!1}function b(a){return a>="a"&&a<="z"||a>="A"&&a<="Z"||"-"===a||"_"===a}function c(a){return a>="a"&&a<="z"||a>="A"&&a<="Z"||a>="0"&&a<="9"||"-"===a||"_"===a}function d(a){return a>="a"&&a<="f"||a>="A"&&a<="F"||a>="0"&&a<="9"}function e(a,e,g,j,k,l){var m,n,o,p,q;return p=a.length,m=null,o=function(b,c){var f,g,h;for(h="",e++,m=a.charAt(e);e<p;){if(m===b)return e++,h;if("\\"===m)if(e++,(m=a.charAt(e))===b)h+=b;else if(f=c[m])h+=f;else{if(d(m)){for(g=m,e++,m=a.charAt(e);d(m);)g+=m,e++,m=a.charAt(e);" "===m&&(e++,m=a.charAt(e)),h+=String.fromCharCode(parseInt(g,16));continue}h+=m}else h+=m;e++,m=a.charAt(e)}return h},n=function(){var b="";for(m=a.charAt(e);e<p;){if(c(m))b+=m;else{if("\\"!==m)return b;if(++e>=p)throw Error("Expected symbol but end of file reached.");if(m=a.charAt(e),f[m])b+=m;else{if(d(m)){var g=m;for(e++,m=a.charAt(e);d(m);)g+=m,e++,m=a.charAt(e);" "===m&&(e++,m=a.charAt(e)),b+=String.fromCharCode(parseInt(g,16));continue}b+=m}}e++,m=a.charAt(e)}return b},q=function(){m=a.charAt(e);for(var b=!1;" "===m||"\t"===m||"\n"===m||"\r"===m||"\f"===m;)b=!0,e++,m=a.charAt(e);return b},this.parse=function(){var b=this.parseSelector();if(e<p)throw Error('Rule expected but "'+a.charAt(e)+'" found.');return b},this.parseSelector=function(){var b,c=b=this.parseSingleSelector();for(m=a.charAt(e);","===m;){if(e++,q(),"selectors"!==b.type&&(b={type:"selectors",selectors:[c]}),!(c=this.parseSingleSelector()))throw Error('Rule expected after ",".');b.selectors.push(c)}return b},this.parseSingleSelector=function(){q();var b={type:"ruleSet"},c=this.parseRule();if(!c)return null;for(var d=b;c&&(c.type="rule",d.rule=c,d=c,q(),m=a.charAt(e),!(e>=p||","===m||")"===m));)if(k[m]){var f=m;if(e++,q(),!(c=this.parseRule()))throw Error('Rule expected after "'+f+'".');c.nestingOperator=f}else(c=this.parseRule())&&(c.nestingOperator=null);return b},this.parseRule=function(){for(var c=null;e<p;)if("*"===(m=a.charAt(e)))e++,(c=c||{}).tagName="*";else if(b(m)||"\\"===m)(c=c||{}).tagName=n();else if("."===m)e++,c=c||{},(c.classNames=c.classNames||[]).push(n());else if("#"===m)e++,(c=c||{}).id=n();else if("["===m){e++,q();var d={name:n()};if(q(),"]"===m)e++;else{var f="";if(j[m]&&(f=m,e++,m=a.charAt(e)),e>=p)throw Error('Expected "=" but end of file reached.');if("="!==m)throw Error('Expected "=" but "'+m+'" found.');d.operator=f+"=",e++,q();var k="";if(d.valueType="string",'"'===m)k=o('"',i);else if("'"===m)k=o("'",h);else if(l&&"$"===m)e++,k=n(),d.valueType="substitute";else{for(;e<p&&"]"!==m;)k+=m,e++,m=a.charAt(e);k=k.trim()}if(q(),e>=p)throw Error('Expected "]" but end of file reached.');if("]"!==m)throw Error('Expected "]" but "'+m+'" found.');e++,d.value=k}c=c||{},(c.attrs=c.attrs||[]).push(d)}else{if(":"!==m)break;e++;var r=n(),s={name:r};if("("===m){e++;var t="";if(q(),"selector"===g[r])s.valueType="selector",t=this.parseSelector();else{if(s.valueType=g[r]||"string",'"'===m)t=o('"',i);else if("'"===m)t=o("'",h);else if(l&&"$"===m)e++,t=n(),s.valueType="substitute";else{for(;e<p&&")"!==m;)t+=m,e++,m=a.charAt(e);t=t.trim()}q()}if(e>=p)throw Error('Expected ")" but end of file reached.');if(")"!==m)throw Error('Expected ")" but "'+m+'" found.');e++,s.value=t}c=c||{},(c.pseudos=c.pseudos||[]).push(s)}return c},this}a.prototype.registerSelectorPseudos=function(a){for(var b=0,c=arguments.length;b<c;b++)a=arguments[b],this.pseudos[a]="selector";return this},a.prototype.unregisterSelectorPseudos=function(a){for(var b=0,c=arguments.length;b<c;b++)a=arguments[b],delete this.pseudos[a];return this},a.prototype.registerNumericPseudos=function(a){for(var b=0,c=arguments.length;b<c;b++)a=arguments[b],this.pseudos[a]="numeric";return this},a.prototype.unregisterNumericPseudos=function(a){for(var b=0,c=arguments.length;b<c;b++)a=arguments[b],delete this.pseudos[a];return this},a.prototype.registerNestingOperators=function(a){for(var b=0,c=arguments.length;b<c;b++)a=arguments[b],this.ruleNestingOperators[a]=!0;return this},a.prototype.unregisterNestingOperators=function(a){for(var b=0,c=arguments.length;b<c;b++)a=arguments[b],delete this.ruleNestingOperators[a];return this},a.prototype.registerAttrEqualityMods=function(a){for(var b=0,c=arguments.length;b<c;b++)a=arguments[b],this.attrEqualityMods[a]=!0;return this},a.prototype.unregisterAttrEqualityMods=function(a){for(var b=0,c=arguments.length;b<c;b++)a=arguments[b],delete this.attrEqualityMods[a];return this},a.prototype.enableSubstitutes=function(){return this.substitutesEnabled=!0,this},a.prototype.disableSubstitutes=function(){return this.substitutesEnabled=!1,this};var f={"!":!0,'"':!0,"#":!0,$:!0,"%":!0,"&":!0,"'":!0,"(":!0,")":!0,"*":!0,"+":!0,",":!0,".":!0,"/":!0,";":!0,"<":!0,"=":!0,">":!0,"?":!0,"@":!0,"[":!0,"\\":!0,"]":!0,"^":!0,"`":!0,"{":!0,"|":!0,"}":!0,"~":!0},g={"\n":"\\n","\r":"\\r","\t":"\\t","\f":"\\f","\v":"\\v"},h={n:"\n",r:"\r",t:"\t",f:"\f","\\":"\\","'":"'"},i={n:"\n",r:"\r",t:"\t",f:"\f","\\":"\\",'"':'"'};a.prototype.parse=function(a){return new e(a,0,this.pseudos,this.attrEqualityMods,this.ruleNestingOperators,this.substitutesEnabled).parse()},a.prototype.escapeIdentifier=function(a){for(var b="",c=0,d=a.length;c<d;){var e=a.charAt(c);if(f[e])b+="\\"+e;else if("_"===e||"-"===e||e>="A"&&e<="Z"||e>="a"&&e<="z"||0!==c&&e>="0"&&e<="9")b+=e;else{var g=e.charCodeAt(0);if(55296==(63488&g)){var h=a.charCodeAt(c++);if(55296!=(64512&g)||56320!=(64512&h))throw Error("UCS-2(decode): illegal sequence");g=((1023&g)<<10)+(1023&h)+65536}b+="\\"+g.toString(16)+" "}c++}return b},a.prototype.escapeStr=function(a){for(var b,c,d="",e=0,f=a.length;e<f;)b=a.charAt(e),'"'===b?b='\\"':"\\"===b?b="\\\\":(c=g[b])&&(b=c),d+=b,e++;return'"'+d+'"'},a.prototype.render=function(a){return this._renderEntity(a).trim()},a.prototype._renderEntity=function(a){var b,c,d;switch(d="",a.type){case"ruleSet":for(b=a.rule,c=[];b;)b.nestingOperator&&c.push(b.nestingOperator),c.push(this._renderEntity(b)),b=b.rule;d=c.join(" ");break;case"selectors":d=a.selectors.map(this._renderEntity,this).join(", ");break;case"rule":a.tagName&&(d="*"===a.tagName?"*":this.escapeIdentifier(a.tagName)),a.id&&(d+="#"+this.escapeIdentifier(a.id)),a.classNames&&(d+=a.classNames.map(function(a){return"."+this.escapeIdentifier(a)},this).join("")),a.attrs&&(d+=a.attrs.map(function(a){return a.operator?"substitute"===a.valueType?"["+this.escapeIdentifier(a.name)+a.operator+"$"+a.value+"]":"["+this.escapeIdentifier(a.name)+a.operator+this.escapeStr(a.value)+"]":"["+this.escapeIdentifier(a.name)+"]"},this).join("")),a.pseudos&&(d+=a.pseudos.map(function(a){return a.valueType?"selector"===a.valueType?":"+this.escapeIdentifier(a.name)+"("+this._renderEntity(a.value)+")":"substitute"===a.valueType?":"+this.escapeIdentifier(a.name)+"($"+a.value+")":"numeric"===a.valueType?":"+this.escapeIdentifier(a.name)+"("+a.value+")":":"+this.escapeIdentifier(a.name)+"("+this.escapeIdentifier(a.value)+")":":"+this.escapeIdentifier(a.name)},this).join(""));break;default:throw Error('Unknown entity type: "'+a.type(NaN))}return d};var j=new a;j.registerNestingOperators(">"),axe.utils.cssParser=j}(axe),L.prototype={get selector(){return this.spec.selector||[axe.utils.getSelector(this.element,this._options)]},get xpath(){return this.spec.xpath||[axe.utils.getXpath(this.element)]},get element(){return this._element},get fromFrame(){return this._fromFrame},toJSON:function(){"use strict";return{selector:this.selector,source:this.source,xpath:this.xpath}}},L.fromFrame=function(a,b,c){return a.selector.unshift(c.selector),a.xpath.unshift(c.xpath),new axe.utils.DqElement(c.element,b,a)},axe.utils.DqElement=L,axe.utils.matchesSelector=function(){"use strict";function a(a){var b,c,d=a.Element.prototype,e=["matches","matchesSelector","mozMatchesSelector","webkitMatchesSelector","msMatchesSelector"],f=e.length;for(b=0;b<f;b++)if(c=e[b],d[c])return c}var b;return function(c,d){return b&&c[b]||(b=a(c.ownerDocument.defaultView)),c[b](d)}}(),axe.utils.escapeSelector=function(a){"use strict";for(var b,c=String(a),d=c.length,e=-1,f="",g=c.charCodeAt(0);++e<d;){if(0==(b=c.charCodeAt(e)))throw new Error("INVALID_CHARACTER_ERR");b>=1&&b<=31||b>=127&&b<=159||0==e&&b>=48&&b<=57||1==e&&b>=48&&b<=57&&45==g?f+="\\"+b.toString(16)+" ":f+=(1!=e||45!=b||45!=g)&&(b>=128||45==b||95==b||b>=48&&b<=57||b>=65&&b<=90||b>=97&&b<=122)?c.charAt(e):"\\"+c.charAt(e)}return f},axe.utils.extendMetaData=function(a,b){Object.assign(a,b),Object.keys(b).filter(function(a){return"function"==typeof b[a]}).forEach(function(c){a[c]=null;try{a[c]=b[c](a)}catch(a){}})},axe.utils.finalizeRuleResult=function(a){return Object.assign(a,axe.utils.aggregateRule(a.nodes)),delete a.nodes,a};var qa="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a};axe.utils.findBy=function(a,b,c){if(Array.isArray(a))return a.find(function(a){return"object"===(void 0===a?"undefined":qa(a))&&a[b]===c})};var axe=axe||{utils:{}};axe.utils.getFlattenedTree=function(a,b){function c(a,c){var d=axe.utils.getFlattenedTree(c,b);return d&&(a=a.concat(d)),a}var d,e,f;if(a.documentElement&&(a=a.documentElement),f=a.nodeName.toLowerCase(),a.shadowRoot&&"marquee"!==f)return b="a"+Math.random().toString().substring(2),e=Array.from(a.shadowRoot.childNodes),e.reduce(c,[]);if("content"===f)return e=Array.from(a.getDistributedNodes()),e.reduce(c,[]);if("slot"===f){e=Array.from(a.assignedNodes()),e.length||(e=N(a));window.getComputedStyle(a);return e.reduce(c,[])}return 1===a.nodeType?(d=M(a,b),e=Array.from(a.childNodes),d.children=e.reduce(c,[]),[d]):3===a.nodeType?[M(a)]:void 0},axe.utils.getNodeFromTree=function(a,b){var c;return a.children.forEach(function(a){var d;a.actualNode===b?c=a:(d=axe.utils.getNodeFromTree(a,b))&&(c=d)}),c},axe.utils.getAllChecks=function(a){"use strict";return[].concat(a.any||[]).concat(a.all||[]).concat(a.none||[])},axe.utils.getCheckOption=function(a,b,c){var d=((c.rules&&c.rules[b]||{}).checks||{})[a.id],e=(c.checks||{})[a.id],f=a.enabled,g=a.options;return e&&(e.hasOwnProperty("enabled")&&(f=e.enabled),e.hasOwnProperty("options")&&(g=e.options)),d&&(d.hasOwnProperty("enabled")&&(f=d.enabled),d.hasOwnProperty("options")&&(g=d.options)),{enabled:f,options:g,absolutePaths:c.absolutePaths}};var ya=function(){function a(a,b){var c=[],d=!0,e=!1,f=void 0;try{for(var g,h=a[Symbol.iterator]();!(d=(g=h.next()).done)&&(c.push(g.value),!b||c.length!==b);d=!0);}catch(a){e=!0,f=a}finally{try{!d&&h.return&&h.return()}finally{if(e)throw f}}return c}return function(b,c){if(Array.isArray(b))return b;if(Symbol.iterator in Object(b))return a(b,c);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();axe.utils.getFriendlyUriEnd=function(){var a=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",b=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!(a.length<=1||"data:"===a.substr(0,5)||"javascript:"===a.substr(0,11)||a.includes("?"))){var c=b.currentDomain,d=b.maxLength,e=void 0===d?25:d,f=Q(a),g=f.path,h=f.domain,i=f.hash,j=g.substr(g.substr(0,g.length-2).lastIndexOf("/")+1);if(i)return j&&(j+i).length<=e?j+i:j.length<2&&i.length>2&&i.length<=e?i:void 0;if(h&&h.length<e&&g.length<=1)return h+g;if(g==="/"+j&&h&&c&&h!==c&&(h+g).length<=e)return h+g;var k=j.lastIndexOf(".");return(-1===k||k>1)&&(-1!==k||j.length>2)&&j.length<=e&&!j.match(/index(\.[a-zA-Z]{2-4})?/)&&!O(j)?j:void 0}};var za=axe.utils.escapeSelector,Aa=["div","span","p","b","i","u","strong","em","h2","h3"],Ba={getElmId:function(a){if(a.id){var b=a.getRootNode&&a.getRootNode()||document,c="#"+za(a.id||"");return c.match(/player_uid_/)||1!==b.querySelectorAll(c).length?void 0:c}},getCustomElm:function(a,b){var c=b.isCustomElm,d=b.nodeName;if(c)return d},getElmRoleProp:function(a){if(a.hasAttribute("role"))return'[role="'+za(a.getAttribute("role"))+'"]'},getUncommonElm:function(a,b){var c=b.isCommonElm,d=b.isCustomElm,e=b.nodeName;if(!c&&!d)return e=za(e),"input"===e&&a.hasAttribute("type")&&(e+='[type="'+a.type+'"]'),e},getElmNameProp:function(a){if(!a.id&&a.name)return'[name="'+za(a.name)+'"]'},getDistinctClass:function(a,b){var c=b.distinctClassList;if(c.length>0&&c.length<3)return"."+c.map(za).join(".")},getFileRefProp:function(a){var b=void 0;if(a.hasAttribute("href"))b="href";else{if(!a.hasAttribute("src"))return;b="src"}var c=axe.utils.getFriendlyUriEnd(a.getAttribute(b));if(c)return"["+b+'$="'+encodeURI(c)+'"]'},getCommonName:function(a,b){var c=b.nodeName;if(b.isCommonElm)return c}};axe.utils.getSelector=function(a){var b=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!a)return"";var c=a.getRootNode&&a.getRootNode()||document;if(11===c.nodeType){for(var d=[];11===c.nodeType;)d.push({elm:a,doc:c}),a=c.host,c=a.getRootNode();return d.push({elm:a,doc:c}),d.reverse().map(function(a){return W(a.elm,b,a.doc)})}return W(a,b,c)},axe.utils.getXpath=function(a){return Y(X(a))};var Ca;axe.utils.injectStyle=Z,axe.utils.isHidden=function(a,b){"use strict";var c;if(9===a.nodeType)return!1;11===a.nodeType&&(a=a.host);var d=window.getComputedStyle(a,null);return!d||!a.parentNode||"none"===d.getPropertyValue("display")||!b&&"hidden"===d.getPropertyValue("visibility")||"true"===a.getAttribute("aria-hidden")||(c=a.assignedSlot?a.assignedSlot:a.parentNode,axe.utils.isHidden(c,!0))},axe.utils.mergeResults=function(a,b){"use strict";var c=[];return a.forEach(function(a){var d=aa(a);d&&d.length&&d.forEach(function(d){d.nodes&&a.frame&&$(d.nodes,b,a.frameElement,a.frame);var e=axe.utils.findBy(c,"id",d.id);e?d.nodes.length&&_(e.nodes,d.nodes):c.push(d)})}),c},axe.utils.nodeSorter=function(a,b){"use strict";return a.actualNode===b.actualNode?0:4&a.actualNode.compareDocumentPosition(b.actualNode)?-1:1},utils.performanceTimer=function(){"use strict";function a(){if(window.performance&&window.performance)return window.performance.now()}var b=null,c=a();return{start:function(){this.mark("mark_axe_start")},end:function(){this.mark("mark_axe_end"),this.measure("axe","mark_axe_start","mark_axe_end"),this.logMeasures("axe")},auditStart:function(){this.mark("mark_audit_start")},auditEnd:function(){this.mark("mark_audit_end"),this.measure("audit_start_to_end","mark_audit_start","mark_audit_end"),this.logMeasures()},mark:function(a){window.performance&&void 0!==window.performance.mark&&window.performance.mark(a)},measure:function(a,b,c){window.performance&&void 0!==window.performance.measure&&window.performance.measure(a,b,c)},logMeasures:function(a){function b(a){axe.log("Measure "+a.name+" took "+a.duration+"ms")}if(window.performance&&void 0!==window.performance.getEntriesByType)for(var c=window.performance.getEntriesByType("measure"),d=0;d<c.length;++d){var e=c[d];if(e.name===a)return void b(e);b(e)}},timeElapsed:function(){return a()-c},reset:function(){b||(b=a()),c=a()}}}(),"function"!=typeof Object.assign&&function(){Object.assign=function(a){"use strict";if(void 0===a||null===a)throw new TypeError("Cannot convert undefined or null to object");for(var b=Object(a),c=1;c<arguments.length;c++){var d=arguments[c];if(void 0!==d&&null!==d)for(var e in d)d.hasOwnProperty(e)&&(b[e]=d[e])}return b}}(),Array.prototype.find||(Array.prototype.find=function(a){if(null===this)throw new TypeError("Array.prototype.find called on null or undefined");if("function"!=typeof a)throw new TypeError("predicate must be a function");for(var b,c=Object(this),d=c.length>>>0,e=arguments[1],f=0;f<d;f++)if(b=c[f],a.call(e,b,f,c))return b}),axe.utils.pollyfillElementsFromPoint=function(){if(document.elementsFromPoint)return document.elementsFromPoint;if(document.msElementsFromPoint)return document.msElementsFromPoint;var a=function(){var a=document.createElement("x");return a.style.cssText="pointer-events:auto","auto"===a.style.pointerEvents}(),b=a?"pointer-events":"visibility",c=a?"none":"hidden",d=document.createElement("style");return d.innerHTML=a?"* { pointer-events: all }":"* { visibility: visible }",function(a,e){var f,g,h,i=[],j=[];for(document.head.appendChild(d);(f=document.elementFromPoint(a,e))&&-1===i.indexOf(f);)i.push(f),j.push({value:f.style.getPropertyValue(b),priority:f.style.getPropertyPriority(b)}),f.style.setProperty(b,c,"important");for(g=j.length;h=j[--g];)i[g].style.setProperty(b,h.value?h.value:"",h.priority);return document.head.removeChild(d),i}},"function"==typeof window.addEventListener&&(document.elementsFromPoint=axe.utils.pollyfillElementsFromPoint()),Array.prototype.includes||(Array.prototype.includes=function(a){"use strict";var b=Object(this),c=parseInt(b.length,10)||0;if(0===c)return!1;var d,e=parseInt(arguments[1],10)||0;e>=0?d=e:(d=c+e)<0&&(d=0);for(var f;d<c;){if(f=b[d],a===f||a!==a&&f!==f)return!0;d++}return!1}),Array.prototype.some||(Array.prototype.some=function(a){"use strict";if(null==this)throw new TypeError("Array.prototype.some called on null or undefined");if("function"!=typeof a)throw new TypeError;for(var b=Object(this),c=b.length>>>0,d=arguments.length>=2?arguments[1]:void 0,e=0;e<c;e++)if(e in b&&a.call(d,b[e],e,b))return!0;return!1}),Array.from||(Array.from=function(){var a=Object.prototype.toString,b=function(b){return"function"==typeof b||"[object Function]"===a.call(b)},c=function(a){var b=Number(a);return isNaN(b)?0:0!==b&&isFinite(b)?(b>0?1:-1)*Math.floor(Math.abs(b)):b},d=Math.pow(2,53)-1,e=function(a){var b=c(a);return Math.min(Math.max(b,0),d)};return function(a){var c=this,d=Object(a);if(null==a)throw new TypeError("Array.from requires an array-like object - not null or undefined");var f,g=arguments.length>1?arguments[1]:void 0;if(void 0!==g){if(!b(g))throw new TypeError("Array.from: when provided, the second argument must be a function");arguments.length>2&&(f=arguments[2])}for(var h,i=e(d.length),j=b(c)?Object(new c(i)):new Array(i),k=0;k<i;)h=d[k],j[k]=g?void 0===f?g(h,k):g.call(f,h,k):h,k+=1;return j.length=i,j}}()),String.prototype.includes||(String.prototype.includes=function(a,b){return"number"!=typeof b&&(b=0),!(b+a.length>this.length)&&-1!==this.indexOf(a,b)});var qa="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a};axe.utils.publishMetaData=function(a){"use strict";var b=axe._audit.data.checks||{},c=axe._audit.data.rules||{},d=axe.utils.findBy(axe._audit.rules,"id",a.id)||{};a.tags=axe.utils.clone(d.tags||[]);var e=ca(b,!0),f=ca(b,!1);a.nodes.forEach(function(a){a.any.forEach(e),a.all.forEach(e),a.none.forEach(f)}),axe.utils.extendMetaData(a,axe.utils.clone(c[a.id]||{}))};var Da=function(){},Ea=function(){},Fa=function(){/*! Credit: XRegExp 0.6.1 (c) 2007-2008 Steven Levithan <http://stevenlevithan.com/regex/xregexp/> MIT License */
-var a=/(?=[\-\[\]{}()*+?.\\\^$|,#\s])/g;return function(b){return b.replace(a,"\\")}}(),Ga=/\\/g;Da=function(a){return a.map(function(a){for(var b=[],c=a.rule;c;)b.push({tag:c.tagName?c.tagName.toLowerCase():"*",combinator:c.nestingOperator?c.nestingOperator:" ",id:c.id,attributes:ja(c.attrs),classes:ka(c.classNames),pseudos:la(c.pseudos)}),c=c.rule;return b})},Ea=function(a,b,c){return b.reduce(function(b,d){var e=a;return d.forEach(function(a,b){if(c=">"!==a.combinator&&c,-1===[" ",">"].indexOf(a.combinator))throw new Error("axe.utils.querySelectorAll does not support the combinator: "+a.combinator);e=e.reduce(function(d,e){return d.concat(ia(b?e.children:e,a,c))},[])}),b.concat(e)},[])},axe.utils.querySelectorAll=function(a,b){a=Array.isArray(a)?a:[a];var c=axe.utils.cssParser.parse(b);return c=c.selectors?c.selectors:[c],c=Da(c),Ea(a,c,!0)};var qa="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a};!function(){"use strict";function a(){}function b(a){if("function"!=typeof a)throw new TypeError("Queue methods require functions as arguments")}function c(){function c(b){return function(c){g[b]=c,(i-=1)||j===a||(k=!0,j(g))}}function d(b){return j=a,m(b),g}function e(){for(var a=g.length;h<a;h++){var b=g[h];try{b.call(null,c(h),d)}catch(a){d(a)}}}var f,g=[],h=0,i=0,j=a,k=!1,l=function(a){f=a,setTimeout(function(){void 0!==f&&null!==f&&axe.log("Uncaught error (of queue)",f)},1)},m=l,n={defer:function(a){if("object"===(void 0===a?"undefined":qa(a))&&a.then&&a.catch){var c=a;a=function(a,b){c.then(a).catch(b)}}if(b(a),void 0===f){if(k)throw new Error("Queue already completed");return g.push(a),++i,e(),n}},then:function(c){if(b(c),j!==a)throw new Error("queue `then` already set");return f||(j=c,i||(k=!0,j(g))),n},catch:function(a){if(b(a),m!==l)throw new Error("queue `catch` already set");return f?(a(f),f=null):m=a,n},abort:d};return n}axe.utils.queue=c}();var qa="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a};!function(a){"use strict";function b(){var a="axe",b="";return void 0!==axe&&axe._audit&&!axe._audit.application&&(a=axe._audit.application),void 0!==axe&&(b=axe.version),a+"."+b}function c(a){if("object"===(void 0===a?"undefined":qa(a))&&"string"==typeof a.uuid&&!0===a._respondable){var c=b();return a._source===c||"axe.x.y.z"===a._source||"axe.x.y.z"===c}return!1}function d(a,c,d,e,f,g){var h;d instanceof Error&&(h={name:d.name,message:d.message,stack:d.stack},d=void 0);var i={uuid:e,topic:c,message:d,error:h,_respondable:!0,_source:b(),_keepalive:f};"function"==typeof g&&(j[e]=g),a.postMessage(JSON.stringify(i),"*")}function e(a,b,c,e,f){d(a,b,c,Ha.v1(),e,f)}function f(a,b,c){return function(e,f,g){d(a,b,e,c,f,g)}}function g(a,b,c){var d=b.topic,e=k[d];if(e){var g=f(a,null,b.uuid);e(b.message,c,g)}}function h(a){var b=a.message||"Unknown error occurred",c=window[a.name]||Error;return a.stack&&(b+="\n"+a.stack.replace(a.message,"")),new c(b)}function i(a){var b;if("string"==typeof a){try{b=JSON.parse(a)}catch(a){}if(c(b))return"object"===qa(b.error)?b.error=h(b.error):b.error=void 0,b}}var j={},k={};e.subscribe=function(a,b){k[a]=b},e.isInFrame=function(a){return a=a||window,!!a.frameElement},"function"==typeof window.addEventListener&&window.addEventListener("message",function(a){var b=i(a.data);if(b){var c=b.uuid,e=b._keepalive,h=j[c];if(h){h(b.error||b.message,e,f(a.source,b.topic,c)),e||delete j[c]}if(!b.error)try{g(a.source,b,e)}catch(e){d(a.source,b.topic,e,c,!1)}}},!1),a.respondable=e}(utils),axe.utils.ruleShouldRun=function(a,b,c){"use strict";var d=c.runOnly||{},e=(c.rules||{})[a.id];return!(a.pageLevel&&!b.page)&&("rule"===d.type?-1!==d.values.indexOf(a.id):e&&"boolean"==typeof e.enabled?e.enabled:"tag"===d.type&&d.values?ma(a,d.values):ma(a,[]))},axe.utils.select=function(a,b){"use strict";for(var c,d=[],e=0,f=b.include.length;e<f;e++)c=b.include[e],c.actualNode.nodeType===c.actualNode.ELEMENT_NODE&&axe.utils.matchesSelector(c.actualNode,a)&&pa(d,[c],b),pa(d,axe.utils.querySelectorAll(c,a),b);return d.sort(axe.utils.nodeSorter)},axe.utils.toArray=function(a){"use strict";return Array.prototype.slice.call(a)};var Ha;!function(a){function b(a,b,c){var d=b&&c||0,e=0;for(b=b||[],a.toLowerCase().replace(/[0-9a-f]{2}/g,function(a){e<16&&(b[d+e++]=l[a])});e<16;)b[d+e++]=0;return b}function c(a,b){var c=b||0,d=k;return d[a[c++]]+d[a[c++]]+d[a[c++]]+d[a[c++]]+"-"+d[a[c++]]+d[a[c++]]+"-"+d[a[c++]]+d[a[c++]]+"-"+d[a[c++]]+d[a[c++]]+"-"+d[a[c++]]+d[a[c++]]+d[a[c++]]+d[a[c++]]+d[a[c++]]+d[a[c++]]}function d(a,b,d){var e=b&&d||0,f=b||[];a=a||{};var g=null!=a.clockseq?a.clockseq:p,h=null!=a.msecs?a.msecs:(new Date).getTime(),i=null!=a.nsecs?a.nsecs:r+1,j=h-q+(i-r)/1e4;if(j<0&&null==a.clockseq&&(g=g+1&16383),(j<0||h>q)&&null==a.nsecs&&(i=0),i>=1e4)throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");q=h,r=i,p=g,h+=122192928e5;var k=(1e4*(268435455&h)+i)%4294967296;f[e++]=k>>>24&255,f[e++]=k>>>16&255,f[e++]=k>>>8&255,f[e++]=255&k;var l=h/4294967296*1e4&268435455;f[e++]=l>>>8&255,f[e++]=255&l,f[e++]=l>>>24&15|16,f[e++]=l>>>16&255,f[e++]=g>>>8|128,f[e++]=255&g;for(var m=a.node||o,n=0;n<6;n++)f[e+n]=m[n];return b||c(f)}function e(a,b,d){var e=b&&d||0;"string"==typeof a&&(b="binary"==a?new j(16):null,a=null),a=a||{};var g=a.random||(a.rng||f)();if(g[6]=15&g[6]|64,g[8]=63&g[8]|128,b)for(var h=0;h<16;h++)b[e+h]=g[h];return b||c(g)}var f,g=a.crypto||a.msCrypto;if(!f&&g&&g.getRandomValues){var h=new Uint8Array(16);f=function(){return g.getRandomValues(h),h}}if(!f){var i=new Array(16);f=function(){for(var a,b=0;b<16;b++)0==(3&b)&&(a=4294967296*Math.random()),i[b]=a>>>((3&b)<<3)&255;return i}}for(var j="function"==typeof a.Buffer?a.Buffer:Array,k=[],l={},m=0;m<256;m++)k[m]=(m+256).toString(16).substr(1),l[k[m]]=m;var n=f(),o=[1|n[0],n[1],n[2],n[3],n[4],n[5]],p=16383&(n[6]<<8|n[7]),q=0,r=0;Ha=e,Ha.v1=d,Ha.v4=e,Ha.parse=b,Ha.unparse=c,Ha.BufferClass=j}(window),axe._load({data:{rules:{accesskeys:{description:"Ensures every accesskey attribute value is unique",help:"accesskey attribute value must be unique"},"area-alt":{description:"Ensures <area> elements of image maps have alternate text",help:"Active <area> elements must have alternate text"},"aria-allowed-attr":{description:"Ensures ARIA attributes are allowed for an element's role",help:"Elements must only use allowed ARIA attributes"},"aria-hidden-body":{description:"Ensures aria-hidden='true' is not present on the document body.",help:"aria-hidden='true' must not be present on the document body"},"aria-required-attr":{description:"Ensures elements with ARIA roles have all required ARIA attributes",help:"Required ARIA attributes must be provided"},"aria-required-children":{description:"Ensures elements with an ARIA role that require child roles contain them",help:"Certain ARIA roles must contain particular children"},"aria-required-parent":{description:"Ensures elements with an ARIA role that require parent roles are contained by them",help:"Certain ARIA roles must be contained by particular parents"},"aria-roles":{description:"Ensures all elements with a role attribute use a valid value",help:"ARIA roles used must conform to valid values"},"aria-valid-attr-value":{description:"Ensures all ARIA attributes have valid values",help:"ARIA attributes must conform to valid values"},"aria-valid-attr":{description:"Ensures attributes that begin with aria- are valid ARIA attributes",help:"ARIA attributes must conform to valid names"},"audio-caption":{description:"Ensures <audio> elements have captions",help:"<audio> elements must have a captions track"},blink:{description:"Ensures <blink> elements are not used",help:"<blink> elements are deprecated and must not be used"},"button-name":{description:"Ensures buttons have discernible text",help:"Buttons must have discernible text"},bypass:{description:"Ensures each page has at least one mechanism for a user to bypass navigation and jump straight to the content",help:"Page must have means to bypass repeated blocks"},checkboxgroup:{description:'Ensures related <input type="checkbox"> elements have a group and that that group designation is consistent',help:"Checkbox inputs with the same name attribute value must be part of a group"},"color-contrast":{description:"Ensures the contrast between foreground and background colors meets WCAG 2 AA contrast ratio thresholds",help:"Elements must have sufficient color contrast"},"definition-list":{description:"Ensures <dl> elements are structured correctly",help:"<dl> elements must only directly contain properly-ordered <dt> and <dd> groups, <script> or <template> elements"},dlitem:{description:"Ensures <dt> and <dd> elements are contained by a <dl>",help:"<dt> and <dd> elements must be contained by a <dl>"},"document-title":{description:"Ensures each HTML document contains a non-empty <title> element",help:"Documents must have <title> element to aid in navigation"},"duplicate-id":{description:"Ensures every id attribute value is unique",help:"id attribute value must be unique"},"empty-heading":{description:"Ensures headings have discernible text",help:"Headings must not be empty"},"frame-title-unique":{description:"Ensures <iframe> and <frame> elements contain a unique title attribute",help:"Frames must have a unique title attribute"},"frame-title":{description:"Ensures <iframe> and <frame> elements contain a non-empty title attribute",help:"Frames must have title attribute"},"heading-order":{description:"Ensures the order of headings is semantically correct",help:"Heading levels should only increase by one"},"hidden-content":{description:"Informs users about hidden content.",help:"Hidden content on the page cannot be analyzed"},"href-no-hash":{description:"Ensures that href values are valid link references to promote only using anchors as links",help:"Anchors must only be used as links with valid URLs or URL fragments"},"html-has-lang":{description:"Ensures every HTML document has a lang attribute",help:"<html> element must have a lang attribute"},"html-lang-valid":{description:"Ensures the lang attribute of the <html> element has a valid value",help:"<html> element must have a valid value for the lang attribute"},"image-alt":{description:"Ensures <img> elements have alternate text or a role of none or presentation",help:"Images must have alternate text"},"image-redundant-alt":{description:"Ensure button and link text is not repeated as image alternative",help:"Text of buttons and links should not be repeated in the image alternative"},"input-image-alt":{description:'Ensures <input type="image"> elements have alternate text',help:"Image buttons must have alternate text"},"label-title-only":{description:"Ensures that every form element is not solely labeled using the title or aria-describedby attributes",help:"Form elements should have a visible label"},label:{description:"Ensures every form element has a label",help:"Form elements must have labels"},"layout-table":{description:"Ensures presentational <table> elements do not use <th>, <caption> elements or the summary attribute",help:"Layout tables must not use data table elements"},"link-in-text-block":{description:"Links can be distinguished without relying on color",help:"Links must be distinguished from surrounding text in a way that does not rely on color"},"link-name":{description:"Ensures links have discernible text",help:"Links must have discernible text"},list:{description:"Ensures that lists are structured correctly",help:"<ul> and <ol> must only directly contain <li>, <script> or <template> elements"},listitem:{description:"Ensures <li> elements are used semantically",help:"<li> elements must be contained in a <ul> or <ol>"},marquee:{description:"Ensures <marquee> elements are not used",help:"<marquee> elements are deprecated and must not be used"},"meta-refresh":{description:'Ensures <meta http-equiv="refresh"> is not used',help:"Timed refresh must not exist"},"meta-viewport-large":{description:'Ensures <meta name="viewport"> can scale a significant amount',help:"Users should be able to zoom and scale the text up to 500%"},"meta-viewport":{description:'Ensures <meta name="viewport"> does not disable text scaling and zooming',help:"Zooming and scaling must not be disabled"},"object-alt":{description:"Ensures <object> elements have alternate text",help:"<object> elements must have alternate text"},"p-as-heading":{description:"Ensure p elements are not used to style headings",help:"Bold, italic text and font-size are not used to style p elements as a heading"},radiogroup:{description:'Ensures related <input type="radio"> elements have a group and that the group designation is consistent',help:"Radio inputs with the same name attribute value must be part of a group"},region:{description:"Ensures all content is contained within a landmark region",help:"Content should be contained in a landmark region"},"scope-attr-valid":{description:"Ensures the scope attribute is used correctly on tables",help:"scope attribute should be used correctly"},"server-side-image-map":{description:"Ensures that server-side image maps are not used",help:"Server-side image maps must not be used"},"skip-link":{description:"Ensures the first link on the page is a skip link",help:"The page should have a skip link as its first link"},tabindex:{description:"Ensures tabindex attribute values are not greater than 0",help:"Elements should not have tabindex greater than zero"},"table-duplicate-name":{description:"Ensure that tables do not have the same summary and caption",help:"The <caption> element should not contain the same text as the summary attribute"},"table-fake-caption":{description:"Ensure that tables with a caption use the <caption> element.",help:"Data or header cells should not be used to give caption to a data table."},"td-has-header":{description:"Ensure that each non-empty data cell in a large table has one or more table headers",help:"All non-empty td element in table larger than 3 by 3 must have an associated table header"},"td-headers-attr":{description:"Ensure that each cell in a table using the headers refers to another cell in that table",help:"All cells in a table element that use the headers attribute must only refer to other cells of that same table"},"th-has-data-cells":{description:"Ensure that each table header in a data table refers to data cells",help:"All th element and elements with role=columnheader/rowheader must data cells which it describes"},"valid-lang":{description:"Ensures lang attributes have valid values",help:"lang attribute must have a valid value"},"video-caption":{description:"Ensures <video> elements have captions",help:"<video> elements must have captions"},"video-description":{description:"Ensures <video> elements have audio descriptions",help:"<video> elements must have an audio description track"}},checks:{accesskeys:{impact:"critical",messages:{pass:function(a){return"Accesskey attribute value is unique"},fail:function(a){return"Document has multiple elements with the same accesskey"}}},"non-empty-alt":{impact:"critical",messages:{pass:function(a){return"Element has a non-empty alt attribute"},fail:function(a){return"Element has no alt attribute or the alt attribute is empty"}}},"non-empty-title":{impact:"critical",messages:{pass:function(a){return"Element has a title attribute"},fail:function(a){return"Element has no title attribute or the title attribute is empty"}}},"aria-label":{impact:"critical",messages:{pass:function(a){return"aria-label attribute exists and is not empty"},fail:function(a){return"aria-label attribute does not exist or is empty"}}},"aria-labelledby":{impact:"critical",messages:{pass:function(a){return"aria-labelledby attribute exists and references elements that are visible to screen readers"},fail:function(a){return"aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty or not visible"}}},"aria-allowed-attr":{impact:"critical",messages:{pass:function(a){return"ARIA attributes are used correctly for the defined role"},fail:function(a){var b="ARIA attribute"+(a.data&&a.data.length>1?"s are":" is")+" not allowed:",c=a.data;if(c)for(var d,e=-1,f=c.length-1;e<f;)d=c[e+=1],b+=" "+d;return b}}},"aria-hidden-body":{impact:"critical",messages:{pass:function(a){return"No aria-hidden attribute is present on document body"},fail:function(a){return"aria-hidden=true should not be present on the document body"}}},"aria-required-attr":{impact:"critical",messages:{pass:function(a){return"All required ARIA attributes are present"},fail:function(a){var b="Required ARIA attribute"+(a.data&&a.data.length>1?"s":"")+" not present:",c=a.data;if(c)for(var d,e=-1,f=c.length-1;e<f;)d=c[e+=1],b+=" "+d;return b}}},"aria-required-children":{impact:"critical",messages:{pass:function(a){return"Required ARIA children are present"},fail:function(a){var b="Required ARIA "+(a.data&&a.data.length>1?"children":"child")+" role not present:",c=a.data;if(c)for(var d,e=-1,f=c.length-1;e<f;)d=c[e+=1],b+=" "+d;return b}}},"aria-required-parent":{impact:"critical",messages:{pass:function(a){return"Required ARIA parent role present"},fail:function(a){var b="Required ARIA parent"+(a.data&&a.data.length>1?"s":"")+" role not present:",c=a.data;if(c)for(var d,e=-1,f=c.length-1;e<f;)d=c[e+=1],b+=" "+d;return b}}},invalidrole:{impact:"critical",messages:{pass:function(a){return"ARIA role is valid"},fail:function(a){return"Role must be one of the valid ARIA roles"}}},abstractrole:{impact:"serious",messages:{pass:function(a){return"Abstract roles are not used"},fail:function(a){return"Abstract roles cannot be directly used"}}},"aria-valid-attr-value":{impact:"critical",messages:{pass:function(a){return"ARIA attribute values are valid"},fail:function(a){var b="Invalid ARIA attribute value"+(a.data&&a.data.length>1?"s":"")+":",c=a.data;if(c)for(var d,e=-1,f=c.length-1;e<f;)d=c[e+=1],b+=" "+d;return b}}},"aria-valid-attr":{impact:"critical",messages:{pass:function(a){return"ARIA attribute name"+(a.data&&a.data.length>1?"s":"")+" are valid"},fail:function(a){var b="Invalid ARIA attribute name"+(a.data&&a.data.length>1?"s":"")+":",c=a.data;if(c)for(var d,e=-1,f=c.length-1;e<f;)d=c[e+=1],b+=" "+d;return b}}},caption:{impact:"critical",messages:{pass:function(a){return"The multimedia element has a captions track"},fail:function(a){return"The multimedia element does not have a captions track"},incomplete:function(a){return"A captions track for this element could not be found"}}},"is-on-screen":{impact:"minor",messages:{pass:function(a){return"Element is not visible"},fail:function(a){return"Element is visible"}}},"non-empty-if-present":{impact:"critical",messages:{pass:function(a){var b="Element ";return a.data?b+="has a non-empty value attribute":b+="does not have a value attribute",b},fail:function(a){return"Element has a value attribute and the value attribute is empty"}}},"non-empty-value":{impact:"critical",messages:{pass:function(a){return"Element has a non-empty value attribute"},fail:function(a){return"Element has no value attribute or the value attribute is empty"}}},"button-has-visible-text":{impact:"critical",messages:{pass:function(a){return"Element has inner text that is visible to screen readers"},fail:function(a){return"Element does not have inner text that is visible to screen readers"}}},"role-presentation":{impact:"moderate",messages:{pass:function(a){return'Element\'s default semantics were overriden with role="presentation"'},fail:function(a){return'Element\'s default semantics were not overridden with role="presentation"'}}},"role-none":{impact:"moderate",messages:{pass:function(a){return'Element\'s default semantics were overriden with role="none"'},fail:function(a){return'Element\'s default semantics were not overridden with role="none"'}}},"focusable-no-name":{impact:"serious",messages:{pass:function(a){return"Element is not in tab order or has accessible text"},fail:function(a){return"Element is in tab order and does not have accessible text"}}},"internal-link-present":{impact:"critical",messages:{pass:function(a){return"Valid skip link found"},fail:function(a){return"No valid skip link found"}}},"header-present":{impact:"moderate",messages:{pass:function(a){return"Page has a header"},fail:function(a){return"Page does not have a header"}}},landmark:{impact:"serious",messages:{pass:function(a){return"Page has a landmark region"},fail:function(a){return"Page does not have a landmark region"}}},"group-labelledby":{impact:"critical",messages:{pass:function(a){return'All elements with the name "'+a.data.name+'" reference the same element with aria-labelledby'},fail:function(a){return'All elements with the name "'+a.data.name+'" do not reference the same element with aria-labelledby'}}},fieldset:{impact:"critical",messages:{pass:function(a){return"Element is contained in a fieldset"},fail:function(a){var b="",c=a.data&&a.data.failureCode;return b+="no-legend"===c?"Fieldset does not have a legend as its first child":"empty-legend"===c?"Legend does not have text that is visible to screen readers":"mixed-inputs"===c?"Fieldset contains unrelated inputs":"no-group-label"===c?"ARIA group does not have aria-label or aria-labelledby":"group-mixed-inputs"===c?"ARIA group contains unrelated inputs":"Element does not have a containing fieldset or ARIA group"}}},"color-contrast":{impact:"serious",messages:{pass:function(a){return"Element has sufficient color contrast of "+a.data.contrastRatio},fail:function(a){return"Element has insufficient color contrast of "+a.data.contrastRatio+" (foreground color: "+a.data.fgColor+", background color: "+a.data.bgColor+", font size: "+a.data.fontSize+", font weight: "+a.data.fontWeight+")"},incomplete:{bgImage:"Element's background color could not be determined due to a background image",bgGradient:"Element's background color could not be determined due to a background gradient",imgNode:"Element's background color could not be determined because element contains an image node",bgOverlap:"Element's background color could not be determined because it is overlapped by another element",fgAlpha:"Element's foreground color could not be determined because of alpha transparency",elmPartiallyObscured:"Element's background color could not be determined because it's partially obscured by another element",equalRatio:"Element has a 1:1 contrast ratio with the background",default:"Unable to determine contrast ratio"}}},"structured-dlitems":{impact:"serious",messages:{pass:function(a){return"When not empty, element has both <dt> and <dd> elements"},fail:function(a){return"When not empty, element does not have at least one <dt> element followed by at least one <dd> element"}}},"only-dlitems":{impact:"serious",messages:{pass:function(a){return"List element only has direct children that are allowed inside <dt> or <dd> elements"},fail:function(a){return"List element has direct children that are not allowed inside <dt> or <dd> elements"}}},dlitem:{impact:"serious",messages:{pass:function(a){return"Description list item has a <dl> parent element"},fail:function(a){return"Description list item does not have a <dl> parent element"}}},"doc-has-title":{impact:"moderate",messages:{pass:function(a){return"Document has a non-empty <title> element"},fail:function(a){return"Document does not have a non-empty <title> element"}}},"duplicate-id":{impact:"moderate",messages:{pass:function(a){return"Document has no elements that share the same id attribute"},fail:function(a){return"Document has multiple elements with the same id attribute: "+a.data}}},"has-visible-text":{impact:"moderate",messages:{pass:function(a){return"Element has text that is visible to screen readers"},fail:function(a){return"Element does not have text that is visible to screen readers"}}},"unique-frame-title":{impact:"serious",messages:{pass:function(a){return"Element's title attribute is unique"},fail:function(a){return"Element's title attribute is not unique"}}},"heading-order":{impact:"minor",messages:{pass:function(a){return"Heading order valid"},fail:function(a){return"Heading order invalid"}}},"hidden-content":{impact:"minor",messages:{pass:function(a){return"All content on the page has been analyzed."},fail:function(a){return"There were problems analyzing the content on this page."},incomplete:function(a){return"There is hidden content on the page that was not analyzed. You will need to trigger the display of this content in order to analyze it."}}},"href-no-hash":{impact:"moderate",messages:{pass:function(a){return"Anchor does not have an href value of #"},fail:function(a){return"Anchor has an href value of #"}}},"has-lang":{impact:"serious",messages:{pass:function(a){return"The <html> element has a lang attribute"},fail:function(a){return"The <html> element does not have a lang attribute"}}},"valid-lang":{impact:"serious",messages:{pass:function(a){return"Value of lang attribute is included in the list of valid languages"},fail:function(a){return"Value of lang attribute not included in the list of valid languages"}}},"has-alt":{impact:"critical",messages:{pass:function(a){return"Element has an alt attribute"},fail:function(a){return"Element does not have an alt attribute"}}},"duplicate-img-label":{impact:"minor",messages:{pass:function(a){return"Element does not duplicate existing text in <img> alt text"},fail:function(a){return"Element contains <img> element with alt text that duplicates existing text"}}},"title-only":{impact:"serious",messages:{pass:function(a){return"Form element does not solely use title attribute for its label"},fail:function(a){return"Only title used to generate label for form element"}}},"implicit-label":{impact:"critical",messages:{pass:function(a){return"Form element has an implicit (wrapped) <label>"},fail:function(a){return"Form element does not have an implicit (wrapped) <label>"}}},"explicit-label":{impact:"critical",messages:{pass:function(a){return"Form element has an explicit <label>"},fail:function(a){return"Form element does not have an explicit <label>"}}},"help-same-as-label":{impact:"minor",messages:{pass:function(a){return"Help text (title or aria-describedby) does not duplicate label text"},fail:function(a){return"Help text (title or aria-describedby) text is the same as the label text"}}},"multiple-label":{impact:"serious",messages:{pass:function(a){return"Form element does not have multiple <label> elements"},fail:function(a){return"Form element has multiple <label> elements"}}},"has-th":{impact:"serious",messages:{pass:function(a){return"Layout table does not use <th> elements"},fail:function(a){return"Layout table uses <th> elements"}}},"has-caption":{impact:"serious",messages:{pass:function(a){return"Layout table does not use <caption> element"},fail:function(a){return"Layout table uses <caption> element"}}},"has-summary":{impact:"serious",messages:{pass:function(a){return"Layout table does not use summary attribute"},fail:function(a){return"Layout table uses summary attribute"}}},"link-in-text-block":{impact:"critical",messages:{pass:function(a){return"Links can be distinguished from surrounding text in a way that does not rely on color"},fail:function(a){return"Links can not be distinguished from surrounding text in a way that does not rely on color"},incomplete:{bgContrast:"Element's contrast ratio could not be determined. Check for a distinct hover/focus style",bgImage:"Element's contrast ratio could not be determined due to a background image",bgGradient:"Element's contrast ratio could not be determined due to a background gradient",imgNode:"Element's contrast ratio could not be determined because element contains an image node",bgOverlap:"Element's contrast ratio could not be determined because of element overlap",default:"Unable to determine contrast ratio"}}},"only-listitems":{impact:"serious",messages:{pass:function(a){return"List element only has direct children that are allowed inside <li> elements"},fail:function(a){return"List element has direct children that are not allowed inside <li> elements"}}},listitem:{impact:"critical",messages:{pass:function(a){return'List item has a <ul>, <ol> or role="list" parent element'},fail:function(a){return'List item does not have a <ul>, <ol> or role="list" parent element'}}},"meta-refresh":{impact:"critical",messages:{pass:function(a){return"<meta> tag does not immediately refresh the page"},fail:function(a){return"<meta> tag forces timed refresh of page"}}},"meta-viewport-large":{impact:"minor",messages:{pass:function(a){return"<meta> tag does not prevent significant zooming"},fail:function(a){return"<meta> tag limits zooming"}}},"meta-viewport":{impact:"critical",messages:{pass:function(a){return"<meta> tag does not disable zooming"},fail:function(a){return"<meta> tag disables zooming"}}},"p-as-heading":{impact:"critical",messages:{pass:function(a){return"<p> elements are not styled as headings"},fail:function(a){return"Heading elements should be used instead of styled p elements"}}},region:{impact:"moderate",messages:{pass:function(a){return"Content contained by ARIA landmark"},fail:function(a){return"Content not contained by an ARIA landmark"}}},"html5-scope":{impact:"serious",messages:{pass:function(a){return"Scope attribute is only used on table header elements (<th>)"},fail:function(a){return"In HTML 5, scope attributes may only be used on table header elements (<th>)"}}},"scope-value":{impact:"critical",messages:{pass:function(a){return"Scope attribute is used correctly"},fail:function(a){return"The value of the scope attribute may only be 'row' or 'col'"}}},exists:{impact:"minor",messages:{pass:function(a){return"Element does not exist"},fail:function(a){return"Element exists"}}},"skip-link":{impact:"critical",messages:{pass:function(a){return"Valid skip link found"},fail:function(a){return"No valid skip link found"}}},tabindex:{impact:"serious",messages:{pass:function(a){return"Element does not have a tabindex greater than 0"},fail:function(a){return"Element has a tabindex greater than 0"}}},"same-caption-summary":{impact:"moderate",messages:{pass:function(a){return"Content of summary attribute and <caption> are not duplicated"},fail:function(a){return"Content of summary attribute and <caption> element are identical"}}},"caption-faked":{impact:"critical",messages:{pass:function(a){return"The first row of a table is not used as a caption"},fail:function(a){return"The first row of the table should be a caption instead of a table cell"}}},"td-has-header":{impact:"critical",messages:{pass:function(a){return"All non-empty data cells have table headers"},fail:function(a){return"Some non-empty data cells do not have table headers"}}},"td-headers-attr":{impact:"serious",messages:{pass:function(a){return"The headers attribute is exclusively used to refer to other cells in the table"},fail:function(a){return"The headers attribute is not exclusively used to refer to other cells in the table"}}},"th-has-data-cells":{impact:"critical",messages:{pass:function(a){return"All table header cells refer to data cells"},fail:function(a){return"Not all table header cells refer to data cells"},incomplete:function(a){return"Table data cells are missing or empty"}}},description:{impact:"serious",messages:{pass:function(a){return"The multimedia element has an audio description track"},fail:function(a){return"The multimedia element does not have an audio description track"},incomplete:function(a){return"An audio description track for this element could not be found"}}}},failureSummaries:{any:{failureMessage:function(a){var b="Fix any of the following:",c=a;if(c)for(var d,e=-1,f=c.length-1;e<f;)d=c[e+=1],b+="\n  "+d.split("\n").join("\n  ");return b}},none:{failureMessage:function(a){
-var b="Fix all of the following:",c=a;if(c)for(var d,e=-1,f=c.length-1;e<f;)d=c[e+=1],b+="\n  "+d.split("\n").join("\n  ");return b}}},incompleteFallbackMessage:function(a){return"aXe couldn't tell the reason. Time to break out the element inspector!"}},rules:[{id:"accesskeys",selector:"[accesskey]",excludeHidden:!1,tags:["wcag2a","wcag211","cat.keyboard"],all:[],any:[],none:["accesskeys"]},{id:"area-alt",selector:"map area[href]",excludeHidden:!1,tags:["cat.text-alternatives","wcag2a","wcag111","section508","section508.22.a"],all:[],any:["non-empty-alt","non-empty-title","aria-label","aria-labelledby"],none:[]},{id:"aria-allowed-attr",matches:function(a){var b=a.getAttribute("role");b||(b=axe.commons.aria.implicitRole(a));var c=axe.commons.aria.allowedAttr(b);if(b&&c){var d=/^aria-/;if(a.hasAttributes())for(var e=a.attributes,f=0,g=e.length;f<g;f++)if(d.test(e[f].name))return!0}return!1},tags:["cat.aria","wcag2a","wcag411","wcag412"],all:[],any:["aria-allowed-attr"],none:[]},{id:"aria-hidden-body",selector:"body",excludeHidden:!1,tags:["cat.aria","wcag2a","wcag412"],all:[],any:["aria-hidden-body"],none:[]},{id:"aria-required-attr",selector:"[role]",tags:["cat.aria","wcag2a","wcag411","wcag412"],all:[],any:["aria-required-attr"],none:[]},{id:"aria-required-children",selector:"[role]",tags:["cat.aria","wcag2a","wcag131"],all:[],any:["aria-required-children"],none:[]},{id:"aria-required-parent",selector:"[role]",tags:["cat.aria","wcag2a","wcag131"],all:[],any:["aria-required-parent"],none:[]},{id:"aria-roles",selector:"[role]",tags:["cat.aria","wcag2a","wcag131","wcag411","wcag412"],all:[],any:[],none:["invalidrole","abstractrole"]},{id:"aria-valid-attr-value",matches:function(a){var b=/^aria-/;if(a.hasAttributes())for(var c=a.attributes,d=0,e=c.length;d<e;d++)if(b.test(c[d].name))return!0;return!1},tags:["cat.aria","wcag2a","wcag131","wcag411","wcag412"],all:[],any:[{options:[],id:"aria-valid-attr-value"}],none:[]},{id:"aria-valid-attr",matches:function(a){var b=/^aria-/;if(a.hasAttributes())for(var c=a.attributes,d=0,e=c.length;d<e;d++)if(b.test(c[d].name))return!0;return!1},tags:["cat.aria","wcag2a","wcag411"],all:[],any:[{options:[],id:"aria-valid-attr"}],none:[]},{id:"audio-caption",selector:"audio",excludeHidden:!1,tags:["cat.time-and-media","wcag2a","wcag122","section508","section508.22.a"],all:[],any:[],none:["caption"]},{id:"blink",selector:"blink",excludeHidden:!1,tags:["cat.time-and-media","wcag2a","wcag222","section508","section508.22.j"],all:[],any:[],none:["is-on-screen"]},{id:"button-name",selector:'button, [role="button"], input[type="button"], input[type="submit"], input[type="reset"]',tags:["cat.name-role-value","wcag2a","wcag412","section508","section508.22.a"],all:[],any:["non-empty-if-present","non-empty-value","button-has-visible-text","aria-label","aria-labelledby","role-presentation","role-none"],none:["focusable-no-name"]},{id:"bypass",selector:"html",pageLevel:!0,matches:function(a){return!!a.querySelector("a[href]")},tags:["cat.keyboard","wcag2a","wcag241","section508","section508.22.o"],all:[],any:["internal-link-present","header-present","landmark"],none:[]},{id:"checkboxgroup",selector:"input[type=checkbox][name]",tags:["cat.forms","best-practice"],all:[],any:["group-labelledby","fieldset"],none:[]},{id:"color-contrast",matches:function(a){var b=a.nodeName.toUpperCase(),c=a.type,d=document;if("true"===a.getAttribute("aria-disabled")||axe.commons.dom.findUp(a,'[aria-disabled="true"]'))return!1;if("INPUT"===b)return-1===["hidden","range","color","checkbox","radio","image"].indexOf(c)&&!a.disabled;if("SELECT"===b)return!!a.options.length&&!a.disabled;if("TEXTAREA"===b)return!a.disabled;if("OPTION"===b)return!1;if("BUTTON"===b&&a.disabled||axe.commons.dom.findUp(a,"button[disabled]"))return!1;if("FIELDSET"===b&&a.disabled||axe.commons.dom.findUp(a,"fieldset[disabled]"))return!1;var e=axe.commons.dom.findUp(a,"label");if("LABEL"===b||e){var f=a;e&&(f=e);var g=f.htmlFor&&d.getElementById(f.htmlFor);if(g&&g.disabled)return!1;var g=a.querySelector('input:not([type="hidden"]):not([type="image"]):not([type="button"]):not([type="submit"]):not([type="reset"]), select, textarea');if(g&&g.disabled)return!1}if(a.id){var g=d.querySelector("[aria-labelledby~="+axe.commons.utils.escapeSelector(a.id)+"]");if(g&&g.disabled)return!1}if(""===axe.commons.text.visible(a,!1,!0))return!1;var h,i,j=document.createRange(),k=a.childNodes,l=k.length;for(i=0;i<l;i++)h=k[i],3===h.nodeType&&""!==axe.commons.text.sanitize(h.nodeValue)&&j.selectNodeContents(h);var m=j.getClientRects();for(l=m.length,i=0;i<l;i++)if(axe.commons.dom.visuallyOverlaps(m[i],a))return!0;return!1},excludeHidden:!1,options:{noScroll:!1},tags:["cat.color","wcag2aa","wcag143"],all:[],any:["color-contrast"],none:[]},{id:"definition-list",selector:"dl",matches:function(a){return!a.getAttribute("role")},tags:["cat.structure","wcag2a","wcag131"],all:[],any:[],none:["structured-dlitems","only-dlitems"]},{id:"dlitem",selector:"dd, dt",matches:function(a){return!a.getAttribute("role")},tags:["cat.structure","wcag2a","wcag131"],all:[],any:["dlitem"],none:[]},{id:"document-title",selector:"html",matches:function(a){return a.ownerDocument.defaultView.self===a.ownerDocument.defaultView.top},tags:["cat.text-alternatives","wcag2a","wcag242"],all:[],any:["doc-has-title"],none:[]},{id:"duplicate-id",selector:"[id]",excludeHidden:!1,tags:["cat.parsing","wcag2a","wcag411"],all:[],any:["duplicate-id"],none:[]},{id:"empty-heading",selector:'h1, h2, h3, h4, h5, h6, [role="heading"]',enabled:!0,tags:["cat.name-role-value","best-practice"],all:[],any:["has-visible-text","role-presentation","role-none"],none:[]},{id:"frame-title-unique",selector:"frame[title], iframe[title]",matches:function(a){var b=a.getAttribute("title");return!!(b?axe.commons.text.sanitize(b).trim():"")},tags:["cat.text-alternatives","best-practice"],all:[],any:[],none:["unique-frame-title"]},{id:"frame-title",selector:"frame, iframe",tags:["cat.text-alternatives","wcag2a","wcag241","section508","section508.22.i"],all:[],any:["aria-label","aria-labelledby","non-empty-title","role-presentation","role-none"],none:[]},{id:"heading-order",selector:"h1,h2,h3,h4,h5,h6,[role=heading]",enabled:!1,tags:["cat.semantics","best-practice"],all:[],any:["heading-order"],none:[]},{id:"hidden-content",selector:"*",excludeHidden:!1,tags:["experimental","review-item"],all:[],any:["hidden-content"],none:[],enabled:!1},{id:"href-no-hash",selector:"a[href]",enabled:!1,tags:["cat.semantics","best-practice"],all:[],any:["href-no-hash"],none:[]},{id:"html-has-lang",selector:"html",tags:["cat.language","wcag2a","wcag311"],all:[],any:["has-lang"],none:[]},{id:"html-lang-valid",selector:"html[lang]",tags:["cat.language","wcag2a","wcag311"],all:[],any:[],none:["valid-lang"]},{id:"image-alt",selector:"img, [role='img']",tags:["cat.text-alternatives","wcag2a","wcag111","section508","section508.22.a"],all:[],any:["has-alt","aria-label","aria-labelledby","non-empty-title","role-presentation","role-none"],none:[]},{id:"image-redundant-alt",selector:'button, [role="button"], a[href], p, li, td, th',tags:["cat.text-alternatives","best-practice"],all:[],any:[],none:["duplicate-img-label"]},{id:"input-image-alt",selector:'input[type="image"]',tags:["cat.text-alternatives","wcag2a","wcag111","section508","section508.22.a"],all:[],any:["non-empty-alt","aria-label","aria-labelledby","non-empty-title"],none:[]},{id:"label-title-only",selector:"input, select, textarea",matches:function(a){if("input"!==a.nodeName.toLowerCase())return!0;var b=a.getAttribute("type").toLowerCase();return"hidden"!==b&&"image"!==b&&"button"!==b&&"submit"!==b&&"reset"!==b},enabled:!1,tags:["cat.forms","best-practice"],all:[],any:[],none:["title-only"]},{id:"label",selector:"input, select, textarea",matches:function(a){if("input"!==a.nodeName.toLowerCase())return!0;var b=a.getAttribute("type").toLowerCase();return"hidden"!==b&&"image"!==b&&"button"!==b&&"submit"!==b&&"reset"!==b},tags:["cat.forms","wcag2a","wcag332","wcag131","section508","section508.22.n"],all:[],any:["aria-label","aria-labelledby","implicit-label","explicit-label","non-empty-title"],none:["help-same-as-label","multiple-label"]},{id:"layout-table",selector:"table",matches:function(a){return!axe.commons.table.isDataTable(a)},tags:["cat.semantics","wcag2a","wcag131"],all:[],any:[],none:["has-th","has-caption","has-summary"]},{id:"link-in-text-block",selector:"a[href], *[role=link]",matches:function(a){var b=axe.commons.text.sanitize(a.textContent),c=a.getAttribute("role");return(!c||"link"===c)&&(!!b&&(!!axe.commons.dom.isVisible(a,!1)&&axe.commons.dom.isInTextBlock(a)))},excludeHidden:!1,tags:["cat.color","experimental","wcag2a","wcag141"],all:["link-in-text-block"],any:[],none:[]},{id:"link-name",selector:"a[href], [role=link][href]",matches:function(a){return"button"!==a.getAttribute("role")},tags:["cat.name-role-value","wcag2a","wcag111","wcag412","section508","section508.22.a"],all:[],any:["has-visible-text","aria-label","aria-labelledby","role-presentation","role-none"],none:["focusable-no-name"]},{id:"list",selector:"ul, ol",matches:function(a){return!a.getAttribute("role")},tags:["cat.structure","wcag2a","wcag131"],all:[],any:[],none:["only-listitems"]},{id:"listitem",selector:"li",matches:function(a){return!a.getAttribute("role")},tags:["cat.structure","wcag2a","wcag131"],all:[],any:["listitem"],none:[]},{id:"marquee",selector:"marquee",excludeHidden:!1,tags:["cat.parsing","wcag2a","wcag222"],all:[],any:[],none:["is-on-screen"]},{id:"meta-refresh",selector:'meta[http-equiv="refresh"]',excludeHidden:!1,tags:["cat.time","wcag2a","wcag2aaa","wcag221","wcag224","wcag325"],all:[],any:["meta-refresh"],none:[]},{id:"meta-viewport-large",selector:'meta[name="viewport"]',excludeHidden:!1,tags:["cat.sensory-and-visual-cues","best-practice"],all:[],any:[{options:{scaleMinimum:5,lowerBound:2},id:"meta-viewport-large"}],none:[]},{id:"meta-viewport",selector:'meta[name="viewport"]',excludeHidden:!1,tags:["cat.sensory-and-visual-cues","wcag2aa","wcag144"],all:[],any:[{options:{scaleMinimum:2},id:"meta-viewport"}],none:[]},{id:"object-alt",selector:"object",tags:["cat.text-alternatives","wcag2a","wcag111","section508","section508.22.a"],all:[],any:["has-visible-text","aria-label","aria-labelledby","non-empty-title"],none:[]},{id:"p-as-heading",selector:"p",matches:function(a){var b=Array.from(a.parentNode.childNodes),c=a.textContent.trim(),d=/[.!?:;](?![.!?:;])/g;return!(0===c.length||(c.match(d)||[]).length>=2)&&0!==b.slice(b.indexOf(a)+1).filter(function(a){return"P"===a.nodeName.toUpperCase()&&""!==a.textContent.trim()}).length},tags:["cat.semantics","wcag2a","wcag131","experimental"],all:[{options:{margins:[{weight:150,italic:!0},{weight:150,size:1.15},{italic:!0,size:1.15},{size:1.4}]},id:"p-as-heading"}],any:[],none:[]},{id:"radiogroup",selector:"input[type=radio][name]",tags:["cat.forms","best-practice"],all:[],any:["group-labelledby","fieldset"],none:[]},{id:"region",selector:"html",pageLevel:!0,enabled:!1,tags:["cat.keyboard","best-practice"],all:[],any:["region"],none:[]},{id:"scope-attr-valid",selector:"td[scope], th[scope]",enabled:!0,tags:["cat.tables","best-practice"],all:["html5-scope","scope-value"],any:[],none:[]},{id:"server-side-image-map",selector:"img[ismap]",tags:["cat.text-alternatives","wcag2a","wcag211","section508","section508.22.f"],all:[],any:[],none:["exists"]},{id:"skip-link",selector:"a[href]",pageLevel:!0,enabled:!1,tags:["cat.keyboard","best-practice"],all:[],any:["skip-link"],none:[]},{id:"tabindex",selector:"[tabindex]",tags:["cat.keyboard","best-practice"],all:[],any:["tabindex"],none:[]},{id:"table-duplicate-name",selector:"table",tags:["cat.tables","best-practice"],all:[],any:[],none:["same-caption-summary"]},{id:"table-fake-caption",selector:"table",matches:function(a){return axe.commons.table.isDataTable(a)},tags:["cat.tables","experimental","wcag2a","wcag131","section508","section508.22.g"],all:["caption-faked"],any:[],none:[]},{id:"td-has-header",selector:"table",matches:function(a){if(axe.commons.table.isDataTable(a)){var b=axe.commons.table.toArray(a);return b.length>=3&&b[0].length>=3&&b[1].length>=3&&b[2].length>=3}return!1},tags:["cat.tables","experimental","wcag2a","wcag131","section508","section508.22.g"],all:["td-has-header"],any:[],none:[]},{id:"td-headers-attr",selector:"table",tags:["cat.tables","wcag2a","wcag131","section508","section508.22.g"],all:["td-headers-attr"],any:[],none:[]},{id:"th-has-data-cells",selector:"table",matches:function(a){return axe.commons.table.isDataTable(a)},tags:["cat.tables","wcag2a","wcag131","section508","section508.22.g"],all:["th-has-data-cells"],any:[],none:[]},{id:"valid-lang",selector:"[lang], [xml\\:lang]",matches:function(a){return"html"!==a.nodeName.toLowerCase()},tags:["cat.language","wcag2aa","wcag312"],all:[],any:[],none:["valid-lang"]},{id:"video-caption",selector:"video",excludeHidden:!1,tags:["cat.text-alternatives","wcag2a","wcag122","wcag123","section508","section508.22.a"],all:[],any:[],none:["caption"]},{id:"video-description",selector:"video",excludeHidden:!1,tags:["cat.text-alternatives","wcag2aa","wcag125","section508","section508.22.b"],all:[],any:[],none:["description"]}],checks:[{id:"abstractrole",evaluate:function(a,b){return"abstract"===axe.commons.aria.getRoleType(a.getAttribute("role"))}},{id:"aria-allowed-attr",evaluate:function(a,b){var c,d,e,f=[],g=a.getAttribute("role"),h=a.attributes;if(g||(g=axe.commons.aria.implicitRole(a)),e=axe.commons.aria.allowedAttr(g),g&&e)for(var i=0,j=h.length;i<j;i++)c=h[i],d=c.name,axe.commons.aria.validateAttr(d)&&-1===e.indexOf(d)&&f.push(d+'="'+c.nodeValue+'"');return!f.length||(this.data(f),!1)}},{id:"aria-hidden-body",evaluate:function(a,b){return"true"!==a.getAttribute("aria-hidden")}},{id:"invalidrole",evaluate:function(a,b){return!axe.commons.aria.isValidRole(a.getAttribute("role"))}},{id:"aria-required-attr",evaluate:function(a,b){var c=[];if(a.hasAttributes()){var d,e=a.getAttribute("role"),f=axe.commons.aria.requiredAttr(e);if(e&&f)for(var g=0,h=f.length;g<h;g++)d=f[g],a.getAttribute(d)||c.push(d)}return!c.length||(this.data(c),!1)}},{id:"aria-required-children",evaluate:function(a,b){function c(a,b,c){if(null===a)return!1;var d=f(b),e=['[role="'+b+'"]'];return d&&(e=e.concat(d)),e=e.join(","),c?g(a,e)||!!a.querySelector(e):!!a.querySelector(e)}function d(a,b){var d,e;for(d=0,e=a.length;d<e;d++)if(null!==a[d]&&c(a[d],b,!0))return!0;return!1}var e=axe.commons.aria.requiredOwned,f=axe.commons.aria.implicitNodes,g=axe.commons.utils.matchesSelector,h=axe.commons.dom.idrefs,i=a.getAttribute("role"),j=e(i);if(!j)return!0;var k=!1,l=j.one;if(!l){var k=!0;l=j.all}var m=function(a,b,e){var f,g=b.length,i=[],j=h(a,"aria-owns");for(f=0;f<g;f++){var k=b[f];if(c(a,k)||d(j,k)){if(!e)return null}else e&&i.push(k)}return i.length?i:!e&&b.length?b:null}(a,l,k);return!m||(this.data(m),!1)}},{id:"aria-required-parent",evaluate:function(a,b){function c(a){return(axe.commons.aria.implicitNodes(a)||[]).concat('[role="'+a+'"]').join(",")}function d(a,b,d){var e,f,g=a.getAttribute("role"),h=[];if(b||(b=axe.commons.aria.requiredContext(g)),!b)return null;for(e=0,f=b.length;e<f;e++){if(d&&axe.utils.matchesSelector(a,c(b[e])))return null;if(axe.commons.dom.findUp(a,c(b[e])))return null;h.push(b[e])}return h}var e=d(a);if(!e)return!0;var f=function(a){for(var b=[],c=null;a;)a.id&&(c=document.querySelector("[aria-owns~="+axe.commons.utils.escapeSelector(a.id)+"]"))&&b.push(c),a=a.parentNode;return b.length?b:null}(a);if(f)for(var g=0,h=f.length;g<h;g++)if(!(e=d(f[g],e,!0)))return!0;return this.data(e),!1}},{id:"aria-valid-attr-value",evaluate:function(a,b){b=Array.isArray(b)?b:[];for(var c,d,e=[],f=/^aria-/,g=a.attributes,h=0,i=g.length;h<i;h++)c=g[h],d=c.name,-1===b.indexOf(d)&&f.test(d)&&!axe.commons.aria.validateAttrValue(a,d)&&e.push(d+'="'+c.nodeValue+'"');return!e.length||(this.data(e),!1)},options:[]},{id:"aria-valid-attr",evaluate:function(a,b){b=Array.isArray(b)?b:[];for(var c,d=[],e=/^aria-/,f=a.attributes,g=0,h=f.length;g<h;g++)c=f[g].name,-1===b.indexOf(c)&&e.test(c)&&!axe.commons.aria.validateAttr(c)&&d.push(c);return!d.length||(this.data(d),!1)},options:[]},{id:"color-contrast",evaluate:function(a,b){if(!axe.commons.dom.isVisible(a,!1))return!0;var c,d=!!(b||{}).noScroll,e=[],f=axe.commons.color.getBackgroundColor(a,e,d),g=axe.commons.color.getForegroundColor(a,d),h=window.getComputedStyle(a),i=parseFloat(h.getPropertyValue("font-size")),j=h.getPropertyValue("font-weight"),k=-1!==["bold","bolder","600","700","800","900"].indexOf(j),l=axe.commons.color.hasValidContrastRatio(f,g,i,k),m=Math.floor(100*l.contrastRatio)/100;null===f&&(c=axe.commons.color.incompleteData.get("bgColor"));var n=!1;1===m&&(n=!0,c=axe.commons.color.incompleteData.set("bgColor","equalRatio"));var o={fgColor:g?g.toHexString():void 0,bgColor:f?f.toHexString():void 0,contrastRatio:l?m:void 0,fontSize:(72*i/96).toFixed(1)+"pt",fontWeight:k?"bold":"normal",missingData:c};return this.data(o),l.isValid&&!n||this.relatedNodes(e),null===g||null===f||n?(c=null,void axe.commons.color.incompleteData.clear()):l.isValid}},{id:"link-in-text-block",evaluate:function(a,b){function c(a,b){var c=a.getRelativeLuminance(),d=b.getRelativeLuminance();return(Math.max(c,d)+.05)/(Math.min(c,d)+.05)}function d(a){var b=window.getComputedStyle(a).getPropertyValue("display");return-1!==f.indexOf(b)||"table-"===b.substr(0,6)}var e=axe.commons.color,f=["block","list-item","table","flex","grid","inline-block"];if(d(a))return!1;for(var g=a.parentNode;1===g.nodeType&&!d(g);)g=g.parentNode;if(e.elementIsDistinct(a,g))return!0;var h,i;if(h=e.getForegroundColor(a),i=e.getForegroundColor(g),h&&i){var j=c(h,i);if(1===j)return!0;if(j>=3)return axe.commons.color.incompleteData.set("fgColor","bgContrast"),this.data({missingData:axe.commons.color.incompleteData.get("fgColor")}),void axe.commons.color.incompleteData.clear();if(h=e.getBackgroundColor(a),i=e.getBackgroundColor(g),!h||!i||c(h,i)>=3){var k=void 0;return k=h&&i?"bgContrast":axe.commons.color.incompleteData.get("bgColor"),axe.commons.color.incompleteData.set("fgColor",k),this.data({missingData:axe.commons.color.incompleteData.get("fgColor")}),void axe.commons.color.incompleteData.clear()}return!1}}},{id:"fieldset",evaluate:function(a,b){function c(a,b){return axe.commons.utils.toArray(a.querySelectorAll('select,textarea,button,input:not([name="'+b+'"]):not([type="hidden"])'))}function d(a,b){var d=a.firstElementChild;if(!d||"LEGEND"!==d.nodeName.toUpperCase())return h.relatedNodes([a]),g="no-legend",!1;if(!axe.commons.text.accessibleText(d))return h.relatedNodes([d]),g="empty-legend",!1;var e=c(a,b);return!e.length||(h.relatedNodes(e),g="mixed-inputs",!1)}function e(a,b){var d=axe.commons.dom.idrefs(a,"aria-labelledby").some(function(a){return a&&axe.commons.text.accessibleText(a)}),e=a.getAttribute("aria-label");if(!(d||e&&axe.commons.text.sanitize(e)))return h.relatedNodes(a),g="no-group-label",!1;var f=c(a,b);return!f.length||(h.relatedNodes(f),g="group-mixed-inputs",!1)}function f(a,b){return axe.commons.utils.toArray(a).filter(function(a){return a!==b})}var g,h=this,i={name:a.getAttribute("name"),type:a.getAttribute("type")},j=function(b){var c=axe.commons.utils.escapeSelector(a.name),i=document.querySelectorAll('input[type="'+axe.commons.utils.escapeSelector(a.type)+'"][name="'+c+'"]');if(i.length<2)return!0;var j=axe.commons.dom.findUp(b,"fieldset"),k=axe.commons.dom.findUp(b,'[role="group"]'+("radio"===a.type?',[role="radiogroup"]':""));return k||j?j?d(j,c):e(k,c):(g="no-group",h.relatedNodes(f(i,b)),!1)}(a);return j||(i.failureCode=g),this.data(i),j},after:function(a,b){var c={};return a.filter(function(a){if(a.result)return!0;var b=a.data;if(b){if(c[b.type]=c[b.type]||{},!c[b.type][b.name])return c[b.type][b.name]=[b],!0;var d=c[b.type][b.name].some(function(a){return a.failureCode===b.failureCode});return d||c[b.type][b.name].push(b),!d}return!1})}},{id:"group-labelledby",evaluate:function(a,b){this.data({name:a.getAttribute("name"),type:a.getAttribute("type")});var c=document.querySelectorAll('input[type="'+axe.commons.utils.escapeSelector(a.type)+'"][name="'+axe.commons.utils.escapeSelector(a.name)+'"]');return c.length<=1||0!==[].map.call(c,function(a){var b=a.getAttribute("aria-labelledby");return b?b.split(/\s+/):[]}).reduce(function(a,b){return a.filter(function(a){return-1!==b.indexOf(a)})}).filter(function(a){var b=document.getElementById(a);return b&&axe.commons.text.accessibleText(b)}).length},after:function(a,b){var c={};return a.filter(function(a){var b=a.data;return!(!b||(c[b.type]=c[b.type]||{},c[b.type][b.name]))&&(c[b.type][b.name]=!0,!0)})}},{id:"accesskeys",evaluate:function(a,b){return axe.commons.dom.isVisible(a,!1)&&(this.data(a.getAttribute("accesskey")),this.relatedNodes([a])),!0},after:function(a,b){var c={};return a.filter(function(a){if(!a.data)return!1;var b=a.data.toUpperCase();return c[b]?(c[b].relatedNodes.push(a.relatedNodes[0]),!1):(c[b]=a,a.relatedNodes=[],!0)}).map(function(a){return a.result=!!a.relatedNodes.length,a})}},{id:"focusable-no-name",evaluate:function(a,b){var c=a.getAttribute("tabindex");return!!(axe.commons.dom.isFocusable(a)&&c>-1)&&!axe.commons.text.accessibleText(a)}},{id:"tabindex",evaluate:function(a,b){return a.tabIndex<=0}},{id:"duplicate-img-label",evaluate:function(a,b){var c=a.querySelectorAll("img"),d=axe.commons.text.visible(a,!0).toLowerCase();if(""===d)return!1;for(var e=0,f=c.length;e<f;e++){var g=c[e];if(axe.commons.text.accessibleText(g).toLowerCase()===d&&"presentation"!==g.getAttribute("role")&&axe.commons.dom.isVisible(g))return!0}return!1}},{id:"explicit-label",evaluate:function(a,b){if(a.id){var c=document.querySelector('label[for="'+axe.commons.utils.escapeSelector(a.id)+'"]');if(c)return!!axe.commons.text.accessibleText(c)}return!1}},{id:"help-same-as-label",evaluate:function(a,b){var c=axe.commons.text.label(a),d=a.getAttribute("title");if(!c)return!1;if(!d&&(d="",a.getAttribute("aria-describedby"))){d=axe.commons.dom.idrefs(a,"aria-describedby").map(function(a){return a?axe.commons.text.accessibleText(a):""}).join("")}return axe.commons.text.sanitize(d)===axe.commons.text.sanitize(c)},enabled:!1},{id:"implicit-label",evaluate:function(a,b){var c=axe.commons.dom.findUp(a,"label");return!!c&&!!axe.commons.text.accessibleText(c)}},{id:"multiple-label",evaluate:function(a,b){var c=[].slice.call(document.querySelectorAll('label[for="'+axe.commons.utils.escapeSelector(a.id)+'"]')),d=a.parentNode;for(c.length&&(c=c.filter(function(a,b){if(0===b&&!axe.commons.dom.isVisible(a,!0)||axe.commons.dom.isVisible(a,!0))return a}));d;)"LABEL"===d.tagName&&-1===c.indexOf(d)&&c.push(d),d=d.parentNode;return this.relatedNodes(c),c.length>1}},{id:"title-only",evaluate:function(a,b){return!(axe.commons.text.label(a)||!a.getAttribute("title")&&!a.getAttribute("aria-describedby"))}},{id:"has-lang",evaluate:function(a,b){return!!(a.getAttribute("lang")||a.getAttribute("xml:lang")||"").trim()}},{id:"valid-lang",evaluate:function(a,b){function c(a){return a.trim().split("-")[0].toLowerCase()}var d,e;return d=(b||axe.commons.utils.validLangs()).map(c),e=["lang","xml:lang"].reduce(function(b,e){var f=a.getAttribute(e);if("string"!=typeof f)return b;var g=c(f);return""!==g&&-1===d.indexOf(g)&&b.push(e+'="'+a.getAttribute(e)+'"'),b},[]),!!e.length&&(this.data(e),!0)}},{id:"dlitem",evaluate:function(a,b){return"DL"===a.parentNode.tagName}},{id:"has-listitem",evaluate:function(a,b){var c=a.children;if(0===c.length)return!0;for(var d=0;d<c.length;d++)if("LI"===c[d].nodeName.toUpperCase())return!1;return!0}},{id:"listitem",evaluate:function(a,b){return-1!==["UL","OL"].indexOf(a.parentNode.nodeName.toUpperCase())||"list"===a.parentNode.getAttribute("role")}},{id:"only-dlitems",evaluate:function(a,b){for(var c,d,e=[],f=a.childNodes,g=["STYLE","META","LINK","MAP","AREA","SCRIPT","DATALIST","TEMPLATE"],h=!1,i=0;i<f.length;i++){c=f[i];var d=c.nodeName.toUpperCase();1===c.nodeType&&"DT"!==d&&"DD"!==d&&-1===g.indexOf(d)?e.push(c):3===c.nodeType&&""!==c.nodeValue.trim()&&(h=!0)}return e.length&&this.relatedNodes(e),!!e.length||h}},{id:"only-listitems",evaluate:function(a,b){for(var c,d,e=[],f=a.childNodes,g=["STYLE","META","LINK","MAP","AREA","SCRIPT","DATALIST","TEMPLATE"],h=!1,i=0;i<f.length;i++)c=f[i],d=c.nodeName.toUpperCase(),1===c.nodeType&&"LI"!==d&&-1===g.indexOf(d)?e.push(c):3===c.nodeType&&""!==c.nodeValue.trim()&&(h=!0);return e.length&&this.relatedNodes(e),!!e.length||h}},{id:"structured-dlitems",evaluate:function(a,b){var c=a.children;if(!c||!c.length)return!1;for(var d,e=!1,f=!1,g=0;g<c.length;g++){if(d=c[g].nodeName.toUpperCase(),"DT"===d&&(e=!0),e&&"DD"===d)return!1;"DD"===d&&(f=!0)}return e||f}},{id:"caption",evaluate:function(a,b){var c=a.querySelectorAll("track");if(c.length){for(var d=0;d<c.length;d++){var e=c[d].getAttribute("kind");if(e&&"captions"===e)return!1}return!0}}},{id:"description",evaluate:function(a,b){var c=a.querySelectorAll("track");if(c.length){for(var d=0;d<c.length;d++){var e=c[d].getAttribute("kind");if(e&&"descriptions"===e)return!1}return!0}}},{id:"meta-viewport-large",evaluate:function(a,b){b=b||{};for(var c,d=a.getAttribute("content")||"",e=d.split(/[;,]/),f={},g=b.scaleMinimum||2,h=b.lowerBound||!1,i=0,j=e.length;i<j;i++){c=e[i].split("=");var k=c.shift().toLowerCase();k&&c.length&&(f[k.trim()]=c.shift().trim().toLowerCase())}return!!(h&&f["maximum-scale"]&&parseFloat(f["maximum-scale"])<h)||!(!h&&"no"===f["user-scalable"])&&!(f["maximum-scale"]&&parseFloat(f["maximum-scale"])<g)},options:{scaleMinimum:5,lowerBound:2}},{id:"meta-viewport",evaluate:function(a,b){b=b||{};for(var c,d=a.getAttribute("content")||"",e=d.split(/[;,]/),f={},g=b.scaleMinimum||2,h=b.lowerBound||!1,i=0,j=e.length;i<j;i++){c=e[i].split("=");var k=c.shift().toLowerCase();k&&c.length&&(f[k.trim()]=c.shift().trim().toLowerCase())}return!!(h&&f["maximum-scale"]&&parseFloat(f["maximum-scale"])<h)||!(!h&&"no"===f["user-scalable"])&&!(f["maximum-scale"]&&parseFloat(f["maximum-scale"])<g)},options:{scaleMinimum:2}},{id:"header-present",evaluate:function(a,b){return!!a.querySelector('h1, h2, h3, h4, h5, h6, [role="heading"]')}},{id:"heading-order",evaluate:function(a,b){var c=a.getAttribute("aria-level");if(null!==c)return this.data(parseInt(c,10)),!0;var d=a.tagName.match(/H(\d)/);return!d||(this.data(parseInt(d[1],10)),!0)},after:function(a,b){if(a.length<2)return a;for(var c=a[0].data,d=1;d<a.length;d++)a[d].result&&a[d].data>c+1&&(a[d].result=!1),c=a[d].data;return a}},{id:"href-no-hash",evaluate:function(a,b){return"#"!==a.getAttribute("href")}},{id:"internal-link-present",evaluate:function(a,b){return!!a.querySelector('a[href^="#"]')}},{id:"landmark",evaluate:function(a,b){return a.getElementsByTagName("main").length>0||!!a.querySelector('[role="main"]')}},{id:"meta-refresh",evaluate:function(a,b){var c=a.getAttribute("content")||"",d=c.split(/[;,]/);return""===c||"0"===d[0]}},{id:"p-as-heading",evaluate:function(a,b){function c(a){for(var b=a,c=a.textContent.trim(),d=c;d===c&&void 0!==b;){var e=-1;if(a=b,0===a.children.length)return a;do{e++,d=a.children[e].textContent.trim()}while(""===d&&e+1<a.children.length);b=a.children[e]}return a}function d(a){switch(a){case"lighter":return 100;case"normal":return 400;case"bold":return 700;case"bolder":return 900}return a=parseInt(a),isNaN(a)?400:a}function e(a){var b=window.getComputedStyle(c(a));return{fontWeight:d(b.getPropertyValue("font-weight")),fontSize:parseInt(b.getPropertyValue("font-size")),isItalic:"italic"===b.getPropertyValue("font-style")}}function f(a,b,c){return c.reduce(function(c,d){return c||(!d.size||a.fontSize/d.size>b.fontSize)&&(!d.weight||a.fontWeight-d.weight>b.fontWeight)&&(!d.italic||a.isItalic&&!b.isItalic)},!1)}var g=Array.from(a.parentNode.children),h=g.indexOf(a);b=b||{};var i=b.margins||[],j=g.slice(h+1).find(function(a){return"P"===a.nodeName.toUpperCase()}),k=g.slice(0,h).reverse().find(function(a){return"P"===a.nodeName.toUpperCase()}),l=e(a),m=j?e(j):null,n=k?e(k):null;if(!m||!f(l,m,i))return!0;var o=axe.commons.dom.findUp(a,"blockquote");return!!(o&&"BLOCKQUOTE"===o.nodeName.toUpperCase()||n&&!f(l,n,i))&&void 0},options:{margins:[{weight:150,italic:!0},{weight:150,size:1.15},{italic:!0,size:1.15},{size:1.4}]}},{id:"region",evaluate:function(a,b){function c(a){return h&&axe.commons.dom.isFocusable(axe.commons.dom.getElementByReference(h,"href"))&&h===a}function d(a){var b=a.getAttribute("role");return b&&-1!==g.indexOf(b)}function e(a){return d(a)?null:c(a)?f(a):axe.commons.dom.isVisible(a,!0)&&(axe.commons.text.visible(a,!0,!0)||axe.commons.dom.isVisualContent(a))?a:f(a)}function f(a){var b=axe.commons.utils.toArray(a.children);return 0===b.length?[]:b.map(e).filter(function(a){return null!==a}).reduce(function(a,b){return a.concat(b)},[])}var g=axe.commons.aria.getRolesByType("landmark"),h=a.querySelector("a[href]"),i=f(a);return this.relatedNodes(i),!i.length},after:function(a,b){return[a[0]]}},{id:"skip-link",evaluate:function(a,b){return axe.commons.dom.isFocusable(axe.commons.dom.getElementByReference(a,"href"))},after:function(a,b){return[a[0]]}},{id:"unique-frame-title",evaluate:function(a,b){var c=axe.commons.text.sanitize(a.title).trim().toLowerCase();return this.data(c),!0},after:function(a,b){var c={};return a.forEach(function(a){c[a.data]=void 0!==c[a.data]?++c[a.data]:0}),a.forEach(function(a){a.result=!!c[a.data]}),a}},{id:"aria-label",evaluate:function(a,b){var c=a.getAttribute("aria-label");return!!(c?axe.commons.text.sanitize(c).trim():"")}},{id:"aria-labelledby",evaluate:function(a,b){return(0,axe.commons.dom.idrefs)(a,"aria-labelledby").some(function(a){return a&&axe.commons.text.accessibleText(a,!0)})}},{id:"button-has-visible-text",evaluate:function(a,b){var c=a.nodeName.toUpperCase(),d=a.getAttribute("role"),e=void 0;return("BUTTON"===c||"button"===d&&"INPUT"!==c)&&(e=axe.commons.text.accessibleText(a),this.data(e),!!e)}},{id:"doc-has-title",evaluate:function(a,b){var c=document.title;return!!(c?axe.commons.text.sanitize(c).trim():"")}},{id:"duplicate-id",evaluate:function(a,b){if(!a.id.trim())return!0;for(var c=document.querySelectorAll('[id="'+axe.commons.utils.escapeSelector(a.id)+'"]'),d=[],e=0;e<c.length;e++)c[e]!==a&&d.push(c[e]);return d.length&&this.relatedNodes(d),this.data(a.getAttribute("id")),c.length<=1},after:function(a,b){var c=[];return a.filter(function(a){return-1===c.indexOf(a.data)&&(c.push(a.data),!0)})}},{id:"exists",evaluate:function(a,b){return!0}},{id:"has-alt",evaluate:function(a,b){var c=a.nodeName.toLowerCase();return a.hasAttribute("alt")&&("img"===c||"input"===c||"area"===c)}},{id:"has-visible-text",evaluate:function(a,b){return axe.commons.text.accessibleText(a).length>0}},{id:"is-on-screen",evaluate:function(a,b){return axe.commons.dom.isVisible(a,!1)&&!axe.commons.dom.isOffscreen(a)}},{id:"non-empty-alt",evaluate:function(a,b){var c=a.getAttribute("alt");return!!(c?axe.commons.text.sanitize(c).trim():"")}},{id:"non-empty-if-present",evaluate:function(a,b){var c=a.nodeName.toUpperCase(),d=(a.getAttribute("type")||"").toLowerCase(),e=a.getAttribute("value");return this.data(e),"INPUT"===c&&-1!==["submit","reset"].indexOf(d)&&null===e}},{id:"non-empty-title",evaluate:function(a,b){var c=a.getAttribute("title");return!!(c?axe.commons.text.sanitize(c).trim():"")}},{id:"non-empty-value",evaluate:function(a,b){var c=a.getAttribute("value");return!!(c?axe.commons.text.sanitize(c).trim():"")}},{id:"role-none",evaluate:function(a,b){return"none"===a.getAttribute("role")}},{id:"role-presentation",evaluate:function(a,b){return"presentation"===a.getAttribute("role")}},{id:"caption-faked",evaluate:function(a,b){var c=axe.commons.table.toGrid(a),d=c[0];return c.length<=1||d.length<=1||a.rows.length<=1||d.reduce(function(a,b,c){return a||b!==d[c+1]&&void 0!==d[c+1]},!1)}},{id:"has-caption",evaluate:function(a,b){return!!a.caption}},{id:"has-summary",evaluate:function(a,b){
-return!!a.summary}},{id:"has-th",evaluate:function(a,b){for(var c,d,e=[],f=0,g=a.rows.length;f<g;f++){c=a.rows[f];for(var h=0,i=c.cells.length;h<i;h++)d=c.cells[h],"TH"!==d.nodeName.toUpperCase()&&-1===["rowheader","columnheader"].indexOf(d.getAttribute("role"))||e.push(d)}return!!e.length&&(this.relatedNodes(e),!0)}},{id:"html5-scope",evaluate:function(a,b){return!axe.commons.dom.isHTML5(document)||"TH"===a.nodeName.toUpperCase()}},{id:"same-caption-summary",evaluate:function(a,b){return!(!a.summary||!a.caption)&&a.summary===axe.commons.text.accessibleText(a.caption)}},{id:"scope-value",evaluate:function(a,b){b=b||{};var c=a.getAttribute("scope").toLowerCase();return-1!==(["row","col","rowgroup","colgroup"]||b.values).indexOf(c)}},{id:"td-has-header",evaluate:function(a,b){var c=axe.commons.table,d=[];return c.getAllCells(a).forEach(function(a){if(axe.commons.dom.hasContent(a)&&c.isDataCell(a)&&!axe.commons.aria.label(a)){var b=c.getHeaders(a);(b=b.reduce(function(a,b){return a||null!==b&&!!axe.commons.dom.hasContent(b)},!1))||d.push(a)}}),!d.length||(this.relatedNodes(d),!1)}},{id:"td-headers-attr",evaluate:function(a,b){for(var c=[],d=0,e=a.rows.length;d<e;d++)for(var f=a.rows[d],g=0,h=f.cells.length;g<h;g++)c.push(f.cells[g]);var i=c.reduce(function(a,b){return b.id&&a.push(b.id),a},[]),j=c.reduce(function(a,b){var c,d,e=(b.getAttribute("headers")||"").split(/\s/).reduce(function(a,b){return b=b.trim(),b&&a.push(b),a},[]);return 0!==e.length&&(b.id&&(c=-1!==e.indexOf(b.id.trim())),d=e.reduce(function(a,b){return a||-1===i.indexOf(b)},!1),(c||d)&&a.push(b)),a},[]);return!(j.length>0)||(this.relatedNodes(j),!1)}},{id:"th-has-data-cells",evaluate:function(a,b){var c=axe.commons.table,d=c.getAllCells(a),e=this,f=[];d.forEach(function(a){var b=a.getAttribute("headers");b&&(f=f.concat(b.split(/\s+/)));var c=a.getAttribute("aria-labelledby");c&&(f=f.concat(c.split(/\s+/)))});var g=d.filter(function(a){return""!==axe.commons.text.sanitize(a.textContent)&&("TH"===a.nodeName.toUpperCase()||-1!==["rowheader","columnheader"].indexOf(a.getAttribute("role")))}),h=c.toGrid(a);return!!g.reduce(function(a,b){if(b.id&&-1!==f.indexOf(b.id))return!!a||a;var d=!1,g=c.getCellPosition(b,h);return c.isColumnHeader(b)&&(d=c.traverse("down",g,h).reduce(function(a,b){return a||axe.commons.dom.hasContent(b)&&!c.isColumnHeader(b)},!1)),!d&&c.isRowHeader(b)&&(d=c.traverse("right",g,h).reduce(function(a,b){return a||axe.commons.dom.hasContent(b)&&!c.isRowHeader(b)},!1)),d||e.relatedNodes(b),a&&d},!0)||void 0}},{id:"hidden-content",evaluate:function(a,b){var c=window.getComputedStyle(a);if(!["SCRIPT","HEAD","TITLE","NOSCRIPT","STYLE","TEMPLATE"].includes(a.tagName.toUpperCase())&&axe.commons.dom.hasContent(a)){if("none"===c.getPropertyValue("display"))return;if("hidden"===c.getPropertyValue("visibility")){if(a.parentNode)var d=window.getComputedStyle(a.parentNode);if(!d||"hidden"!==d.getPropertyValue("visibility"))return}}return!0}}],commons:function(){function a(a){return a.getPropertyValue("font-family").split(/[,;]/g).map(function(a){return a.trim().toLowerCase()})}function b(b,c){var d=window.getComputedStyle(b);if("none"!==d.getPropertyValue("background-image"))return!0;if(["border-bottom","border-top","outline"].reduce(function(a,b){var c=new y.Color;return c.parseRgbString(d.getPropertyValue(b+"-color")),a||"none"!==d.getPropertyValue(b+"-style")&&parseFloat(d.getPropertyValue(b+"-width"))>0&&0!==c.alpha},!1))return!0;var e=window.getComputedStyle(c);if(a(d)[0]!==a(e)[0])return!0;var f=["text-decoration-line","text-decoration-style","font-weight","font-style","font-size"].reduce(function(a,b){return a||d.getPropertyValue(b)!==e.getPropertyValue(b)},!1),g=d.getPropertyValue("text-decoration");return g.split(" ").length<3&&(f=f||g!==e.getPropertyValue("text-decoration")),f}function c(a,b){var c=a.nodeName.toUpperCase();if(C.includes(c))return axe.commons.color.incompleteData.set("bgColor","imgNode"),!0;b=b||window.getComputedStyle(a);var d=b.getPropertyValue("background-image"),e="none"!==d;if(e){var f=/gradient/.test(d);axe.commons.color.incompleteData.set("bgColor",f?"bgGradient":"bgImage")}return e}function d(a,b){b=b||window.getComputedStyle(a);var c=new y.Color;if(c.parseRgbString(b.getPropertyValue("background-color")),0!==c.alpha){var d=b.getPropertyValue("opacity");c.alpha=c.alpha*d}return c}function e(a,b){var c=a.getClientRects()[0],d=document.elementsFromPoint(c.left,c.top);if(d)for(var e=0;e<d.length;e++)if(d[e]!==a&&d[e]===b)return!0;return!1}function f(a,b,c){var f=0;if(a>0)for(var g=a-1;g>=0;g--){var h=b[g],i=window.getComputedStyle(h),j=d(h,i);j.alpha&&e(c,h)?f+=j.alpha:b.splice(g,1)}return f}function g(a,b,c){var d=a!==b&&!z.visuallyContains(a,b)&&0!==c.alpha;return d&&axe.commons.color.incompleteData.set("bgColor","elmPartiallyObscured"),d}function h(a,b){var c={TD:"TR",INPUT:"LABEL"},d=a.map(function(a){return a.tagName}),e=a;for(var f in c)if(c.hasOwnProperty(f)){if(b.tagName===f){var g=axe.commons.dom.findUp(b,c[f]);if(g&&-1===a.indexOf(g)){var h=axe.commons.dom.visuallyOverlaps(b.getBoundingClientRect(),g);h&&e.splice(a.indexOf(b)+1,0,g)}}b.tagName===c[f]&&-1===d.indexOf(b.tagName)&&e.splice(d.indexOf(f)+1,0,b)}return e}function i(a){var b=a.indexOf(document.body),e=a;return b>1&&!c(document.documentElement)&&0===d(document.documentElement).alpha&&(e.splice(b,1),e.splice(a.indexOf(document.documentElement),1),e.push(document.body)),e}function j(a,b){"use strict";var c=b(a);for(a=a.firstChild;a;)!1!==c&&j(a,b),a=a.nextSibling}function k(a){"use strict";var b=window.getComputedStyle(a).getPropertyValue("display");return-1!==D.indexOf(b)||"table-"===b.substr(0,6)}function l(a){"use strict";var b=a.match(/rect\s*\(([0-9]+)px,?\s*([0-9]+)px,?\s*([0-9]+)px,?\s*([0-9]+)px\s*\)/);return!(!b||5!==b.length)&&(b[3]-b[1]<=0&&b[2]-b[4]<=0)}function m(a){var b=null;return a.id&&(b=document.querySelector('label[for="'+axe.utils.escapeSelector(a.id)+'"]'))?b:b=z.findUp(a,"label")}function n(a){return-1!==["button","reset","submit"].indexOf(a.type)}function o(a){var b=a.nodeName.toUpperCase();return"TEXTAREA"===b||"SELECT"===b||"INPUT"===b&&"hidden"!==a.type.toLowerCase()}function p(a){return-1!==["BUTTON","SUMMARY","A"].indexOf(a.nodeName.toUpperCase())}function q(a){return-1!==["TABLE","FIGURE"].indexOf(a.nodeName.toUpperCase())}function r(a){var b=a.nodeName.toUpperCase();if("INPUT"===b)return!a.hasAttribute("type")||-1!==G.indexOf(a.getAttribute("type").toLowerCase())&&a.value?a.value:"";if("SELECT"===b){var c=a.options;if(c&&c.length){for(var d="",e=0;e<c.length;e++)c[e].selected&&(d+=" "+c[e].text);return B.sanitize(d)}return""}return"TEXTAREA"===b&&a.value?a.value:""}function s(a,b){var c=a.querySelector(b.toLowerCase());return c?B.accessibleText(c):""}function t(a){if(!a)return!1;switch(a.nodeName.toUpperCase()){case"SELECT":case"TEXTAREA":return!0;case"INPUT":return!a.hasAttribute("type")||-1!==G.indexOf(a.getAttribute("type").toLowerCase());default:return!1}}function u(a){var b=a.nodeName.toUpperCase();return"INPUT"===b&&"image"===a.type.toLowerCase()||-1!==["IMG","APPLET","AREA"].indexOf(b)}function v(a){return!!B.sanitize(a)}var commons={},w=commons.aria={},x=w._lut={};x.attributes={"aria-activedescendant":{type:"idref"},"aria-atomic":{type:"boolean",values:["true","false"]},"aria-autocomplete":{type:"nmtoken",values:["inline","list","both","none"]},"aria-busy":{type:"boolean",values:["true","false"]},"aria-checked":{type:"nmtoken",values:["true","false","mixed","undefined"]},"aria-colcount":{type:"int"},"aria-colindex":{type:"int"},"aria-colspan":{type:"int"},"aria-controls":{type:"idrefs"},"aria-current":{type:"nmtoken",values:["page","step","location","date","time","true","false"]},"aria-describedby":{type:"idrefs"},"aria-disabled":{type:"boolean",values:["true","false"]},"aria-dropeffect":{type:"nmtokens",values:["copy","move","reference","execute","popup","none"]},"aria-expanded":{type:"nmtoken",values:["true","false","undefined"]},"aria-flowto":{type:"idrefs"},"aria-grabbed":{type:"nmtoken",values:["true","false","undefined"]},"aria-haspopup":{type:"boolean",values:["true","false"]},"aria-hidden":{type:"boolean",values:["true","false"]},"aria-invalid":{type:"nmtoken",values:["true","false","spelling","grammar"]},"aria-label":{type:"string"},"aria-labelledby":{type:"idrefs"},"aria-level":{type:"int"},"aria-live":{type:"nmtoken",values:["off","polite","assertive"]},"aria-multiline":{type:"boolean",values:["true","false"]},"aria-multiselectable":{type:"boolean",values:["true","false"]},"aria-orientation":{type:"nmtoken",values:["horizontal","vertical"]},"aria-owns":{type:"idrefs"},"aria-posinset":{type:"int"},"aria-pressed":{type:"nmtoken",values:["true","false","mixed","undefined"]},"aria-readonly":{type:"boolean",values:["true","false"]},"aria-relevant":{type:"nmtokens",values:["additions","removals","text","all"]},"aria-required":{type:"boolean",values:["true","false"]},"aria-rowcount":{type:"int"},"aria-rowindex":{type:"int"},"aria-rowspan":{type:"int"},"aria-selected":{type:"nmtoken",values:["true","false","undefined"]},"aria-setsize":{type:"int"},"aria-sort":{type:"nmtoken",values:["ascending","descending","other","none"]},"aria-valuemax":{type:"decimal"},"aria-valuemin":{type:"decimal"},"aria-valuenow":{type:"decimal"},"aria-valuetext":{type:"string"}},x.globalAttributes=["aria-atomic","aria-busy","aria-controls","aria-current","aria-describedby","aria-disabled","aria-dropeffect","aria-flowto","aria-grabbed","aria-haspopup","aria-hidden","aria-invalid","aria-label","aria-labelledby","aria-live","aria-owns","aria-relevant"],x.role={alert:{type:"widget",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null},alertdialog:{type:"widget",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null},application:{type:"landmark",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null},article:{type:"structure",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["article"]},banner:{type:"landmark",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["header"]},button:{type:"widget",attributes:{allowed:["aria-expanded","aria-pressed"]},owned:null,nameFrom:["author","contents"],context:null,implicit:["button",'input[type="button"]','input[type="image"]','input[type="reset"]','input[type="submit"]',"summary"]},cell:{type:"structure",attributes:{allowed:["aria-colindex","aria-colspan","aria-rowindex","aria-rowspan"]},owned:null,nameFrom:["author","contents"],context:["row"],implicit:["td","th"]},checkbox:{type:"widget",attributes:{required:["aria-checked"]},owned:null,nameFrom:["author","contents"],context:null,implicit:['input[type="checkbox"]']},columnheader:{type:"structure",attributes:{allowed:["aria-expanded","aria-sort","aria-readonly","aria-selected","aria-required"]},owned:null,nameFrom:["author","contents"],context:["row"],implicit:["th"]},combobox:{type:"composite",attributes:{required:["aria-expanded"],allowed:["aria-autocomplete","aria-required","aria-activedescendant"]},owned:{all:["listbox","textbox"]},nameFrom:["author"],context:null},command:{nameFrom:["author"],type:"abstract"},complementary:{type:"landmark",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["aside"]},composite:{nameFrom:["author"],type:"abstract"},contentinfo:{type:"landmark",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["footer"]},definition:{type:"structure",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["dd"]},dialog:{type:"widget",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["dialog"]},directory:{type:"structure",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author","contents"],context:null},document:{type:"structure",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["body"]},form:{type:"landmark",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["form"]},grid:{type:"composite",attributes:{allowed:["aria-level","aria-multiselectable","aria-readonly","aria-activedescendant","aria-expanded"]},owned:{one:["rowgroup","row"]},nameFrom:["author"],context:null,implicit:["table"]},gridcell:{type:"widget",attributes:{allowed:["aria-selected","aria-readonly","aria-expanded","aria-required"]},owned:null,nameFrom:["author","contents"],context:["row"],implicit:["td","th"]},group:{type:"structure",attributes:{allowed:["aria-activedescendant","aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["details","optgroup"]},heading:{type:"structure",attributes:{allowed:["aria-level","aria-expanded"]},owned:null,nameFrom:["author","contents"],context:null,implicit:["h1","h2","h3","h4","h5","h6"]},img:{type:"structure",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["img"]},input:{nameFrom:["author"],type:"abstract"},landmark:{nameFrom:["author"],type:"abstract"},link:{type:"widget",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author","contents"],context:null,implicit:["a[href]"]},list:{type:"structure",attributes:{allowed:["aria-expanded"]},owned:{all:["listitem"]},nameFrom:["author"],context:null,implicit:["ol","ul","dl"]},listbox:{type:"composite",attributes:{allowed:["aria-activedescendant","aria-multiselectable","aria-required","aria-expanded"]},owned:{all:["option"]},nameFrom:["author"],context:null,implicit:["select"]},listitem:{type:"structure",attributes:{allowed:["aria-level","aria-posinset","aria-setsize","aria-expanded"]},owned:null,nameFrom:["author","contents"],context:["list"],implicit:["li","dt"]},log:{type:"widget",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null},main:{type:"landmark",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["main"]},marquee:{type:"widget",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null},math:{type:"structure",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["math"]},menu:{type:"composite",attributes:{allowed:["aria-activedescendant","aria-expanded"]},owned:{one:["menuitem","menuitemradio","menuitemcheckbox"]},nameFrom:["author"],context:null,implicit:['menu[type="context"]']},menubar:{type:"composite",attributes:{allowed:["aria-activedescendant","aria-expanded"]},owned:null,nameFrom:["author"],context:null},menuitem:{type:"widget",attributes:null,owned:null,nameFrom:["author","contents"],context:["menu","menubar"],implicit:['menuitem[type="command"]']},menuitemcheckbox:{type:"widget",attributes:{required:["aria-checked"]},owned:null,nameFrom:["author","contents"],context:["menu","menubar"],implicit:['menuitem[type="checkbox"]']},menuitemradio:{type:"widget",attributes:{allowed:["aria-selected","aria-posinset","aria-setsize"],required:["aria-checked"]},owned:null,nameFrom:["author","contents"],context:["menu","menubar"],implicit:['menuitem[type="radio"]']},navigation:{type:"landmark",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["nav"]},none:{type:"structure",attributes:null,owned:null,nameFrom:["author"],context:null},note:{type:"structure",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null},option:{type:"widget",attributes:{allowed:["aria-selected","aria-posinset","aria-setsize","aria-checked"]},owned:null,nameFrom:["author","contents"],context:["listbox"],implicit:["option"]},presentation:{type:"structure",attributes:null,owned:null,nameFrom:["author"],context:null},progressbar:{type:"widget",attributes:{allowed:["aria-valuetext","aria-valuenow","aria-valuemax","aria-valuemin"]},owned:null,nameFrom:["author"],context:null,implicit:["progress"]},radio:{type:"widget",attributes:{allowed:["aria-selected","aria-posinset","aria-setsize"],required:["aria-checked"]},owned:null,nameFrom:["author","contents"],context:null,implicit:['input[type="radio"]']},radiogroup:{type:"composite",attributes:{allowed:["aria-activedescendant","aria-required","aria-expanded"]},owned:{all:["radio"]},nameFrom:["author"],context:null},range:{nameFrom:["author"],type:"abstract"},region:{type:"structure",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["section"]},roletype:{type:"abstract"},row:{type:"structure",attributes:{allowed:["aria-level","aria-selected","aria-activedescendant","aria-expanded"]},owned:{one:["cell","columnheader","rowheader","gridcell"]},nameFrom:["author","contents"],context:["rowgroup","grid","treegrid","table"],implicit:["tr"]},rowgroup:{type:"structure",attributes:{allowed:["aria-activedescendant","aria-expanded"]},owned:{all:["row"]},nameFrom:["author","contents"],context:["grid","table"],implicit:["tbody","thead","tfoot"]},rowheader:{type:"structure",attributes:{allowed:["aria-sort","aria-required","aria-readonly","aria-expanded","aria-selected"]},owned:null,nameFrom:["author","contents"],context:["row"],implicit:["th"]},scrollbar:{type:"widget",attributes:{required:["aria-controls","aria-orientation","aria-valuenow","aria-valuemax","aria-valuemin"],allowed:["aria-valuetext"]},owned:null,nameFrom:["author"],context:null},search:{type:"landmark",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null},searchbox:{type:"widget",attributes:{allowed:["aria-activedescendant","aria-autocomplete","aria-multiline","aria-readonly","aria-required"]},owned:null,nameFrom:["author"],context:null,implicit:['input[type="search"]']},section:{nameFrom:["author","contents"],type:"abstract"},sectionhead:{nameFrom:["author","contents"],type:"abstract"},select:{nameFrom:["author"],type:"abstract"},separator:{type:"structure",attributes:{allowed:["aria-expanded","aria-orientation"]},owned:null,nameFrom:["author"],context:null,implicit:["hr"]},slider:{type:"widget",attributes:{allowed:["aria-valuetext","aria-orientation"],required:["aria-valuenow","aria-valuemax","aria-valuemin"]},owned:null,nameFrom:["author"],context:null,implicit:['input[type="range"]']},spinbutton:{type:"widget",attributes:{allowed:["aria-valuetext","aria-required"],required:["aria-valuenow","aria-valuemax","aria-valuemin"]},owned:null,nameFrom:["author"],context:null,implicit:['input[type="number"]']},status:{type:"widget",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["output"]},structure:{type:"abstract"},switch:{type:"widget",attributes:{required:["aria-checked"]},owned:null,nameFrom:["author","contents"],context:null},tab:{type:"widget",attributes:{allowed:["aria-selected","aria-expanded"]},owned:null,nameFrom:["author","contents"],context:["tablist"]},table:{type:"structure",attributes:{allowed:["aria-colcount","aria-rowcount"]},owned:{one:["rowgroup","row"]},nameFrom:["author"],context:null,implicit:["table"]},tablist:{type:"composite",attributes:{allowed:["aria-activedescendant","aria-expanded","aria-level","aria-multiselectable"]},owned:{all:["tab"]},nameFrom:["author"],context:null},tabpanel:{type:"widget",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null},text:{type:"structure",owned:null,nameFrom:["author","contents"],context:null},textbox:{type:"widget",attributes:{allowed:["aria-activedescendant","aria-autocomplete","aria-multiline","aria-readonly","aria-required"]},owned:null,nameFrom:["author"],context:null,implicit:['input[type="text"]','input[type="email"]','input[type="password"]','input[type="tel"]','input[type="url"]',"input:not([type])","textarea"]},timer:{type:"widget",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null},toolbar:{type:"structure",attributes:{allowed:["aria-activedescendant","aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:['menu[type="toolbar"]']},tooltip:{type:"widget",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author","contents"],context:null},tree:{type:"composite",attributes:{allowed:["aria-activedescendant","aria-multiselectable","aria-required","aria-expanded"]},owned:{all:["treeitem"]},nameFrom:["author"],context:null},treegrid:{type:"composite",attributes:{allowed:["aria-activedescendant","aria-expanded","aria-level","aria-multiselectable","aria-readonly","aria-required"]},owned:{all:["treeitem"]},nameFrom:["author"],context:null},treeitem:{type:"widget",attributes:{allowed:["aria-checked","aria-selected","aria-expanded","aria-level","aria-posinset","aria-setsize"]},owned:null,nameFrom:["author","contents"],context:["treegrid","tree"]},widget:{type:"abstract"},window:{nameFrom:["author"],type:"abstract"}};var y={};commons.color=y;var z=commons.dom={},A=commons.table={},B=commons.text={};commons.utils=axe.utils;w.requiredAttr=function(a){"use strict";var b=x.role[a];return b&&b.attributes&&b.attributes.required||[]},w.allowedAttr=function(a){"use strict";var b=x.role[a],c=b&&b.attributes&&b.attributes.allowed||[],d=b&&b.attributes&&b.attributes.required||[];return c.concat(x.globalAttributes).concat(d)},w.validateAttr=function(a){"use strict";return!!x.attributes[a]},w.validateAttrValue=function(a,b){"use strict";var c,d,e=a.getAttribute(b),f=x.attributes[b],g=z.getRootNode(a);if(!f)return!0;switch(f.type){case"boolean":case"nmtoken":return"string"==typeof e&&-1!==f.values.indexOf(e.toLowerCase());case"nmtokens":return d=axe.utils.tokenList(e),d.reduce(function(a,b){return a&&-1!==f.values.indexOf(b)},0!==d.length);case"idref":return!(!e||!g.getElementById(e));case"idrefs":return d=axe.utils.tokenList(e),d.reduce(function(a,b){return!(!a||!g.getElementById(b))},0!==d.length);case"string":return!0;case"decimal":return!(!(c=e.match(/^[-+]?([0-9]*)\.?([0-9]*)$/))||!c[1]&&!c[2]);case"int":return/^[-+]?[0-9]+$/.test(e)}},w.label=function(a){var b,c;return a.actualNode.getAttribute("aria-labelledby")&&(b=z.idrefs(a.actualNode,"aria-labelledby"),c=b.map(function(a){var b=axe.utils.getNodeFromTree(axe._tree[0],a);return b?B.visible(b,!0):""}).join(" ").trim())?c:(c=a.actualNode.getAttribute("aria-label"),c&&(c=B.sanitize(c).trim())?c:null)},w.isValidRole=function(a){"use strict";return!!x.role[a]},w.getRolesWithNameFromContents=function(){return Object.keys(x.role).filter(function(a){return x.role[a].nameFrom&&-1!==x.role[a].nameFrom.indexOf("contents")})},w.getRolesByType=function(a){return Object.keys(x.role).filter(function(b){return x.role[b].type===a})},w.getRoleType=function(a){var b=x.role[a];return b&&b.type||null},w.requiredOwned=function(a){"use strict";var b=null,c=x.role[a];return c&&(b=axe.utils.clone(c.owned)),b},w.requiredContext=function(a){"use strict";var b=null,c=x.role[a];return c&&(b=axe.utils.clone(c.context)),b},w.implicitNodes=function(a){"use strict";var b=null,c=x.role[a];return c&&c.implicit&&(b=axe.utils.clone(c.implicit)),b},w.implicitRole=function(a){"use strict";var b=function(b,c){var d=function(b){return axe.utils.matchesSelector(a,b)};return c.implicit&&c.implicit.some(d)&&b.push(c.name),b},c=Object.keys(x.role).map(function(a){var b=x.role[a];return{name:a,implicit:b&&b.implicit}}),d=c.reduce(b,[]);if(!d.length)return null;for(var e=a.attributes,f=[],g=0,h=e.length;g<h;g++){var i=e[g];i.name.match(/^aria-/)&&f.push(i.name)}return function(a,b){var c=function(a){return w.allowedAttr(a).reduce(function(a,c){return a+(b.indexOf(c)>-1?1:0)},0)};return a.map(function(a){return{score:c(a),name:a}}).sort(function(a,b){return b.score-a.score}).map(function(a){return a.name})}(d,f).shift()},y.Color=function(a,b,c,d){this.red=a,this.green=b,this.blue=c,this.alpha=d,this.toHexString=function(){var a=Math.round(this.red).toString(16),b=Math.round(this.green).toString(16),c=Math.round(this.blue).toString(16);return"#"+(this.red>15.5?a:"0"+a)+(this.green>15.5?b:"0"+b)+(this.blue>15.5?c:"0"+c)};var e=/^rgb\((\d+), (\d+), (\d+)\)$/,f=/^rgba\((\d+), (\d+), (\d+), (\d*(\.\d+)?)\)/;this.parseRgbString=function(a){if("transparent"===a)return this.red=0,this.green=0,this.blue=0,void(this.alpha=0);var b=a.match(e);return b?(this.red=parseInt(b[1],10),this.green=parseInt(b[2],10),this.blue=parseInt(b[3],10),void(this.alpha=1)):(b=a.match(f),b?(this.red=parseInt(b[1],10),this.green=parseInt(b[2],10),this.blue=parseInt(b[3],10),void(this.alpha=parseFloat(b[4]))):void 0)},this.getRelativeLuminance=function(){var a=this.red/255,b=this.green/255,c=this.blue/255;return.2126*(a<=.03928?a/12.92:Math.pow((a+.055)/1.055,2.4))+.7152*(b<=.03928?b/12.92:Math.pow((b+.055)/1.055,2.4))+.0722*(c<=.03928?c/12.92:Math.pow((c+.055)/1.055,2.4))}},y.flattenColors=function(a,b){var c=a.alpha,d=(1-c)*b.red+c*a.red,e=(1-c)*b.green+c*a.green,f=(1-c)*b.blue+c*a.blue,g=a.alpha+b.alpha*(1-a.alpha);return new y.Color(d,e,f,g)},y.getContrast=function(a,b){if(!b||!a)return null;b.alpha<1&&(b=y.flattenColors(b,a));var c=a.getRelativeLuminance(),d=b.getRelativeLuminance();return(Math.max(d,c)+.05)/(Math.min(d,c)+.05)},y.hasValidContrastRatio=function(a,b,c,d){var e=y.getContrast(a,b),f=d&&Math.ceil(72*c)/96<14||!d&&Math.ceil(72*c)/96<18;return{isValid:f&&e>=4.5||!f&&e>=3,contrastRatio:e}},y.elementIsDistinct=b;var C=["IMG","CANVAS","OBJECT","IFRAME","VIDEO","SVG"];y.getBackgroundStack=function(a){var b=a.getBoundingClientRect(),c=void 0,d=void 0;if(!(b.left>window.innerWidth||b.top>window.innerHeight)){c=Math.min(Math.ceil(b.left+b.width/2),window.innerWidth-1),d=Math.min(Math.ceil(b.top+b.height/2),window.innerHeight-1);var e=document.elementsFromPoint(c,d);e=h(e,a),e=z.reduceToElementsBelowFloating(e,a),e=i(e);var g=e.indexOf(a);return f(g,e,a)>=.99?(axe.commons.color.incompleteData.set("bgColor","bgOverlap"),null):-1!==g?e:null}},y.getBackgroundColor=function(a){var b=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];!0!==(arguments.length>2&&void 0!==arguments[2]&&arguments[2])&&a.scrollIntoView();var e=[],f=y.getBackgroundStack(a);if((f||[]).some(function(f){var h=window.getComputedStyle(f),i=d(f,h);return g(a,f,i)||c(f,h)?(e=null,b.push(f),!0):0!==i.alpha&&(b.push(f),e.push(i),1===i.alpha)}),null!==e&&null!==f){e.push(new y.Color(255,255,255,1));return e.reduce(y.flattenColors)}return null},z.isOpaque=function(a){var b=window.getComputedStyle(a);return c(a,b)||1===d(a,b).alpha},y.getForegroundColor=function(a,b){var c=window.getComputedStyle(a),d=new y.Color;d.parseRgbString(c.getPropertyValue("color"));var e=c.getPropertyValue("opacity");if(d.alpha=d.alpha*e,1===d.alpha)return d;var f=y.getBackgroundColor(a,[],b);if(null===f){var g=axe.commons.color.incompleteData.get("bgColor");return axe.commons.color.incompleteData.set("fgColor",g),null}return y.flattenColors(d,f)},y.incompleteData=function(){var a={};return{set:function(b,c){if("string"!=typeof b)throw new Error("Incomplete data: key must be a string");return c&&(a[b]=c),a[b]},get:function(b){return a[b]},clear:function(){a={}}}}(),z.reduceToElementsBelowFloating=function(a,b){var c,d,e,f=["fixed","sticky"],g=[],h=!1;for(c=0;c<a.length;++c)d=a[c],d===b&&(h=!0),e=window.getComputedStyle(d),h||-1===f.indexOf(e.position)?g.push(d):g=[];return g},z.findUp=function(a,b){"use strict";var c,d,e=axe.commons.dom.getRootNode(a);if(d=e.querySelectorAll(b),d=axe.utils.toArray(d),e===document&&!d.length)return null;for(c=a.assignedSlot?a.assignedSlot:a.parentNode,11===c.nodeType&&(c=c.host);c&&-1===d.indexOf(c);)if((c=c.assignedSlot?c.assignedSlot:c.parentNode)&&11===c.nodeType&&(c=c.host,e=axe.commons.dom.getRootNode(c),d=e.querySelectorAll(b),d=axe.utils.toArray(d),e===document&&!d.length))return null;return c},z.getElementByReference=function(a,b){"use strict";var c,d=a.getAttribute(b),e=document;if(d&&"#"===d.charAt(0)){if(d=d.substring(1),c=e.getElementById(d))return c;if(c=e.getElementsByName(d),c.length)return c[0]}return null},z.getElementCoordinates=function(a){"use strict";var b=z.getScrollOffset(document),c=b.left,d=b.top,e=a.getBoundingClientRect();return{top:e.top+d,right:e.right+c,bottom:e.bottom+d,left:e.left+c,width:e.right-e.left,height:e.bottom-e.top}},z.getRootNode=function(a){var b=a.getRootNode&&a.getRootNode()||document;return b===a&&(b=document),b},z.getScrollOffset=function(a){"use strict";if(!a.nodeType&&a.document&&(a=a.document),9===a.nodeType){var b=a.documentElement,c=a.body;return{left:b&&b.scrollLeft||c&&c.scrollLeft||0,top:b&&b.scrollTop||c&&c.scrollTop||0}}return{left:a.scrollLeft,top:a.scrollTop}},z.getViewportSize=function(a){"use strict";var b,c=a.document,d=c.documentElement;return a.innerWidth?{width:a.innerWidth,height:a.innerHeight}:d?{width:d.clientWidth,height:d.clientHeight}:(b=c.body,{width:b.clientWidth,height:b.clientHeight})},z.hasContent=function(a){if(a.actualNode.textContent.trim()||w.label(a))return!0;for(var b=axe.utils.querySelectorAll(a,"*"),c=0;c<b.length;c++)if(w.label(b[c])||z.isVisualContent(b[c].actualNode))return!0;return!1},z.idrefs=function(a,b){"use strict";var c,d,e=z.getRootNode(a),f=[],g=a.getAttribute(b);if(g)for(g=axe.utils.tokenList(g),c=0,d=g.length;c<d;c++)f.push(e.getElementById(g[c]));return f},z.isFocusable=function(a){"use strict";if(!a||a.disabled||!z.isVisible(a)&&"AREA"!==a.nodeName.toUpperCase())return!1;switch(a.nodeName.toUpperCase()){case"A":case"AREA":if(a.href)return!0;break;case"INPUT":return"hidden"!==a.type;case"TEXTAREA":case"SELECT":case"DETAILS":case"BUTTON":return!0}var b=a.getAttribute("tabindex");return!(!b||isNaN(parseInt(b,10)))},z.isHTML5=function(a){var b=a.doctype;return null!==b&&("html"===b.name&&!b.publicId&&!b.systemId)};var D=["block","list-item","table","flex","grid","inline-block"];z.isInTextBlock=function(a){"use strict";if(k(a))return!1;for(var b=a.parentNode;1===b.nodeType&&!k(b);)b=b.parentNode;var c="",d="",e=0;return j(b,function(b){if(2===e)return!1;if(3===b.nodeType&&(c+=b.nodeValue),1===b.nodeType){var f=(b.nodeName||"").toUpperCase();if(-1!==["BR","HR"].indexOf(f))0===e?(c="",d=""):e=2;else{if("none"===b.style.display||"hidden"===b.style.overflow||-1===["",null,"none"].indexOf(b.style.float)||-1===["",null,"relative"].indexOf(b.style.position))return!1;if("A"===f&&b.href||"link"===(b.getAttribute("role")||"").toLowerCase())return b===a&&(e=1),d+=b.textContent,!1}}}),c=axe.commons.text.sanitize(c),d=axe.commons.text.sanitize(d),c.length>d.length},z.isNode=function(a){"use strict";return a instanceof Node},z.isOffscreen=function(a){"use strict";var b,c=document.documentElement,d=window.getComputedStyle(a),e=window.getComputedStyle(document.body||c).getPropertyValue("direction"),f=z.getElementCoordinates(a);if(f.bottom<0&&(function(a,b){for(a=a.parentNode;"html"!==a.nodeName.toLowerCase();){if(a.scrollTop&&(b+=a.scrollTop)>=0)return!1;a=a.parentNode}return!0}(a,f.bottom)||"absolute"===d.position))return!0;if(0===f.left&&0===f.right)return!1;if("ltr"===e){if(f.right<=0)return!0}else if(b=Math.max(c.scrollWidth,z.getViewportSize(window).width),f.left>=b)return!0;return!1},z.isVisible=function(a,b,c){"use strict";var d,e,f;return 9===a.nodeType||(11===a.nodeType&&(a=a.host),null!==(d=window.getComputedStyle(a,null))&&(e=a.nodeName.toUpperCase(),!("none"===d.getPropertyValue("display")||"STYLE"===e.toUpperCase()||"SCRIPT"===e.toUpperCase()||!b&&l(d.getPropertyValue("clip"))||!c&&("hidden"===d.getPropertyValue("visibility")||!b&&z.isOffscreen(a))||b&&"true"===a.getAttribute("aria-hidden"))&&(!!(f=a.assignedSlot?a.assignedSlot:a.parentNode)&&z.isVisible(f,b,!0))))};var E=["checkbox","img","radio","range","slider","spinbutton","textbox"];z.isVisualContent=function(a){var b=a.getAttribute("role");if(b)return-1!==E.indexOf(b);switch(a.tagName.toUpperCase()){case"IMG":case"IFRAME":case"OBJECT":case"VIDEO":case"AUDIO":case"CANVAS":case"SVG":case"MATH":case"BUTTON":case"SELECT":case"TEXTAREA":case"KEYGEN":case"PROGRESS":case"METER":return!0;case"INPUT":return"hidden"!==a.type;default:return!1}},
-z.visuallyContains=function(a,b){var c=a.getBoundingClientRect(),d={top:c.top+.01,bottom:c.bottom-.01,left:c.left+.01,right:c.right-.01},e=b.getBoundingClientRect(),f=e.top,g=e.left,h={top:f-b.scrollTop,bottom:f-b.scrollTop+b.scrollHeight,left:g-b.scrollLeft,right:g-b.scrollLeft+b.scrollWidth},i=window.getComputedStyle(b);return"inline"===i.getPropertyValue("display")||!(d.left<h.left&&d.left<e.left||d.top<h.top&&d.top<e.top||d.right>h.right&&d.right>e.right||d.bottom>h.bottom&&d.bottom>e.bottom)&&(!(d.right>e.right||d.bottom>e.bottom)||("scroll"===i.overflow||"auto"===i.overflow||"hidden"===i.overflow||b instanceof HTMLBodyElement||b instanceof HTMLHtmlElement))},z.visuallyOverlaps=function(a,b){var c=b.getBoundingClientRect(),d=c.top,e=c.left,f={top:d-b.scrollTop,bottom:d-b.scrollTop+b.scrollHeight,left:e-b.scrollLeft,right:e-b.scrollLeft+b.scrollWidth};if(a.left>f.right&&a.left>c.right||a.top>f.bottom&&a.top>c.bottom||a.right<f.left&&a.right<c.left||a.bottom<f.top&&a.bottom<c.top)return!1;var g=window.getComputedStyle(b);return!(a.left>c.right||a.top>c.bottom)||("scroll"===g.overflow||"auto"===g.overflow||b instanceof HTMLBodyElement||b instanceof HTMLHtmlElement)},A.getAllCells=function(a){var b,c,d,e,f=[];for(b=0,d=a.rows.length;b<d;b++)for(c=0,e=a.rows[b].cells.length;c<e;c++)f.push(a.rows[b].cells[c]);return f},A.getCellPosition=function(a,b){var c,d;for(b||(b=A.toGrid(z.findUp(a,"table"))),c=0;c<b.length;c++)if(b[c]&&-1!==(d=b[c].indexOf(a)))return{x:d,y:c}},A.getHeaders=function(a){if(a.hasAttribute("headers"))return commons.dom.idrefs(a,"headers");var b=commons.table.toGrid(commons.dom.findUp(a,"table")),c=commons.table.getCellPosition(a,b);return[].concat(A.traverse("left",c,b).filter(function(a){return A.isRowHeader(a)}),A.traverse("up",c,b).filter(function(a){return A.isColumnHeader(a)})).reverse()},A.getScope=function(a){var b=a.getAttribute("scope"),c=a.getAttribute("role");if(a instanceof Element==!1||-1===["TD","TH"].indexOf(a.nodeName.toUpperCase()))throw new TypeError("Expected TD or TH element");if("columnheader"===c)return"col";if("rowheader"===c)return"row";if("col"===b||"row"===b)return b;if("TH"!==a.nodeName.toUpperCase())return!1;var d=A.toGrid(z.findUp(a,"table")),e=A.getCellPosition(a);return d[e.y].reduce(function(a,b){return a&&"TH"===b.nodeName.toUpperCase()},!0)?"col":d.map(function(a){return a[e.x]}).reduce(function(a,b){return a&&"TH"===b.nodeName.toUpperCase()},!0)?"row":"auto"},A.isColumnHeader=function(a){return-1!==["col","auto"].indexOf(A.getScope(a))},A.isDataCell=function(a){return!(!a.children.length&&!a.textContent.trim())&&"TD"===a.nodeName.toUpperCase()},A.isDataTable=function(a){var b=a.getAttribute("role");if(("presentation"===b||"none"===b)&&!z.isFocusable(a))return!1;if("true"===a.getAttribute("contenteditable")||z.findUp(a,'[contenteditable="true"]'))return!0;if("grid"===b||"treegrid"===b||"table"===b)return!0;if("landmark"===commons.aria.getRoleType(b))return!0;if("0"===a.getAttribute("datatable"))return!1;if(a.getAttribute("summary"))return!0;if(a.tHead||a.tFoot||a.caption)return!0;for(var c=0,d=a.children.length;c<d;c++)if("COLGROUP"===a.children[c].nodeName.toUpperCase())return!0;for(var e,f,g=0,h=a.rows.length,i=!1,j=0;j<h;j++){e=a.rows[j];for(var k=0,l=e.cells.length;k<l;k++){if(f=e.cells[k],"TH"===f.nodeName.toUpperCase())return!0;if(i||f.offsetWidth===f.clientWidth&&f.offsetHeight===f.clientHeight||(i=!0),f.getAttribute("scope")||f.getAttribute("headers")||f.getAttribute("abbr"))return!0;if(-1!==["columnheader","rowheader"].indexOf(f.getAttribute("role")))return!0;if(1===f.children.length&&"ABBR"===f.children[0].nodeName.toUpperCase())return!0;g++}}if(a.getElementsByTagName("table").length)return!1;if(h<2)return!1;var m=a.rows[Math.ceil(h/2)];if(1===m.cells.length&&1===m.cells[0].colSpan)return!1;if(m.cells.length>=5)return!0;if(i)return!0;var n,o;for(j=0;j<h;j++){if(e=a.rows[j],n&&n!==window.getComputedStyle(e).getPropertyValue("background-color"))return!0;if(n=window.getComputedStyle(e).getPropertyValue("background-color"),o&&o!==window.getComputedStyle(e).getPropertyValue("background-image"))return!0;o=window.getComputedStyle(e).getPropertyValue("background-image")}return h>=20||!(z.getElementCoordinates(a).width>.95*z.getViewportSize(window).width)&&(!(g<10)&&!a.querySelector("object, embed, iframe, applet"))},A.isHeader=function(a){return!(!A.isColumnHeader(a)&&!A.isRowHeader(a))||!!a.id&&!!document.querySelector('[headers~="'+axe.utils.escapeSelector(a.id)+'"]')},A.isRowHeader=function(a){return-1!==["row","auto"].indexOf(A.getScope(a))},A.toGrid=function(a){for(var b=[],c=a.rows,d=0,e=c.length;d<e;d++){var f=c[d].cells;b[d]=b[d]||[];for(var g=0,h=0,i=f.length;h<i;h++)for(var j=0;j<f[h].colSpan;j++){for(var k=0;k<f[h].rowSpan;k++){for(b[d+k]=b[d+k]||[];b[d+k][g];)g++;b[d+k][g]=f[h]}g++}}return b},A.toArray=A.toGrid,function(a){var b=function a(b,c,d,e){var f,g=d[c.y]?d[c.y][c.x]:void 0;return g?"function"==typeof e&&!0===(f=e(g,c,d))?[g]:(f=a(b,{x:c.x+b.x,y:c.y+b.y},d,e),f.unshift(g),f):[]};a.traverse=function(a,c,d,e){if(Array.isArray(c)&&(e=d,d=c,c={x:0,y:0}),"string"==typeof a)switch(a){case"left":a={x:-1,y:0};break;case"up":a={x:0,y:-1};break;case"right":a={x:1,y:0};break;case"down":a={x:0,y:1}}return b(a,{x:c.x+a.x,y:c.y+a.y},d,e)}}(A);var F={submit:"Submit",reset:"Reset"},G=["text","search","tel","url","email","date","time","number","range","color"],H=["A","EM","STRONG","SMALL","MARK","ABBR","DFN","I","B","S","U","CODE","VAR","SAMP","KBD","SUP","SUB","Q","CITE","SPAN","BDO","BDI","BR","WBR","INS","DEL","IMG","EMBED","OBJECT","IFRAME","MAP","AREA","SCRIPT","NOSCRIPT","RUBY","VIDEO","AUDIO","INPUT","TEXTAREA","SELECT","BUTTON","LABEL","OUTPUT","DATALIST","KEYGEN","PROGRESS","COMMAND","CANVAS","TIME","METER"];B.accessibleText=function(a,b){function c(a,b,c){for(var d,e=a.childNodes,g="",h=0;h<e.length;h++)d=e[h],3===d.nodeType?g+=d.textContent:1===d.nodeType&&(-1===H.indexOf(d.nodeName.toUpperCase())&&(g+=" "),g+=f(e[h],b,c));return g}function d(a,b,d){var e="",g=a.nodeName.toUpperCase();if(p(a)&&(e=c(a,!1,!1)||"",v(e)))return e;if("FIGURE"===g&&(e=s(a,"figcaption"),v(e)))return e;if("TABLE"===g){if(e=s(a,"caption"),v(e))return e;if(e=a.getAttribute("title")||a.getAttribute("summary")||"",v(e))return e}if(u(a))return a.getAttribute("alt")||"";if(o(a)&&!d){if(n(a))return a.value||a.title||F[a.type]||"";var h=m(a);if(h)return f(h,b,!0)}return""}function e(a,b,c){return!b&&a.hasAttribute("aria-labelledby")?B.sanitize(z.idrefs(a,"aria-labelledby").map(function(b){return a===b&&g.pop(),f(b,!0,a!==b)}).join(" ")):c&&t(a)||!a.hasAttribute("aria-label")?"":B.sanitize(a.getAttribute("aria-label"))}var f,g=[];return f=function(a,b,f){"use strict";var h;if(null===a||-1!==g.indexOf(a))return"";if(!b&&!z.isVisible(a,!0))return"";g.push(a);var i=a.getAttribute("role");return h=e(a,b,f),v(h)?h:(h=d(a,b,f),v(h)?h:f&&(h=r(a),v(h))?h:q(a)||i&&-1===w.getRolesWithNameFromContents().indexOf(i)||(h=c(a,b,f),!v(h))?a.hasAttribute("title")?a.getAttribute("title"):"":h)},B.sanitize(f(a,b))},B.label=function(a){var b,c,d;return(c=w.label(a))?c:a.actualNode.id&&(d=axe.commons.dom.getRootNode(a.actualNode),b=d.querySelector('label[for="'+axe.utils.escapeSelector(a.actualNode.id)+'"]'),b=axe.utils.getNodeFromTree(axe._tree[0],b),c=b&&B.visible(b,!0))?c:(b=z.findUp(a.actualNode,"label"),b=axe.utils.getNodeFromTree(axe._tree[0],b),(c=b&&B.visible(b,!0))||null)},B.sanitize=function(a){"use strict";return a.replace(/\r\n/g,"\n").replace(/\u00A0/g," ").replace(/[\s]{2,}/g," ").trim()},B.visible=function(a,b,c){"use strict";var d,e,f,g=a.children,h=g.length,i="";for(d=0;d<h;d++)e=g[d],3===e.actualNode.nodeType?(f=e.actualNode.nodeValue)&&z.isVisible(a.actualNode,b)&&(i+=f):c||(i+=B.visible(e,b));return B.sanitize(i)},axe.utils.toArray=function(a){"use strict";return Array.prototype.slice.call(a)},axe.utils.tokenList=function(a){"use strict";return a.trim().replace(/\s{2,}/g," ").split(" ")}
-;var I=["aa","ab","ae","af","ak","am","an","ar","as","av","ay","az","ba","be","bg","bh","bi","bm","bn","bo","br","bs","ca","ce","ch","co","cr","cs","cu","cv","cy","da","de","dv","dz","ee","el","en","eo","es","et","eu","fa","ff","fi","fj","fo","fr","fy","ga","gd","gl","gn","gu","gv","ha","he","hi","ho","hr","ht","hu","hy","hz","ia","id","ie","ig","ii","ik","in","io","is","it","iu","iw","ja","ji","jv","jw","ka","kg","ki","kj","kk","kl","km","kn","ko","kr","ks","ku","kv","kw","ky","la","lb","lg","li","ln","lo","lt","lu","lv","mg","mh","mi","mk","ml","mn","mo","mr","ms","mt","my","na","nb","nd","ne","ng","nl","nn","no","nr","nv","ny","oc","oj","om","or","os","pa","pi","pl","ps","pt","qu","rm","rn","ro","ru","rw","sa","sc","sd","se","sg","sh","si","sk","sl","sm","sn","so","sq","sr","ss","st","su","sv","sw","ta","te","tg","th","ti","tk","tl","tn","to","tr","ts","tt","tw","ty","ug","uk","ur","uz","ve","vi","vo","wa","wo","xh","yi","yo","za","zh","zu","aaa","aab","aac","aad","aae","aaf","aag","aah","aai","aak","aal","aam","aan","aao","aap","aaq","aas","aat","aau","aav","aaw","aax","aaz","aba","abb","abc","abd","abe","abf","abg","abh","abi","abj","abl","abm","abn","abo","abp","abq","abr","abs","abt","abu","abv","abw","abx","aby","abz","aca","acb","acd","ace","acf","ach","aci","ack","acl","acm","acn","acp","acq","acr","acs","act","acu","acv","acw","acx","acy","acz","ada","adb","add","ade","adf","adg","adh","adi","adj","adl","adn","ado","adp","adq","adr","ads","adt","adu","adw","adx","ady","adz","aea","aeb","aec","aed","aee","aek","ael","aem","aen","aeq","aer","aes","aeu","aew","aey","aez","afa","afb","afd","afe","afg","afh","afi","afk","afn","afo","afp","afs","aft","afu","afz","aga","agb","agc","agd","age","agf","agg","agh","agi","agj","agk","agl","agm","agn","ago","agp","agq","agr","ags","agt","agu","agv","agw","agx","agy","agz","aha","ahb","ahg","ahh","ahi","ahk","ahl","ahm","ahn","aho","ahp","ahr","ahs","aht","aia","aib","aic","aid","aie","aif","aig","aih","aii","aij","aik","ail","aim","ain","aio","aip","aiq","air","ais","ait","aiw","aix","aiy","aja","ajg","aji","ajn","ajp","ajt","aju","ajw","ajz","akb","akc","akd","ake","akf","akg","akh","aki","akj","akk","akl","akm","ako","akp","akq","akr","aks","akt","aku","akv","akw","akx","aky","akz","ala","alc","ald","ale","alf","alg","alh","ali","alj","alk","all","alm","aln","alo","alp","alq","alr","als","alt","alu","alv","alw","alx","aly","alz","ama","amb","amc","ame","amf","amg","ami","amj","amk","aml","amm","amn","amo","amp","amq","amr","ams","amt","amu","amv","amw","amx","amy","amz","ana","anb","anc","and","ane","anf","ang","anh","ani","anj","ank","anl","anm","ann","ano","anp","anq","anr","ans","ant","anu","anv","anw","anx","any","anz","aoa","aob","aoc","aod","aoe","aof","aog","aoh","aoi","aoj","aok","aol","aom","aon","aor","aos","aot","aou","aox","aoz","apa","apb","apc","apd","ape","apf","apg","aph","api","apj","apk","apl","apm","apn","apo","app","apq","apr","aps","apt","apu","apv","apw","apx","apy","apz","aqa","aqc","aqd","aqg","aql","aqm","aqn","aqp","aqr","aqt","aqz","arb","arc","ard","are","arh","ari","arj","ark","arl","arn","aro","arp","arq","arr","ars","art","aru","arv","arw","arx","ary","arz","asa","asb","asc","asd","ase","asf","asg","ash","asi","asj","ask","asl","asn","aso","asp","asq","asr","ass","ast","asu","asv","asw","asx","asy","asz","ata","atb","atc","atd","ate","atg","ath","ati","atj","atk","atl","atm","atn","ato","atp","atq","atr","ats","att","atu","atv","atw","atx","aty","atz","aua","aub","auc","aud","aue","auf","aug","auh","aui","auj","auk","aul","aum","aun","auo","aup","auq","aur","aus","aut","auu","auw","aux","auy","auz","avb","avd","avi","avk","avl","avm","avn","avo","avs","avt","avu","avv","awa","awb","awc","awd","awe","awg","awh","awi","awk","awm","awn","awo","awr","aws","awt","awu","awv","aww","awx","awy","axb","axe","axg","axk","axl","axm","axx","aya","ayb","ayc","ayd","aye","ayg","ayh","ayi","ayk","ayl","ayn","ayo","ayp","ayq","ayr","ays","ayt","ayu","ayx","ayy","ayz","aza","azb","azc","azd","azg","azj","azm","azn","azo","azt","azz","baa","bab","bac","bad","bae","baf","bag","bah","bai","baj","bal","ban","bao","bap","bar","bas","bat","bau","bav","baw","bax","bay","baz","bba","bbb","bbc","bbd","bbe","bbf","bbg","bbh","bbi","bbj","bbk","bbl","bbm","bbn","bbo","bbp","bbq","bbr","bbs","bbt","bbu","bbv","bbw","bbx","bby","bbz","bca","bcb","bcc","bcd","bce","bcf","bcg","bch","bci","bcj","bck","bcl","bcm","bcn","bco","bcp","bcq","bcr","bcs","bct","bcu","bcv","bcw","bcy","bcz","bda","bdb","bdc","bdd","bde","bdf","bdg","bdh","bdi","bdj","bdk","bdl","bdm","bdn","bdo","bdp","bdq","bdr","bds","bdt","bdu","bdv","bdw","bdx","bdy","bdz","bea","beb","bec","bed","bee","bef","beg","beh","bei","bej","bek","bem","beo","bep","beq","ber","bes","bet","beu","bev","bew","bex","bey","bez","bfa","bfb","bfc","bfd","bfe","bff","bfg","bfh","bfi","bfj","bfk","bfl","bfm","bfn","bfo","bfp","bfq","bfr","bfs","bft","bfu","bfw","bfx","bfy","bfz","bga","bgb","bgc","bgd","bge","bgf","bgg","bgi","bgj","bgk","bgl","bgm","bgn","bgo","bgp","bgq","bgr","bgs","bgt","bgu","bgv","bgw","bgx","bgy","bgz","bha","bhb","bhc","bhd","bhe","bhf","bhg","bhh","bhi","bhj","bhk","bhl","bhm","bhn","bho","bhp","bhq","bhr","bhs","bht","bhu","bhv","bhw","bhx","bhy","bhz","bia","bib","bic","bid","bie","bif","big","bij","bik","bil","bim","bin","bio","bip","biq","bir","bit","biu","biv","biw","bix","biy","biz","bja","bjb","bjc","bjd","bje","bjf","bjg","bjh","bji","bjj","bjk","bjl","bjm","bjn","bjo","bjp","bjq","bjr","bjs","bjt","bju","bjv","bjw","bjx","bjy","bjz","bka","bkb","bkc","bkd","bkf","bkg","bkh","bki","bkj","bkk","bkl","bkm","bkn","bko","bkp","bkq","bkr","bks","bkt","bku","bkv","bkw","bkx","bky","bkz","bla","blb","blc","bld","ble","blf","blg","blh","bli","blj","blk","bll","blm","bln","blo","blp","blq","blr","bls","blt","blv","blw","blx","bly","blz","bma","bmb","bmc","bmd","bme","bmf","bmg","bmh","bmi","bmj","bmk","bml","bmm","bmn","bmo","bmp","bmq","bmr","bms","bmt","bmu","bmv","bmw","bmx","bmy","bmz","bna","bnb","bnc","bnd","bne","bnf","bng","bni","bnj","bnk","bnl","bnm","bnn","bno","bnp","bnq","bnr","bns","bnt","bnu","bnv","bnw","bnx","bny","bnz","boa","bob","boe","bof","bog","boh","boi","boj","bok","bol","bom","bon","boo","bop","boq","bor","bot","bou","bov","bow","box","boy","boz","bpa","bpb","bpd","bpg","bph","bpi","bpj","bpk","bpl","bpm","bpn","bpo","bpp","bpq","bpr","bps","bpt","bpu","bpv","bpw","bpx","bpy","bpz","bqa","bqb","bqc","bqd","bqf","bqg","bqh","bqi","bqj","bqk","bql","bqm","bqn","bqo","bqp","bqq","bqr","bqs","bqt","bqu","bqv","bqw","bqx","bqy","bqz","bra","brb","brc","brd","brf","brg","brh","bri","brj","brk","brl","brm","brn","bro","brp","brq","brr","brs","brt","bru","brv","brw","brx","bry","brz","bsa","bsb","bsc","bse","bsf","bsg","bsh","bsi","bsj","bsk","bsl","bsm","bsn","bso","bsp","bsq","bsr","bss","bst","bsu","bsv","bsw","bsx","bsy","bta","btb","btc","btd","bte","btf","btg","bth","bti","btj","btk","btl","btm","btn","bto","btp","btq","btr","bts","btt","btu","btv","btw","btx","bty","btz","bua","bub","buc","bud","bue","buf","bug","buh","bui","buj","buk","bum","bun","buo","bup","buq","bus","but","buu","buv","buw","bux","buy","buz","bva","bvb","bvc","bvd","bve","bvf","bvg","bvh","bvi","bvj","bvk","bvl","bvm","bvn","bvo","bvp","bvq","bvr","bvt","bvu","bvv","bvw","bvx","bvy","bvz","bwa","bwb","bwc","bwd","bwe","bwf","bwg","bwh","bwi","bwj","bwk","bwl","bwm","bwn","bwo","bwp","bwq","bwr","bws","bwt","bwu","bww","bwx","bwy","bwz","bxa","bxb","bxc","bxd","bxe","bxf","bxg","bxh","bxi","bxj","bxk","bxl","bxm","bxn","bxo","bxp","bxq","bxr","bxs","bxu","bxv","bxw","bxx","bxz","bya","byb","byc","byd","bye","byf","byg","byh","byi","byj","byk","byl","bym","byn","byo","byp","byq","byr","bys","byt","byv","byw","byx","byy","byz","bza","bzb","bzc","bzd","bze","bzf","bzg","bzh","bzi","bzj","bzk","bzl","bzm","bzn","bzo","bzp","bzq","bzr","bzs","bzt","bzu","bzv","bzw","bzx","bzy","bzz","caa","cab","cac","cad","cae","caf","cag","cah","cai","caj","cak","cal","cam","can","cao","cap","caq","car","cas","cau","cav","caw","cax","cay","caz","cba","cbb","cbc","cbd","cbe","cbg","cbh","cbi","cbj","cbk","cbl","cbn","cbo","cbq","cbr","cbs","cbt","cbu","cbv","cbw","cby","cca","ccc","ccd","cce","ccg","cch","ccj","ccl","ccm","ccn","cco","ccp","ccq","ccr","ccs","cda","cdc","cdd","cde","cdf","cdg","cdh","cdi","cdj","cdm","cdn","cdo","cdr","cds","cdy","cdz","cea","ceb","ceg","cek","cel","cen","cet","cfa","cfd","cfg","cfm","cga","cgc","cgg","cgk","chb","chc","chd","chf","chg","chh","chj","chk","chl","chm","chn","cho","chp","chq","chr","cht","chw","chx","chy","chz","cia","cib","cic","cid","cie","cih","cik","cim","cin","cip","cir","ciw","ciy","cja","cje","cjh","cji","cjk","cjm","cjn","cjo","cjp","cjr","cjs","cjv","cjy","cka","ckb","ckh","ckl","ckn","cko","ckq","ckr","cks","ckt","cku","ckv","ckx","cky","ckz","cla","clc","cld","cle","clh","cli","clj","clk","cll","clm","clo","clt","clu","clw","cly","cma","cmc","cme","cmg","cmi","cmk","cml","cmm","cmn","cmo","cmr","cms","cmt","cna","cnb","cnc","cng","cnh","cni","cnk","cnl","cno","cns","cnt","cnu","cnw","cnx","coa","cob","coc","cod","coe","cof","cog","coh","coj","cok","col","com","con","coo","cop","coq","cot","cou","cov","cow","cox","coy","coz","cpa","cpb","cpc","cpe","cpf","cpg","cpi","cpn","cpo","cpp","cps","cpu","cpx","cpy","cqd","cqu","cra","crb","crc","crd","crf","crg","crh","cri","crj","crk","crl","crm","crn","cro","crp","crq","crr","crs","crt","crv","crw","crx","cry","crz","csa","csb","csc","csd","cse","csf","csg","csh","csi","csj","csk","csl","csm","csn","cso","csq","csr","css","cst","csu","csv","csw","csy","csz","cta","ctc","ctd","cte","ctg","cth","ctl","ctm","ctn","cto","ctp","cts","ctt","ctu","ctz","cua","cub","cuc","cug","cuh","cui","cuj","cuk","cul","cum","cuo","cup","cuq","cur","cus","cut","cuu","cuv","cuw","cux","cvg","cvn","cwa","cwb","cwd","cwe","cwg","cwt","cya","cyb","cyo","czh","czk","czn","czo","czt","daa","dac","dad","dae","daf","dag","dah","dai","daj","dak","dal","dam","dao","dap","daq","dar","das","dau","dav","daw","dax","day","daz","dba","dbb","dbd","dbe","dbf","dbg","dbi","dbj","dbl","dbm","dbn","dbo","dbp","dbq","dbr","dbt","dbu","dbv","dbw","dby","dcc","dcr","dda","ddd","dde","ddg","ddi","ddj","ddn","ddo","ddr","dds","ddw","dec","ded","dee","def","deg","deh","dei","dek","del","dem","den","dep","deq","der","des","dev","dez","dga","dgb","dgc","dgd","dge","dgg","dgh","dgi","dgk","dgl","dgn","dgo","dgr","dgs","dgt","dgu","dgw","dgx","dgz","dha","dhd","dhg","dhi","dhl","dhm","dhn","dho","dhr","dhs","dhu","dhv","dhw","dhx","dia","dib","dic","did","dif","dig","dih","dii","dij","dik","dil","dim","din","dio","dip","diq","dir","dis","dit","diu","diw","dix","diy","diz","dja","djb","djc","djd","dje","djf","dji","djj","djk","djl","djm","djn","djo","djr","dju","djw","dka","dkk","dkl","dkr","dks","dkx","dlg","dlk","dlm","dln","dma","dmb","dmc","dmd","dme","dmg","dmk","dml","dmm","dmn","dmo","dmr","dms","dmu","dmv","dmw","dmx","dmy","dna","dnd","dne","dng","dni","dnj","dnk","dnn","dnr","dnt","dnu","dnv","dnw","dny","doa","dob","doc","doe","dof","doh","doi","dok","dol","don","doo","dop","doq","dor","dos","dot","dov","dow","dox","doy","doz","dpp","dra","drb","drc","drd","dre","drg","drh","dri","drl","drn","dro","drq","drr","drs","drt","dru","drw","dry","dsb","dse","dsh","dsi","dsl","dsn","dso","dsq","dta","dtb","dtd","dth","dti","dtk","dtm","dtn","dto","dtp","dtr","dts","dtt","dtu","dty","dua","dub","duc","dud","due","duf","dug","duh","dui","duj","duk","dul","dum","dun","duo","dup","duq","dur","dus","duu","duv","duw","dux","duy","duz","dva","dwa","dwl","dwr","dws","dwu","dww","dwy","dya","dyb","dyd","dyg","dyi","dym","dyn","dyo","dyu","dyy","dza","dzd","dze","dzg","dzl","dzn","eaa","ebg","ebk","ebo","ebr","ebu","ecr","ecs","ecy","eee","efa","efe","efi","ega","egl","ego","egx","egy","ehu","eip","eit","eiv","eja","eka","ekc","eke","ekg","eki","ekk","ekl","ekm","eko","ekp","ekr","eky","ele","elh","eli","elk","elm","elo","elp","elu","elx","ema","emb","eme","emg","emi","emk","emm","emn","emo","emp","ems","emu","emw","emx","emy","ena","enb","enc","end","enf","enh","enl","enm","enn","eno","enq","enr","enu","env","enw","enx","eot","epi","era","erg","erh","eri","erk","ero","err","ers","ert","erw","ese","esg","esh","esi","esk","esl","esm","esn","eso","esq","ess","esu","esx","esy","etb","etc","eth","etn","eto","etr","ets","ett","etu","etx","etz","euq","eve","evh","evn","ewo","ext","eya","eyo","eza","eze","faa","fab","fad","faf","fag","fah","fai","faj","fak","fal","fam","fan","fap","far","fat","fau","fax","fay","faz","fbl","fcs","fer","ffi","ffm","fgr","fia","fie","fil","fip","fir","fit","fiu","fiw","fkk","fkv","fla","flh","fli","fll","fln","flr","fly","fmp","fmu","fnb","fng","fni","fod","foi","fom","fon","for","fos","fox","fpe","fqs","frc","frd","frk","frm","fro","frp","frq","frr","frs","frt","fse","fsl","fss","fub","fuc","fud","fue","fuf","fuh","fui","fuj","fum","fun","fuq","fur","fut","fuu","fuv","fuy","fvr","fwa","fwe","gaa","gab","gac","gad","gae","gaf","gag","gah","gai","gaj","gak","gal","gam","gan","gao","gap","gaq","gar","gas","gat","gau","gav","gaw","gax","gay","gaz","gba","gbb","gbc","gbd","gbe","gbf","gbg","gbh","gbi","gbj","gbk","gbl","gbm","gbn","gbo","gbp","gbq","gbr","gbs","gbu","gbv","gbw","gbx","gby","gbz","gcc","gcd","gce","gcf","gcl","gcn","gcr","gct","gda","gdb","gdc","gdd","gde","gdf","gdg","gdh","gdi","gdj","gdk","gdl","gdm","gdn","gdo","gdq","gdr","gds","gdt","gdu","gdx","gea","geb","gec","ged","geg","geh","gei","gej","gek","gel","gem","geq","ges","gev","gew","gex","gey","gez","gfk","gft","gfx","gga","ggb","ggd","gge","ggg","ggk","ggl","ggn","ggo","ggr","ggt","ggu","ggw","gha","ghc","ghe","ghh","ghk","ghl","ghn","gho","ghr","ghs","ght","gia","gib","gic","gid","gie","gig","gih","gil","gim","gin","gio","gip","giq","gir","gis","git","giu","giw","gix","giy","giz","gji","gjk","gjm","gjn","gjr","gju","gka","gke","gkn","gko","gkp","gku","glc","gld","glh","gli","glj","glk","gll","glo","glr","glu","glw","gly","gma","gmb","gmd","gme","gmg","gmh","gml","gmm","gmn","gmq","gmu","gmv","gmw","gmx","gmy","gmz","gna","gnb","gnc","gnd","gne","gng","gnh","gni","gnk","gnl","gnm","gnn","gno","gnq","gnr","gnt","gnu","gnw","gnz","goa","gob","goc","god","goe","gof","gog","goh","goi","goj","gok","gol","gom","gon","goo","gop","goq","gor","gos","got","gou","gow","gox","goy","goz","gpa","gpe","gpn","gqa","gqi","gqn","gqr","gqu","gra","grb","grc","grd","grg","grh","gri","grj","grk","grm","gro","grq","grr","grs","grt","gru","grv","grw","grx","gry","grz","gse","gsg","gsl","gsm","gsn","gso","gsp","gss","gsw","gta","gti","gtu","gua","gub","guc","gud","gue","guf","gug","guh","gui","guk","gul","gum","gun","guo","gup","guq","gur","gus","gut","guu","guv","guw","gux","guz","gva","gvc","gve","gvf","gvj","gvl","gvm","gvn","gvo","gvp","gvr","gvs","gvy","gwa","gwb","gwc","gwd","gwe","gwf","gwg","gwi","gwj","gwm","gwn","gwr","gwt","gwu","gww","gwx","gxx","gya","gyb","gyd","gye","gyf","gyg","gyi","gyl","gym","gyn","gyr","gyy","gza","gzi","gzn","haa","hab","hac","had","hae","haf","hag","hah","hai","haj","hak","hal","ham","han","hao","hap","haq","har","has","hav","haw","hax","hay","haz","hba","hbb","hbn","hbo","hbu","hca","hch","hdn","hds","hdy","hea","hed","heg","heh","hei","hem","hgm","hgw","hhi","hhr","hhy","hia","hib","hid","hif","hig","hih","hii","hij","hik","hil","him","hio","hir","hit","hiw","hix","hji","hka","hke","hkk","hks","hla","hlb","hld","hle","hlt","hlu","hma","hmb","hmc","hmd","hme","hmf","hmg","hmh","hmi","hmj","hmk","hml","hmm","hmn","hmp","hmq","hmr","hms","hmt","hmu","hmv","hmw","hmx","hmy","hmz","hna","hnd","hne","hnh","hni","hnj","hnn","hno","hns","hnu","hoa","hob","hoc","hod","hoe","hoh","hoi","hoj","hok","hol","hom","hoo","hop","hor","hos","hot","hov","how","hoy","hoz","hpo","hps","hra","hrc","hre","hrk","hrm","hro","hrp","hrr","hrt","hru","hrw","hrx","hrz","hsb","hsh","hsl","hsn","hss","hti","hto","hts","htu","htx","hub","huc","hud","hue","huf","hug","huh","hui","huj","huk","hul","hum","huo","hup","huq","hur","hus","hut","huu","huv","huw","hux","huy","huz","hvc","hve","hvk","hvn","hvv","hwa","hwc","hwo","hya","hyx","iai","ian","iap","iar","iba","ibb","ibd","ibe","ibg","ibh","ibi","ibl","ibm","ibn","ibr","ibu","iby","ica","ich","icl","icr","ida","idb","idc","idd","ide","idi","idr","ids","idt","idu","ifa","ifb","ife","iff","ifk","ifm","ifu","ify","igb","ige","igg","igl","igm","ign","igo","igs","igw","ihb","ihi","ihp","ihw","iin","iir","ijc","ije","ijj","ijn","ijo","ijs","ike","iki","ikk","ikl","iko","ikp","ikr","iks","ikt","ikv","ikw","ikx","ikz","ila","ilb","ilg","ili","ilk","ill","ilm","ilo","ilp","ils","ilu","ilv","ilw","ima","ime","imi","iml","imn","imo","imr","ims","imy","inb","inc","ine","ing","inh","inj","inl","inm","inn","ino","inp","ins","int","inz","ior","iou","iow","ipi","ipo","iqu","iqw","ira","ire","irh","iri","irk","irn","iro","irr","iru","irx","iry","isa","isc","isd","ise","isg","ish","isi","isk","ism","isn","iso","isr","ist","isu","itb","itc","itd","ite","iti","itk","itl","itm","ito","itr","its","itt","itv","itw","itx","ity","itz","ium","ivb","ivv","iwk","iwm","iwo","iws","ixc","ixl","iya","iyo","iyx","izh","izi","izr","izz","jaa","jab","jac","jad","jae","jaf","jah","jaj","jak","jal","jam","jan","jao","jaq","jar","jas","jat","jau","jax","jay","jaz","jbe","jbi","jbj","jbk","jbn","jbo","jbr","jbt","jbu","jbw","jcs","jct","jda","jdg","jdt","jeb","jee","jeg","jeh","jei","jek","jel","jen","jer","jet","jeu","jgb","jge","jgk","jgo","jhi","jhs","jia","jib","jic","jid","jie","jig","jih","jii","jil","jim","jio","jiq","jit","jiu","jiv","jiy","jje","jjr","jka","jkm","jko","jkp","jkr","jku","jle","jls","jma","jmb","jmc","jmd","jmi","jml","jmn","jmr","jms","jmw","jmx","jna","jnd","jng","jni","jnj","jnl","jns","job","jod","jog","jor","jos","jow","jpa","jpr","jpx","jqr","jra","jrb","jrr","jrt","jru","jsl","jua","jub","juc","jud","juh","jui","juk","jul","jum","jun","juo","jup","jur","jus","jut","juu","juw","juy","jvd","jvn","jwi","jya","jye","jyy","kaa","kab","kac","kad","kae","kaf","kag","kah","kai","kaj","kak","kam","kao","kap","kaq","kar","kav","kaw","kax","kay","kba","kbb","kbc","kbd","kbe","kbf","kbg","kbh","kbi","kbj","kbk","kbl","kbm","kbn","kbo","kbp","kbq","kbr","kbs","kbt","kbu","kbv","kbw","kbx","kby","kbz","kca","kcb","kcc","kcd","kce","kcf","kcg","kch","kci","kcj","kck","kcl","kcm","kcn","kco","kcp","kcq","kcr","kcs","kct","kcu","kcv","kcw","kcx","kcy","kcz","kda","kdc","kdd","kde","kdf","kdg","kdh","kdi","kdj","kdk","kdl","kdm","kdn","kdo","kdp","kdq","kdr","kdt","kdu","kdv","kdw","kdx","kdy","kdz","kea","keb","kec","ked","kee","kef","keg","keh","kei","kej","kek","kel","kem","ken","keo","kep","keq","ker","kes","ket","keu","kev","kew","kex","key","kez","kfa","kfb","kfc","kfd","kfe","kff","kfg","kfh","kfi","kfj","kfk","kfl","kfm","kfn","kfo","kfp","kfq","kfr","kfs","kft","kfu","kfv","kfw","kfx","kfy","kfz","kga","kgb","kgc","kgd","kge","kgf","kgg","kgh","kgi","kgj","kgk","kgl","kgm","kgn","kgo","kgp","kgq","kgr","kgs","kgt","kgu","kgv","kgw","kgx","kgy","kha","khb","khc","khd","khe","khf","khg","khh","khi","khj","khk","khl","khn","kho","khp","khq","khr","khs","kht","khu","khv","khw","khx","khy","khz","kia","kib","kic","kid","kie","kif","kig","kih","kii","kij","kil","kim","kio","kip","kiq","kis","kit","kiu","kiv","kiw","kix","kiy","kiz","kja","kjb","kjc","kjd","kje","kjf","kjg","kjh","kji","kjj","kjk","kjl","kjm","kjn","kjo","kjp","kjq","kjr","kjs","kjt","kju","kjv","kjx","kjy","kjz","kka","kkb","kkc","kkd","kke","kkf","kkg","kkh","kki","kkj","kkk","kkl","kkm","kkn","kko","kkp","kkq","kkr","kks","kkt","kku","kkv","kkw","kkx","kky","kkz","kla","klb","klc","kld","kle","klf","klg","klh","kli","klj","klk","kll","klm","kln","klo","klp","klq","klr","kls","klt","klu","klv","klw","klx","kly","klz","kma","kmb","kmc","kmd","kme","kmf","kmg","kmh","kmi","kmj","kmk","kml","kmm","kmn","kmo","kmp","kmq","kmr","kms","kmt","kmu","kmv","kmw","kmx","kmy","kmz","kna","knb","knc","knd","kne","knf","kng","kni","knj","knk","knl","knm","knn","kno","knp","knq","knr","kns","knt","knu","knv","knw","knx","kny","knz","koa","koc","kod","koe","kof","kog","koh","koi","koj","kok","kol","koo","kop","koq","kos","kot","kou","kov","kow","kox","koy","koz","kpa","kpb","kpc","kpd","kpe","kpf","kpg","kph","kpi","kpj","kpk","kpl","kpm","kpn","kpo","kpp","kpq","kpr","kps","kpt","kpu","kpv","kpw","kpx","kpy","kpz","kqa","kqb","kqc","kqd","kqe","kqf","kqg","kqh","kqi","kqj","kqk","kql","kqm","kqn","kqo","kqp","kqq","kqr","kqs","kqt","kqu","kqv","kqw","kqx","kqy","kqz","kra","krb","krc","krd","kre","krf","krh","kri","krj","krk","krl","krm","krn","kro","krp","krr","krs","krt","kru","krv","krw","krx","kry","krz","ksa","ksb","ksc","ksd","kse","ksf","ksg","ksh","ksi","ksj","ksk","ksl","ksm","ksn","kso","ksp","ksq","ksr","kss","kst","ksu","ksv","ksw","ksx","ksy","ksz","kta","ktb","ktc","ktd","kte","ktf","ktg","kth","kti","ktj","ktk","ktl","ktm","ktn","kto","ktp","ktq","ktr","kts","ktt","ktu","ktv","ktw","ktx","kty","ktz","kub","kuc","kud","kue","kuf","kug","kuh","kui","kuj","kuk","kul","kum","kun","kuo","kup","kuq","kus","kut","kuu","kuv","kuw","kux","kuy","kuz","kva","kvb","kvc","kvd","kve","kvf","kvg","kvh","kvi","kvj","kvk","kvl","kvm","kvn","kvo","kvp","kvq","kvr","kvs","kvt","kvu","kvv","kvw","kvx","kvy","kvz","kwa","kwb","kwc","kwd","kwe","kwf","kwg","kwh","kwi","kwj","kwk","kwl","kwm","kwn","kwo","kwp","kwq","kwr","kws","kwt","kwu","kwv","kww","kwx","kwy","kwz","kxa","kxb","kxc","kxd","kxe","kxf","kxh","kxi","kxj","kxk","kxl","kxm","kxn","kxo","kxp","kxq","kxr","kxs","kxt","kxu","kxv","kxw","kxx","kxy","kxz","kya","kyb","kyc","kyd","kye","kyf","kyg","kyh","kyi","kyj","kyk","kyl","kym","kyn","kyo","kyp","kyq","kyr","kys","kyt","kyu","kyv","kyw","kyx","kyy","kyz","kza","kzb","kzc","kzd","kze","kzf","kzg","kzh","kzi","kzj","kzk","kzl","kzm","kzn","kzo","kzp","kzq","kzr","kzs","kzt","kzu","kzv","kzw","kzx","kzy","kzz","laa","lab","lac","lad","lae","laf","lag","lah","lai","laj","lak","lal","lam","lan","lap","laq","lar","las","lau","law","lax","lay","laz","lba","lbb","lbc","lbe","lbf","lbg","lbi","lbj","lbk","lbl","lbm","lbn","lbo","lbq","lbr","lbs","lbt","lbu","lbv","lbw","lbx","lby","lbz","lcc","lcd","lce","lcf","lch","lcl","lcm","lcp","lcq","lcs","lda","ldb","ldd","ldg","ldh","ldi","ldj","ldk","ldl","ldm","ldn","ldo","ldp","ldq","lea","leb","lec","led","lee","lef","leg","leh","lei","lej","lek","lel","lem","len","leo","lep","leq","ler","les","let","leu","lev","lew","lex","ley","lez","lfa","lfn","lga","lgb","lgg","lgh","lgi","lgk","lgl","lgm","lgn","lgq","lgr","lgt","lgu","lgz","lha","lhh","lhi","lhl","lhm","lhn","lhp","lhs","lht","lhu","lia","lib","lic","lid","lie","lif","lig","lih","lii","lij","lik","lil","lio","lip","liq","lir","lis","liu","liv","liw","lix","liy","liz","lja","lje","lji","ljl","ljp","ljw","ljx","lka","lkb","lkc","lkd","lke","lkh","lki","lkj","lkl","lkm","lkn","lko","lkr","lks","lkt","lku","lky","lla","llb","llc","lld","lle","llf","llg","llh","lli","llj","llk","lll","llm","lln","llo","llp","llq","lls","llu","llx","lma","lmb","lmc","lmd","lme","lmf","lmg","lmh","lmi","lmj","lmk","lml","lmm","lmn","lmo","lmp","lmq","lmr","lmu","lmv","lmw","lmx","lmy","lmz","lna","lnb","lnd","lng","lnh","lni","lnj","lnl","lnm","lnn","lno","lns","lnu","lnw","lnz","loa","lob","loc","loe","lof","log","loh","loi","loj","lok","lol","lom","lon","loo","lop","loq","lor","los","lot","lou","lov","low","lox","loy","loz","lpa","lpe","lpn","lpo","lpx","lra","lrc","lre","lrg","lri","lrk","lrl","lrm","lrn","lro","lrr","lrt","lrv","lrz","lsa","lsd","lse","lsg","lsh","lsi","lsl","lsm","lso","lsp","lsr","lss","lst","lsy","ltc","ltg","lth","lti","ltn","lto","lts","ltu","lua","luc","lud","lue","luf","lui","luj","luk","lul","lum","lun","luo","lup","luq","lur","lus","lut","luu","luv","luw","luy","luz","lva","lvk","lvs","lvu","lwa","lwe","lwg","lwh","lwl","lwm","lwo","lwt","lwu","lww","lya","lyg","lyn","lzh","lzl","lzn","lzz","maa","mab","mad","mae","maf","mag","mai","maj","mak","mam","man","map","maq","mas","mat","mau","mav","maw","max","maz","mba","mbb","mbc","mbd","mbe","mbf","mbh","mbi","mbj","mbk","mbl","mbm","mbn","mbo","mbp","mbq","mbr","mbs","mbt","mbu","mbv","mbw","mbx","mby","mbz","mca","mcb","mcc","mcd","mce","mcf","mcg","mch","mci","mcj","mck","mcl","mcm","mcn","mco","mcp","mcq","mcr","mcs","mct","mcu","mcv","mcw","mcx","mcy","mcz","mda","mdb","mdc","mdd","mde","mdf","mdg","mdh","mdi","mdj","mdk","mdl","mdm","mdn","mdp","mdq","mdr","mds","mdt","mdu","mdv","mdw","mdx","mdy","mdz","mea","meb","mec","med","mee","mef","meg","meh","mei","mej","mek","mel","mem","men","meo","mep","meq","mer","mes","met","meu","mev","mew","mey","mez","mfa","mfb","mfc","mfd","mfe","mff","mfg","mfh","mfi","mfj","mfk","mfl","mfm","mfn","mfo","mfp","mfq","mfr","mfs","mft","mfu","mfv","mfw","mfx","mfy","mfz","mga","mgb","mgc","mgd","mge","mgf","mgg","mgh","mgi","mgj","mgk","mgl","mgm","mgn","mgo","mgp","mgq","mgr","mgs","mgt","mgu","mgv","mgw","mgx","mgy","mgz","mha","mhb","mhc","mhd","mhe","mhf","mhg","mhh","mhi","mhj","mhk","mhl","mhm","mhn","mho","mhp","mhq","mhr","mhs","mht","mhu","mhw","mhx","mhy","mhz","mia","mib","mic","mid","mie","mif","mig","mih","mii","mij","mik","mil","mim","min","mio","mip","miq","mir","mis","mit","miu","miw","mix","miy","miz","mja","mjb","mjc","mjd","mje","mjg","mjh","mji","mjj","mjk","mjl","mjm","mjn","mjo","mjp","mjq","mjr","mjs","mjt","mju","mjv","mjw","mjx","mjy","mjz","mka","mkb","mkc","mke","mkf","mkg","mkh","mki","mkj","mkk","mkl","mkm","mkn","mko","mkp","mkq","mkr","mks","mkt","mku","mkv","mkw","mkx","mky","mkz","mla","mlb","mlc","mld","mle","mlf","mlh","mli","mlj","mlk","mll","mlm","mln","mlo","mlp","mlq","mlr","mls","mlu","mlv","mlw","mlx","mlz","mma","mmb","mmc","mmd","mme","mmf","mmg","mmh","mmi","mmj","mmk","mml","mmm","mmn","mmo","mmp","mmq","mmr","mmt","mmu","mmv","mmw","mmx","mmy","mmz","mna","mnb","mnc","mnd","mne","mnf","mng","mnh","mni","mnj","mnk","mnl","mnm","mnn","mno","mnp","mnq","mnr","mns","mnt","mnu","mnv","mnw","mnx","mny","mnz","moa","moc","mod","moe","mof","mog","moh","moi","moj","mok","mom","moo","mop","moq","mor","mos","mot","mou","mov","mow","mox","moy","moz","mpa","mpb","mpc","mpd","mpe","mpg","mph","mpi","mpj","mpk","mpl","mpm","mpn","mpo","mpp","mpq","mpr","mps","mpt","mpu","mpv","mpw","mpx","mpy","mpz","mqa","mqb","mqc","mqe","mqf","mqg","mqh","mqi","mqj","mqk","mql","mqm","mqn","mqo","mqp","mqq","mqr","mqs","mqt","mqu","mqv","mqw","mqx","mqy","mqz","mra","mrb","mrc","mrd","mre","mrf","mrg","mrh","mrj","mrk","mrl","mrm","mrn","mro","mrp","mrq","mrr","mrs","mrt","mru","mrv","mrw","mrx","mry","mrz","msb","msc","msd","mse","msf","msg","msh","msi","msj","msk","msl","msm","msn","mso","msp","msq","msr","mss","mst","msu","msv","msw","msx","msy","msz","mta","mtb","mtc","mtd","mte","mtf","mtg","mth","mti","mtj","mtk","mtl","mtm","mtn","mto","mtp","mtq","mtr","mts","mtt","mtu","mtv","mtw","mtx","mty","mua","mub","muc","mud","mue","mug","muh","mui","muj","muk","mul","mum","mun","muo","mup","muq","mur","mus","mut","muu","muv","mux","muy","muz","mva","mvb","mvd","mve","mvf","mvg","mvh","mvi","mvk","mvl","mvm","mvn","mvo","mvp","mvq","mvr","mvs","mvt","mvu","mvv","mvw","mvx","mvy","mvz","mwa","mwb","mwc","mwd","mwe","mwf","mwg","mwh","mwi","mwj","mwk","mwl","mwm","mwn","mwo","mwp","mwq","mwr","mws","mwt","mwu","mwv","mww","mwx","mwy","mwz","mxa","mxb","mxc","mxd","mxe","mxf","mxg","mxh","mxi","mxj","mxk","mxl","mxm","mxn","mxo","mxp","mxq","mxr","mxs","mxt","mxu","mxv","mxw","mxx","mxy","mxz","myb","myc","myd","mye","myf","myg","myh","myi","myj","myk","myl","mym","myn","myo","myp","myq","myr","mys","myt","myu","myv","myw","myx","myy","myz","mza","mzb","mzc","mzd","mze","mzg","mzh","mzi","mzj","mzk","mzl","mzm","mzn","mzo","mzp","mzq","mzr","mzs","mzt","mzu","mzv","mzw","mzx","mzy","mzz","naa","nab","nac","nad","nae","naf","nag","nah","nai","naj","nak","nal","nam","nan","nao","nap","naq","nar","nas","nat","naw","nax","nay","naz","nba","nbb","nbc","nbd","nbe","nbf","nbg","nbh","nbi","nbj","nbk","nbm","nbn","nbo","nbp","nbq","nbr","nbs","nbt","nbu","nbv","nbw","nbx","nby","nca","ncb","ncc","ncd","nce","ncf","ncg","nch","nci","ncj","nck","ncl","ncm","ncn","nco","ncp","ncq","ncr","ncs","nct","ncu","ncx","ncz","nda","ndb","ndc","ndd","ndf","ndg","ndh","ndi","ndj","ndk","ndl","ndm","ndn","ndp","ndq","ndr","nds","ndt","ndu","ndv","ndw","ndx","ndy","ndz","nea","neb","nec","ned","nee","nef","neg","neh","nei","nej","nek","nem","nen","neo","neq","ner","nes","net","neu","nev","new","nex","ney","nez","nfa","nfd","nfl","nfr","nfu","nga","ngb","ngc","ngd","nge","ngf","ngg","ngh","ngi","ngj","ngk","ngl","ngm","ngn","ngo","ngp","ngq","ngr","ngs","ngt","ngu","ngv","ngw","ngx","ngy","ngz","nha","nhb","nhc","nhd","nhe","nhf","nhg","nhh","nhi","nhk","nhm","nhn","nho","nhp","nhq","nhr","nht","nhu","nhv","nhw","nhx","nhy","nhz","nia","nib","nic","nid","nie","nif","nig","nih","nii","nij","nik","nil","nim","nin","nio","niq","nir","nis","nit","niu","niv","niw","nix","niy","niz","nja","njb","njd","njh","nji","njj","njl","njm","njn","njo","njr","njs","njt","nju","njx","njy","njz","nka","nkb","nkc","nkd","nke","nkf","nkg","nkh","nki","nkj","nkk","nkm","nkn","nko","nkp","nkq","nkr","nks","nkt","nku","nkv","nkw","nkx","nkz","nla","nlc","nle","nlg","nli","nlj","nlk","nll","nln","nlo","nlq","nlr","nlu","nlv","nlw","nlx","nly","nlz","nma","nmb","nmc","nmd","nme","nmf","nmg","nmh","nmi","nmj","nmk","nml","nmm","nmn","nmo","nmp","nmq","nmr","nms","nmt","nmu","nmv","nmw","nmx","nmy","nmz","nna","nnb","nnc","nnd","nne","nnf","nng","nnh","nni","nnj","nnk","nnl","nnm","nnn","nnp","nnq","nnr","nns","nnt","nnu","nnv","nnw","nnx","nny","nnz","noa","noc","nod","noe","nof","nog","noh","noi","noj","nok","nol","nom","non","noo","nop","noq","nos","not","nou","nov","now","noy","noz","npa","npb","npg","nph","npi","npl","npn","npo","nps","npu","npx","npy","nqg","nqk","nql","nqm","nqn","nqo","nqq","nqy","nra","nrb","nrc","nre","nrf","nrg","nri","nrk","nrl","nrm","nrn","nrp","nrr","nrt","nru","nrx","nrz","nsa","nsc","nsd","nse","nsf","nsg","nsh","nsi","nsk","nsl","nsm","nsn","nso","nsp","nsq","nsr","nss","nst","nsu","nsv","nsw","nsx","nsy","nsz","ntd","nte","ntg","nti","ntj","ntk","ntm","nto","ntp","ntr","nts","ntu","ntw","ntx","nty","ntz","nua","nub","nuc","nud","nue","nuf","nug","nuh","nui","nuj","nuk","nul","num","nun","nuo","nup","nuq","nur","nus","nut","nuu","nuv","nuw","nux","nuy","nuz","nvh","nvm","nvo","nwa","nwb","nwc","nwe","nwg","nwi","nwm","nwo","nwr","nwx","nwy","nxa","nxd","nxe","nxg","nxi","nxk","nxl","nxm","nxn","nxo","nxq","nxr","nxu","nxx","nyb","nyc","nyd","nye","nyf","nyg","nyh","nyi","nyj","nyk","nyl","nym","nyn","nyo","nyp","nyq","nyr","nys","nyt","nyu","nyv","nyw","nyx","nyy","nza","nzb","nzi","nzk","nzm","nzs","nzu","nzy","nzz","oaa","oac","oar","oav","obi","obk","obl","obm","obo","obr","obt","obu","oca","och","oco","ocu","oda","odk","odt","odu","ofo","ofs","ofu","ogb","ogc","oge","ogg","ogo","ogu","oht","ohu","oia","oin","ojb","ojc","ojg","ojp","ojs","ojv","ojw","oka","okb","okd","oke","okg","okh","oki","okj","okk","okl","okm","okn","oko","okr","oks","oku","okv","okx","ola","old","ole","olk","olm","olo","olr","olt","olu","oma","omb","omc","ome","omg","omi","omk","oml","omn","omo","omp","omq","omr","omt","omu","omv","omw","omx","ona","onb","one","ong","oni","onj","onk","onn","ono","onp","onr","ons","ont","onu","onw","onx","ood","oog","oon","oor","oos","opa","opk","opm","opo","opt","opy","ora","orc","ore","org","orh","orn","oro","orr","ors","ort","oru","orv","orw","orx","ory","orz","osa","osc","osi","oso","osp","ost","osu","osx","ota","otb","otd","ote","oti","otk","otl","otm","otn","oto","otq","otr","ots","ott","otu","otw","otx","oty","otz","oua","oub","oue","oui","oum","oun","ovd","owi","owl","oyb","oyd","oym","oyy","ozm","paa","pab","pac","pad","pae","paf","pag","pah","pai","pak","pal","pam","pao","pap","paq","par","pas","pat","pau","pav","paw","pax","pay","paz","pbb","pbc","pbe","pbf","pbg","pbh","pbi","pbl","pbn","pbo","pbp","pbr","pbs","pbt","pbu","pbv","pby","pbz","pca","pcb","pcc","pcd","pce","pcf","pcg","pch","pci","pcj","pck","pcl","pcm","pcn","pcp","pcr","pcw","pda","pdc","pdi","pdn","pdo","pdt","pdu","pea","peb","ped","pee","pef","peg","peh","pei","pej","pek","pel","pem","peo","pep","peq","pes","pev","pex","pey","pez","pfa","pfe","pfl","pga","pgd","pgg","pgi","pgk","pgl","pgn","pgs","pgu","pgy","pgz","pha","phd","phg","phh","phi","phk","phl","phm","phn","pho","phq","phr","pht","phu","phv","phw","pia","pib","pic","pid","pie","pif","pig","pih","pii","pij","pil","pim","pin","pio","pip","pir","pis","pit","piu","piv","piw","pix","piy","piz","pjt","pka","pkb","pkc","pkg","pkh","pkn","pko","pkp","pkr","pks","pkt","pku","pla","plb","plc","pld","ple","plf","plg","plh","plj","plk","pll","pln","plo","plp","plq","plr","pls","plt","plu","plv","plw","ply","plz","pma","pmb","pmc","pmd","pme","pmf","pmh","pmi","pmj","pmk","pml","pmm","pmn","pmo","pmq","pmr","pms","pmt","pmu","pmw","pmx","pmy","pmz","pna","pnb","pnc","pne","png","pnh","pni","pnj","pnk","pnl","pnm","pnn","pno","pnp","pnq","pnr","pns","pnt","pnu","pnv","pnw","pnx","pny","pnz","poc","pod","poe","pof","pog","poh","poi","pok","pom","pon","poo","pop","poq","pos","pot","pov","pow","pox","poy","poz","ppa","ppe","ppi","ppk","ppl","ppm","ppn","ppo","ppp","ppq","ppr","pps","ppt","ppu","pqa","pqe","pqm","pqw","pra","prb","prc","prd","pre","prf","prg","prh","pri","prk","prl","prm","prn","pro","prp","prq","prr","prs","prt","pru","prw","prx","pry","prz","psa","psc","psd","pse","psg","psh","psi","psl","psm","psn","pso","psp","psq","psr","pss","pst","psu","psw","psy","pta","pth","pti","ptn","pto","ptp","ptq","ptr","ptt","ptu","ptv","ptw","pty","pua","pub","puc","pud","pue","puf","pug","pui","puj","puk","pum","puo","pup","puq","pur","put","puu","puw","pux","puy","puz","pwa","pwb","pwg","pwi","pwm","pwn","pwo","pwr","pww","pxm","pye","pym","pyn","pys","pyu","pyx","pyy","pzn","qaa..qtz","qua","qub","quc","qud","quf","qug","quh","qui","quk","qul","qum","qun","qup","quq","qur","qus","quv","quw","qux","quy","quz","qva","qvc","qve","qvh","qvi","qvj","qvl","qvm","qvn","qvo","qvp","qvs","qvw","qvy","qvz","qwa","qwc","qwe","qwh","qwm","qws","qwt","qxa","qxc","qxh","qxl","qxn","qxo","qxp","qxq","qxr","qxs","qxt","qxu","qxw","qya","qyp","raa","rab","rac","rad","raf","rag","rah","rai","raj","rak","ral","ram","ran","rao","rap","raq","rar","ras","rat","rau","rav","raw","rax","ray","raz","rbb","rbk","rbl","rbp","rcf","rdb","rea","reb","ree","reg","rei","rej","rel","rem","ren","rer","res","ret","rey","rga","rge","rgk","rgn","rgr","rgs","rgu","rhg","rhp","ria","rie","rif","ril","rim","rin","rir","rit","riu","rjg","rji","rjs","rka","rkb","rkh","rki","rkm","rkt","rkw","rma","rmb","rmc","rmd","rme","rmf","rmg","rmh","rmi","rmk","rml","rmm","rmn","rmo","rmp","rmq","rmr","rms","rmt","rmu","rmv","rmw","rmx","rmy","rmz","rna","rnd","rng","rnl","rnn","rnp","rnr","rnw","roa","rob","roc","rod","roe","rof","rog","rol","rom","roo","rop","ror","rou","row","rpn","rpt","rri","rro","rrt","rsb","rsi","rsl","rsm","rtc","rth","rtm","rts","rtw","rub","ruc","rue","ruf","rug","ruh","rui","ruk","ruo","rup","ruq","rut","ruu","ruy","ruz","rwa","rwk","rwm","rwo","rwr","rxd","rxw","ryn","rys","ryu","rzh","saa","sab","sac","sad","sae","saf","sah","sai","saj","sak","sal","sam","sao","sap","saq","sar","sas","sat","sau","sav","saw","sax","say","saz","sba","sbb","sbc","sbd","sbe","sbf","sbg","sbh","sbi","sbj","sbk","sbl","sbm","sbn","sbo","sbp","sbq","sbr","sbs","sbt","sbu","sbv","sbw","sbx","sby","sbz","sca","scb","sce","scf","scg","sch","sci","sck","scl","scn","sco","scp","scq","scs","sct","scu","scv","scw","scx","sda","sdb","sdc","sde","sdf","sdg","sdh","sdj","sdk","sdl","sdm","sdn","sdo","sdp","sdr","sds","sdt","sdu","sdv","sdx","sdz","sea","seb","sec","sed","see","sef","seg","seh","sei","sej","sek","sel","sem","sen","seo","sep","seq","ser","ses","set","seu","sev","sew","sey","sez","sfb","sfe","sfm","sfs","sfw","sga","sgb","sgc","sgd","sge","sgg","sgh","sgi","sgj","sgk","sgl","sgm","sgn","sgo","sgp","sgr","sgs","sgt","sgu","sgw","sgx","sgy","sgz","sha","shb","shc","shd","she","shg","shh","shi","shj","shk","shl","shm","shn","sho","shp","shq","shr","shs","sht","shu","shv","shw","shx","shy","shz","sia","sib","sid","sie","sif","sig","sih","sii","sij","sik","sil","sim","sio","sip","siq","sir","sis","sit","siu","siv","siw","six","siy","siz","sja","sjb","sjd","sje","sjg","sjk","sjl","sjm","sjn","sjo","sjp","sjr","sjs","sjt","sju","sjw","ska","skb","skc","skd","ske","skf","skg","skh","ski","skj","skk","skm","skn","sko","skp","skq","skr","sks","skt","sku","skv","skw","skx","sky","skz","sla","slc","sld","sle","slf","slg","slh","sli","slj","sll","slm","sln","slp","slq","slr","sls","slt","slu","slw","slx","sly","slz","sma","smb","smc","smd","smf","smg","smh","smi","smj","smk","sml","smm","smn","smp","smq","smr","sms","smt","smu","smv","smw","smx","smy","smz","snb","snc","sne","snf","sng","snh","sni","snj","snk","snl","snm","snn","sno","snp","snq","snr","sns","snu","snv","snw","snx","sny","snz","soa","sob","soc","sod","soe","sog","soh","soi","soj","sok","sol","son","soo","sop","soq","sor","sos","sou","sov","sow","sox","soy","soz","spb","spc","spd","spe","spg","spi","spk","spl","spm","spn","spo","spp","spq","spr","sps","spt","spu","spv","spx","spy","sqa","sqh","sqj","sqk","sqm","sqn","sqo","sqq","sqr","sqs","sqt","squ","sra","srb","src","sre","srf","srg","srh","sri","srk","srl","srm","srn","sro","srq","srr","srs","srt","sru","srv","srw","srx","sry","srz","ssa","ssb","ssc","ssd","sse","ssf","ssg","ssh","ssi","ssj","ssk","ssl","ssm","ssn","sso","ssp","ssq","ssr","sss","sst","ssu","ssv","ssx","ssy","ssz","sta","stb","std","ste","stf","stg","sth","sti","stj","stk","stl","stm","stn","sto","stp","stq","str","sts","stt","stu","stv","stw","sty","sua","sub","suc","sue","sug","sui","suj","suk","sul","sum","suq","sur","sus","sut","suv","suw","sux","suy","suz","sva","svb","svc","sve","svk","svm","svr","svs","svx","swb","swc","swf","swg","swh","swi","swj","swk","swl","swm","swn","swo","swp","swq","swr","sws","swt","swu","swv","sww","swx","swy","sxb","sxc","sxe","sxg","sxk","sxl","sxm","sxn","sxo","sxr","sxs","sxu","sxw","sya","syb","syc","syd","syi","syk","syl","sym","syn","syo","syr","sys","syw","syx","syy","sza","szb","szc","szd","sze","szg","szl","szn","szp","szs","szv","szw","taa","tab","tac","tad","tae","taf","tag","tai","taj","tak","tal","tan","tao","tap","taq","tar","tas","tau","tav","taw","tax","tay","taz","tba","tbb","tbc","tbd","tbe","tbf","tbg","tbh","tbi","tbj","tbk","tbl","tbm","tbn","tbo","tbp","tbq","tbr","tbs","tbt","tbu","tbv","tbw","tbx","tby","tbz","tca","tcb","tcc","tcd","tce","tcf","tcg","tch","tci","tck","tcl","tcm","tcn","tco","tcp","tcq","tcs","tct","tcu","tcw","tcx","tcy","tcz","tda","tdb","tdc","tdd","tde","tdf","tdg","tdh","tdi","tdj","tdk","tdl","tdm","tdn","tdo","tdq","tdr","tds","tdt","tdu","tdv","tdx","tdy","tea","teb","tec","ted","tee","tef","teg","teh","tei","tek","tem","ten","teo","tep","teq","ter","tes","tet","teu","tev","tew","tex","tey","tfi","tfn","tfo","tfr","tft","tga","tgb","tgc","tgd","tge","tgf","tgg","tgh","tgi","tgj","tgn","tgo","tgp","tgq","tgr","tgs","tgt","tgu","tgv","tgw","tgx","tgy","tgz","thc","thd","the","thf","thh","thi","thk","thl","thm","thn","thp","thq","thr","ths","tht","thu","thv","thw","thx","thy","thz","tia","tic","tid","tie","tif","tig","tih","tii","tij","tik","til","tim","tin","tio","tip","tiq","tis","tit","tiu","tiv","tiw","tix","tiy","tiz","tja","tjg","tji","tjl","tjm","tjn","tjo","tjs","tju","tjw","tka","tkb","tkd","tke","tkf","tkg","tkk","tkl","tkm","tkn","tkp","tkq","tkr","tks","tkt","tku","tkv","tkw","tkx","tkz","tla","tlb","tlc","tld","tlf","tlg","tlh","tli","tlj","tlk","tll","tlm","tln","tlo","tlp","tlq","tlr","tls","tlt","tlu","tlv","tlw","tlx","tly","tma","tmb","tmc","tmd","tme","tmf","tmg","tmh","tmi","tmj","tmk","tml","tmm","tmn","tmo","tmp","tmq","tmr","tms","tmt","tmu","tmv","tmw","tmy","tmz","tna","tnb","tnc","tnd","tne","tnf","tng","tnh","tni","tnk","tnl","tnm","tnn","tno","tnp","tnq","tnr","tns","tnt","tnu","tnv","tnw","tnx","tny","tnz","tob","toc","tod","toe","tof","tog","toh","toi","toj","tol","tom","too","top","toq","tor","tos","tou","tov","tow","tox","toy","toz","tpa","tpc","tpe","tpf","tpg","tpi","tpj","tpk","tpl","tpm","tpn","tpo","tpp","tpq","tpr","tpt","tpu","tpv","tpw","tpx","tpy","tpz","tqb","tql","tqm","tqn","tqo","tqp","tqq","tqr","tqt","tqu","tqw","tra","trb","trc","trd","tre","trf","trg","trh","tri","trj","trk","trl","trm","trn","tro","trp","trq","trr","trs","trt","tru","trv","trw","trx","try","trz","tsa","tsb","tsc","tsd","tse","tsf","tsg","tsh","tsi","tsj","tsk","tsl","tsm","tsp","tsq","tsr","tss","tst","tsu","tsv","tsw","tsx","tsy","tsz","tta","ttb","ttc","ttd","tte","ttf","ttg","tth","tti","ttj","ttk","ttl","ttm","ttn","tto","ttp","ttq","ttr","tts","ttt","ttu","ttv","ttw","tty","ttz","tua","tub","tuc","tud","tue","tuf","tug","tuh","tui","tuj","tul","tum","tun","tuo","tup","tuq","tus","tut","tuu","tuv","tuw","tux","tuy","tuz","tva","tvd","tve","tvk","tvl","tvm","tvn","tvo","tvs","tvt","tvu","tvw","tvy","twa","twb","twc","twd","twe","twf","twg","twh","twl","twm","twn","two","twp","twq","twr","twt","twu","tww","twx","twy","txa","txb","txc","txe","txg","txh","txi","txj","txm","txn","txo","txq","txr","txs","txt","txu","txx","txy","tya","tye","tyh","tyi","tyj","tyl","tyn","typ","tyr","tys","tyt","tyu","tyv","tyx","tyz","tza","tzh","tzj","tzl","tzm","tzn","tzo","tzx","uam","uan","uar","uba","ubi","ubl","ubr","ubu","uby","uda","ude","udg","udi","udj","udl","udm","udu","ues","ufi","uga","ugb","uge","ugn","ugo","ugy","uha","uhn","uis","uiv","uji","uka","ukg","ukh","ukk","ukl","ukp","ukq","uks","uku","ukw","uky","ula","ulb","ulc","ule","ulf","uli","ulk","ull","ulm","uln","ulu","ulw","uma","umb","umc","umd","umg","umi","umm","umn","umo","ump","umr","ums","umu","una","und","une","ung","unk","unm","unn","unp","unr","unu","unx","unz","uok","upi","upv","ura","urb","urc","ure","urf","urg","urh","uri","urj","urk","url","urm","urn","uro","urp","urr","urt","uru","urv","urw","urx","ury","urz","usa","ush","usi","usk","usp","usu","uta","ute","utp","utr","utu","uum","uun","uur","uuu","uve","uvh","uvl","uwa","uya","uzn","uzs","vaa","vae","vaf","vag","vah","vai","vaj","val","vam","van","vao","vap","var","vas","vau","vav","vay","vbb","vbk","vec","ved","vel","vem","veo","vep","ver","vgr","vgt","vic","vid","vif","vig","vil","vin","vis","vit","viv","vka","vki","vkj","vkk","vkl","vkm","vko","vkp","vkt","vku","vlp","vls","vma","vmb","vmc","vmd","vme","vmf","vmg","vmh","vmi","vmj","vmk","vml","vmm","vmp","vmq","vmr","vms","vmu","vmv","vmw","vmx","vmy","vmz","vnk","vnm","vnp","vor","vot","vra","vro","vrs","vrt","vsi","vsl","vsv","vto","vum","vun","vut","vwa","waa","wab","wac","wad","wae","waf","wag","wah","wai","waj","wak","wal","wam","wan","wao","wap","waq","war","was","wat","wau","wav","waw","wax","way","waz","wba","wbb","wbe","wbf","wbh","wbi","wbj","wbk","wbl","wbm","wbp","wbq","wbr","wbs","wbt","wbv","wbw","wca","wci","wdd","wdg","wdj","wdk","wdu","wdy","wea","wec","wed","weg","weh","wei","wem","wen","weo","wep","wer","wes","wet","weu","wew","wfg","wga","wgb","wgg","wgi","wgo","wgu","wgw","wgy","wha","whg","whk","whu","wib","wic","wie","wif","wig","wih","wii","wij","wik","wil","wim","win","wir","wit","wiu","wiv","wiw","wiy","wja","wji","wka","wkb","wkd","wkl","wku","wkw","wky","wla","wlc","wle","wlg","wli","wlk","wll","wlm","wlo","wlr","wls","wlu","wlv","wlw","wlx","wly","wma","wmb","wmc","wmd","wme","wmh","wmi","wmm","wmn","wmo","wms","wmt","wmw","wmx","wnb","wnc","wnd","wne","wng","wni","wnk","wnm","wnn","wno","wnp","wnu","wnw","wny","woa","wob","woc","wod","woe","wof","wog","woi","wok","wom","won","woo","wor","wos","wow","woy","wpc","wra","wrb","wrd","wrg","wrh","wri","wrk","wrl","wrm","wrn","wro","wrp","wrr","wrs","wru","wrv","wrw","wrx","wry","wrz","wsa","wsg","wsi","wsk","wsr","wss","wsu","wsv","wtf","wth","wti","wtk","wtm","wtw","wua","wub","wud","wuh","wul","wum","wun","wur","wut","wuu","wuv","wux","wuy","wwa","wwb","wwo","wwr","www","wxa","wxw","wya","wyb","wyi","wym","wyr","wyy","xaa","xab","xac","xad","xae","xag","xai","xaj","xak","xal","xam","xan","xao","xap","xaq","xar","xas","xat","xau","xav","xaw","xay","xba","xbb","xbc","xbd","xbe","xbg","xbi","xbj","xbm","xbn","xbo","xbp","xbr","xbw","xbx","xby","xcb","xcc","xce","xcg","xch","xcl","xcm","xcn","xco","xcr","xct","xcu","xcv","xcw","xcy","xda","xdc","xdk","xdm","xdo","xdy","xeb","xed","xeg","xel","xem","xep","xer","xes","xet","xeu","xfa","xga","xgb","xgd","xgf","xgg","xgi","xgl","xgm","xgn","xgr","xgu","xgw","xha","xhc","xhd","xhe","xhr","xht","xhu","xhv","xia","xib","xii","xil","xin","xip","xir","xis","xiv","xiy","xjb","xjt","xka","xkb","xkc","xkd","xke","xkf","xkg","xkh","xki","xkj","xkk","xkl","xkn","xko","xkp","xkq","xkr","xks","xkt","xku","xkv","xkw","xkx","xky","xkz","xla","xlb","xlc","xld","xle","xlg","xli","xln","xlo","xlp","xls","xlu","xly","xma","xmb","xmc","xmd","xme","xmf","xmg","xmh","xmj","xmk","xml","xmm","xmn","xmo","xmp","xmq","xmr","xms","xmt","xmu","xmv","xmw","xmx","xmy","xmz","xna","xnb","xnd","xng","xnh","xni","xnk","xnn","xno","xnr","xns","xnt","xnu","xny","xnz","xoc","xod","xog","xoi","xok","xom","xon","xoo","xop","xor","xow","xpa","xpc","xpe","xpg","xpi","xpj","xpk","xpm","xpn","xpo","xpp","xpq","xpr","xps","xpt","xpu","xpy","xqa","xqt","xra","xrb","xrd","xre","xrg","xri","xrm","xrn","xrq","xrr","xrt","xru","xrw","xsa","xsb","xsc","xsd","xse","xsh","xsi","xsj","xsl","xsm","xsn","xso","xsp","xsq","xsr","xss","xsu","xsv","xsy","xta","xtb","xtc","xtd","xte","xtg","xth","xti","xtj","xtl","xtm","xtn","xto","xtp","xtq","xtr","xts","xtt","xtu","xtv","xtw","xty","xtz","xua","xub","xud","xug","xuj","xul","xum","xun","xuo","xup","xur","xut","xuu","xve","xvi","xvn","xvo","xvs","xwa","xwc","xwd","xwe","xwg","xwj","xwk","xwl","xwo","xwr","xwt","xww","xxb","xxk","xxm","xxr","xxt","xya","xyb","xyj","xyk","xyl","xyt","xyy","xzh","xzm","xzp","yaa","yab","yac","yad","yae","yaf","yag","yah","yai","yaj","yak","yal","yam","yan","yao","yap","yaq","yar","yas","yat","yau","yav","yaw","yax","yay","yaz","yba","ybb","ybd","ybe","ybh","ybi","ybj","ybk","ybl","ybm","ybn","ybo","ybx","yby","ych","ycl","ycn","ycp","yda","ydd","yde","ydg","ydk","yds","yea","yec","yee","yei","yej","yel","yen","yer","yes","yet","yeu","yev","yey","yga","ygi","ygl","ygm","ygp","ygr","ygs","ygu","ygw","yha","yhd","yhl","yhs","yia","yif","yig","yih","yii","yij","yik","yil","yim","yin","yip","yiq","yir","yis","yit","yiu","yiv","yix","yiy","yiz","yka","ykg","yki","ykk","ykl","ykm","ykn","yko","ykr","ykt","yku","yky","yla","ylb","yle","ylg","yli","yll","ylm","yln","ylo","ylr","ylu","yly","yma","ymb","ymc","ymd","yme","ymg","ymh","ymi","ymk","yml","ymm","ymn","ymo","ymp","ymq","ymr","yms","ymt","ymx","ymz","yna","ynd","yne","yng","ynh","ynk","ynl","ynn","yno","ynq","yns","ynu","yob","yog","yoi","yok","yol","yom","yon","yos","yot","yox","yoy","ypa","ypb","ypg","yph","ypk","ypm","ypn","ypo","ypp","ypz","yra","yrb","yre","yri","yrk","yrl","yrm","yrn","yro","yrs","yrw","yry","ysc","ysd","ysg","ysl","ysn","yso","ysp","ysr","yss","ysy","yta","ytl","ytp","ytw","yty","yua","yub","yuc","yud","yue","yuf","yug","yui","yuj","yuk","yul","yum","yun","yup","yuq","yur","yut","yuu","yuw","yux","yuy","yuz","yva","yvt","ywa","ywg","ywl","ywn","ywq","ywr","ywt","ywu","yww","yxa","yxg","yxl","yxm","yxu","yxy","yyr","yyu","yyz","yzg","yzk","zaa","zab","zac","zad","zae","zaf","zag","zah","zai","zaj","zak","zal","zam","zao","zap","zaq","zar","zas","zat","zau","zav","zaw","zax","zay","zaz","zbc","zbe","zbl","zbt","zbw","zca","zch","zdj","zea","zeg","zeh","zen","zga","zgb","zgh","zgm","zgn","zgr","zhb","zhd","zhi","zhn","zhw","zhx","zia","zib","zik","zil","zim","zin","zir","ziw","ziz","zka","zkb","zkd","zkg","zkh","zkk","zkn","zko","zkp","zkr","zkt","zku","zkv","zkz","zle","zlj","zlm","zln","zlq","zls","zlw","zma","zmb","zmc","zmd","zme","zmf","zmg","zmh","zmi","zmj","zmk","zml","zmm","zmn","zmo","zmp","zmq","zmr","zms","zmt","zmu","zmv","zmw","zmx","zmy","zmz","zna","znd","zne","zng","znk","zns","zoc","zoh","zom","zoo","zoq","zor","zos","zpa","zpb","zpc","zpd","zpe","zpf","zpg","zph","zpi","zpj","zpk","zpl","zpm","zpn","zpo","zpp","zpq","zpr","zps","zpt","zpu","zpv","zpw","zpx","zpy","zpz","zqe","zra","zrg","zrn","zro","zrp","zrs","zsa","zsk","zsl","zsm","zsr","zsu","zte","ztg","ztl","ztm","ztn","ztp","ztq","zts","ztt","ztu","ztx","zty","zua","zuh","zum","zun","zuy","zwa","zxx","zyb","zyg","zyj","zyn","zyp","zza","zzj"]
-;return axe.utils.validLangs=function(){"use strict";return I},commons}()})}("object"==typeof window?window:this);
\ No newline at end of file
+function a(){this.pseudos={},this.attrEqualityMods={},this.ruleNestingOperators={},this.substitutesEnabled=!1}function b(a){return a>="a"&&a<="z"||a>="A"&&a<="Z"||"-"===a||"_"===a}function c(a){return a>="a"&&a<="z"||a>="A"&&a<="Z"||a>="0"&&a<="9"||"-"===a||"_"===a}function d(a){return a>="a"&&a<="f"||a>="A"&&a<="F"||a>="0"&&a<="9"}function e(a,e,g,j,k,l){var m,n,o,p,q;return p=a.length,m=null,o=function(b,c){var f,g,h;for(h="",e++,m=a.charAt(e);e<p;){if(m===b)return e++,h;if("\\"===m)if(e++,(m=a.charAt(e))===b)h+=b;else if(f=c[m])h+=f;else{if(d(m)){for(g=m,e++,m=a.charAt(e);d(m);)g+=m,e++,m=a.charAt(e);" "===m&&(e++,m=a.charAt(e)),h+=String.fromCharCode(parseInt(g,16));continue}h+=m}else h+=m;e++,m=a.charAt(e)}return h},n=function(){var b="";for(m=a.charAt(e);e<p;){if(c(m))b+=m;else{if("\\"!==m)return b;if(++e>=p)throw Error("Expected symbol but end of file reached.");if(m=a.charAt(e),f[m])b+=m;else{if(d(m)){var g=m;for(e++,m=a.charAt(e);d(m);)g+=m,e++,m=a.charAt(e);" "===m&&(e++,m=a.charAt(e)),b+=String.fromCharCode(parseInt(g,16));continue}b+=m}}e++,m=a.charAt(e)}return b},q=function(){m=a.charAt(e);for(var b=!1;" "===m||"\t"===m||"\n"===m||"\r"===m||"\f"===m;)b=!0,e++,m=a.charAt(e);return b},this.parse=function(){var b=this.parseSelector();if(e<p)throw Error('Rule expected but "'+a.charAt(e)+'" found.');return b},this.parseSelector=function(){var b,c=b=this.parseSingleSelector();for(m=a.charAt(e);","===m;){if(e++,q(),"selectors"!==b.type&&(b={type:"selectors",selectors:[c]}),!(c=this.parseSingleSelector()))throw Error('Rule expected after ",".');b.selectors.push(c)}return b},this.parseSingleSelector=function(){q();var b={type:"ruleSet"},c=this.parseRule();if(!c)return null;for(var d=b;c&&(c.type="rule",d.rule=c,d=c,q(),m=a.charAt(e),!(e>=p||","===m||")"===m));)if(k[m]){var f=m;if(e++,q(),!(c=this.parseRule()))throw Error('Rule expected after "'+f+'".');c.nestingOperator=f}else(c=this.parseRule())&&(c.nestingOperator=null);return b},this.parseRule=function(){for(var c=null;e<p;)if("*"===(m=a.charAt(e)))e++,(c=c||{}).tagName="*";else if(b(m)||"\\"===m)(c=c||{}).tagName=n();else if("."===m)e++,c=c||{},(c.classNames=c.classNames||[]).push(n());else if("#"===m)e++,(c=c||{}).id=n();else if("["===m){e++,q();var d={name:n()};if(q(),"]"===m)e++;else{var f="";if(j[m]&&(f=m,e++,m=a.charAt(e)),e>=p)throw Error('Expected "=" but end of file reached.');if("="!==m)throw Error('Expected "=" but "'+m+'" found.');d.operator=f+"=",e++,q();var k="";if(d.valueType="string",'"'===m)k=o('"',i);else if("'"===m)k=o("'",h);else if(l&&"$"===m)e++,k=n(),d.valueType="substitute";else{for(;e<p&&"]"!==m;)k+=m,e++,m=a.charAt(e);k=k.trim()}if(q(),e>=p)throw Error('Expected "]" but end of file reached.');if("]"!==m)throw Error('Expected "]" but "'+m+'" found.');e++,d.value=k}c=c||{},(c.attrs=c.attrs||[]).push(d)}else{if(":"!==m)break;e++;var r=n(),s={name:r};if("("===m){e++;var t="";if(q(),"selector"===g[r])s.valueType="selector",t=this.parseSelector();else{if(s.valueType=g[r]||"string",'"'===m)t=o('"',i);else if("'"===m)t=o("'",h);else if(l&&"$"===m)e++,t=n(),s.valueType="substitute";else{for(;e<p&&")"!==m;)t+=m,e++,m=a.charAt(e);t=t.trim()}q()}if(e>=p)throw Error('Expected ")" but end of file reached.');if(")"!==m)throw Error('Expected ")" but "'+m+'" found.');e++,s.value=t}c=c||{},(c.pseudos=c.pseudos||[]).push(s)}return c},this}a.prototype.registerSelectorPseudos=function(a){for(var b=0,c=arguments.length;b<c;b++)a=arguments[b],this.pseudos[a]="selector";return this},a.prototype.unregisterSelectorPseudos=function(a){for(var b=0,c=arguments.length;b<c;b++)a=arguments[b],delete this.pseudos[a];return this},a.prototype.registerNumericPseudos=function(a){for(var b=0,c=arguments.length;b<c;b++)a=arguments[b],this.pseudos[a]="numeric";return this},a.prototype.unregisterNumericPseudos=function(a){for(var b=0,c=arguments.length;b<c;b++)a=arguments[b],delete this.pseudos[a];return this},a.prototype.registerNestingOperators=function(a){for(var b=0,c=arguments.length;b<c;b++)a=arguments[b],this.ruleNestingOperators[a]=!0;return this},a.prototype.unregisterNestingOperators=function(a){for(var b=0,c=arguments.length;b<c;b++)a=arguments[b],delete this.ruleNestingOperators[a];return this},a.prototype.registerAttrEqualityMods=function(a){for(var b=0,c=arguments.length;b<c;b++)a=arguments[b],this.attrEqualityMods[a]=!0;return this},a.prototype.unregisterAttrEqualityMods=function(a){for(var b=0,c=arguments.length;b<c;b++)a=arguments[b],delete this.attrEqualityMods[a];return this},a.prototype.enableSubstitutes=function(){return this.substitutesEnabled=!0,this},a.prototype.disableSubstitutes=function(){return this.substitutesEnabled=!1,this};var f={"!":!0,'"':!0,"#":!0,$:!0,"%":!0,"&":!0,"'":!0,"(":!0,")":!0,"*":!0,"+":!0,",":!0,".":!0,"/":!0,";":!0,"<":!0,"=":!0,">":!0,"?":!0,"@":!0,"[":!0,"\\":!0,"]":!0,"^":!0,"`":!0,"{":!0,"|":!0,"}":!0,"~":!0},g={"\n":"\\n","\r":"\\r","\t":"\\t","\f":"\\f","\v":"\\v"},h={n:"\n",r:"\r",t:"\t",f:"\f","\\":"\\","'":"'"},i={n:"\n",r:"\r",t:"\t",f:"\f","\\":"\\",'"':'"'};a.prototype.parse=function(a){return new e(a,0,this.pseudos,this.attrEqualityMods,this.ruleNestingOperators,this.substitutesEnabled).parse()},a.prototype.escapeIdentifier=function(a){for(var b="",c=0,d=a.length;c<d;){var e=a.charAt(c);if(f[e])b+="\\"+e;else if("_"===e||"-"===e||e>="A"&&e<="Z"||e>="a"&&e<="z"||0!==c&&e>="0"&&e<="9")b+=e;else{var g=e.charCodeAt(0);if(55296==(63488&g)){var h=a.charCodeAt(c++);if(55296!=(64512&g)||56320!=(64512&h))throw Error("UCS-2(decode): illegal sequence");g=((1023&g)<<10)+(1023&h)+65536}b+="\\"+g.toString(16)+" "}c++}return b},a.prototype.escapeStr=function(a){for(var b,c,d="",e=0,f=a.length;e<f;)b=a.charAt(e),'"'===b?b='\\"':"\\"===b?b="\\\\":(c=g[b])&&(b=c),d+=b,e++;return'"'+d+'"'},a.prototype.render=function(a){return this._renderEntity(a).trim()},a.prototype._renderEntity=function(a){var b,c,d;switch(d="",a.type){case"ruleSet":for(b=a.rule,c=[];b;)b.nestingOperator&&c.push(b.nestingOperator),c.push(this._renderEntity(b)),b=b.rule;d=c.join(" ");break;case"selectors":d=a.selectors.map(this._renderEntity,this).join(", ");break;case"rule":a.tagName&&(d="*"===a.tagName?"*":this.escapeIdentifier(a.tagName)),a.id&&(d+="#"+this.escapeIdentifier(a.id)),a.classNames&&(d+=a.classNames.map(function(a){return"."+this.escapeIdentifier(a)},this).join("")),a.attrs&&(d+=a.attrs.map(function(a){return a.operator?"substitute"===a.valueType?"["+this.escapeIdentifier(a.name)+a.operator+"$"+a.value+"]":"["+this.escapeIdentifier(a.name)+a.operator+this.escapeStr(a.value)+"]":"["+this.escapeIdentifier(a.name)+"]"},this).join("")),a.pseudos&&(d+=a.pseudos.map(function(a){return a.valueType?"selector"===a.valueType?":"+this.escapeIdentifier(a.name)+"("+this._renderEntity(a.value)+")":"substitute"===a.valueType?":"+this.escapeIdentifier(a.name)+"($"+a.value+")":"numeric"===a.valueType?":"+this.escapeIdentifier(a.name)+"("+a.value+")":":"+this.escapeIdentifier(a.name)+"("+this.escapeIdentifier(a.value)+")":":"+this.escapeIdentifier(a.name)},this).join(""));break;default:throw Error('Unknown entity type: "'+a.type(NaN))}return d};var j=new a;j.registerNestingOperators(">"),axe.utils.cssParser=j}(axe),L.prototype={get selector(){return this.spec.selector||[axe.utils.getSelector(this.element,this._options)]},get xpath(){return this.spec.xpath||[axe.utils.getXpath(this.element)]},get element(){return this._element},get fromFrame(){return this._fromFrame},toJSON:function(){"use strict";return{selector:this.selector,source:this.source,xpath:this.xpath}}},L.fromFrame=function(a,b,c){return a.selector.unshift(c.selector),a.xpath.unshift(c.xpath),new axe.utils.DqElement(c.element,b,a)},axe.utils.DqElement=L,axe.utils.matchesSelector=function(){"use strict";function a(a){var b,c,d=a.Element.prototype,e=["matches","matchesSelector","mozMatchesSelector","webkitMatchesSelector","msMatchesSelector"],f=e.length;for(b=0;b<f;b++)if(c=e[b],d[c])return c}var b;return function(c,d){return b&&c[b]||(b=a(c.ownerDocument.defaultView)),c[b](d)}}(),axe.utils.escapeSelector=function(a){"use strict";for(var b,c=String(a),d=c.length,e=-1,f="",g=c.charCodeAt(0);++e<d;){if(0==(b=c.charCodeAt(e)))throw new Error("INVALID_CHARACTER_ERR");b>=1&&b<=31||b>=127&&b<=159||0==e&&b>=48&&b<=57||1==e&&b>=48&&b<=57&&45==g?f+="\\"+b.toString(16)+" ":f+=(1!=e||45!=b||45!=g)&&(b>=128||45==b||95==b||b>=48&&b<=57||b>=65&&b<=90||b>=97&&b<=122)?c.charAt(e):"\\"+c.charAt(e)}return f},axe.utils.extendMetaData=function(a,b){Object.assign(a,b),Object.keys(b).filter(function(a){return"function"==typeof b[a]}).forEach(function(c){a[c]=null;try{a[c]=b[c](a)}catch(a){}})},axe.utils.finalizeRuleResult=function(a){return Object.assign(a,axe.utils.aggregateRule(a.nodes)),delete a.nodes,a};var ta="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a};axe.utils.findBy=function(a,b,c){if(Array.isArray(a))return a.find(function(a){return"object"===(void 0===a?"undefined":ta(a))&&a[b]===c})};var axe=axe||{utils:{}};axe.utils.getFlattenedTree=function(a,b){function c(a,c){var d=axe.utils.getFlattenedTree(c,b);return d&&(a=a.concat(d)),a}var d,e,f;if(a.documentElement&&(a=a.documentElement),f=a.nodeName.toLowerCase(),a.shadowRoot&&"marquee"!==f)return d=M(a,b),b="a"+Math.random().toString().substring(2),e=Array.from(a.shadowRoot.childNodes),d.children=e.reduce(c,[]),[d];if("content"===f)return e=Array.from(a.getDistributedNodes()),e.reduce(c,[]);if("slot"===f){e=Array.from(a.assignedNodes()),e.length||(e=N(a));window.getComputedStyle(a);return e.reduce(c,[])}return 1===a.nodeType?(d=M(a,b),e=Array.from(a.childNodes),d.children=e.reduce(c,[]),[d]):3===a.nodeType?[M(a)]:void 0},axe.utils.getNodeFromTree=function(a,b){var c;return a.actualNode===b?a:(a.children.forEach(function(a){var d;a.actualNode===b?c=a:(d=axe.utils.getNodeFromTree(a,b))&&(c=d)}),c)},axe.utils.getAllChecks=function(a){"use strict";return[].concat(a.any||[]).concat(a.all||[]).concat(a.none||[])},axe.utils.getCheckOption=function(a,b,c){var d=((c.rules&&c.rules[b]||{}).checks||{})[a.id],e=(c.checks||{})[a.id],f=a.enabled,g=a.options;return e&&(e.hasOwnProperty("enabled")&&(f=e.enabled),e.hasOwnProperty("options")&&(g=e.options)),d&&(d.hasOwnProperty("enabled")&&(f=d.enabled),d.hasOwnProperty("options")&&(g=d.options)),{enabled:f,options:g,absolutePaths:c.absolutePaths}};var Ba=function(){function a(a,b){var c=[],d=!0,e=!1,f=void 0;try{for(var g,h=a[Symbol.iterator]();!(d=(g=h.next()).done)&&(c.push(g.value),!b||c.length!==b);d=!0);}catch(a){e=!0,f=a}finally{try{!d&&h.return&&h.return()}finally{if(e)throw f}}return c}return function(b,c){if(Array.isArray(b))return b;if(Symbol.iterator in Object(b))return a(b,c);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();axe.utils.getFriendlyUriEnd=function(){var a=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",b=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!(a.length<=1||"data:"===a.substr(0,5)||"javascript:"===a.substr(0,11)||a.includes("?"))){var c=b.currentDomain,d=b.maxLength,e=void 0===d?25:d,f=Q(a),g=f.path,h=f.domain,i=f.hash,j=g.substr(g.substr(0,g.length-2).lastIndexOf("/")+1);if(i)return j&&(j+i).length<=e?j+i:j.length<2&&i.length>2&&i.length<=e?i:void 0;if(h&&h.length<e&&g.length<=1)return h+g;if(g==="/"+j&&h&&c&&h!==c&&(h+g).length<=e)return h+g;var k=j.lastIndexOf(".");return(-1===k||k>1)&&(-1!==k||j.length>2)&&j.length<=e&&!j.match(/index(\.[a-zA-Z]{2-4})?/)&&!O(j)?j:void 0}};var Ca=axe.utils.escapeSelector,Da=["div","span","p","b","i","u","strong","em","h2","h3"],Ea={getElmId:function(a){if(a.getAttribute("id")){var b=a.getRootNode&&a.getRootNode()||document,c="#"+Ca(a.getAttribute("id")||"");return c.match(/player_uid_/)||1!==b.querySelectorAll(c).length?void 0:c}},getCustomElm:function(a,b){var c=b.isCustomElm,d=b.nodeName;if(c)return d},getElmRoleProp:function(a){if(a.hasAttribute("role"))return'[role="'+Ca(a.getAttribute("role"))+'"]'},getUncommonElm:function(a,b){var c=b.isCommonElm,d=b.isCustomElm,e=b.nodeName;if(!c&&!d)return e=Ca(e),"input"===e&&a.hasAttribute("type")&&(e+='[type="'+a.type+'"]'),e},getElmNameProp:function(a){if(!a.hasAttribute("id")&&a.name)return'[name="'+Ca(a.name)+'"]'},getDistinctClass:function(a,b){var c=b.distinctClassList;if(c.length>0&&c.length<3)return"."+c.map(Ca).join(".")},getFileRefProp:function(a){var b=void 0;if(a.hasAttribute("href"))b="href";else{if(!a.hasAttribute("src"))return;b="src"}var c=axe.utils.getFriendlyUriEnd(a.getAttribute(b));if(c)return"["+b+'$="'+encodeURI(c)+'"]'},getCommonName:function(a,b){var c=b.nodeName;if(b.isCommonElm)return c}};axe.utils.getSelector=function(a){var b=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!a)return"";var c=a.getRootNode&&a.getRootNode()||document;if(11===c.nodeType){for(var d=[];11===c.nodeType;)d.push({elm:a,doc:c}),a=c.host,c=a.getRootNode();return d.push({elm:a,doc:c}),d.reverse().map(function(a){return W(a.elm,b,a.doc)})}return W(a,b,c)},axe.utils.getXpath=function(a){return Y(X(a))};var Fa;axe.utils.injectStyle=Z,axe.utils.isHidden=function(a,b){"use strict";var c;if(9===a.nodeType)return!1;11===a.nodeType&&(a=a.host);var d=window.getComputedStyle(a,null);return!d||!a.parentNode||"none"===d.getPropertyValue("display")||!b&&"hidden"===d.getPropertyValue("visibility")||"true"===a.getAttribute("aria-hidden")||(c=a.assignedSlot?a.assignedSlot:a.parentNode,axe.utils.isHidden(c,!0))},axe.utils.mergeResults=function(a,b){"use strict";var c=[];return a.forEach(function(a){var d=aa(a);d&&d.length&&d.forEach(function(d){d.nodes&&a.frame&&$(d.nodes,b,a.frameElement,a.frame);var e=axe.utils.findBy(c,"id",d.id);e?d.nodes.length&&_(e.nodes,d.nodes):c.push(d)})}),c},axe.utils.nodeSorter=function(a,b){"use strict";return a.actualNode===b.actualNode?0:4&a.actualNode.compareDocumentPosition(b.actualNode)?-1:1},utils.performanceTimer=function(){"use strict";function a(){if(window.performance&&window.performance)return window.performance.now()}var b=null,c=a();return{start:function(){this.mark("mark_axe_start")},end:function(){this.mark("mark_axe_end"),this.measure("axe","mark_axe_start","mark_axe_end"),this.logMeasures("axe")},auditStart:function(){this.mark("mark_audit_start")},auditEnd:function(){this.mark("mark_audit_end"),this.measure("audit_start_to_end","mark_audit_start","mark_audit_end"),this.logMeasures()},mark:function(a){window.performance&&void 0!==window.performance.mark&&window.performance.mark(a)},measure:function(a,b,c){window.performance&&void 0!==window.performance.measure&&window.performance.measure(a,b,c)},logMeasures:function(a){function b(a){axe.log("Measure "+a.name+" took "+a.duration+"ms")}if(window.performance&&void 0!==window.performance.getEntriesByType)for(var c=window.performance.getEntriesByType("measure"),d=0;d<c.length;++d){var e=c[d];if(e.name===a)return void b(e);b(e)}},timeElapsed:function(){return a()-c},reset:function(){b||(b=a()),c=a()}}}(),"function"!=typeof Object.assign&&function(){Object.assign=function(a){"use strict";if(void 0===a||null===a)throw new TypeError("Cannot convert undefined or null to object");for(var b=Object(a),c=1;c<arguments.length;c++){var d=arguments[c];if(void 0!==d&&null!==d)for(var e in d)d.hasOwnProperty(e)&&(b[e]=d[e])}return b}}(),Array.prototype.find||(Array.prototype.find=function(a){if(null===this)throw new TypeError("Array.prototype.find called on null or undefined");if("function"!=typeof a)throw new TypeError("predicate must be a function");for(var b,c=Object(this),d=c.length>>>0,e=arguments[1],f=0;f<d;f++)if(b=c[f],a.call(e,b,f,c))return b}),axe.utils.pollyfillElementsFromPoint=function(){if(document.elementsFromPoint)return document.elementsFromPoint;if(document.msElementsFromPoint)return document.msElementsFromPoint;var a=function(){var a=document.createElement("x");return a.style.cssText="pointer-events:auto","auto"===a.style.pointerEvents}(),b=a?"pointer-events":"visibility",c=a?"none":"hidden",d=document.createElement("style");return d.innerHTML=a?"* { pointer-events: all }":"* { visibility: visible }",function(a,e){var f,g,h,i=[],j=[];for(document.head.appendChild(d);(f=document.elementFromPoint(a,e))&&-1===i.indexOf(f);)i.push(f),j.push({value:f.style.getPropertyValue(b),priority:f.style.getPropertyPriority(b)}),f.style.setProperty(b,c,"important");for(g=j.length;h=j[--g];)i[g].style.setProperty(b,h.value?h.value:"",h.priority);return document.head.removeChild(d),i}},"function"==typeof window.addEventListener&&(document.elementsFromPoint=axe.utils.pollyfillElementsFromPoint()),Array.prototype.includes||(Array.prototype.includes=function(a){"use strict";var b=Object(this),c=parseInt(b.length,10)||0;if(0===c)return!1;var d,e=parseInt(arguments[1],10)||0;e>=0?d=e:(d=c+e)<0&&(d=0);for(var f;d<c;){if(f=b[d],a===f||a!==a&&f!==f)return!0;d++}return!1}),Array.prototype.some||(Array.prototype.some=function(a){"use strict";if(null==this)throw new TypeError("Array.prototype.some called on null or undefined");if("function"!=typeof a)throw new TypeError;for(var b=Object(this),c=b.length>>>0,d=arguments.length>=2?arguments[1]:void 0,e=0;e<c;e++)if(e in b&&a.call(d,b[e],e,b))return!0;return!1}),Array.from||(Array.from=function(){var a=Object.prototype.toString,b=function(b){return"function"==typeof b||"[object Function]"===a.call(b)},c=function(a){var b=Number(a);return isNaN(b)?0:0!==b&&isFinite(b)?(b>0?1:-1)*Math.floor(Math.abs(b)):b},d=Math.pow(2,53)-1,e=function(a){var b=c(a);return Math.min(Math.max(b,0),d)};return function(a){var c=this,d=Object(a);if(null==a)throw new TypeError("Array.from requires an array-like object - not null or undefined");var f,g=arguments.length>1?arguments[1]:void 0;if(void 0!==g){if(!b(g))throw new TypeError("Array.from: when provided, the second argument must be a function");arguments.length>2&&(f=arguments[2])}for(var h,i=e(d.length),j=b(c)?Object(new c(i)):new Array(i),k=0;k<i;)h=d[k],j[k]=g?void 0===f?g(h,k):g.call(f,h,k):h,k+=1;return j.length=i,j}}()),String.prototype.includes||(String.prototype.includes=function(a,b){return"number"!=typeof b&&(b=0),!(b+a.length>this.length)&&-1!==this.indexOf(a,b)});var ta="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a};axe.utils.publishMetaData=function(a){"use strict";var b=axe._audit.data.checks||{},c=axe._audit.data.rules||{},d=axe.utils.findBy(axe._audit.rules,"id",a.id)||{};a.tags=axe.utils.clone(d.tags||[]);var e=ca(b,!0),f=ca(b,!1);a.nodes.forEach(function(a){a.any.forEach(e),a.all.forEach(e),a.none.forEach(f)}),axe.utils.extendMetaData(a,axe.utils.clone(c[a.id]||{}))};var Ga=function(){},Ha=function(){},Ia=function(){/*! Credit: XRegExp 0.6.1 (c) 2007-2008 Steven Levithan <http://stevenlevithan.com/regex/xregexp/> MIT License */
+var a=/(?=[\-\[\]{}()*+?.\\\^$|,#\s])/g;return function(b){return b.replace(a,"\\")}}(),Ja=/\\/g;Ga=function(a){return a.map(function(a){for(var b=[],c=a.rule;c;)b.push({tag:c.tagName?c.tagName.toLowerCase():"*",combinator:c.nestingOperator?c.nestingOperator:" ",id:c.id,attributes:ja(c.attrs),classes:ka(c.classNames),pseudos:la(c.pseudos)}),c=c.rule;return b})},Ha=function(a,b,c){return b.reduce(function(b,d){var e=a;return d.forEach(function(a,b){if(c=">"!==a.combinator&&c,-1===[" ",">"].indexOf(a.combinator))throw new Error("axe.utils.querySelectorAll does not support the combinator: "+a.combinator);e=e.reduce(function(d,e){return d.concat(ia(b?e.children:e,a,c))},[])}),b.concat(e)},[])},axe.utils.querySelectorAll=function(a,b){a=Array.isArray(a)?a:[a];var c=axe.utils.cssParser.parse(b);return c=c.selectors?c.selectors:[c],c=Ga(c),Ha(a,c,!0)};var ta="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a};!function(){"use strict";function a(){}function b(a){if("function"!=typeof a)throw new TypeError("Queue methods require functions as arguments")}function c(){function c(b){return function(c){g[b]=c,(i-=1)||j===a||(k=!0,j(g))}}function d(b){return j=a,m(b),g}function e(){for(var a=g.length;h<a;h++){var b=g[h];try{b.call(null,c(h),d)}catch(a){d(a)}}}var f,g=[],h=0,i=0,j=a,k=!1,l=function(a){f=a,setTimeout(function(){void 0!==f&&null!==f&&axe.log("Uncaught error (of queue)",f)},1)},m=l,n={defer:function(a){if("object"===(void 0===a?"undefined":ta(a))&&a.then&&a.catch){var c=a;a=function(a,b){c.then(a).catch(b)}}if(b(a),void 0===f){if(k)throw new Error("Queue already completed");return g.push(a),++i,e(),n}},then:function(c){if(b(c),j!==a)throw new Error("queue `then` already set");return f||(j=c,i||(k=!0,j(g))),n},catch:function(a){if(b(a),m!==l)throw new Error("queue `catch` already set");return f?(a(f),f=null):m=a,n},abort:d};return n}axe.utils.queue=c}();var ta="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a};!function(a){"use strict";function b(){var a="axe",b="";return void 0!==axe&&axe._audit&&!axe._audit.application&&(a=axe._audit.application),void 0!==axe&&(b=axe.version),a+"."+b}function c(a){if("object"===(void 0===a?"undefined":ta(a))&&"string"==typeof a.uuid&&!0===a._respondable){var c=b();return a._source===c||"axe.x.y.z"===a._source||"axe.x.y.z"===c}return!1}function d(a,c,d,e,f,g){var h;d instanceof Error&&(h={name:d.name,message:d.message,stack:d.stack},d=void 0);var i={uuid:e,topic:c,message:d,error:h,_respondable:!0,_source:b(),_keepalive:f};"function"==typeof g&&(j[e]=g),a.postMessage(JSON.stringify(i),"*")}function e(a,b,c,e,f){d(a,b,c,Ka.v1(),e,f)}function f(a,b,c){return function(e,f,g){d(a,b,e,c,f,g)}}function g(a,b,c){var d=b.topic,e=k[d];if(e){var g=f(a,null,b.uuid);e(b.message,c,g)}}function h(a){var b=a.message||"Unknown error occurred",c=window[a.name]||Error;return a.stack&&(b+="\n"+a.stack.replace(a.message,"")),new c(b)}function i(a){var b;if("string"==typeof a){try{b=JSON.parse(a)}catch(a){}if(c(b))return"object"===ta(b.error)?b.error=h(b.error):b.error=void 0,b}}var j={},k={};e.subscribe=function(a,b){k[a]=b},e.isInFrame=function(a){return a=a||window,!!a.frameElement},"function"==typeof window.addEventListener&&window.addEventListener("message",function(a){var b=i(a.data);if(b){var c=b.uuid,e=b._keepalive,h=j[c];if(h){h(b.error||b.message,e,f(a.source,b.topic,c)),e||delete j[c]}if(!b.error)try{g(a.source,b,e)}catch(e){d(a.source,b.topic,e,c,!1)}}},!1),a.respondable=e}(utils),axe.utils.ruleShouldRun=function(a,b,c){"use strict";var d=c.runOnly||{},e=(c.rules||{})[a.id];return!(a.pageLevel&&!b.page)&&("rule"===d.type?-1!==d.values.indexOf(a.id):e&&"boolean"==typeof e.enabled?e.enabled:"tag"===d.type&&d.values?ma(a,d.values):ma(a,[]))},axe.utils.getScrollState=function(){var a=arguments.length>0&&void 0!==arguments[0]?arguments[0]:window,b=a.document.documentElement;return[void 0!==a.pageXOffset?{elm:a,top:a.pageYOffset,left:a.pageXOffset}:{elm:b,top:b.scrollTop,left:b.scrollLeft}].concat(pa(document.body))},axe.utils.setScrollState=function(a){a.forEach(function(a){return oa(a.elm,a.top,a.left)})},axe.utils.select=function(a,b){"use strict";for(var c,d=[],e=0,f=b.include.length;e<f;e++)c=b.include[e],c.actualNode.nodeType===c.actualNode.ELEMENT_NODE&&axe.utils.matchesSelector(c.actualNode,a)&&sa(d,[c],b),sa(d,axe.utils.querySelectorAll(c,a),b);return d.sort(axe.utils.nodeSorter)},axe.utils.toArray=function(a){"use strict";return Array.prototype.slice.call(a)};var Ka;!function(a){function b(a,b,c){var d=b&&c||0,e=0;for(b=b||[],a.toLowerCase().replace(/[0-9a-f]{2}/g,function(a){e<16&&(b[d+e++]=l[a])});e<16;)b[d+e++]=0;return b}function c(a,b){var c=b||0,d=k;return d[a[c++]]+d[a[c++]]+d[a[c++]]+d[a[c++]]+"-"+d[a[c++]]+d[a[c++]]+"-"+d[a[c++]]+d[a[c++]]+"-"+d[a[c++]]+d[a[c++]]+"-"+d[a[c++]]+d[a[c++]]+d[a[c++]]+d[a[c++]]+d[a[c++]]+d[a[c++]]}function d(a,b,d){var e=b&&d||0,f=b||[];a=a||{};var g=null!=a.clockseq?a.clockseq:p,h=null!=a.msecs?a.msecs:(new Date).getTime(),i=null!=a.nsecs?a.nsecs:r+1,j=h-q+(i-r)/1e4;if(j<0&&null==a.clockseq&&(g=g+1&16383),(j<0||h>q)&&null==a.nsecs&&(i=0),i>=1e4)throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");q=h,r=i,p=g,h+=122192928e5;var k=(1e4*(268435455&h)+i)%4294967296;f[e++]=k>>>24&255,f[e++]=k>>>16&255,f[e++]=k>>>8&255,f[e++]=255&k;var l=h/4294967296*1e4&268435455;f[e++]=l>>>8&255,f[e++]=255&l,f[e++]=l>>>24&15|16,f[e++]=l>>>16&255,f[e++]=g>>>8|128,f[e++]=255&g;for(var m=a.node||o,n=0;n<6;n++)f[e+n]=m[n];return b||c(f)}function e(a,b,d){var e=b&&d||0;"string"==typeof a&&(b="binary"==a?new j(16):null,a=null),a=a||{};var g=a.random||(a.rng||f)();if(g[6]=15&g[6]|64,g[8]=63&g[8]|128,b)for(var h=0;h<16;h++)b[e+h]=g[h];return b||c(g)}var f,g=a.crypto||a.msCrypto;if(!f&&g&&g.getRandomValues){var h=new Uint8Array(16);f=function(){return g.getRandomValues(h),h}}if(!f){var i=new Array(16);f=function(){for(var a,b=0;b<16;b++)0==(3&b)&&(a=4294967296*Math.random()),i[b]=a>>>((3&b)<<3)&255;return i}}for(var j="function"==typeof a.Buffer?a.Buffer:Array,k=[],l={},m=0;m<256;m++)k[m]=(m+256).toString(16).substr(1),l[k[m]]=m;var n=f(),o=[1|n[0],n[1],n[2],n[3],n[4],n[5]],p=16383&(n[6]<<8|n[7]),q=0,r=0;Ka=e,Ka.v1=d,Ka.v4=e,Ka.parse=b,Ka.unparse=c,Ka.BufferClass=j}(window),axe._load({data:{rules:{accesskeys:{description:"Ensures every accesskey attribute value is unique",help:"accesskey attribute value must be unique"},"area-alt":{description:"Ensures <area> elements of image maps have alternate text",help:"Active <area> elements must have alternate text"},"aria-allowed-attr":{description:"Ensures ARIA attributes are allowed for an element's role",help:"Elements must only use allowed ARIA attributes"},"aria-hidden-body":{description:"Ensures aria-hidden='true' is not present on the document body.",help:"aria-hidden='true' must not be present on the document body"},"aria-required-attr":{description:"Ensures elements with ARIA roles have all required ARIA attributes",help:"Required ARIA attributes must be provided"},"aria-required-children":{description:"Ensures elements with an ARIA role that require child roles contain them",help:"Certain ARIA roles must contain particular children"},"aria-required-parent":{description:"Ensures elements with an ARIA role that require parent roles are contained by them",help:"Certain ARIA roles must be contained by particular parents"},"aria-roles":{description:"Ensures all elements with a role attribute use a valid value",help:"ARIA roles used must conform to valid values"},"aria-valid-attr-value":{description:"Ensures all ARIA attributes have valid values",help:"ARIA attributes must conform to valid values"},"aria-valid-attr":{description:"Ensures attributes that begin with aria- are valid ARIA attributes",help:"ARIA attributes must conform to valid names"},"audio-caption":{description:"Ensures <audio> elements have captions",help:"<audio> elements must have a captions track"},blink:{description:"Ensures <blink> elements are not used",help:"<blink> elements are deprecated and must not be used"},"button-name":{description:"Ensures buttons have discernible text",help:"Buttons must have discernible text"},bypass:{description:"Ensures each page has at least one mechanism for a user to bypass navigation and jump straight to the content",help:"Page must have means to bypass repeated blocks"},checkboxgroup:{description:'Ensures related <input type="checkbox"> elements have a group and that that group designation is consistent',help:"Checkbox inputs with the same name attribute value must be part of a group"},"color-contrast":{description:"Ensures the contrast between foreground and background colors meets WCAG 2 AA contrast ratio thresholds",help:"Elements must have sufficient color contrast"},"definition-list":{description:"Ensures <dl> elements are structured correctly",help:"<dl> elements must only directly contain properly-ordered <dt> and <dd> groups, <script> or <template> elements"},dlitem:{description:"Ensures <dt> and <dd> elements are contained by a <dl>",help:"<dt> and <dd> elements must be contained by a <dl>"},"document-title":{description:"Ensures each HTML document contains a non-empty <title> element",help:"Documents must have <title> element to aid in navigation"},"duplicate-id":{description:"Ensures every id attribute value is unique",help:"id attribute value must be unique"},"empty-heading":{description:"Ensures headings have discernible text",help:"Headings must not be empty"},"frame-title-unique":{description:"Ensures <iframe> and <frame> elements contain a unique title attribute",help:"Frames must have a unique title attribute"},"frame-title":{description:"Ensures <iframe> and <frame> elements contain a non-empty title attribute",help:"Frames must have title attribute"},"heading-order":{description:"Ensures the order of headings is semantically correct",help:"Heading levels should only increase by one"},"hidden-content":{description:"Informs users about hidden content.",help:"Hidden content on the page cannot be analyzed"},"href-no-hash":{description:"Ensures that href values are valid link references to promote only using anchors as links",help:"Anchors must only be used as links with valid URLs or URL fragments"},"html-has-lang":{description:"Ensures every HTML document has a lang attribute",help:"<html> element must have a lang attribute"},"html-lang-valid":{description:"Ensures the lang attribute of the <html> element has a valid value",help:"<html> element must have a valid value for the lang attribute"},"image-alt":{description:"Ensures <img> elements have alternate text or a role of none or presentation",help:"Images must have alternate text"},"image-redundant-alt":{description:"Ensure button and link text is not repeated as image alternative",help:"Text of buttons and links should not be repeated in the image alternative"},"input-image-alt":{description:'Ensures <input type="image"> elements have alternate text',help:"Image buttons must have alternate text"},"label-title-only":{description:"Ensures that every form element is not solely labeled using the title or aria-describedby attributes",help:"Form elements should have a visible label"},label:{description:"Ensures every form element has a label",help:"Form elements must have labels"},"layout-table":{description:"Ensures presentational <table> elements do not use <th>, <caption> elements or the summary attribute",help:"Layout tables must not use data table elements"},"link-in-text-block":{description:"Links can be distinguished without relying on color",help:"Links must be distinguished from surrounding text in a way that does not rely on color"},"link-name":{description:"Ensures links have discernible text",help:"Links must have discernible text"},list:{description:"Ensures that lists are structured correctly",help:"<ul> and <ol> must only directly contain <li>, <script> or <template> elements"},listitem:{description:"Ensures <li> elements are used semantically",help:"<li> elements must be contained in a <ul> or <ol>"},marquee:{description:"Ensures <marquee> elements are not used",help:"<marquee> elements are deprecated and must not be used"},"meta-refresh":{description:'Ensures <meta http-equiv="refresh"> is not used',help:"Timed refresh must not exist"},"meta-viewport-large":{description:'Ensures <meta name="viewport"> can scale a significant amount',help:"Users should be able to zoom and scale the text up to 500%"},"meta-viewport":{description:'Ensures <meta name="viewport"> does not disable text scaling and zooming',help:"Zooming and scaling must not be disabled"},"object-alt":{description:"Ensures <object> elements have alternate text",help:"<object> elements must have alternate text"},"p-as-heading":{description:"Ensure p elements are not used to style headings",help:"Bold, italic text and font-size are not used to style p elements as a heading"},radiogroup:{description:'Ensures related <input type="radio"> elements have a group and that the group designation is consistent',help:"Radio inputs with the same name attribute value must be part of a group"},region:{description:"Ensures all content is contained within a landmark region",help:"Content should be contained in a landmark region"},"scope-attr-valid":{description:"Ensures the scope attribute is used correctly on tables",help:"scope attribute should be used correctly"},"server-side-image-map":{description:"Ensures that server-side image maps are not used",help:"Server-side image maps must not be used"},"skip-link":{description:"Ensures the first link on the page is a skip link",help:"The page should have a skip link as its first link"},tabindex:{description:"Ensures tabindex attribute values are not greater than 0",help:"Elements should not have tabindex greater than zero"},"table-duplicate-name":{description:"Ensure that tables do not have the same summary and caption",help:"The <caption> element should not contain the same text as the summary attribute"},"table-fake-caption":{description:"Ensure that tables with a caption use the <caption> element.",help:"Data or header cells should not be used to give caption to a data table."},"td-has-header":{description:"Ensure that each non-empty data cell in a large table has one or more table headers",help:"All non-empty td element in table larger than 3 by 3 must have an associated table header"},"td-headers-attr":{description:"Ensure that each cell in a table using the headers refers to another cell in that table",help:"All cells in a table element that use the headers attribute must only refer to other cells of that same table"},"th-has-data-cells":{description:"Ensure that each table header in a data table refers to data cells",help:"All th element and elements with role=columnheader/rowheader must data cells which it describes"},"valid-lang":{description:"Ensures lang attributes have valid values",help:"lang attribute must have a valid value"},"video-caption":{description:"Ensures <video> elements have captions",help:"<video> elements must have captions"},"video-description":{description:"Ensures <video> elements have audio descriptions",help:"<video> elements must have an audio description track"}},checks:{accesskeys:{impact:"serious",messages:{pass:function(a){return"Accesskey attribute value is unique"},fail:function(a){return"Document has multiple elements with the same accesskey"}}},"non-empty-alt":{impact:"critical",messages:{pass:function(a){return"Element has a non-empty alt attribute"},fail:function(a){return"Element has no alt attribute or the alt attribute is empty"}}},"non-empty-title":{impact:"serious",messages:{pass:function(a){return"Element has a title attribute"},fail:function(a){return"Element has no title attribute or the title attribute is empty"}}},"aria-label":{impact:"serious",messages:{pass:function(a){return"aria-label attribute exists and is not empty"},fail:function(a){return"aria-label attribute does not exist or is empty"}}},"aria-labelledby":{impact:"serious",messages:{pass:function(a){return"aria-labelledby attribute exists and references elements that are visible to screen readers"},fail:function(a){return"aria-labelledby attribute does not exist, references elements that do not exist or references elements that are empty or not visible"}}},"aria-allowed-attr":{impact:"critical",messages:{pass:function(a){return"ARIA attributes are used correctly for the defined role"},fail:function(a){var b="ARIA attribute"+(a.data&&a.data.length>1?"s are":" is")+" not allowed:",c=a.data;if(c)for(var d,e=-1,f=c.length-1;e<f;)d=c[e+=1],b+=" "+d;return b}}},"aria-hidden-body":{impact:"critical",messages:{pass:function(a){return"No aria-hidden attribute is present on document body"},fail:function(a){return"aria-hidden=true should not be present on the document body"}}},"aria-required-attr":{impact:"critical",messages:{pass:function(a){return"All required ARIA attributes are present"},fail:function(a){var b="Required ARIA attribute"+(a.data&&a.data.length>1?"s":"")+" not present:",c=a.data;if(c)for(var d,e=-1,f=c.length-1;e<f;)d=c[e+=1],b+=" "+d;return b}}},"aria-required-children":{impact:"critical",messages:{pass:function(a){return"Required ARIA children are present"},fail:function(a){var b="Required ARIA "+(a.data&&a.data.length>1?"children":"child")+" role not present:",c=a.data;if(c)for(var d,e=-1,f=c.length-1;e<f;)d=c[e+=1],b+=" "+d;return b}}},"aria-required-parent":{impact:"critical",messages:{pass:function(a){return"Required ARIA parent role present"},fail:function(a){var b="Required ARIA parent"+(a.data&&a.data.length>1?"s":"")+" role not present:",c=a.data;if(c)for(var d,e=-1,f=c.length-1;e<f;)d=c[e+=1],b+=" "+d;return b}}},invalidrole:{impact:"critical",messages:{pass:function(a){return"ARIA role is valid"},fail:function(a){return"Role must be one of the valid ARIA roles"}}},abstractrole:{impact:"serious",messages:{pass:function(a){return"Abstract roles are not used"},fail:function(a){return"Abstract roles cannot be directly used"}}},"aria-valid-attr-value":{impact:"critical",messages:{pass:function(a){return"ARIA attribute values are valid"},fail:function(a){var b="Invalid ARIA attribute value"+(a.data&&a.data.length>1?"s":"")+":",c=a.data;if(c)for(var d,e=-1,f=c.length-1;e<f;)d=c[e+=1],b+=" "+d;return b}}},"aria-valid-attr":{impact:"critical",messages:{pass:function(a){return"ARIA attribute name"+(a.data&&a.data.length>1?"s":"")+" are valid"},fail:function(a){var b="Invalid ARIA attribute name"+(a.data&&a.data.length>1?"s":"")+":",c=a.data;if(c)for(var d,e=-1,f=c.length-1;e<f;)d=c[e+=1],b+=" "+d;return b}}},caption:{impact:"critical",messages:{pass:function(a){return"The multimedia element has a captions track"},fail:function(a){return"The multimedia element does not have a captions track"},incomplete:function(a){return"A captions track for this element could not be found"}}},"is-on-screen":{impact:"serious",messages:{pass:function(a){return"Element is not visible"},fail:function(a){return"Element is visible"}}},"non-empty-if-present":{impact:"critical",messages:{pass:function(a){var b="Element ";return a.data?b+="has a non-empty value attribute":b+="does not have a value attribute",b},fail:function(a){return"Element has a value attribute and the value attribute is empty"}}},"non-empty-value":{impact:"critical",messages:{pass:function(a){return"Element has a non-empty value attribute"},fail:function(a){return"Element has no value attribute or the value attribute is empty"}}},"button-has-visible-text":{impact:"critical",messages:{pass:function(a){return"Element has inner text that is visible to screen readers"},fail:function(a){return"Element does not have inner text that is visible to screen readers"}}},"role-presentation":{impact:"minor",messages:{pass:function(a){return'Element\'s default semantics were overriden with role="presentation"'},fail:function(a){return'Element\'s default semantics were not overridden with role="presentation"'}}},"role-none":{impact:"minor",messages:{pass:function(a){return'Element\'s default semantics were overriden with role="none"'},fail:function(a){return'Element\'s default semantics were not overridden with role="none"'}}},"focusable-no-name":{impact:"serious",messages:{pass:function(a){return"Element is not in tab order or has accessible text"},fail:function(a){return"Element is in tab order and does not have accessible text"}}},"internal-link-present":{impact:"serious",messages:{pass:function(a){return"Valid skip link found"},fail:function(a){return"No valid skip link found"}}},"header-present":{impact:"serious",messages:{pass:function(a){return"Page has a header"},fail:function(a){return"Page does not have a header"}}},landmark:{impact:"serious",messages:{pass:function(a){return"Page has a landmark region"},fail:function(a){return"Page does not have a landmark region"}}},"group-labelledby":{impact:"critical",messages:{pass:function(a){return'All elements with the name "'+a.data.name+'" reference the same element with aria-labelledby'},fail:function(a){return'All elements with the name "'+a.data.name+'" do not reference the same element with aria-labelledby'}}},fieldset:{impact:"critical",messages:{pass:function(a){return"Element is contained in a fieldset"},fail:function(a){var b="",c=a.data&&a.data.failureCode;return b+="no-legend"===c?"Fieldset does not have a legend as its first child":"empty-legend"===c?"Legend does not have text that is visible to screen readers":"mixed-inputs"===c?"Fieldset contains unrelated inputs":"no-group-label"===c?"ARIA group does not have aria-label or aria-labelledby":"group-mixed-inputs"===c?"ARIA group contains unrelated inputs":"Element does not have a containing fieldset or ARIA group"}}},"color-contrast":{impact:"serious",messages:{pass:function(a){return"Element has sufficient color contrast of "+a.data.contrastRatio},fail:function(a){return"Element has insufficient color contrast of "+a.data.contrastRatio+" (foreground color: "+a.data.fgColor+", background color: "+a.data.bgColor+", font size: "+a.data.fontSize+", font weight: "+a.data.fontWeight+")"},incomplete:{bgImage:"Element's background color could not be determined due to a background image",bgGradient:"Element's background color could not be determined due to a background gradient",imgNode:"Element's background color could not be determined because element contains an image node",bgOverlap:"Element's background color could not be determined because it is overlapped by another element",fgAlpha:"Element's foreground color could not be determined because of alpha transparency",elmPartiallyObscured:"Element's background color could not be determined because it's partially obscured by another element",equalRatio:"Element has a 1:1 contrast ratio with the background",default:"Unable to determine contrast ratio"}}},"structured-dlitems":{impact:"serious",messages:{pass:function(a){return"When not empty, element has both <dt> and <dd> elements"},fail:function(a){return"When not empty, element does not have at least one <dt> element followed by at least one <dd> element"}}},"only-dlitems":{impact:"serious",messages:{pass:function(a){return"List element only has direct children that are allowed inside <dt> or <dd> elements"},fail:function(a){return"List element has direct children that are not allowed inside <dt> or <dd> elements"}}},dlitem:{impact:"serious",messages:{pass:function(a){return"Description list item has a <dl> parent element"},fail:function(a){return"Description list item does not have a <dl> parent element"}}},"doc-has-title":{impact:"serious",messages:{pass:function(a){return"Document has a non-empty <title> element"},fail:function(a){return"Document does not have a non-empty <title> element"}}},"duplicate-id":{impact:"moderate",messages:{pass:function(a){return"Document has no elements that share the same id attribute"},fail:function(a){return"Document has multiple elements with the same id attribute: "+a.data}}},"has-visible-text":{impact:"minor",messages:{pass:function(a){return"Element has text that is visible to screen readers"},fail:function(a){return"Element does not have text that is visible to screen readers"}}},"unique-frame-title":{impact:"serious",messages:{pass:function(a){return"Element's title attribute is unique"},fail:function(a){return"Element's title attribute is not unique"}}},"heading-order":{impact:"moderate",messages:{pass:function(a){return"Heading order valid"},fail:function(a){return"Heading order invalid"}}},"hidden-content":{impact:"minor",messages:{pass:function(a){return"All content on the page has been analyzed."},fail:function(a){return"There were problems analyzing the content on this page."},incomplete:function(a){return"There is hidden content on the page that was not analyzed. You will need to trigger the display of this content in order to analyze it."}}},"href-no-hash":{impact:"moderate",messages:{pass:function(a){return"Anchor does not have an href value of #"},fail:function(a){return"Anchor has an href value of #"}}},"has-lang":{impact:"serious",messages:{pass:function(a){return"The <html> element has a lang attribute"},fail:function(a){return"The <html> element does not have a lang attribute"}}},"valid-lang":{impact:"serious",messages:{pass:function(a){return"Value of lang attribute is included in the list of valid languages"},fail:function(a){return"Value of lang attribute not included in the list of valid languages"}}},"has-alt":{impact:"critical",messages:{pass:function(a){return"Element has an alt attribute"},fail:function(a){return"Element does not have an alt attribute"}}},"duplicate-img-label":{impact:"minor",messages:{pass:function(a){return"Element does not duplicate existing text in <img> alt text"},fail:function(a){return"Element contains <img> element with alt text that duplicates existing text"}}},"title-only":{impact:"serious",messages:{pass:function(a){return"Form element does not solely use title attribute for its label"},fail:function(a){return"Only title used to generate label for form element"}}},"implicit-label":{impact:"critical",messages:{pass:function(a){return"Form element has an implicit (wrapped) <label>"},fail:function(a){return"Form element does not have an implicit (wrapped) <label>"}}},"explicit-label":{impact:"critical",messages:{pass:function(a){return"Form element has an explicit <label>"},fail:function(a){return"Form element does not have an explicit <label>"}}},"help-same-as-label":{impact:"minor",messages:{pass:function(a){return"Help text (title or aria-describedby) does not duplicate label text"},fail:function(a){return"Help text (title or aria-describedby) text is the same as the label text"}}},"multiple-label":{impact:"serious",messages:{pass:function(a){return"Form element does not have multiple <label> elements"},fail:function(a){return"Form element has multiple <label> elements"}}},"has-th":{impact:"serious",messages:{pass:function(a){return"Layout table does not use <th> elements"},fail:function(a){return"Layout table uses <th> elements"}}},"has-caption":{impact:"serious",messages:{pass:function(a){return"Layout table does not use <caption> element"},fail:function(a){return"Layout table uses <caption> element"}}},"has-summary":{impact:"serious",messages:{pass:function(a){return"Layout table does not use summary attribute"},fail:function(a){return"Layout table uses summary attribute"}}},"link-in-text-block":{impact:"serious",messages:{pass:function(a){return"Links can be distinguished from surrounding text in a way that does not rely on color"},fail:function(a){return"Links can not be distinguished from surrounding text in a way that does not rely on color"},incomplete:{bgContrast:"Element's contrast ratio could not be determined. Check for a distinct hover/focus style",bgImage:"Element's contrast ratio could not be determined due to a background image",bgGradient:"Element's contrast ratio could not be determined due to a background gradient",imgNode:"Element's contrast ratio could not be determined because element contains an image node",bgOverlap:"Element's contrast ratio could not be determined because of element overlap",default:"Unable to determine contrast ratio"}}},"only-listitems":{impact:"serious",messages:{pass:function(a){return"List element only has direct children that are allowed inside <li> elements"},fail:function(a){return"List element has direct children that are not allowed inside <li> elements"}}},listitem:{impact:"serious",messages:{pass:function(a){return'List item has a <ul>, <ol> or role="list" parent element'},fail:function(a){return'List item does not have a <ul>, <ol> or role="list" parent element'}}},"meta-refresh":{impact:"critical",messages:{pass:function(a){return"<meta> tag does not immediately refresh the page"},fail:function(a){return"<meta> tag forces timed refresh of page"}}},"meta-viewport-large":{impact:"minor",messages:{pass:function(a){return"<meta> tag does not prevent significant zooming on mobile devices"},fail:function(a){return"<meta> tag limits zooming on mobile devices"}}},"meta-viewport":{impact:"critical",messages:{pass:function(a){return"<meta> tag does not disable zooming on mobile devices"},fail:function(a){return"<meta> tag disables zooming on mobile devices"}}},"p-as-heading":{impact:"serious",messages:{pass:function(a){return"<p> elements are not styled as headings"},fail:function(a){return"Heading elements should be used instead of styled p elements"}}},region:{impact:"moderate",messages:{pass:function(a){return"Content contained by ARIA landmark"},fail:function(a){return"Content not contained by an ARIA landmark"}}},"html5-scope":{impact:"moderate",messages:{pass:function(a){return"Scope attribute is only used on table header elements (<th>)"},fail:function(a){return"In HTML 5, scope attributes may only be used on table header elements (<th>)"}}},"scope-value":{impact:"critical",messages:{pass:function(a){return"Scope attribute is used correctly"},fail:function(a){return"The value of the scope attribute may only be 'row' or 'col'"}}},exists:{impact:"minor",messages:{pass:function(a){return"Element does not exist"},fail:function(a){return"Element exists"}}},"skip-link":{impact:"moderate",messages:{pass:function(a){return"Valid skip link found"},fail:function(a){return"No valid skip link found"}}},tabindex:{impact:"serious",messages:{pass:function(a){return"Element does not have a tabindex greater than 0"},fail:function(a){return"Element has a tabindex greater than 0"}}},"same-caption-summary":{impact:"minor",messages:{pass:function(a){return"Content of summary attribute and <caption> are not duplicated"},fail:function(a){return"Content of summary attribute and <caption> element are identical"}}},"caption-faked":{impact:"serious",messages:{pass:function(a){return"The first row of a table is not used as a caption"},fail:function(a){return"The first row of the table should be a caption instead of a table cell"}}},"td-has-header":{impact:"critical",messages:{pass:function(a){return"All non-empty data cells have table headers"},fail:function(a){return"Some non-empty data cells do not have table headers"}}},"td-headers-attr":{impact:"serious",messages:{pass:function(a){return"The headers attribute is exclusively used to refer to other cells in the table"},fail:function(a){return"The headers attribute is not exclusively used to refer to other cells in the table"}}},"th-has-data-cells":{impact:"serious",messages:{pass:function(a){return"All table header cells refer to data cells"},fail:function(a){return"Not all table header cells refer to data cells"},incomplete:function(a){return"Table data cells are missing or empty"}}},description:{impact:"critical",messages:{pass:function(a){
+return"The multimedia element has an audio description track"},fail:function(a){return"The multimedia element does not have an audio description track"},incomplete:function(a){return"An audio description track for this element could not be found"}}}},failureSummaries:{any:{failureMessage:function(a){var b="Fix any of the following:",c=a;if(c)for(var d,e=-1,f=c.length-1;e<f;)d=c[e+=1],b+="\n  "+d.split("\n").join("\n  ");return b}},none:{failureMessage:function(a){var b="Fix all of the following:",c=a;if(c)for(var d,e=-1,f=c.length-1;e<f;)d=c[e+=1],b+="\n  "+d.split("\n").join("\n  ");return b}}},incompleteFallbackMessage:function(a){return"aXe couldn't tell the reason. Time to break out the element inspector!"}},rules:[{id:"accesskeys",selector:"[accesskey]",excludeHidden:!1,tags:["wcag2a","wcag211","cat.keyboard"],all:[],any:[],none:["accesskeys"]},{id:"area-alt",selector:"map area[href]",excludeHidden:!1,tags:["cat.text-alternatives","wcag2a","wcag111","section508","section508.22.a"],all:[],any:["non-empty-alt","non-empty-title","aria-label","aria-labelledby"],none:[]},{id:"aria-allowed-attr",matches:function(a,b){var c=a.getAttribute("role");c||(c=axe.commons.aria.implicitRole(a));var d=axe.commons.aria.allowedAttr(c);if(c&&d){var e=/^aria-/;if(a.hasAttributes())for(var f=a.attributes,g=0,h=f.length;g<h;g++)if(e.test(f[g].name))return!0}return!1},tags:["cat.aria","wcag2a","wcag411","wcag412"],all:[],any:["aria-allowed-attr"],none:[]},{id:"aria-hidden-body",selector:"body",excludeHidden:!1,tags:["cat.aria","wcag2a","wcag412"],all:[],any:["aria-hidden-body"],none:[]},{id:"aria-required-attr",selector:"[role]",tags:["cat.aria","wcag2a","wcag411","wcag412"],all:[],any:["aria-required-attr"],none:[]},{id:"aria-required-children",selector:"[role]",tags:["cat.aria","wcag2a","wcag131"],all:[],any:["aria-required-children"],none:[]},{id:"aria-required-parent",selector:"[role]",tags:["cat.aria","wcag2a","wcag131"],all:[],any:["aria-required-parent"],none:[]},{id:"aria-roles",selector:"[role]",tags:["cat.aria","wcag2a","wcag131","wcag411","wcag412"],all:[],any:[],none:["invalidrole","abstractrole"]},{id:"aria-valid-attr-value",matches:function(a,b){var c=/^aria-/;if(a.hasAttributes())for(var d=a.attributes,e=0,f=d.length;e<f;e++)if(c.test(d[e].name))return!0;return!1},tags:["cat.aria","wcag2a","wcag131","wcag411","wcag412"],all:[],any:[{options:[],id:"aria-valid-attr-value"}],none:[]},{id:"aria-valid-attr",matches:function(a,b){var c=/^aria-/;if(a.hasAttributes())for(var d=a.attributes,e=0,f=d.length;e<f;e++)if(c.test(d[e].name))return!0;return!1},tags:["cat.aria","wcag2a","wcag411"],all:[],any:[{options:[],id:"aria-valid-attr"}],none:[]},{id:"audio-caption",selector:"audio",excludeHidden:!1,tags:["cat.time-and-media","wcag2a","wcag122","section508","section508.22.a"],all:[],any:[],none:["caption"]},{id:"blink",selector:"blink",excludeHidden:!1,tags:["cat.time-and-media","wcag2a","wcag222","section508","section508.22.j"],all:[],any:[],none:["is-on-screen"]},{id:"button-name",selector:'button, [role="button"], input[type="button"], input[type="submit"], input[type="reset"]',tags:["cat.name-role-value","wcag2a","wcag412","section508","section508.22.a"],all:[],any:["non-empty-if-present","non-empty-value","button-has-visible-text","aria-label","aria-labelledby","role-presentation","role-none"],none:["focusable-no-name"]},{id:"bypass",selector:"html",pageLevel:!0,matches:function(a,b){return!!a.querySelector("a[href]")},tags:["cat.keyboard","wcag2a","wcag241","section508","section508.22.o"],all:[],any:["internal-link-present","header-present","landmark"],none:[]},{id:"checkboxgroup",selector:"input[type=checkbox][name]",tags:["cat.forms","best-practice"],all:[],any:["group-labelledby","fieldset"],none:[]},{id:"color-contrast",matches:function(a,b){var c=a.nodeName.toUpperCase(),d=a.type;if("true"===a.getAttribute("aria-disabled")||axe.commons.dom.findUp(a,'[aria-disabled="true"]'))return!1;if("INPUT"===c)return-1===["hidden","range","color","checkbox","radio","image"].indexOf(d)&&!a.disabled;if("SELECT"===c)return!!a.options.length&&!a.disabled;if("TEXTAREA"===c)return!a.disabled;if("OPTION"===c)return!1;if("BUTTON"===c&&a.disabled||axe.commons.dom.findUp(a,"button[disabled]"))return!1;if("FIELDSET"===c&&a.disabled||axe.commons.dom.findUp(a,"fieldset[disabled]"))return!1;var e=axe.commons.dom.findUp(a,"label");if("LABEL"===c||e){var f=a;e&&(f=e);var g=axe.commons.dom.getRootNode(f),h=f.htmlFor&&g.getElementById(f.htmlFor);if(h&&h.disabled)return!1;var h=axe.utils.querySelectorAll(b,'input:not([type="hidden"]):not([type="image"]):not([type="button"]):not([type="submit"]):not([type="reset"]), select, textarea');if(h.length&&h[0].actualNode.disabled)return!1}if(a.getAttribute("id")){var i=axe.commons.utils.escapeSelector(a.getAttribute("id")),j=axe.commons.dom.getRootNode(a),h=j.querySelector("[aria-labelledby~="+i+"]");if(h&&h.disabled)return!1}if(""===axe.commons.text.visible(b,!1,!0))return!1;var k,l,m=document.createRange(),n=b.children,o=n.length;for(l=0;l<o;l++)k=n[l],3===k.actualNode.nodeType&&""!==axe.commons.text.sanitize(k.actualNode.nodeValue)&&m.selectNodeContents(k.actualNode);var p=m.getClientRects();for(o=p.length,l=0;l<o;l++)if(axe.commons.dom.visuallyOverlaps(p[l],a))return!0;return!1},excludeHidden:!1,options:{noScroll:!1},tags:["cat.color","wcag2aa","wcag143"],all:[],any:["color-contrast"],none:[]},{id:"definition-list",selector:"dl",matches:function(a,b){return!a.getAttribute("role")},tags:["cat.structure","wcag2a","wcag131"],all:[],any:[],none:["structured-dlitems","only-dlitems"]},{id:"dlitem",selector:"dd, dt",matches:function(a,b){return!a.getAttribute("role")},tags:["cat.structure","wcag2a","wcag131"],all:[],any:["dlitem"],none:[]},{id:"document-title",selector:"html",matches:function(a,b){return a.ownerDocument.defaultView.self===a.ownerDocument.defaultView.top},tags:["cat.text-alternatives","wcag2a","wcag242"],all:[],any:["doc-has-title"],none:[]},{id:"duplicate-id",selector:"[id]",excludeHidden:!1,tags:["cat.parsing","wcag2a","wcag411"],all:[],any:["duplicate-id"],none:[]},{id:"empty-heading",selector:'h1, h2, h3, h4, h5, h6, [role="heading"]',enabled:!0,tags:["cat.name-role-value","best-practice"],all:[],any:["has-visible-text","role-presentation","role-none"],none:[]},{id:"frame-title-unique",selector:"frame[title], iframe[title]",matches:function(a,b){var c=a.getAttribute("title");return!!(c?axe.commons.text.sanitize(c).trim():"")},tags:["cat.text-alternatives","best-practice"],all:[],any:[],none:["unique-frame-title"]},{id:"frame-title",selector:"frame, iframe",tags:["cat.text-alternatives","wcag2a","wcag241","section508","section508.22.i"],all:[],any:["aria-label","aria-labelledby","non-empty-title","role-presentation","role-none"],none:[]},{id:"heading-order",selector:"h1,h2,h3,h4,h5,h6,[role=heading]",enabled:!1,tags:["cat.semantics","best-practice"],all:[],any:["heading-order"],none:[]},{id:"hidden-content",selector:"*",excludeHidden:!1,tags:["experimental","review-item"],all:[],any:["hidden-content"],none:[],enabled:!1},{id:"href-no-hash",selector:"a[href]",enabled:!1,tags:["cat.semantics","best-practice"],all:[],any:["href-no-hash"],none:[]},{id:"html-has-lang",selector:"html",tags:["cat.language","wcag2a","wcag311"],all:[],any:["has-lang"],none:[]},{id:"html-lang-valid",selector:"html[lang]",tags:["cat.language","wcag2a","wcag311"],all:[],any:[],none:["valid-lang"]},{id:"image-alt",selector:"img, [role='img']",tags:["cat.text-alternatives","wcag2a","wcag111","section508","section508.22.a"],all:[],any:["has-alt","aria-label","aria-labelledby","non-empty-title","role-presentation","role-none"],none:[]},{id:"image-redundant-alt",selector:'button, [role="button"], a[href], p, li, td, th',tags:["cat.text-alternatives","best-practice"],all:[],any:[],none:["duplicate-img-label"]},{id:"input-image-alt",selector:'input[type="image"]',tags:["cat.text-alternatives","wcag2a","wcag111","section508","section508.22.a"],all:[],any:["non-empty-alt","aria-label","aria-labelledby","non-empty-title"],none:[]},{id:"label-title-only",selector:"input, select, textarea",matches:function(a,b){if("input"!==a.nodeName.toLowerCase())return!0;var c=a.getAttribute("type").toLowerCase();return"hidden"!==c&&"image"!==c&&"button"!==c&&"submit"!==c&&"reset"!==c},enabled:!1,tags:["cat.forms","best-practice"],all:[],any:[],none:["title-only"]},{id:"label",selector:"input, select, textarea",matches:function(a,b){if("input"!==a.nodeName.toLowerCase())return!0;var c=a.getAttribute("type").toLowerCase();return"hidden"!==c&&"image"!==c&&"button"!==c&&"submit"!==c&&"reset"!==c},tags:["cat.forms","wcag2a","wcag332","wcag131","section508","section508.22.n"],all:[],any:["aria-label","aria-labelledby","implicit-label","explicit-label","non-empty-title"],none:["help-same-as-label","multiple-label"]},{id:"layout-table",selector:"table",matches:function(a,b){return!axe.commons.table.isDataTable(a)},tags:["cat.semantics","wcag2a","wcag131"],all:[],any:[],none:["has-th","has-caption","has-summary"]},{id:"link-in-text-block",selector:"a[href], *[role=link]",matches:function(a,b){var c=axe.commons.text.sanitize(a.textContent),d=a.getAttribute("role");return(!d||"link"===d)&&(!!c&&(!!axe.commons.dom.isVisible(a,!1)&&axe.commons.dom.isInTextBlock(a)))},excludeHidden:!1,tags:["cat.color","experimental","wcag2a","wcag141"],all:["link-in-text-block"],any:[],none:[]},{id:"link-name",selector:"a[href], [role=link][href]",matches:function(a,b){return"button"!==a.getAttribute("role")},tags:["cat.name-role-value","wcag2a","wcag111","wcag412","wcag244","section508","section508.22.a"],all:[],any:["has-visible-text","aria-label","aria-labelledby","role-presentation","role-none"],none:["focusable-no-name"]},{id:"list",selector:"ul, ol",matches:function(a,b){return!a.getAttribute("role")},tags:["cat.structure","wcag2a","wcag131"],all:[],any:[],none:["only-listitems"]},{id:"listitem",selector:"li",matches:function(a,b){return!a.getAttribute("role")},tags:["cat.structure","wcag2a","wcag131"],all:[],any:["listitem"],none:[]},{id:"marquee",selector:"marquee",excludeHidden:!1,tags:["cat.parsing","wcag2a","wcag222"],all:[],any:[],none:["is-on-screen"]},{id:"meta-refresh",selector:'meta[http-equiv="refresh"]',excludeHidden:!1,tags:["cat.time","wcag2a","wcag2aaa","wcag221","wcag224","wcag325"],all:[],any:["meta-refresh"],none:[]},{id:"meta-viewport-large",selector:'meta[name="viewport"]',excludeHidden:!1,tags:["cat.sensory-and-visual-cues","best-practice"],all:[],any:[{options:{scaleMinimum:5,lowerBound:2},id:"meta-viewport-large"}],none:[]},{id:"meta-viewport",selector:'meta[name="viewport"]',excludeHidden:!1,tags:["cat.sensory-and-visual-cues","wcag2aa","wcag144"],all:[],any:[{options:{scaleMinimum:2},id:"meta-viewport"}],none:[]},{id:"object-alt",selector:"object",tags:["cat.text-alternatives","wcag2a","wcag111","section508","section508.22.a"],all:[],any:["has-visible-text","aria-label","aria-labelledby","non-empty-title"],none:[]},{id:"p-as-heading",selector:"p",matches:function(a,b){var c=Array.from(a.parentNode.childNodes),d=a.textContent.trim(),e=/[.!?:;](?![.!?:;])/g;return!(0===d.length||(d.match(e)||[]).length>=2)&&0!==c.slice(c.indexOf(a)+1).filter(function(a){return"P"===a.nodeName.toUpperCase()&&""!==a.textContent.trim()}).length},tags:["cat.semantics","wcag2a","wcag131","experimental"],all:[{options:{margins:[{weight:150,italic:!0},{weight:150,size:1.15},{italic:!0,size:1.15},{size:1.4}]},id:"p-as-heading"}],any:[],none:[]},{id:"radiogroup",selector:"input[type=radio][name]",tags:["cat.forms","best-practice"],all:[],any:["group-labelledby","fieldset"],none:[]},{id:"region",selector:"html",pageLevel:!0,enabled:!1,tags:["cat.keyboard","best-practice"],all:[],any:["region"],none:[]},{id:"scope-attr-valid",selector:"td[scope], th[scope]",enabled:!0,tags:["cat.tables","best-practice"],all:["html5-scope","scope-value"],any:[],none:[]},{id:"server-side-image-map",selector:"img[ismap]",tags:["cat.text-alternatives","wcag2a","wcag211","section508","section508.22.f"],all:[],any:[],none:["exists"]},{id:"skip-link",selector:"a[href]",pageLevel:!0,enabled:!1,tags:["cat.keyboard","best-practice"],all:[],any:["skip-link"],none:[]},{id:"tabindex",selector:"[tabindex]",tags:["cat.keyboard","best-practice"],all:[],any:["tabindex"],none:[]},{id:"table-duplicate-name",selector:"table",tags:["cat.tables","best-practice"],all:[],any:[],none:["same-caption-summary"]},{id:"table-fake-caption",selector:"table",matches:function(a,b){return axe.commons.table.isDataTable(a)},tags:["cat.tables","experimental","wcag2a","wcag131","section508","section508.22.g"],all:["caption-faked"],any:[],none:[]},{id:"td-has-header",selector:"table",matches:function(a,b){if(axe.commons.table.isDataTable(a)){var c=axe.commons.table.toArray(a);return c.length>=3&&c[0].length>=3&&c[1].length>=3&&c[2].length>=3}return!1},tags:["cat.tables","experimental","wcag2a","wcag131","section508","section508.22.g"],all:["td-has-header"],any:[],none:[]},{id:"td-headers-attr",selector:"table",tags:["cat.tables","wcag2a","wcag131","section508","section508.22.g"],all:["td-headers-attr"],any:[],none:[]},{id:"th-has-data-cells",selector:"table",matches:function(a,b){return axe.commons.table.isDataTable(a)},tags:["cat.tables","wcag2a","wcag131","section508","section508.22.g"],all:["th-has-data-cells"],any:[],none:[]},{id:"valid-lang",selector:"[lang], [xml\\:lang]",matches:function(a,b){return"html"!==a.nodeName.toLowerCase()},tags:["cat.language","wcag2aa","wcag312"],all:[],any:[],none:["valid-lang"]},{id:"video-caption",selector:"video",excludeHidden:!1,tags:["cat.text-alternatives","wcag2a","wcag122","wcag123","section508","section508.22.a"],all:[],any:[],none:["caption"]},{id:"video-description",selector:"video",excludeHidden:!1,tags:["cat.text-alternatives","wcag2aa","wcag125","section508","section508.22.b"],all:[],any:[],none:["description"]}],checks:[{id:"abstractrole",evaluate:function(a,b,c){return"abstract"===axe.commons.aria.getRoleType(a.getAttribute("role"))}},{id:"aria-allowed-attr",evaluate:function(a,b,c){var d,e,f,g=[],h=a.getAttribute("role"),i=a.attributes;if(h||(h=axe.commons.aria.implicitRole(a)),f=axe.commons.aria.allowedAttr(h),h&&f)for(var j=0,k=i.length;j<k;j++)d=i[j],e=d.name,axe.commons.aria.validateAttr(e)&&-1===f.indexOf(e)&&g.push(e+'="'+d.nodeValue+'"');return!g.length||(this.data(g),!1)}},{id:"aria-hidden-body",evaluate:function(a,b,c){return"true"!==a.getAttribute("aria-hidden")}},{id:"invalidrole",evaluate:function(a,b,c){return!axe.commons.aria.isValidRole(a.getAttribute("role"))}},{id:"aria-required-attr",evaluate:function(a,b,c){var d=[];if(a.hasAttributes()){var e,f=a.getAttribute("role"),g=axe.commons.aria.requiredAttr(f);if(f&&g)for(var h=0,i=g.length;h<i;h++)e=g[h],a.getAttribute(e)||d.push(e)}return!d.length||(this.data(d),!1)}},{id:"aria-required-children",evaluate:function(a,b,c){function d(a,b,c,d){if(null===a)return!1;var e=g(c),f=['[role="'+c+'"]'];return e&&(f=f.concat(e)),f=f.join(","),d?h(a,f)||!!axe.utils.querySelectorAll(b,f)[0]:!!axe.utils.querySelectorAll(b,f)[0]}function e(a,b){var c,e;for(c=0,e=a.length;c<e;c++)if(null!==a[c]){var f=axe.utils.getNodeFromTree(axe._tree[0],a[c]);if(d(a[c],f,b,!0))return!0}return!1}var f=axe.commons.aria.requiredOwned,g=axe.commons.aria.implicitNodes,h=axe.commons.utils.matchesSelector,i=axe.commons.dom.idrefs,j=a.getAttribute("role"),k=f(j);if(!k)return!0;var l=!1,m=k.one;if(!m){var l=!0;m=k.all}var n=function(a,b,f){var g,h=b.length,j=[],k=i(a,"aria-owns");for(g=0;g<h;g++){var l=b[g];if(d(a,c,l)||e(k,l)){if(!f)return null}else f&&j.push(l)}return j.length?j:!f&&b.length?b:null}(a,m,l);return!n||(this.data(n),!1)}},{id:"aria-required-parent",evaluate:function(a,b,c){function d(a){return(axe.commons.aria.implicitNodes(a)||[]).concat('[role="'+a+'"]').join(",")}function e(a,b,c){var e,f,g=a.getAttribute("role"),h=[];if(b||(b=axe.commons.aria.requiredContext(g)),!b)return null;for(e=0,f=b.length;e<f;e++){if(c&&axe.utils.matchesSelector(a,d(b[e])))return null;if(axe.commons.dom.findUp(a,d(b[e])))return null;h.push(b[e])}return h}var f=e(a);if(!f)return!0;var g=function(a){for(var b=[],c=null;a;){if(a.getAttribute("id")){var d=axe.commons.utils.escapeSelector(a.getAttribute("id"));c=axe.commons.dom.getRootNode(a).querySelector("[aria-owns~="+d+"]"),c&&b.push(c)}a=a.parentElement}return b.length?b:null}(a);if(g)for(var h=0,i=g.length;h<i;h++)if(!(f=e(g[h],f,!0)))return!0;return this.data(f),!1}},{id:"aria-valid-attr-value",evaluate:function(a,b,c){b=Array.isArray(b)?b:[];for(var d,e,f=[],g=/^aria-/,h=a.attributes,i=0,j=h.length;i<j;i++)d=h[i],e=d.name,-1===b.indexOf(e)&&g.test(e)&&!axe.commons.aria.validateAttrValue(a,e)&&f.push(e+'="'+d.nodeValue+'"');return!f.length||(this.data(f),!1)},options:[]},{id:"aria-valid-attr",evaluate:function(a,b,c){b=Array.isArray(b)?b:[];for(var d,e=[],f=/^aria-/,g=a.attributes,h=0,i=g.length;h<i;h++)d=g[h].name,-1===b.indexOf(d)&&f.test(d)&&!axe.commons.aria.validateAttr(d)&&e.push(d);return!e.length||(this.data(e),!1)},options:[]},{id:"color-contrast",evaluate:function(a,b,c){if(!axe.commons.dom.isVisible(a,!1))return!0;var d,e=!!(b||{}).noScroll,f=[],g=axe.commons.color.getBackgroundColor(a,f,e),h=axe.commons.color.getForegroundColor(a,e),i=window.getComputedStyle(a),j=parseFloat(i.getPropertyValue("font-size")),k=i.getPropertyValue("font-weight"),l=-1!==["bold","bolder","600","700","800","900"].indexOf(k),m=axe.commons.color.hasValidContrastRatio(g,h,j,l),n=Math.floor(100*m.contrastRatio)/100;null===g&&(d=axe.commons.color.incompleteData.get("bgColor"));var o=!1;1===n&&(o=!0,d=axe.commons.color.incompleteData.set("bgColor","equalRatio"));var p={fgColor:h?h.toHexString():void 0,bgColor:g?g.toHexString():void 0,contrastRatio:m?n:void 0,fontSize:(72*j/96).toFixed(1)+"pt",fontWeight:l?"bold":"normal",missingData:d};return this.data(p),null===h||null===g||o?(d=null,axe.commons.color.incompleteData.clear(),void this.relatedNodes(f)):(m.isValid||this.relatedNodes(f),m.isValid)}},{id:"link-in-text-block",evaluate:function(a,b,c){function d(a,b){var c=a.getRelativeLuminance(),d=b.getRelativeLuminance();return(Math.max(c,d)+.05)/(Math.min(c,d)+.05)}function e(a){var b=window.getComputedStyle(a).getPropertyValue("display");return-1!==i.indexOf(b)||"table-"===b.substr(0,6)}var f=axe.commons,g=f.color,h=f.dom,i=["block","list-item","table","flex","grid","inline-block"];if(e(a))return!1;for(var j=h.getComposedParent(a);1===j.nodeType&&!e(j);)j=h.getComposedParent(j);if(this.relatedNodes([j]),g.elementIsDistinct(a,j))return!0;var k,l;if(k=g.getForegroundColor(a),l=g.getForegroundColor(j),k&&l){var m=d(k,l);if(1===m)return!0;if(m>=3)return axe.commons.color.incompleteData.set("fgColor","bgContrast"),this.data({missingData:axe.commons.color.incompleteData.get("fgColor")}),void axe.commons.color.incompleteData.clear();if(k=g.getBackgroundColor(a),l=g.getBackgroundColor(j),!k||!l||d(k,l)>=3){var n=void 0;return n=k&&l?"bgContrast":axe.commons.color.incompleteData.get("bgColor"),axe.commons.color.incompleteData.set("fgColor",n),this.data({missingData:axe.commons.color.incompleteData.get("fgColor")}),void axe.commons.color.incompleteData.clear()}return!1}}},{id:"fieldset",evaluate:function(a,b,c){function d(a,b){return axe.commons.utils.toArray(a.querySelectorAll('select,textarea,button,input:not([name="'+b+'"]):not([type="hidden"])'))}function e(a,b){var c=a.firstElementChild;if(!c||"LEGEND"!==c.nodeName.toUpperCase())return i.relatedNodes([a]),h="no-legend",!1;if(!axe.commons.text.accessibleText(c))return i.relatedNodes([c]),h="empty-legend",!1;var e=d(a,b);return!e.length||(i.relatedNodes(e),h="mixed-inputs",!1)}function f(a,b){var c=axe.commons.dom.idrefs(a,"aria-labelledby").some(function(a){return a&&axe.commons.text.accessibleText(a)}),e=a.getAttribute("aria-label");if(!(c||e&&axe.commons.text.sanitize(e)))return i.relatedNodes(a),h="no-group-label",!1;var f=d(a,b);return!f.length||(i.relatedNodes(f),h="group-mixed-inputs",!1)}function g(a,b){return axe.commons.utils.toArray(a).filter(function(a){return a!==b})}var h,i=this,j={name:a.getAttribute("name"),type:a.getAttribute("type")},k=function(b){var c=axe.commons.utils.escapeSelector(a.name),d=axe.commons.dom.getRootNode(a),j=d.querySelectorAll('input[type="'+axe.commons.utils.escapeSelector(a.type)+'"][name="'+c+'"]');if(j.length<2)return!0;var k=axe.commons.dom.findUp(b,"fieldset"),l=axe.commons.dom.findUp(b,'[role="group"]'+("radio"===a.type?',[role="radiogroup"]':""));return l||k?k?e(k,c):f(l,c):(h="no-group",i.relatedNodes(g(j,b)),!1)}(a);return k||(j.failureCode=h),this.data(j),k},after:function(a,b){var c={};return a.filter(function(a){if(a.result)return!0;var b=a.data;if(b){if(c[b.type]=c[b.type]||{},!c[b.type][b.name])return c[b.type][b.name]=[b],!0;var d=c[b.type][b.name].some(function(a){return a.failureCode===b.failureCode});return d||c[b.type][b.name].push(b),!d}return!1})}},{id:"group-labelledby",evaluate:function(a,b,c){this.data({name:a.getAttribute("name"),type:a.getAttribute("type")});var d=axe.commons.dom.getRootNode(a),e=d.querySelectorAll('input[type="'+axe.commons.utils.escapeSelector(a.type)+'"][name="'+axe.commons.utils.escapeSelector(a.name)+'"]');return e.length<=1||0!==[].map.call(e,function(a){var b=a.getAttribute("aria-labelledby");return b?b.split(/\s+/):[]}).reduce(function(a,b){return a.filter(function(a){return b.includes(a)})}).filter(function(a){var b=d.getElementById(a);return b&&axe.commons.text.accessibleText(b)}).length},after:function(a,b){var c={};return a.filter(function(a){var b=a.data;return!(!b||(c[b.type]=c[b.type]||{},c[b.type][b.name]))&&(c[b.type][b.name]=!0,!0)})}},{id:"accesskeys",evaluate:function(a,b,c){return axe.commons.dom.isVisible(a,!1)&&(this.data(a.getAttribute("accesskey")),this.relatedNodes([a])),!0},after:function(a,b){var c={};return a.filter(function(a){if(!a.data)return!1;var b=a.data.toUpperCase();return c[b]?(c[b].relatedNodes.push(a.relatedNodes[0]),!1):(c[b]=a,a.relatedNodes=[],!0)}).map(function(a){return a.result=!!a.relatedNodes.length,a})}},{id:"focusable-no-name",evaluate:function(a,b,c){var d=a.getAttribute("tabindex");return!!(axe.commons.dom.isFocusable(a)&&d>-1)&&!axe.commons.text.accessibleText(a)}},{id:"tabindex",evaluate:function(a,b,c){return a.tabIndex<=0}},{id:"duplicate-img-label",evaluate:function(a,b,c){var d=axe.commons.text.visible(c,!0).toLowerCase();return""!==d&&axe.utils.querySelectorAll(c,"img").filter(function(a){var b=a.actualNode;return axe.commons.dom.isVisible(b)&&!["none","presentation"].includes(b.getAttribute("role"))}).some(function(a){return d===axe.commons.text.accessibleText(a).toLowerCase()})}},{id:"explicit-label",evaluate:function(a,b,c){if(a.getAttribute("id")){var d=axe.commons.dom.getRootNode(a),e=axe.commons.utils.escapeSelector(a.getAttribute("id")),f=d.querySelector('label[for="'+e+'"]');if(f)return!!axe.commons.text.accessibleText(f)}return!1}},{id:"help-same-as-label",evaluate:function(a,b,c){var d=axe.commons.text.label(c),e=a.getAttribute("title");if(!d)return!1;if(!e&&(e="",a.getAttribute("aria-describedby"))){e=axe.commons.dom.idrefs(a,"aria-describedby").map(function(a){return a?axe.commons.text.accessibleText(a):""}).join("")}return axe.commons.text.sanitize(e)===axe.commons.text.sanitize(d)},enabled:!1},{id:"implicit-label",evaluate:function(a,b,c){var d=axe.commons.dom.findUp(a,"label");return!!d&&!!axe.commons.text.accessibleText(d)}},{id:"multiple-label",evaluate:function(a,b,c){var d=axe.commons.utils.escapeSelector(a.getAttribute("id")),e=Array.from(document.querySelectorAll('label[for="'+d+'"]')),f=a.parentNode;for(e.length&&(e=e.filter(function(a,b){if(0===b&&!axe.commons.dom.isVisible(a,!0)||axe.commons.dom.isVisible(a,!0))return a}));f;)"LABEL"===f.tagName&&-1===e.indexOf(f)&&e.push(f),f=f.parentNode;return this.relatedNodes(e),e.length>1}},{id:"title-only",evaluate:function(a,b,c){return!(axe.commons.text.label(c)||!a.getAttribute("title")&&!a.getAttribute("aria-describedby"))}},{id:"has-lang",evaluate:function(a,b,c){return!!(a.getAttribute("lang")||a.getAttribute("xml:lang")||"").trim()}},{id:"valid-lang",evaluate:function(a,b,c){function d(a){return a.trim().split("-")[0].toLowerCase()}var e,f;return e=(b||axe.commons.utils.validLangs()).map(d),f=["lang","xml:lang"].reduce(function(b,c){var f=a.getAttribute(c);if("string"!=typeof f)return b;var g=d(f);return""!==g&&-1===e.indexOf(g)&&b.push(c+'="'+a.getAttribute(c)+'"'),b},[]),!!f.length&&(this.data(f),!0)}},{id:"dlitem",evaluate:function(a,b,c){return"DL"===axe.commons.dom.getComposedParent(a).nodeName.toUpperCase()}},{id:"has-listitem",evaluate:function(a,b,c){return c.children.every(function(a){return"LI"!==a.actualNode.nodeName.toUpperCase()})}},{id:"listitem",evaluate:function(a,b,c){var d=axe.commons.dom.getComposedParent(a);return["UL","OL"].includes(d.nodeName.toUpperCase())||"list"===(d.getAttribute("role")||"").toLowerCase()}},{id:"only-dlitems",evaluate:function(a,b,c){var d=[],e=["STYLE","META","LINK","MAP","AREA","SCRIPT","DATALIST","TEMPLATE"],f=!1;return c.children.forEach(function(a){var b=a.actualNode,c=b.nodeName.toUpperCase();1===b.nodeType&&"DT"!==c&&"DD"!==c&&-1===e.indexOf(c)?d.push(b):3===b.nodeType&&""!==b.nodeValue.trim()&&(f=!0)}),d.length&&this.relatedNodes(d),!!d.length||f}},{id:"only-listitems",evaluate:function(a,b,c){var d=[],e=["STYLE","META","LINK","MAP","AREA","SCRIPT","DATALIST","TEMPLATE"],f=!1;return c.children.forEach(function(a){var b=a.actualNode,c=b.nodeName.toUpperCase();1===b.nodeType&&"LI"!==c&&-1===e.indexOf(c)?d.push(b):3===b.nodeType&&""!==b.nodeValue.trim()&&(f=!0)}),d.length&&this.relatedNodes(d),!!d.length||f}},{id:"structured-dlitems",evaluate:function(a,b,c){var d=c.children;if(!d||!d.length)return!1;for(var e,f=!1,g=!1,h=0;h<d.length;h++){if(e=d[h].actualNode.nodeName.toUpperCase(),"DT"===e&&(f=!0),f&&"DD"===e)return!1;"DD"===e&&(g=!0)}return f||g}},{id:"caption",evaluate:function(a,b,c){var d=axe.utils.querySelectorAll(c,"track");if(d.length)return!d.some(function(a){return"captions"===(a.actualNode.getAttribute("kind")||"").toLowerCase()})}},{id:"description",evaluate:function(a,b,c){var d=axe.utils.querySelectorAll(c,"track");if(d.length){var e=!d.some(function(a){return"descriptions"===(a.actualNode.getAttribute("kind")||"").toLowerCase()});return axe.log(d.map(function(a){return a.actualNode.getAttribute("kind")}),e),e}}},{id:"meta-viewport-large",evaluate:function(a,b,c){b=b||{};for(var d,e=a.getAttribute("content")||"",f=e.split(/[;,]/),g={},h=b.scaleMinimum||2,i=b.lowerBound||!1,j=0,k=f.length;j<k;j++){d=f[j].split("=");var l=d.shift().toLowerCase();l&&d.length&&(g[l.trim()]=d.shift().trim().toLowerCase())}return!!(i&&g["maximum-scale"]&&parseFloat(g["maximum-scale"])<i)||!(!i&&"no"===g["user-scalable"])&&!(g["maximum-scale"]&&parseFloat(g["maximum-scale"])<h)},options:{scaleMinimum:5,lowerBound:2}},{id:"meta-viewport",evaluate:function(a,b,c){b=b||{};for(var d,e=a.getAttribute("content")||"",f=e.split(/[;,]/),g={},h=b.scaleMinimum||2,i=b.lowerBound||!1,j=0,k=f.length;j<k;j++){d=f[j].split("=");var l=d.shift().toLowerCase();l&&d.length&&(g[l.trim()]=d.shift().trim().toLowerCase())}return!!(i&&g["maximum-scale"]&&parseFloat(g["maximum-scale"])<i)||!(!i&&"no"===g["user-scalable"])&&!(g["maximum-scale"]&&parseFloat(g["maximum-scale"])<h)},options:{scaleMinimum:2}},{id:"header-present",evaluate:function(a,b,c){return!!a.querySelector('h1, h2, h3, h4, h5, h6, [role="heading"]')}},{id:"heading-order",evaluate:function(a,b,c){var d=a.getAttribute("aria-level");if(null!==d)return this.data(parseInt(d,10)),!0;var e=a.tagName.match(/H(\d)/);return!e||(this.data(parseInt(e[1],10)),!0)},after:function(a,b){if(a.length<2)return a;for(var c=a[0].data,d=1;d<a.length;d++)a[d].result&&a[d].data>c+1&&(a[d].result=!1),c=a[d].data;return a}},{id:"href-no-hash",evaluate:function(a,b,c){return"#"!==a.getAttribute("href")}},{id:"internal-link-present",evaluate:function(a,b,c){return!!a.querySelector('a[href^="#"]')}},{id:"landmark",evaluate:function(a,b,c){return axe.utils.querySelectorAll(c,'main, [role="main"]').length>0}},{id:"meta-refresh",evaluate:function(a,b,c){var d=a.getAttribute("content")||"",e=d.split(/[;,]/);return""===d||"0"===e[0]}},{id:"p-as-heading",evaluate:function(a,b,c){function d(a){for(var b=a,c=a.textContent.trim(),d=c;d===c&&void 0!==b;){var e=-1;if(a=b,0===a.children.length)return a;do{e++,d=a.children[e].textContent.trim()}while(""===d&&e+1<a.children.length);b=a.children[e]}return a}function e(a){switch(a){case"lighter":return 100;case"normal":return 400;case"bold":return 700;case"bolder":return 900}return a=parseInt(a),isNaN(a)?400:a}function f(a){var b=window.getComputedStyle(d(a));return{fontWeight:e(b.getPropertyValue("font-weight")),fontSize:parseInt(b.getPropertyValue("font-size")),isItalic:"italic"===b.getPropertyValue("font-style")}}function g(a,b,c){return c.reduce(function(c,d){return c||(!d.size||a.fontSize/d.size>b.fontSize)&&(!d.weight||a.fontWeight-d.weight>b.fontWeight)&&(!d.italic||a.isItalic&&!b.isItalic)},!1)}var h=Array.from(a.parentNode.children),i=h.indexOf(a);b=b||{};var j=b.margins||[],k=h.slice(i+1).find(function(a){return"P"===a.nodeName.toUpperCase()}),l=h.slice(0,i).reverse().find(function(a){return"P"===a.nodeName.toUpperCase()}),m=f(a),n=k?f(k):null,o=l?f(l):null;if(!n||!g(m,n,j))return!0;var p=axe.commons.dom.findUp(a,"blockquote");return!!(p&&"BLOCKQUOTE"===p.nodeName.toUpperCase()||o&&!g(m,o,j))&&void 0},options:{margins:[{weight:150,italic:!0},{weight:150,size:1.15},{italic:!0,size:1.15},{size:1.4}]}},{id:"region",evaluate:function(a,b,c){function d(a){return j&&j===a}function e(a){return a.hasAttribute("role")?k.includes(a.getAttribute("role").toLowerCase()):l.includes(a.nodeName.toUpperCase())}function f(a){var b=a.actualNode;return e(b)||d(b)||!h.isVisible(b,!0)?[]:h.hasContent(b,!0)?[b]:a.children.filter(function(a){return 1===a.actualNode.nodeType}).map(f).reduce(function(a,b){return a.concat(b)},[])}var g=axe.commons,h=g.dom,i=g.aria,j=function(a){var b=axe.utils.querySelectorAll(a,"a[href]")[0];if(b&&axe.commons.dom.getElementByReference(b.actualNode,"href"))return b.actualNode}(c),k=i.getRolesByType("landmark"),l=k.reduce(function(a,b){return a.concat(i.implicitNodes(b))},[]).filter(function(a){return null!==a}).map(function(a){return a.toUpperCase()}),m=f(c);return this.relatedNodes(m),0===m.length},after:function(a,b){return[a[0]]}},{id:"skip-link",evaluate:function(a,b,c){return axe.commons.dom.isFocusable(axe.commons.dom.getElementByReference(a,"href"))},after:function(a,b){return[a[0]]}},{id:"unique-frame-title",evaluate:function(a,b,c){var d=axe.commons.text.sanitize(a.title).trim().toLowerCase();return this.data(d),!0},after:function(a,b){var c={};return a.forEach(function(a){c[a.data]=void 0!==c[a.data]?++c[a.data]:0}),a.forEach(function(a){a.result=!!c[a.data]}),a}},{id:"aria-label",evaluate:function(a,b,c){var d=a.getAttribute("aria-label");return!!(d?axe.commons.text.sanitize(d).trim():"")}},{id:"aria-labelledby",evaluate:function(a,b,c){return(0,axe.commons.dom.idrefs)(a,"aria-labelledby").some(function(a){return a&&axe.commons.text.accessibleText(a,!0)})}},{id:"button-has-visible-text",evaluate:function(a,b,c){var d=a.nodeName.toUpperCase(),e=a.getAttribute("role"),f=void 0;return("BUTTON"===d||"button"===e&&"INPUT"!==d)&&(f=axe.commons.text.accessibleText(a),this.data(f),!!f)}},{id:"doc-has-title",evaluate:function(a,b,c){var d=document.title;return!!(d?axe.commons.text.sanitize(d).trim():"")}},{id:"duplicate-id",evaluate:function(a,b,c){if(!a.getAttribute("id").trim())return!0;for(var d=axe.commons.utils.escapeSelector(a.getAttribute("id")),e=document.querySelectorAll('[id="'+d+'"]'),f=[],g=0;g<e.length;g++)e[g]!==a&&f.push(e[g]);return f.length&&this.relatedNodes(f),this.data(a.getAttribute("id")),e.length<=1},after:function(a,b){var c=[];return a.filter(function(a){return-1===c.indexOf(a.data)&&(c.push(a.data),!0)})}},{
+id:"exists",evaluate:function(a,b,c){return!0}},{id:"has-alt",evaluate:function(a,b,c){var d=a.nodeName.toLowerCase();return a.hasAttribute("alt")&&("img"===d||"input"===d||"area"===d)}},{id:"has-visible-text",evaluate:function(a,b,c){return axe.commons.text.accessibleText(a).length>0}},{id:"is-on-screen",evaluate:function(a,b,c){return axe.commons.dom.isVisible(a,!1)&&!axe.commons.dom.isOffscreen(a)}},{id:"non-empty-alt",evaluate:function(a,b,c){var d=a.getAttribute("alt");return!!(d?axe.commons.text.sanitize(d).trim():"")}},{id:"non-empty-if-present",evaluate:function(a,b,c){var d=a.nodeName.toUpperCase(),e=(a.getAttribute("type")||"").toLowerCase(),f=a.getAttribute("value");return this.data(f),"INPUT"===d&&-1!==["submit","reset"].indexOf(e)&&null===f}},{id:"non-empty-title",evaluate:function(a,b,c){var d=a.getAttribute("title");return!!(d?axe.commons.text.sanitize(d).trim():"")}},{id:"non-empty-value",evaluate:function(a,b,c){var d=a.getAttribute("value");return!!(d?axe.commons.text.sanitize(d).trim():"")}},{id:"role-none",evaluate:function(a,b,c){return"none"===a.getAttribute("role")}},{id:"role-presentation",evaluate:function(a,b,c){return"presentation"===a.getAttribute("role")}},{id:"caption-faked",evaluate:function(a,b,c){var d=axe.commons.table.toGrid(a),e=d[0];return d.length<=1||e.length<=1||a.rows.length<=1||e.reduce(function(a,b,c){return a||b!==e[c+1]&&void 0!==e[c+1]},!1)}},{id:"has-caption",evaluate:function(a,b,c){return!!a.caption}},{id:"has-summary",evaluate:function(a,b,c){return!!a.summary}},{id:"has-th",evaluate:function(a,b,c){for(var d,e,f=[],g=0,h=a.rows.length;g<h;g++){d=a.rows[g];for(var i=0,j=d.cells.length;i<j;i++)e=d.cells[i],"TH"!==e.nodeName.toUpperCase()&&-1===["rowheader","columnheader"].indexOf(e.getAttribute("role"))||f.push(e)}return!!f.length&&(this.relatedNodes(f),!0)}},{id:"html5-scope",evaluate:function(a,b,c){return!axe.commons.dom.isHTML5(document)||"TH"===a.nodeName.toUpperCase()}},{id:"same-caption-summary",evaluate:function(a,b,c){return!(!a.summary||!a.caption)&&a.summary===axe.commons.text.accessibleText(a.caption)}},{id:"scope-value",evaluate:function(a,b,c){b=b||{};var d=a.getAttribute("scope").toLowerCase();return-1!==(["row","col","rowgroup","colgroup"]||b.values).indexOf(d)}},{id:"td-has-header",evaluate:function(a,b,c){var d=axe.commons.table,e=[];return d.getAllCells(a).forEach(function(a){if(axe.commons.dom.hasContent(a)&&d.isDataCell(a)&&!axe.commons.aria.label(a)){var b=d.getHeaders(a);(b=b.reduce(function(a,b){return a||null!==b&&!!axe.commons.dom.hasContent(b)},!1))||e.push(a)}}),!e.length||(this.relatedNodes(e),!1)}},{id:"td-headers-attr",evaluate:function(a,b,c){for(var d=[],e=0,f=a.rows.length;e<f;e++)for(var g=a.rows[e],h=0,i=g.cells.length;h<i;h++)d.push(g.cells[h]);var j=d.reduce(function(a,b){return b.getAttribute("id")&&a.push(b.getAttribute("id")),a},[]),k=d.reduce(function(a,b){var c,d,e=(b.getAttribute("headers")||"").split(/\s/).reduce(function(a,b){return b=b.trim(),b&&a.push(b),a},[]);return 0!==e.length&&(b.getAttribute("id")&&(c=-1!==e.indexOf(b.getAttribute("id").trim())),d=e.reduce(function(a,b){return a||-1===j.indexOf(b)},!1),(c||d)&&a.push(b)),a},[]);return!(k.length>0)||(this.relatedNodes(k),!1)}},{id:"th-has-data-cells",evaluate:function(a,b,c){var d=axe.commons.table,e=d.getAllCells(a),f=this,g=[];e.forEach(function(a){var b=a.getAttribute("headers");b&&(g=g.concat(b.split(/\s+/)));var c=a.getAttribute("aria-labelledby");c&&(g=g.concat(c.split(/\s+/)))});var h=e.filter(function(a){return""!==axe.commons.text.sanitize(a.textContent)&&("TH"===a.nodeName.toUpperCase()||-1!==["rowheader","columnheader"].indexOf(a.getAttribute("role")))}),i=d.toGrid(a);return!!h.reduce(function(a,b){if(b.getAttribute("id")&&g.includes(b.getAttribute("id")))return!!a||a;var c=!1,e=d.getCellPosition(b,i);return d.isColumnHeader(b)&&(c=d.traverse("down",e,i).reduce(function(a,b){return a||axe.commons.dom.hasContent(b)&&!d.isColumnHeader(b)},!1)),!c&&d.isRowHeader(b)&&(c=d.traverse("right",e,i).reduce(function(a,b){return a||axe.commons.dom.hasContent(b)&&!d.isRowHeader(b)},!1)),c||f.relatedNodes(b),a&&c},!0)||void 0}},{id:"hidden-content",evaluate:function(a,b,c){if(!["SCRIPT","HEAD","TITLE","NOSCRIPT","STYLE","TEMPLATE"].includes(a.tagName.toUpperCase())&&axe.commons.dom.hasContent(c)){var d=window.getComputedStyle(a);if("none"===d.getPropertyValue("display"))return;if("hidden"===d.getPropertyValue("visibility")){var e=axe.commons.dom.getComposedParent(a),f=e&&window.getComputedStyle(e);if(!f||"hidden"!==f.getPropertyValue("visibility"))return}}return!0}}],commons:function(){function a(a){return a.getPropertyValue("font-family").split(/[,;]/g).map(function(a){return a.trim().toLowerCase()})}function b(b,c){var d=window.getComputedStyle(b);if("none"!==d.getPropertyValue("background-image"))return!0;if(["border-bottom","border-top","outline"].reduce(function(a,b){var c=new A.Color;return c.parseRgbString(d.getPropertyValue(b+"-color")),a||"none"!==d.getPropertyValue(b+"-style")&&parseFloat(d.getPropertyValue(b+"-width"))>0&&0!==c.alpha},!1))return!0;var e=window.getComputedStyle(c);if(a(d)[0]!==a(e)[0])return!0;var f=["text-decoration-line","text-decoration-style","font-weight","font-style","font-size"].reduce(function(a,b){return a||d.getPropertyValue(b)!==e.getPropertyValue(b)},!1),g=d.getPropertyValue("text-decoration");return g.split(" ").length<3&&(f=f||g!==e.getPropertyValue("text-decoration")),f}function c(a,b){var c=a.nodeName.toUpperCase();if(E.includes(c))return axe.commons.color.incompleteData.set("bgColor","imgNode"),!0;b=b||window.getComputedStyle(a);var d=b.getPropertyValue("background-image"),e="none"!==d;if(e){var f=/gradient/.test(d);axe.commons.color.incompleteData.set("bgColor",f?"bgGradient":"bgImage")}return e}function d(a,b){b=b||window.getComputedStyle(a);var c=new A.Color;if(c.parseRgbString(b.getPropertyValue("background-color")),0!==c.alpha){var d=b.getPropertyValue("opacity");c.alpha=c.alpha*d}return c}function e(a,b){var c=a.getClientRects()[0],d=document.elementsFromPoint(c.left,c.top);if(d)for(var e=0;e<d.length;e++)if(d[e]!==a&&d[e]===b)return!0;return!1}function f(a,b,c){var f=0;if(a>0)for(var g=a-1;g>=0;g--){var h=b[g],i=window.getComputedStyle(h),j=d(h,i);j.alpha&&e(c,h)?f+=j.alpha:b.splice(g,1)}return f}function g(a,b,c){var d=a!==b&&!B.visuallyContains(a,b)&&0!==c.alpha;return d&&axe.commons.color.incompleteData.set("bgColor","elmPartiallyObscured"),d}function h(a,b){var c={TD:"TR",INPUT:"LABEL"},d=a.map(function(a){return a.tagName}),e=a;for(var f in c)if(c.hasOwnProperty(f)){if(b.tagName===f){var g=axe.commons.dom.findUp(b,c[f]);if(g&&-1===a.indexOf(g)){var h=axe.commons.dom.visuallyOverlaps(b.getBoundingClientRect(),g);h&&e.splice(a.indexOf(b)+1,0,g)}}b.tagName===c[f]&&-1===d.indexOf(b.tagName)&&e.splice(d.indexOf(f)+1,0,b)}return e}function i(a){var b=a.indexOf(document.body),e=a;return b>1&&!c(document.documentElement)&&0===d(document.documentElement).alpha&&(e.splice(b,1),e.splice(a.indexOf(document.documentElement),1),e.push(document.body)),e}function j(a){if(!F.includes(a.actualNode.nodeName.toUpperCase()))return a.children.some(function(a){var b=a.actualNode;return 3===b.nodeType&&b.nodeValue.trim()})}function k(a,b){!1!==b(a.actualNode)&&a.children.forEach(function(a){return k(a,b)})}function l(a){var b=window.getComputedStyle(a).getPropertyValue("display");return G.includes(b)||"table-"===b.substr(0,6)}function m(a){for(var b=B.getComposedParent(a);b&&!l(b);)b=B.getComposedParent(b);return axe.utils.getNodeFromTree(axe._tree[0],b)}function n(a){"use strict";var b=a.match(/rect\s*\(([0-9]+)px,?\s*([0-9]+)px,?\s*([0-9]+)px,?\s*([0-9]+)px\s*\)/);return!(!b||5!==b.length)&&(b[3]-b[1]<=0&&b[2]-b[4]<=0)}function o(a){var b=a.actualNode,c=void 0;return c=b.id?B.findElmsInContext({elm:"label",attr:"for",value:b.id,context:b})[0]:B.findUp(b,"label"),axe.utils.getNodeFromTree(axe._tree[0],c)}function p(a){return["button","reset","submit"].includes(a.actualNode.type.toLowerCase())}function q(a){var b=a.actualNode,c=b.nodeName.toUpperCase();return"TEXTAREA"===c||"SELECT"===c||"INPUT"===c&&"hidden"!==b.type.toLowerCase()}function r(a){return["BUTTON","SUMMARY","A"].includes(a.actualNode.nodeName.toUpperCase())}function s(a){return["TABLE","FIGURE"].includes(a.actualNode.nodeName.toUpperCase())}function t(a){var b=a.actualNode,c=b.nodeName.toUpperCase();if("INPUT"===c)return!b.hasAttribute("type")||J.includes(b.type.toLowerCase())?b.value:"";if("SELECT"===c){var d=b.options;if(d&&d.length){for(var e="",f=0;f<d.length;f++)d[f].selected&&(e+=" "+d[f].text);return D.sanitize(e)}return""}return"TEXTAREA"===c&&b.value?b.value:""}function u(a,b){var c=a.actualNode,d=c.querySelector(b.toLowerCase());return d?D.accessibleText(d):""}function v(a){if(!a)return!1;var b=a.actualNode;switch(b.nodeName.toUpperCase()){case"SELECT":case"TEXTAREA":return!0;case"INPUT":return!b.hasAttribute("type")||J.includes(b.getAttribute("type").toLowerCase());default:return!1}}function w(a){var b=a.actualNode,c=b.nodeName.toUpperCase();return["IMG","APPLET","AREA"].includes(c)||"INPUT"===c&&"image"===b.type.toLowerCase()}function x(a){return!!D.sanitize(a)}var commons={},y=commons.aria={},z=y._lut={};z.attributes={"aria-activedescendant":{type:"idref"},"aria-atomic":{type:"boolean",values:["true","false"]},"aria-autocomplete":{type:"nmtoken",values:["inline","list","both","none"]},"aria-busy":{type:"boolean",values:["true","false"]},"aria-checked":{type:"nmtoken",values:["true","false","mixed","undefined"]},"aria-colcount":{type:"int"},"aria-colindex":{type:"int"},"aria-colspan":{type:"int"},"aria-controls":{type:"idrefs"},"aria-current":{type:"nmtoken",values:["page","step","location","date","time","true","false"]},"aria-describedby":{type:"idrefs"},"aria-disabled":{type:"boolean",values:["true","false"]},"aria-dropeffect":{type:"nmtokens",values:["copy","move","reference","execute","popup","none"]},"aria-expanded":{type:"nmtoken",values:["true","false","undefined"]},"aria-flowto":{type:"idrefs"},"aria-grabbed":{type:"nmtoken",values:["true","false","undefined"]},"aria-haspopup":{type:"boolean",values:["true","false"]},"aria-hidden":{type:"boolean",values:["true","false"]},"aria-invalid":{type:"nmtoken",values:["true","false","spelling","grammar"]},"aria-label":{type:"string"},"aria-labelledby":{type:"idrefs"},"aria-level":{type:"int"},"aria-live":{type:"nmtoken",values:["off","polite","assertive"]},"aria-multiline":{type:"boolean",values:["true","false"]},"aria-multiselectable":{type:"boolean",values:["true","false"]},"aria-orientation":{type:"nmtoken",values:["horizontal","vertical"]},"aria-owns":{type:"idrefs"},"aria-posinset":{type:"int"},"aria-pressed":{type:"nmtoken",values:["true","false","mixed","undefined"]},"aria-readonly":{type:"boolean",values:["true","false"]},"aria-relevant":{type:"nmtokens",values:["additions","removals","text","all"]},"aria-required":{type:"boolean",values:["true","false"]},"aria-rowcount":{type:"int"},"aria-rowindex":{type:"int"},"aria-rowspan":{type:"int"},"aria-selected":{type:"nmtoken",values:["true","false","undefined"]},"aria-setsize":{type:"int"},"aria-sort":{type:"nmtoken",values:["ascending","descending","other","none"]},"aria-valuemax":{type:"decimal"},"aria-valuemin":{type:"decimal"},"aria-valuenow":{type:"decimal"},"aria-valuetext":{type:"string"}},z.globalAttributes=["aria-atomic","aria-busy","aria-controls","aria-current","aria-describedby","aria-disabled","aria-dropeffect","aria-flowto","aria-grabbed","aria-haspopup","aria-hidden","aria-invalid","aria-label","aria-labelledby","aria-live","aria-owns","aria-relevant"],z.role={alert:{type:"widget",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null},alertdialog:{type:"widget",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null},application:{type:"landmark",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null},article:{type:"structure",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["article"]},banner:{type:"landmark",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["header"]},button:{type:"widget",attributes:{allowed:["aria-expanded","aria-pressed"]},owned:null,nameFrom:["author","contents"],context:null,implicit:["button",'input[type="button"]','input[type="image"]','input[type="reset"]','input[type="submit"]',"summary"]},cell:{type:"structure",attributes:{allowed:["aria-colindex","aria-colspan","aria-rowindex","aria-rowspan"]},owned:null,nameFrom:["author","contents"],context:["row"],implicit:["td","th"]},checkbox:{type:"widget",attributes:{required:["aria-checked"]},owned:null,nameFrom:["author","contents"],context:null,implicit:['input[type="checkbox"]']},columnheader:{type:"structure",attributes:{allowed:["aria-expanded","aria-sort","aria-readonly","aria-selected","aria-required"]},owned:null,nameFrom:["author","contents"],context:["row"],implicit:["th"]},combobox:{type:"composite",attributes:{required:["aria-expanded"],allowed:["aria-autocomplete","aria-required","aria-activedescendant"]},owned:{all:["listbox","textbox"]},nameFrom:["author"],context:null},command:{nameFrom:["author"],type:"abstract"},complementary:{type:"landmark",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["aside"]},composite:{nameFrom:["author"],type:"abstract"},contentinfo:{type:"landmark",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["footer"]},definition:{type:"structure",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["dd"]},dialog:{type:"widget",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["dialog"]},directory:{type:"structure",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author","contents"],context:null},document:{type:"structure",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["body"]},form:{type:"landmark",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["form"]},grid:{type:"composite",attributes:{allowed:["aria-level","aria-multiselectable","aria-readonly","aria-activedescendant","aria-expanded"]},owned:{one:["rowgroup","row"]},nameFrom:["author"],context:null,implicit:["table"]},gridcell:{type:"widget",attributes:{allowed:["aria-selected","aria-readonly","aria-expanded","aria-required"]},owned:null,nameFrom:["author","contents"],context:["row"],implicit:["td","th"]},group:{type:"structure",attributes:{allowed:["aria-activedescendant","aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["details","optgroup"]},heading:{type:"structure",attributes:{allowed:["aria-level","aria-expanded"]},owned:null,nameFrom:["author","contents"],context:null,implicit:["h1","h2","h3","h4","h5","h6"]},img:{type:"structure",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["img"]},input:{nameFrom:["author"],type:"abstract"},landmark:{nameFrom:["author"],type:"abstract"},link:{type:"widget",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author","contents"],context:null,implicit:["a[href]"]},list:{type:"structure",attributes:{allowed:["aria-expanded"]},owned:{all:["listitem"]},nameFrom:["author"],context:null,implicit:["ol","ul","dl"]},listbox:{type:"composite",attributes:{allowed:["aria-activedescendant","aria-multiselectable","aria-required","aria-expanded"]},owned:{all:["option"]},nameFrom:["author"],context:null,implicit:["select"]},listitem:{type:"structure",attributes:{allowed:["aria-level","aria-posinset","aria-setsize","aria-expanded"]},owned:null,nameFrom:["author","contents"],context:["list"],implicit:["li","dt"]},log:{type:"widget",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null},main:{type:"landmark",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["main"]},marquee:{type:"widget",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null},math:{type:"structure",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["math"]},menu:{type:"composite",attributes:{allowed:["aria-activedescendant","aria-expanded"]},owned:{one:["menuitem","menuitemradio","menuitemcheckbox"]},nameFrom:["author"],context:null,implicit:['menu[type="context"]']},menubar:{type:"composite",attributes:{allowed:["aria-activedescendant","aria-expanded"]},owned:null,nameFrom:["author"],context:null},menuitem:{type:"widget",attributes:null,owned:null,nameFrom:["author","contents"],context:["menu","menubar"],implicit:['menuitem[type="command"]']},menuitemcheckbox:{type:"widget",attributes:{required:["aria-checked"]},owned:null,nameFrom:["author","contents"],context:["menu","menubar"],implicit:['menuitem[type="checkbox"]']},menuitemradio:{type:"widget",attributes:{allowed:["aria-selected","aria-posinset","aria-setsize"],required:["aria-checked"]},owned:null,nameFrom:["author","contents"],context:["menu","menubar"],implicit:['menuitem[type="radio"]']},navigation:{type:"landmark",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["nav"]},none:{type:"structure",attributes:null,owned:null,nameFrom:["author"],context:null},note:{type:"structure",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null},option:{type:"widget",attributes:{allowed:["aria-selected","aria-posinset","aria-setsize","aria-checked"]},owned:null,nameFrom:["author","contents"],context:["listbox"],implicit:["option"]},presentation:{type:"structure",attributes:null,owned:null,nameFrom:["author"],context:null},progressbar:{type:"widget",attributes:{allowed:["aria-valuetext","aria-valuenow","aria-valuemax","aria-valuemin"]},owned:null,nameFrom:["author"],context:null,implicit:["progress"]},radio:{type:"widget",attributes:{allowed:["aria-selected","aria-posinset","aria-setsize"],required:["aria-checked"]},owned:null,nameFrom:["author","contents"],context:null,implicit:['input[type="radio"]']},radiogroup:{type:"composite",attributes:{allowed:["aria-activedescendant","aria-required","aria-expanded"]},owned:{all:["radio"]},nameFrom:["author"],context:null},range:{nameFrom:["author"],type:"abstract"},region:{type:"structure",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["section"]},roletype:{type:"abstract"},row:{type:"structure",attributes:{allowed:["aria-level","aria-selected","aria-activedescendant","aria-expanded"]},owned:{one:["cell","columnheader","rowheader","gridcell"]},nameFrom:["author","contents"],context:["rowgroup","grid","treegrid","table"],implicit:["tr"]},rowgroup:{type:"structure",attributes:{allowed:["aria-activedescendant","aria-expanded"]},owned:{all:["row"]},nameFrom:["author","contents"],context:["grid","table"],implicit:["tbody","thead","tfoot"]},rowheader:{type:"structure",attributes:{allowed:["aria-sort","aria-required","aria-readonly","aria-expanded","aria-selected"]},owned:null,nameFrom:["author","contents"],context:["row"],implicit:["th"]},scrollbar:{type:"widget",attributes:{required:["aria-controls","aria-orientation","aria-valuenow","aria-valuemax","aria-valuemin"],allowed:["aria-valuetext"]},owned:null,nameFrom:["author"],context:null},search:{type:"landmark",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null},searchbox:{type:"widget",attributes:{allowed:["aria-activedescendant","aria-autocomplete","aria-multiline","aria-readonly","aria-required"]},owned:null,nameFrom:["author"],context:null,implicit:['input[type="search"]']},section:{nameFrom:["author","contents"],type:"abstract"},sectionhead:{nameFrom:["author","contents"],type:"abstract"},select:{nameFrom:["author"],type:"abstract"},separator:{type:"structure",attributes:{allowed:["aria-expanded","aria-orientation"]},owned:null,nameFrom:["author"],context:null,implicit:["hr"]},slider:{type:"widget",attributes:{allowed:["aria-valuetext","aria-orientation"],required:["aria-valuenow","aria-valuemax","aria-valuemin"]},owned:null,nameFrom:["author"],context:null,implicit:['input[type="range"]']},spinbutton:{type:"widget",attributes:{allowed:["aria-valuetext","aria-required"],required:["aria-valuenow","aria-valuemax","aria-valuemin"]},owned:null,nameFrom:["author"],context:null,implicit:['input[type="number"]']},status:{type:"widget",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:["output"]},structure:{type:"abstract"},switch:{type:"widget",attributes:{required:["aria-checked"]},owned:null,nameFrom:["author","contents"],context:null},tab:{type:"widget",attributes:{allowed:["aria-selected","aria-expanded"]},owned:null,nameFrom:["author","contents"],context:["tablist"]},table:{type:"structure",attributes:{allowed:["aria-colcount","aria-rowcount"]},owned:{one:["rowgroup","row"]},nameFrom:["author"],context:null,implicit:["table"]},tablist:{type:"composite",attributes:{allowed:["aria-activedescendant","aria-expanded","aria-level","aria-multiselectable"]},owned:{all:["tab"]},nameFrom:["author"],context:null},tabpanel:{type:"widget",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null},text:{type:"structure",owned:null,nameFrom:["author","contents"],context:null},textbox:{type:"widget",attributes:{allowed:["aria-activedescendant","aria-autocomplete","aria-multiline","aria-readonly","aria-required"]},owned:null,nameFrom:["author"],context:null,implicit:['input[type="text"]','input[type="email"]','input[type="password"]','input[type="tel"]','input[type="url"]',"input:not([type])","textarea"]},timer:{type:"widget",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author"],context:null},toolbar:{type:"structure",attributes:{allowed:["aria-activedescendant","aria-expanded"]},owned:null,nameFrom:["author"],context:null,implicit:['menu[type="toolbar"]']},tooltip:{type:"widget",attributes:{allowed:["aria-expanded"]},owned:null,nameFrom:["author","contents"],context:null},tree:{type:"composite",attributes:{allowed:["aria-activedescendant","aria-multiselectable","aria-required","aria-expanded"]},owned:{all:["treeitem"]},nameFrom:["author"],context:null},treegrid:{type:"composite",attributes:{allowed:["aria-activedescendant","aria-expanded","aria-level","aria-multiselectable","aria-readonly","aria-required"]},owned:{all:["treeitem"]},nameFrom:["author"],context:null},treeitem:{type:"widget",attributes:{allowed:["aria-checked","aria-selected","aria-expanded","aria-level","aria-posinset","aria-setsize"]},owned:null,nameFrom:["author","contents"],context:["treegrid","tree"]},widget:{type:"abstract"},window:{nameFrom:["author"],type:"abstract"}};var A={};commons.color=A;var B=commons.dom={},C=commons.table={},D=commons.text={};commons.utils=axe.utils;y.requiredAttr=function(a){"use strict";var b=z.role[a];return b&&b.attributes&&b.attributes.required||[]},y.allowedAttr=function(a){"use strict";var b=z.role[a],c=b&&b.attributes&&b.attributes.allowed||[],d=b&&b.attributes&&b.attributes.required||[];return c.concat(z.globalAttributes).concat(d)},y.validateAttr=function(a){"use strict";return!!z.attributes[a]},y.validateAttrValue=function(a,b){"use strict";var c,d,e=a.getAttribute(b),f=z.attributes[b],g=B.getRootNode(a);if(!f)return!0;switch(f.type){case"boolean":case"nmtoken":return"string"==typeof e&&-1!==f.values.indexOf(e.toLowerCase());case"nmtokens":return d=axe.utils.tokenList(e),d.reduce(function(a,b){return a&&-1!==f.values.indexOf(b)},0!==d.length);case"idref":return!(!e||!g.getElementById(e));case"idrefs":return d=axe.utils.tokenList(e),d.reduce(function(a,b){return!(!a||!g.getElementById(b))},0!==d.length);case"string":return!0;case"decimal":return!(!(c=e.match(/^[-+]?([0-9]*)\.?([0-9]*)$/))||!c[1]&&!c[2]);case"int":return/^[-+]?[0-9]+$/.test(e)}},y.label=function(a){var b,c;return a.actualNode instanceof Node==!1&&(a=axe.utils.getNodeFromTree(axe._tree[0],a)),a.actualNode.getAttribute("aria-labelledby")&&(b=B.idrefs(a.actualNode,"aria-labelledby"),c=b.map(function(a){var b=axe.utils.getNodeFromTree(axe._tree[0],a);return b?D.visible(b,!0):""}).join(" ").trim())?c:(c=a.actualNode.getAttribute("aria-label"),c&&(c=D.sanitize(c).trim())?c:null)},y.isValidRole=function(a){"use strict";return!!z.role[a]},y.getRolesWithNameFromContents=function(){return Object.keys(z.role).filter(function(a){return z.role[a].nameFrom&&-1!==z.role[a].nameFrom.indexOf("contents")})},y.getRolesByType=function(a){return Object.keys(z.role).filter(function(b){return z.role[b].type===a})},y.getRoleType=function(a){var b=z.role[a];return b&&b.type||null},y.requiredOwned=function(a){"use strict";var b=null,c=z.role[a];return c&&(b=axe.utils.clone(c.owned)),b},y.requiredContext=function(a){"use strict";var b=null,c=z.role[a];return c&&(b=axe.utils.clone(c.context)),b},y.implicitNodes=function(a){"use strict";var b=null,c=z.role[a];return c&&c.implicit&&(b=axe.utils.clone(c.implicit)),b},y.implicitRole=function(a){"use strict";var b=function(b,c){var d=function(b){return axe.utils.matchesSelector(a,b)};return c.implicit&&c.implicit.some(d)&&b.push(c.name),b},c=Object.keys(z.role).map(function(a){var b=z.role[a];return{name:a,implicit:b&&b.implicit}}),d=c.reduce(b,[]);if(!d.length)return null;for(var e=a.attributes,f=[],g=0,h=e.length;g<h;g++){var i=e[g];i.name.match(/^aria-/)&&f.push(i.name)}return function(a,b){var c=function(a){return y.allowedAttr(a).reduce(function(a,c){return a+(b.indexOf(c)>-1?1:0)},0)};return a.map(function(a){return{score:c(a),name:a}}).sort(function(a,b){return b.score-a.score}).map(function(a){return a.name})}(d,f).shift()},A.Color=function(a,b,c,d){this.red=a,this.green=b,this.blue=c,this.alpha=d,this.toHexString=function(){var a=Math.round(this.red).toString(16),b=Math.round(this.green).toString(16),c=Math.round(this.blue).toString(16);return"#"+(this.red>15.5?a:"0"+a)+(this.green>15.5?b:"0"+b)+(this.blue>15.5?c:"0"+c)};var e=/^rgb\((\d+), (\d+), (\d+)\)$/,f=/^rgba\((\d+), (\d+), (\d+), (\d*(\.\d+)?)\)/;this.parseRgbString=function(a){if("transparent"===a)return this.red=0,this.green=0,this.blue=0,void(this.alpha=0);var b=a.match(e);return b?(this.red=parseInt(b[1],10),this.green=parseInt(b[2],10),this.blue=parseInt(b[3],10),void(this.alpha=1)):(b=a.match(f),b?(this.red=parseInt(b[1],10),this.green=parseInt(b[2],10),this.blue=parseInt(b[3],10),void(this.alpha=parseFloat(b[4]))):void 0)},this.getRelativeLuminance=function(){var a=this.red/255,b=this.green/255,c=this.blue/255;return.2126*(a<=.03928?a/12.92:Math.pow((a+.055)/1.055,2.4))+.7152*(b<=.03928?b/12.92:Math.pow((b+.055)/1.055,2.4))+.0722*(c<=.03928?c/12.92:Math.pow((c+.055)/1.055,2.4))}},A.flattenColors=function(a,b){var c=a.alpha,d=(1-c)*b.red+c*a.red,e=(1-c)*b.green+c*a.green,f=(1-c)*b.blue+c*a.blue,g=a.alpha+b.alpha*(1-a.alpha);return new A.Color(d,e,f,g)},A.getContrast=function(a,b){if(!b||!a)return null;b.alpha<1&&(b=A.flattenColors(b,a));var c=a.getRelativeLuminance(),d=b.getRelativeLuminance();return(Math.max(d,c)+.05)/(Math.min(d,c)+.05)},A.hasValidContrastRatio=function(a,b,c,d){var e=A.getContrast(a,b),f=d&&Math.ceil(72*c)/96<14||!d&&Math.ceil(72*c)/96<18;return{isValid:f&&e>=4.5||!f&&e>=3,contrastRatio:e}},A.elementIsDistinct=b;var E=["IMG","CANVAS","OBJECT","IFRAME","VIDEO","SVG"];A.getBackgroundStack=function(a){var b=a.getBoundingClientRect(),c=void 0,d=void 0;if(!(b.left>window.innerWidth||b.top>window.innerHeight)){c=Math.min(Math.ceil(b.left+b.width/2),window.innerWidth-1),d=Math.min(Math.ceil(b.top+b.height/2),window.innerHeight-1);var e=document.elementsFromPoint(c,d);e=h(e,a),e=B.reduceToElementsBelowFloating(e,a),e=i(e);var g=e.indexOf(a);return f(g,e,a)>=.99?(axe.commons.color.incompleteData.set("bgColor","bgOverlap"),null):-1!==g?e:null}},A.getBackgroundColor=function(a){var b=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];if(!0!==(arguments.length>2&&void 0!==arguments[2]&&arguments[2])){var e=a.clientHeight-2>=2*window.innerHeight;a.scrollIntoView(e)}var f=[],h=A.getBackgroundStack(a);if((h||[]).some(function(e){var h=window.getComputedStyle(e),i=d(e,h);return g(a,e,i)||c(e,h)?(f=null,b.push(e),!0):0!==i.alpha&&(b.push(e),f.push(i),1===i.alpha)}),null!==f&&null!==h){f.push(new A.Color(255,255,255,1));return f.reduce(A.flattenColors)}return null},B.isOpaque=function(a){var b=window.getComputedStyle(a);return c(a,b)||1===d(a,b).alpha},A.getForegroundColor=function(a,b){var c=window.getComputedStyle(a),d=new A.Color;d.parseRgbString(c.getPropertyValue("color"));var e=c.getPropertyValue("opacity");if(d.alpha=d.alpha*e,1===d.alpha)return d;var f=A.getBackgroundColor(a,[],b);if(null===f){var g=axe.commons.color.incompleteData.get("bgColor");return axe.commons.color.incompleteData.set("fgColor",g),null}return A.flattenColors(d,f)},A.incompleteData=function(){var a={};return{set:function(b,c){if("string"!=typeof b)throw new Error("Incomplete data: key must be a string");return c&&(a[b]=c),a[b]},get:function(b){return a[b]},clear:function(){a={}}}}(),B.reduceToElementsBelowFloating=function(a,b){var c,d,e,f=["fixed","sticky"],g=[],h=!1;for(c=0;c<a.length;++c)d=a[c],d===b&&(h=!0),e=window.getComputedStyle(d),h||-1===f.indexOf(e.position)?g.push(d):g=[];return g},B.findElmsInContext=function(a){var b=a.context,c=a.value,d=a.attr,e=a.elm,f=void 0===e?"":e,g=void 0;b=b.actualNode||b;var h=axe.utils.escapeSelector(c);return g=9===b.nodeType||11===b.nodeType?b:B.getRootNode(b),Array.from(g.querySelectorAll(f+"["+d+"="+h+"]"))},B.findUp=function(a,b){var c=void 0,d=void 0,e=a;do{if(e=e.assignedSlot?e.assignedSlot:e.parentNode,e&&11===e.nodeType&&(d=null,e=e.host),!d&&(c=axe.commons.dom.getRootNode(e),d=c.querySelectorAll(b),d=axe.utils.toArray(d),c===document&&!d.length))return null}while(e&&!d.includes(e));return e},B.getComposedParent=function a(b){if(b.assignedSlot)return a(b.assignedSlot);if(b.parentNode){var c=b.parentNode;if(1===c.nodeType)return c;if(c.host)return c.host}return null},B.getElementByReference=function(a,b){var c=a.getAttribute(b);if(c&&"#"===c.charAt(0)){c=c.substring(1);var d=document.getElementById(c);if(d)return d;if(d=document.getElementsByName(c),d.length)return d[0]}return null},B.getElementCoordinates=function(a){"use strict";var b=B.getScrollOffset(document),c=b.left,d=b.top,e=a.getBoundingClientRect();return{top:e.top+d,right:e.right+c,bottom:e.bottom+d,left:e.left+c,width:e.right-e.left,height:e.bottom-e.top}},B.getRootNode=function(a){var b=a.getRootNode&&a.getRootNode()||document;return b===a&&(b=document),b},B.getScrollOffset=function(a){"use strict";if(!a.nodeType&&a.document&&(a=a.document),9===a.nodeType){var b=a.documentElement,c=a.body;return{left:b&&b.scrollLeft||c&&c.scrollLeft||0,top:b&&b.scrollTop||c&&c.scrollTop||0}}return{left:a.scrollLeft,top:a.scrollTop}},B.getViewportSize=function(a){"use strict";var b,c=a.document,d=c.documentElement;return a.innerWidth?{width:a.innerWidth,height:a.innerHeight}:d?{width:d.clientWidth,height:d.clientHeight}:(b=c.body,{width:b.clientWidth,height:b.clientHeight})};var F=["HEAD","TITLE","TEMPLATE","SCRIPT","STYLE","IFRAME","OBJECT","VIDEO","AUDIO","NOSCRIPT"];B.hasContent=function(a,b){return a.actualNode||(a=axe.utils.getNodeFromTree(axe._tree[0],a)),j(a)||B.isVisualContent(a.actualNode)||!!y.label(a)||!b&&a.children.some(function(a){return 1===a.actualNode.nodeType&&B.hasContent(a)})},B.idrefs=function(a,b){"use strict";var c,d,e=B.getRootNode(a),f=[],g=a.getAttribute(b);if(g)for(g=axe.utils.tokenList(g),c=0,d=g.length;c<d;c++)f.push(e.getElementById(g[c]));return f},B.isFocusable=function(a){"use strict";if(!a||a.disabled||!B.isVisible(a)&&"AREA"!==a.nodeName.toUpperCase())return!1;switch(a.nodeName.toUpperCase()){case"A":case"AREA":if(a.href)return!0;break;case"INPUT":return"hidden"!==a.type
+;case"TEXTAREA":case"SELECT":case"DETAILS":case"BUTTON":return!0}var b=a.getAttribute("tabindex");return!(!b||isNaN(parseInt(b,10)))},B.isHTML5=function(a){var b=a.doctype;return null!==b&&("html"===b.name&&!b.publicId&&!b.systemId)};var G=["block","list-item","table","flex","grid","inline-block"];B.isInTextBlock=function(a){if(l(a))return!1;var b=m(a),c="",d="",e=0;return k(b,function(b){if(2===e)return!1;if(3===b.nodeType&&(c+=b.nodeValue),1===b.nodeType){var f=(b.nodeName||"").toUpperCase();if(["BR","HR"].includes(f))0===e?(c="",d=""):e=2;else{if("none"===b.style.display||"hidden"===b.style.overflow||!["",null,"none"].includes(b.style.float)||!["",null,"relative"].includes(b.style.position))return!1;if("A"===f&&b.href||"link"===(b.getAttribute("role")||"").toLowerCase())return b===a&&(e=1),d+=b.textContent,!1}}}),c=axe.commons.text.sanitize(c),d=axe.commons.text.sanitize(d),c.length>d.length},B.isNode=function(a){"use strict";return a instanceof Node},B.isOffscreen=function(a){"use strict";var b,c=document.documentElement,d=window.getComputedStyle(a),e=window.getComputedStyle(document.body||c).getPropertyValue("direction"),f=B.getElementCoordinates(a);if(f.bottom<0&&(function(a,b){for(a=a.parentNode;"html"!==a.nodeName.toLowerCase();){if(a.scrollTop&&(b+=a.scrollTop)>=0)return!1;a=a.parentNode}return!0}(a,f.bottom)||"absolute"===d.position))return!0;if(0===f.left&&0===f.right)return!1;if("ltr"===e){if(f.right<=0)return!0}else if(b=Math.max(c.scrollWidth,B.getViewportSize(window).width),f.left>=b)return!0;return!1},B.isVisible=function(a,b,c){"use strict";var d,e,f;return 9===a.nodeType||(11===a.nodeType&&(a=a.host),null!==(d=window.getComputedStyle(a,null))&&(e=a.nodeName.toUpperCase(),!("none"===d.getPropertyValue("display")||"STYLE"===e.toUpperCase()||"SCRIPT"===e.toUpperCase()||!b&&n(d.getPropertyValue("clip"))||!c&&("hidden"===d.getPropertyValue("visibility")||!b&&B.isOffscreen(a))||b&&"true"===a.getAttribute("aria-hidden"))&&(!!(f=a.assignedSlot?a.assignedSlot:a.parentNode)&&B.isVisible(f,b,!0))))};var H=["checkbox","img","radio","range","slider","spinbutton","textbox"];B.isVisualContent=function(a){var b=a.getAttribute("role");if(b)return-1!==H.indexOf(b);switch(a.tagName.toUpperCase()){case"IMG":case"IFRAME":case"OBJECT":case"VIDEO":case"AUDIO":case"CANVAS":case"SVG":case"MATH":case"BUTTON":case"SELECT":case"TEXTAREA":case"KEYGEN":case"PROGRESS":case"METER":return!0;case"INPUT":return"hidden"!==a.type;default:return!1}},B.visuallyContains=function(a,b){var c=a.getBoundingClientRect(),d={top:c.top+.01,bottom:c.bottom-.01,left:c.left+.01,right:c.right-.01},e=b.getBoundingClientRect(),f=e.top,g=e.left,h={top:f-b.scrollTop,bottom:f-b.scrollTop+b.scrollHeight,left:g-b.scrollLeft,right:g-b.scrollLeft+b.scrollWidth},i=window.getComputedStyle(b);return"inline"===i.getPropertyValue("display")||!(d.left<h.left&&d.left<e.left||d.top<h.top&&d.top<e.top||d.right>h.right&&d.right>e.right||d.bottom>h.bottom&&d.bottom>e.bottom)&&(!(d.right>e.right||d.bottom>e.bottom)||("scroll"===i.overflow||"auto"===i.overflow||"hidden"===i.overflow||b instanceof HTMLBodyElement||b instanceof HTMLHtmlElement))},B.visuallyOverlaps=function(a,b){var c=b.getBoundingClientRect(),d=c.top,e=c.left,f={top:d-b.scrollTop,bottom:d-b.scrollTop+b.scrollHeight,left:e-b.scrollLeft,right:e-b.scrollLeft+b.scrollWidth};if(a.left>f.right&&a.left>c.right||a.top>f.bottom&&a.top>c.bottom||a.right<f.left&&a.right<c.left||a.bottom<f.top&&a.bottom<c.top)return!1;var g=window.getComputedStyle(b);return!(a.left>c.right||a.top>c.bottom)||("scroll"===g.overflow||"auto"===g.overflow||b instanceof HTMLBodyElement||b instanceof HTMLHtmlElement)},C.getAllCells=function(a){var b,c,d,e,f=[];for(b=0,d=a.rows.length;b<d;b++)for(c=0,e=a.rows[b].cells.length;c<e;c++)f.push(a.rows[b].cells[c]);return f},C.getCellPosition=function(a,b){var c,d;for(b||(b=C.toGrid(B.findUp(a,"table"))),c=0;c<b.length;c++)if(b[c]&&-1!==(d=b[c].indexOf(a)))return{x:d,y:c}},C.getHeaders=function(a){if(a.hasAttribute("headers"))return commons.dom.idrefs(a,"headers");var b=commons.table.toGrid(commons.dom.findUp(a,"table")),c=commons.table.getCellPosition(a,b);return[].concat(C.traverse("left",c,b).filter(function(a){return C.isRowHeader(a)}),C.traverse("up",c,b).filter(function(a){return C.isColumnHeader(a)})).reverse()},C.getScope=function(a){var b=a.getAttribute("scope"),c=a.getAttribute("role");if(a instanceof Element==!1||-1===["TD","TH"].indexOf(a.nodeName.toUpperCase()))throw new TypeError("Expected TD or TH element");if("columnheader"===c)return"col";if("rowheader"===c)return"row";if("col"===b||"row"===b)return b;if("TH"!==a.nodeName.toUpperCase())return!1;var d=C.toGrid(B.findUp(a,"table")),e=C.getCellPosition(a);return d[e.y].reduce(function(a,b){return a&&"TH"===b.nodeName.toUpperCase()},!0)?"col":d.map(function(a){return a[e.x]}).reduce(function(a,b){return a&&"TH"===b.nodeName.toUpperCase()},!0)?"row":"auto"},C.isColumnHeader=function(a){return-1!==["col","auto"].indexOf(C.getScope(a))},C.isDataCell=function(a){return!(!a.children.length&&!a.textContent.trim())&&"TD"===a.nodeName.toUpperCase()},C.isDataTable=function(a){var b=a.getAttribute("role");if(("presentation"===b||"none"===b)&&!B.isFocusable(a))return!1;if("true"===a.getAttribute("contenteditable")||B.findUp(a,'[contenteditable="true"]'))return!0;if("grid"===b||"treegrid"===b||"table"===b)return!0;if("landmark"===commons.aria.getRoleType(b))return!0;if("0"===a.getAttribute("datatable"))return!1;if(a.getAttribute("summary"))return!0;if(a.tHead||a.tFoot||a.caption)return!0;for(var c=0,d=a.children.length;c<d;c++)if("COLGROUP"===a.children[c].nodeName.toUpperCase())return!0;for(var e,f,g=0,h=a.rows.length,i=!1,j=0;j<h;j++){e=a.rows[j];for(var k=0,l=e.cells.length;k<l;k++){if(f=e.cells[k],"TH"===f.nodeName.toUpperCase())return!0;if(i||f.offsetWidth===f.clientWidth&&f.offsetHeight===f.clientHeight||(i=!0),f.getAttribute("scope")||f.getAttribute("headers")||f.getAttribute("abbr"))return!0;if(-1!==["columnheader","rowheader"].indexOf(f.getAttribute("role")))return!0;if(1===f.children.length&&"ABBR"===f.children[0].nodeName.toUpperCase())return!0;g++}}if(a.getElementsByTagName("table").length)return!1;if(h<2)return!1;var m=a.rows[Math.ceil(h/2)];if(1===m.cells.length&&1===m.cells[0].colSpan)return!1;if(m.cells.length>=5)return!0;if(i)return!0;var n,o;for(j=0;j<h;j++){if(e=a.rows[j],n&&n!==window.getComputedStyle(e).getPropertyValue("background-color"))return!0;if(n=window.getComputedStyle(e).getPropertyValue("background-color"),o&&o!==window.getComputedStyle(e).getPropertyValue("background-image"))return!0;o=window.getComputedStyle(e).getPropertyValue("background-image")}return h>=20||!(B.getElementCoordinates(a).width>.95*B.getViewportSize(window).width)&&(!(g<10)&&!a.querySelector("object, embed, iframe, applet"))},C.isHeader=function(a){if(C.isColumnHeader(a)||C.isRowHeader(a))return!0;if(a.getAttribute("id")){var b=axe.utils.escapeSelector(a.getAttribute("id"));return!!document.querySelector('[headers~="'+b+'"]')}return!1},C.isRowHeader=function(a){return-1!==["row","auto"].indexOf(C.getScope(a))},C.toGrid=function(a){for(var b=[],c=a.rows,d=0,e=c.length;d<e;d++){var f=c[d].cells;b[d]=b[d]||[];for(var g=0,h=0,i=f.length;h<i;h++)for(var j=0;j<f[h].colSpan;j++){for(var k=0;k<f[h].rowSpan;k++){for(b[d+k]=b[d+k]||[];b[d+k][g];)g++;b[d+k][g]=f[h]}g++}}return b},C.toArray=C.toGrid,function(a){var b=function a(b,c,d,e){var f,g=d[c.y]?d[c.y][c.x]:void 0;return g?"function"==typeof e&&!0===(f=e(g,c,d))?[g]:(f=a(b,{x:c.x+b.x,y:c.y+b.y},d,e),f.unshift(g),f):[]};a.traverse=function(a,c,d,e){if(Array.isArray(c)&&(e=d,d=c,c={x:0,y:0}),"string"==typeof a)switch(a){case"left":a={x:-1,y:0};break;case"up":a={x:0,y:-1};break;case"right":a={x:1,y:0};break;case"down":a={x:0,y:1}}return b(a,{x:c.x+a.x,y:c.y+a.y},d,e)}}(C);var I={submit:"Submit",reset:"Reset"},J=["text","search","tel","url","email","date","time","number","range","color"],K=["A","EM","STRONG","SMALL","MARK","ABBR","DFN","I","B","S","U","CODE","VAR","SAMP","KBD","SUP","SUB","Q","CITE","SPAN","BDO","BDI","BR","WBR","INS","DEL","IMG","EMBED","OBJECT","IFRAME","MAP","AREA","SCRIPT","NOSCRIPT","RUBY","VIDEO","AUDIO","INPUT","TEXTAREA","SELECT","BUTTON","LABEL","OUTPUT","DATALIST","KEYGEN","PROGRESS","COMMAND","CANVAS","TIME","METER"];D.accessibleText=function(a,b){function c(a,b,c){return a.children.reduce(function(a,d){var e=d.actualNode;return 3===e.nodeType?a+=e.nodeValue:1===e.nodeType&&(K.includes(e.nodeName.toUpperCase())||(a+=" "),a+=f(d,b,c)),a},"")}function d(a,b,d){var e="",g=a.actualNode,h=g.nodeName.toUpperCase();if(r(a)&&(e=c(a,!1,!1)||"",x(e)))return e;if("FIGURE"===h&&(e=u(a,"figcaption"),x(e)))return e;if("TABLE"===h){if(e=u(a,"caption"),x(e))return e;if(e=g.getAttribute("title")||g.getAttribute("summary")||"",x(e))return e}if(w(a))return g.getAttribute("alt")||"";if(q(a)&&!d){if(p(a))return g.value||g.title||I[g.type]||"";var i=o(a);if(i)return f(i,b,!0)}return""}function e(a,b,c){var d="",e=a.actualNode;return!b&&e.hasAttribute("aria-labelledby")&&(d=D.sanitize(B.idrefs(e,"aria-labelledby").map(function(a){if(null!==a){e===a&&g.pop();var b=axe.utils.getNodeFromTree(axe._tree[0],a);return f(b,!0,e!==a)}return""}).join(" "))),d||c&&v(a)||!e.hasAttribute("aria-label")?d:D.sanitize(e.getAttribute("aria-label"))}var f=void 0,g=[];return a instanceof Node&&(a=axe.utils.getNodeFromTree(axe._tree[0],a)),f=function(a,b,f){var h=void 0;if(!a||g.includes(a))return"";if(null!==a&&a.actualNode instanceof Node!=!0)throw new Error("Invalid argument. Virtual Node must be provided");if(!b&&!B.isVisible(a.actualNode,!0))return"";g.push(a);var i=a.actualNode.getAttribute("role");return h=e(a,b,f),x(h)?h:(h=d(a,b,f),x(h)?h:f&&(h=t(a),x(h))?h:s(a)||i&&-1===y.getRolesWithNameFromContents().indexOf(i)||(h=c(a,b,f),!x(h))?a.actualNode.hasAttribute("title")?a.actualNode.getAttribute("title"):"":h)},D.sanitize(f(a,b))},D.label=function(a){var b,c,d;if(c=y.label(a))return c;if(a.actualNode.id){var e=axe.commons.utils.escapeSelector(a.actualNode.getAttribute("id"));if(d=axe.commons.dom.getRootNode(a.actualNode),b=d.querySelector('label[for="'+e+'"]'),b=axe.utils.getNodeFromTree(axe._tree[0],b),c=b&&D.visible(b,!0))return c}return b=B.findUp(a.actualNode,"label"),b=axe.utils.getNodeFromTree(axe._tree[0],b),(c=b&&D.visible(b,!0))||null},D.sanitize=function(a){"use strict";return a.replace(/\r\n/g,"\n").replace(/\u00A0/g," ").replace(/[\s]{2,}/g," ").trim()},D.visible=function(a,b,c){"use strict";var d,e,f,g=a.children,h=g.length,i="";for(d=0;d<h;d++)e=g[d],3===e.actualNode.nodeType?(f=e.actualNode.nodeValue)&&B.isVisible(a.actualNode,b)&&(i+=f):c||(i+=D.visible(e,b));return D.sanitize(i)},axe.utils.toArray=function(a){"use strict";return Array.prototype.slice.call(a)},axe.utils.tokenList=function(a){"use strict";return a.trim().replace(/\s{2,}/g," ").split(" ")}
+;var L=["aa","ab","ae","af","ak","am","an","ar","as","av","ay","az","ba","be","bg","bh","bi","bm","bn","bo","br","bs","ca","ce","ch","co","cr","cs","cu","cv","cy","da","de","dv","dz","ee","el","en","eo","es","et","eu","fa","ff","fi","fj","fo","fr","fy","ga","gd","gl","gn","gu","gv","ha","he","hi","ho","hr","ht","hu","hy","hz","ia","id","ie","ig","ii","ik","in","io","is","it","iu","iw","ja","ji","jv","jw","ka","kg","ki","kj","kk","kl","km","kn","ko","kr","ks","ku","kv","kw","ky","la","lb","lg","li","ln","lo","lt","lu","lv","mg","mh","mi","mk","ml","mn","mo","mr","ms","mt","my","na","nb","nd","ne","ng","nl","nn","no","nr","nv","ny","oc","oj","om","or","os","pa","pi","pl","ps","pt","qu","rm","rn","ro","ru","rw","sa","sc","sd","se","sg","sh","si","sk","sl","sm","sn","so","sq","sr","ss","st","su","sv","sw","ta","te","tg","th","ti","tk","tl","tn","to","tr","ts","tt","tw","ty","ug","uk","ur","uz","ve","vi","vo","wa","wo","xh","yi","yo","za","zh","zu","aaa","aab","aac","aad","aae","aaf","aag","aah","aai","aak","aal","aam","aan","aao","aap","aaq","aas","aat","aau","aav","aaw","aax","aaz","aba","abb","abc","abd","abe","abf","abg","abh","abi","abj","abl","abm","abn","abo","abp","abq","abr","abs","abt","abu","abv","abw","abx","aby","abz","aca","acb","acd","ace","acf","ach","aci","ack","acl","acm","acn","acp","acq","acr","acs","act","acu","acv","acw","acx","acy","acz","ada","adb","add","ade","adf","adg","adh","adi","adj","adl","adn","ado","adp","adq","adr","ads","adt","adu","adw","adx","ady","adz","aea","aeb","aec","aed","aee","aek","ael","aem","aen","aeq","aer","aes","aeu","aew","aey","aez","afa","afb","afd","afe","afg","afh","afi","afk","afn","afo","afp","afs","aft","afu","afz","aga","agb","agc","agd","age","agf","agg","agh","agi","agj","agk","agl","agm","agn","ago","agp","agq","agr","ags","agt","agu","agv","agw","agx","agy","agz","aha","ahb","ahg","ahh","ahi","ahk","ahl","ahm","ahn","aho","ahp","ahr","ahs","aht","aia","aib","aic","aid","aie","aif","aig","aih","aii","aij","aik","ail","aim","ain","aio","aip","aiq","air","ais","ait","aiw","aix","aiy","aja","ajg","aji","ajn","ajp","ajt","aju","ajw","ajz","akb","akc","akd","ake","akf","akg","akh","aki","akj","akk","akl","akm","ako","akp","akq","akr","aks","akt","aku","akv","akw","akx","aky","akz","ala","alc","ald","ale","alf","alg","alh","ali","alj","alk","all","alm","aln","alo","alp","alq","alr","als","alt","alu","alv","alw","alx","aly","alz","ama","amb","amc","ame","amf","amg","ami","amj","amk","aml","amm","amn","amo","amp","amq","amr","ams","amt","amu","amv","amw","amx","amy","amz","ana","anb","anc","and","ane","anf","ang","anh","ani","anj","ank","anl","anm","ann","ano","anp","anq","anr","ans","ant","anu","anv","anw","anx","any","anz","aoa","aob","aoc","aod","aoe","aof","aog","aoh","aoi","aoj","aok","aol","aom","aon","aor","aos","aot","aou","aox","aoz","apa","apb","apc","apd","ape","apf","apg","aph","api","apj","apk","apl","apm","apn","apo","app","apq","apr","aps","apt","apu","apv","apw","apx","apy","apz","aqa","aqc","aqd","aqg","aql","aqm","aqn","aqp","aqr","aqt","aqz","arb","arc","ard","are","arh","ari","arj","ark","arl","arn","aro","arp","arq","arr","ars","art","aru","arv","arw","arx","ary","arz","asa","asb","asc","asd","ase","asf","asg","ash","asi","asj","ask","asl","asn","aso","asp","asq","asr","ass","ast","asu","asv","asw","asx","asy","asz","ata","atb","atc","atd","ate","atg","ath","ati","atj","atk","atl","atm","atn","ato","atp","atq","atr","ats","att","atu","atv","atw","atx","aty","atz","aua","aub","auc","aud","aue","auf","aug","auh","aui","auj","auk","aul","aum","aun","auo","aup","auq","aur","aus","aut","auu","auw","aux","auy","auz","avb","avd","avi","avk","avl","avm","avn","avo","avs","avt","avu","avv","awa","awb","awc","awd","awe","awg","awh","awi","awk","awm","awn","awo","awr","aws","awt","awu","awv","aww","awx","awy","axb","axe","axg","axk","axl","axm","axx","aya","ayb","ayc","ayd","aye","ayg","ayh","ayi","ayk","ayl","ayn","ayo","ayp","ayq","ayr","ays","ayt","ayu","ayx","ayy","ayz","aza","azb","azc","azd","azg","azj","azm","azn","azo","azt","azz","baa","bab","bac","bad","bae","baf","bag","bah","bai","baj","bal","ban","bao","bap","bar","bas","bat","bau","bav","baw","bax","bay","baz","bba","bbb","bbc","bbd","bbe","bbf","bbg","bbh","bbi","bbj","bbk","bbl","bbm","bbn","bbo","bbp","bbq","bbr","bbs","bbt","bbu","bbv","bbw","bbx","bby","bbz","bca","bcb","bcc","bcd","bce","bcf","bcg","bch","bci","bcj","bck","bcl","bcm","bcn","bco","bcp","bcq","bcr","bcs","bct","bcu","bcv","bcw","bcy","bcz","bda","bdb","bdc","bdd","bde","bdf","bdg","bdh","bdi","bdj","bdk","bdl","bdm","bdn","bdo","bdp","bdq","bdr","bds","bdt","bdu","bdv","bdw","bdx","bdy","bdz","bea","beb","bec","bed","bee","bef","beg","beh","bei","bej","bek","bem","beo","bep","beq","ber","bes","bet","beu","bev","bew","bex","bey","bez","bfa","bfb","bfc","bfd","bfe","bff","bfg","bfh","bfi","bfj","bfk","bfl","bfm","bfn","bfo","bfp","bfq","bfr","bfs","bft","bfu","bfw","bfx","bfy","bfz","bga","bgb","bgc","bgd","bge","bgf","bgg","bgi","bgj","bgk","bgl","bgm","bgn","bgo","bgp","bgq","bgr","bgs","bgt","bgu","bgv","bgw","bgx","bgy","bgz","bha","bhb","bhc","bhd","bhe","bhf","bhg","bhh","bhi","bhj","bhk","bhl","bhm","bhn","bho","bhp","bhq","bhr","bhs","bht","bhu","bhv","bhw","bhx","bhy","bhz","bia","bib","bic","bid","bie","bif","big","bij","bik","bil","bim","bin","bio","bip","biq","bir","bit","biu","biv","biw","bix","biy","biz","bja","bjb","bjc","bjd","bje","bjf","bjg","bjh","bji","bjj","bjk","bjl","bjm","bjn","bjo","bjp","bjq","bjr","bjs","bjt","bju","bjv","bjw","bjx","bjy","bjz","bka","bkb","bkc","bkd","bkf","bkg","bkh","bki","bkj","bkk","bkl","bkm","bkn","bko","bkp","bkq","bkr","bks","bkt","bku","bkv","bkw","bkx","bky","bkz","bla","blb","blc","bld","ble","blf","blg","blh","bli","blj","blk","bll","blm","bln","blo","blp","blq","blr","bls","blt","blv","blw","blx","bly","blz","bma","bmb","bmc","bmd","bme","bmf","bmg","bmh","bmi","bmj","bmk","bml","bmm","bmn","bmo","bmp","bmq","bmr","bms","bmt","bmu","bmv","bmw","bmx","bmy","bmz","bna","bnb","bnc","bnd","bne","bnf","bng","bni","bnj","bnk","bnl","bnm","bnn","bno","bnp","bnq","bnr","bns","bnt","bnu","bnv","bnw","bnx","bny","bnz","boa","bob","boe","bof","bog","boh","boi","boj","bok","bol","bom","bon","boo","bop","boq","bor","bot","bou","bov","bow","box","boy","boz","bpa","bpb","bpd","bpg","bph","bpi","bpj","bpk","bpl","bpm","bpn","bpo","bpp","bpq","bpr","bps","bpt","bpu","bpv","bpw","bpx","bpy","bpz","bqa","bqb","bqc","bqd","bqf","bqg","bqh","bqi","bqj","bqk","bql","bqm","bqn","bqo","bqp","bqq","bqr","bqs","bqt","bqu","bqv","bqw","bqx","bqy","bqz","bra","brb","brc","brd","brf","brg","brh","bri","brj","brk","brl","brm","brn","bro","brp","brq","brr","brs","brt","bru","brv","brw","brx","bry","brz","bsa","bsb","bsc","bse","bsf","bsg","bsh","bsi","bsj","bsk","bsl","bsm","bsn","bso","bsp","bsq","bsr","bss","bst","bsu","bsv","bsw","bsx","bsy","bta","btb","btc","btd","bte","btf","btg","bth","bti","btj","btk","btl","btm","btn","bto","btp","btq","btr","bts","btt","btu","btv","btw","btx","bty","btz","bua","bub","buc","bud","bue","buf","bug","buh","bui","buj","buk","bum","bun","buo","bup","buq","bus","but","buu","buv","buw","bux","buy","buz","bva","bvb","bvc","bvd","bve","bvf","bvg","bvh","bvi","bvj","bvk","bvl","bvm","bvn","bvo","bvp","bvq","bvr","bvt","bvu","bvv","bvw","bvx","bvy","bvz","bwa","bwb","bwc","bwd","bwe","bwf","bwg","bwh","bwi","bwj","bwk","bwl","bwm","bwn","bwo","bwp","bwq","bwr","bws","bwt","bwu","bww","bwx","bwy","bwz","bxa","bxb","bxc","bxd","bxe","bxf","bxg","bxh","bxi","bxj","bxk","bxl","bxm","bxn","bxo","bxp","bxq","bxr","bxs","bxu","bxv","bxw","bxx","bxz","bya","byb","byc","byd","bye","byf","byg","byh","byi","byj","byk","byl","bym","byn","byo","byp","byq","byr","bys","byt","byv","byw","byx","byy","byz","bza","bzb","bzc","bzd","bze","bzf","bzg","bzh","bzi","bzj","bzk","bzl","bzm","bzn","bzo","bzp","bzq","bzr","bzs","bzt","bzu","bzv","bzw","bzx","bzy","bzz","caa","cab","cac","cad","cae","caf","cag","cah","cai","caj","cak","cal","cam","can","cao","cap","caq","car","cas","cau","cav","caw","cax","cay","caz","cba","cbb","cbc","cbd","cbe","cbg","cbh","cbi","cbj","cbk","cbl","cbn","cbo","cbq","cbr","cbs","cbt","cbu","cbv","cbw","cby","cca","ccc","ccd","cce","ccg","cch","ccj","ccl","ccm","ccn","cco","ccp","ccq","ccr","ccs","cda","cdc","cdd","cde","cdf","cdg","cdh","cdi","cdj","cdm","cdn","cdo","cdr","cds","cdy","cdz","cea","ceb","ceg","cek","cel","cen","cet","cfa","cfd","cfg","cfm","cga","cgc","cgg","cgk","chb","chc","chd","chf","chg","chh","chj","chk","chl","chm","chn","cho","chp","chq","chr","cht","chw","chx","chy","chz","cia","cib","cic","cid","cie","cih","cik","cim","cin","cip","cir","ciw","ciy","cja","cje","cjh","cji","cjk","cjm","cjn","cjo","cjp","cjr","cjs","cjv","cjy","cka","ckb","ckh","ckl","ckn","cko","ckq","ckr","cks","ckt","cku","ckv","ckx","cky","ckz","cla","clc","cld","cle","clh","cli","clj","clk","cll","clm","clo","clt","clu","clw","cly","cma","cmc","cme","cmg","cmi","cmk","cml","cmm","cmn","cmo","cmr","cms","cmt","cna","cnb","cnc","cng","cnh","cni","cnk","cnl","cno","cns","cnt","cnu","cnw","cnx","coa","cob","coc","cod","coe","cof","cog","coh","coj","cok","col","com","con","coo","cop","coq","cot","cou","cov","cow","cox","coy","coz","cpa","cpb","cpc","cpe","cpf","cpg","cpi","cpn","cpo","cpp","cps","cpu","cpx","cpy","cqd","cqu","cra","crb","crc","crd","crf","crg","crh","cri","crj","crk","crl","crm","crn","cro","crp","crq","crr","crs","crt","crv","crw","crx","cry","crz","csa","csb","csc","csd","cse","csf","csg","csh","csi","csj","csk","csl","csm","csn","cso","csq","csr","css","cst","csu","csv","csw","csy","csz","cta","ctc","ctd","cte","ctg","cth","ctl","ctm","ctn","cto","ctp","cts","ctt","ctu","ctz","cua","cub","cuc","cug","cuh","cui","cuj","cuk","cul","cum","cuo","cup","cuq","cur","cus","cut","cuu","cuv","cuw","cux","cvg","cvn","cwa","cwb","cwd","cwe","cwg","cwt","cya","cyb","cyo","czh","czk","czn","czo","czt","daa","dac","dad","dae","daf","dag","dah","dai","daj","dak","dal","dam","dao","dap","daq","dar","das","dau","dav","daw","dax","day","daz","dba","dbb","dbd","dbe","dbf","dbg","dbi","dbj","dbl","dbm","dbn","dbo","dbp","dbq","dbr","dbt","dbu","dbv","dbw","dby","dcc","dcr","dda","ddd","dde","ddg","ddi","ddj","ddn","ddo","ddr","dds","ddw","dec","ded","dee","def","deg","deh","dei","dek","del","dem","den","dep","deq","der","des","dev","dez","dga","dgb","dgc","dgd","dge","dgg","dgh","dgi","dgk","dgl","dgn","dgo","dgr","dgs","dgt","dgu","dgw","dgx","dgz","dha","dhd","dhg","dhi","dhl","dhm","dhn","dho","dhr","dhs","dhu","dhv","dhw","dhx","dia","dib","dic","did","dif","dig","dih","dii","dij","dik","dil","dim","din","dio","dip","diq","dir","dis","dit","diu","diw","dix","diy","diz","dja","djb","djc","djd","dje","djf","dji","djj","djk","djl","djm","djn","djo","djr","dju","djw","dka","dkk","dkl","dkr","dks","dkx","dlg","dlk","dlm","dln","dma","dmb","dmc","dmd","dme","dmg","dmk","dml","dmm","dmn","dmo","dmr","dms","dmu","dmv","dmw","dmx","dmy","dna","dnd","dne","dng","dni","dnj","dnk","dnn","dnr","dnt","dnu","dnv","dnw","dny","doa","dob","doc","doe","dof","doh","doi","dok","dol","don","doo","dop","doq","dor","dos","dot","dov","dow","dox","doy","doz","dpp","dra","drb","drc","drd","dre","drg","drh","dri","drl","drn","dro","drq","drr","drs","drt","dru","drw","dry","dsb","dse","dsh","dsi","dsl","dsn","dso","dsq","dta","dtb","dtd","dth","dti","dtk","dtm","dtn","dto","dtp","dtr","dts","dtt","dtu","dty","dua","dub","duc","dud","due","duf","dug","duh","dui","duj","duk","dul","dum","dun","duo","dup","duq","dur","dus","duu","duv","duw","dux","duy","duz","dva","dwa","dwl","dwr","dws","dwu","dww","dwy","dya","dyb","dyd","dyg","dyi","dym","dyn","dyo","dyu","dyy","dza","dzd","dze","dzg","dzl","dzn","eaa","ebg","ebk","ebo","ebr","ebu","ecr","ecs","ecy","eee","efa","efe","efi","ega","egl","ego","egx","egy","ehu","eip","eit","eiv","eja","eka","ekc","eke","ekg","eki","ekk","ekl","ekm","eko","ekp","ekr","eky","ele","elh","eli","elk","elm","elo","elp","elu","elx","ema","emb","eme","emg","emi","emk","emm","emn","emo","emp","ems","emu","emw","emx","emy","ena","enb","enc","end","enf","enh","enl","enm","enn","eno","enq","enr","enu","env","enw","enx","eot","epi","era","erg","erh","eri","erk","ero","err","ers","ert","erw","ese","esg","esh","esi","esk","esl","esm","esn","eso","esq","ess","esu","esx","esy","etb","etc","eth","etn","eto","etr","ets","ett","etu","etx","etz","euq","eve","evh","evn","ewo","ext","eya","eyo","eza","eze","faa","fab","fad","faf","fag","fah","fai","faj","fak","fal","fam","fan","fap","far","fat","fau","fax","fay","faz","fbl","fcs","fer","ffi","ffm","fgr","fia","fie","fil","fip","fir","fit","fiu","fiw","fkk","fkv","fla","flh","fli","fll","fln","flr","fly","fmp","fmu","fnb","fng","fni","fod","foi","fom","fon","for","fos","fox","fpe","fqs","frc","frd","frk","frm","fro","frp","frq","frr","frs","frt","fse","fsl","fss","fub","fuc","fud","fue","fuf","fuh","fui","fuj","fum","fun","fuq","fur","fut","fuu","fuv","fuy","fvr","fwa","fwe","gaa","gab","gac","gad","gae","gaf","gag","gah","gai","gaj","gak","gal","gam","gan","gao","gap","gaq","gar","gas","gat","gau","gav","gaw","gax","gay","gaz","gba","gbb","gbc","gbd","gbe","gbf","gbg","gbh","gbi","gbj","gbk","gbl","gbm","gbn","gbo","gbp","gbq","gbr","gbs","gbu","gbv","gbw","gbx","gby","gbz","gcc","gcd","gce","gcf","gcl","gcn","gcr","gct","gda","gdb","gdc","gdd","gde","gdf","gdg","gdh","gdi","gdj","gdk","gdl","gdm","gdn","gdo","gdq","gdr","gds","gdt","gdu","gdx","gea","geb","gec","ged","geg","geh","gei","gej","gek","gel","gem","geq","ges","gev","gew","gex","gey","gez","gfk","gft","gfx","gga","ggb","ggd","gge","ggg","ggk","ggl","ggn","ggo","ggr","ggt","ggu","ggw","gha","ghc","ghe","ghh","ghk","ghl","ghn","gho","ghr","ghs","ght","gia","gib","gic","gid","gie","gig","gih","gil","gim","gin","gio","gip","giq","gir","gis","git","giu","giw","gix","giy","giz","gji","gjk","gjm","gjn","gjr","gju","gka","gke","gkn","gko","gkp","gku","glc","gld","glh","gli","glj","glk","gll","glo","glr","glu","glw","gly","gma","gmb","gmd","gme","gmg","gmh","gml","gmm","gmn","gmq","gmu","gmv","gmw","gmx","gmy","gmz","gna","gnb","gnc","gnd","gne","gng","gnh","gni","gnk","gnl","gnm","gnn","gno","gnq","gnr","gnt","gnu","gnw","gnz","goa","gob","goc","god","goe","gof","gog","goh","goi","goj","gok","gol","gom","gon","goo","gop","goq","gor","gos","got","gou","gow","gox","goy","goz","gpa","gpe","gpn","gqa","gqi","gqn","gqr","gqu","gra","grb","grc","grd","grg","grh","gri","grj","grk","grm","gro","grq","grr","grs","grt","gru","grv","grw","grx","gry","grz","gse","gsg","gsl","gsm","gsn","gso","gsp","gss","gsw","gta","gti","gtu","gua","gub","guc","gud","gue","guf","gug","guh","gui","guk","gul","gum","gun","guo","gup","guq","gur","gus","gut","guu","guv","guw","gux","guz","gva","gvc","gve","gvf","gvj","gvl","gvm","gvn","gvo","gvp","gvr","gvs","gvy","gwa","gwb","gwc","gwd","gwe","gwf","gwg","gwi","gwj","gwm","gwn","gwr","gwt","gwu","gww","gwx","gxx","gya","gyb","gyd","gye","gyf","gyg","gyi","gyl","gym","gyn","gyr","gyy","gza","gzi","gzn","haa","hab","hac","had","hae","haf","hag","hah","hai","haj","hak","hal","ham","han","hao","hap","haq","har","has","hav","haw","hax","hay","haz","hba","hbb","hbn","hbo","hbu","hca","hch","hdn","hds","hdy","hea","hed","heg","heh","hei","hem","hgm","hgw","hhi","hhr","hhy","hia","hib","hid","hif","hig","hih","hii","hij","hik","hil","him","hio","hir","hit","hiw","hix","hji","hka","hke","hkk","hks","hla","hlb","hld","hle","hlt","hlu","hma","hmb","hmc","hmd","hme","hmf","hmg","hmh","hmi","hmj","hmk","hml","hmm","hmn","hmp","hmq","hmr","hms","hmt","hmu","hmv","hmw","hmx","hmy","hmz","hna","hnd","hne","hnh","hni","hnj","hnn","hno","hns","hnu","hoa","hob","hoc","hod","hoe","hoh","hoi","hoj","hok","hol","hom","hoo","hop","hor","hos","hot","hov","how","hoy","hoz","hpo","hps","hra","hrc","hre","hrk","hrm","hro","hrp","hrr","hrt","hru","hrw","hrx","hrz","hsb","hsh","hsl","hsn","hss","hti","hto","hts","htu","htx","hub","huc","hud","hue","huf","hug","huh","hui","huj","huk","hul","hum","huo","hup","huq","hur","hus","hut","huu","huv","huw","hux","huy","huz","hvc","hve","hvk","hvn","hvv","hwa","hwc","hwo","hya","hyx","iai","ian","iap","iar","iba","ibb","ibd","ibe","ibg","ibh","ibi","ibl","ibm","ibn","ibr","ibu","iby","ica","ich","icl","icr","ida","idb","idc","idd","ide","idi","idr","ids","idt","idu","ifa","ifb","ife","iff","ifk","ifm","ifu","ify","igb","ige","igg","igl","igm","ign","igo","igs","igw","ihb","ihi","ihp","ihw","iin","iir","ijc","ije","ijj","ijn","ijo","ijs","ike","iki","ikk","ikl","iko","ikp","ikr","iks","ikt","ikv","ikw","ikx","ikz","ila","ilb","ilg","ili","ilk","ill","ilm","ilo","ilp","ils","ilu","ilv","ilw","ima","ime","imi","iml","imn","imo","imr","ims","imy","inb","inc","ine","ing","inh","inj","inl","inm","inn","ino","inp","ins","int","inz","ior","iou","iow","ipi","ipo","iqu","iqw","ira","ire","irh","iri","irk","irn","iro","irr","iru","irx","iry","isa","isc","isd","ise","isg","ish","isi","isk","ism","isn","iso","isr","ist","isu","itb","itc","itd","ite","iti","itk","itl","itm","ito","itr","its","itt","itv","itw","itx","ity","itz","ium","ivb","ivv","iwk","iwm","iwo","iws","ixc","ixl","iya","iyo","iyx","izh","izi","izr","izz","jaa","jab","jac","jad","jae","jaf","jah","jaj","jak","jal","jam","jan","jao","jaq","jar","jas","jat","jau","jax","jay","jaz","jbe","jbi","jbj","jbk","jbn","jbo","jbr","jbt","jbu","jbw","jcs","jct","jda","jdg","jdt","jeb","jee","jeg","jeh","jei","jek","jel","jen","jer","jet","jeu","jgb","jge","jgk","jgo","jhi","jhs","jia","jib","jic","jid","jie","jig","jih","jii","jil","jim","jio","jiq","jit","jiu","jiv","jiy","jje","jjr","jka","jkm","jko","jkp","jkr","jku","jle","jls","jma","jmb","jmc","jmd","jmi","jml","jmn","jmr","jms","jmw","jmx","jna","jnd","jng","jni","jnj","jnl","jns","job","jod","jog","jor","jos","jow","jpa","jpr","jpx","jqr","jra","jrb","jrr","jrt","jru","jsl","jua","jub","juc","jud","juh","jui","juk","jul","jum","jun","juo","jup","jur","jus","jut","juu","juw","juy","jvd","jvn","jwi","jya","jye","jyy","kaa","kab","kac","kad","kae","kaf","kag","kah","kai","kaj","kak","kam","kao","kap","kaq","kar","kav","kaw","kax","kay","kba","kbb","kbc","kbd","kbe","kbf","kbg","kbh","kbi","kbj","kbk","kbl","kbm","kbn","kbo","kbp","kbq","kbr","kbs","kbt","kbu","kbv","kbw","kbx","kby","kbz","kca","kcb","kcc","kcd","kce","kcf","kcg","kch","kci","kcj","kck","kcl","kcm","kcn","kco","kcp","kcq","kcr","kcs","kct","kcu","kcv","kcw","kcx","kcy","kcz","kda","kdc","kdd","kde","kdf","kdg","kdh","kdi","kdj","kdk","kdl","kdm","kdn","kdo","kdp","kdq","kdr","kdt","kdu","kdv","kdw","kdx","kdy","kdz","kea","keb","kec","ked","kee","kef","keg","keh","kei","kej","kek","kel","kem","ken","keo","kep","keq","ker","kes","ket","keu","kev","kew","kex","key","kez","kfa","kfb","kfc","kfd","kfe","kff","kfg","kfh","kfi","kfj","kfk","kfl","kfm","kfn","kfo","kfp","kfq","kfr","kfs","kft","kfu","kfv","kfw","kfx","kfy","kfz","kga","kgb","kgc","kgd","kge","kgf","kgg","kgh","kgi","kgj","kgk","kgl","kgm","kgn","kgo","kgp","kgq","kgr","kgs","kgt","kgu","kgv","kgw","kgx","kgy","kha","khb","khc","khd","khe","khf","khg","khh","khi","khj","khk","khl","khn","kho","khp","khq","khr","khs","kht","khu","khv","khw","khx","khy","khz","kia","kib","kic","kid","kie","kif","kig","kih","kii","kij","kil","kim","kio","kip","kiq","kis","kit","kiu","kiv","kiw","kix","kiy","kiz","kja","kjb","kjc","kjd","kje","kjf","kjg","kjh","kji","kjj","kjk","kjl","kjm","kjn","kjo","kjp","kjq","kjr","kjs","kjt","kju","kjv","kjx","kjy","kjz","kka","kkb","kkc","kkd","kke","kkf","kkg","kkh","kki","kkj","kkk","kkl","kkm","kkn","kko","kkp","kkq","kkr","kks","kkt","kku","kkv","kkw","kkx","kky","kkz","kla","klb","klc","kld","kle","klf","klg","klh","kli","klj","klk","kll","klm","kln","klo","klp","klq","klr","kls","klt","klu","klv","klw","klx","kly","klz","kma","kmb","kmc","kmd","kme","kmf","kmg","kmh","kmi","kmj","kmk","kml","kmm","kmn","kmo","kmp","kmq","kmr","kms","kmt","kmu","kmv","kmw","kmx","kmy","kmz","kna","knb","knc","knd","kne","knf","kng","kni","knj","knk","knl","knm","knn","kno","knp","knq","knr","kns","knt","knu","knv","knw","knx","kny","knz","koa","koc","kod","koe","kof","kog","koh","koi","koj","kok","kol","koo","kop","koq","kos","kot","kou","kov","kow","kox","koy","koz","kpa","kpb","kpc","kpd","kpe","kpf","kpg","kph","kpi","kpj","kpk","kpl","kpm","kpn","kpo","kpp","kpq","kpr","kps","kpt","kpu","kpv","kpw","kpx","kpy","kpz","kqa","kqb","kqc","kqd","kqe","kqf","kqg","kqh","kqi","kqj","kqk","kql","kqm","kqn","kqo","kqp","kqq","kqr","kqs","kqt","kqu","kqv","kqw","kqx","kqy","kqz","kra","krb","krc","krd","kre","krf","krh","kri","krj","krk","krl","krm","krn","kro","krp","krr","krs","krt","kru","krv","krw","krx","kry","krz","ksa","ksb","ksc","ksd","kse","ksf","ksg","ksh","ksi","ksj","ksk","ksl","ksm","ksn","kso","ksp","ksq","ksr","kss","kst","ksu","ksv","ksw","ksx","ksy","ksz","kta","ktb","ktc","ktd","kte","ktf","ktg","kth","kti","ktj","ktk","ktl","ktm","ktn","kto","ktp","ktq","ktr","kts","ktt","ktu","ktv","ktw","ktx","kty","ktz","kub","kuc","kud","kue","kuf","kug","kuh","kui","kuj","kuk","kul","kum","kun","kuo","kup","kuq","kus","kut","kuu","kuv","kuw","kux","kuy","kuz","kva","kvb","kvc","kvd","kve","kvf","kvg","kvh","kvi","kvj","kvk","kvl","kvm","kvn","kvo","kvp","kvq","kvr","kvs","kvt","kvu","kvv","kvw","kvx","kvy","kvz","kwa","kwb","kwc","kwd","kwe","kwf","kwg","kwh","kwi","kwj","kwk","kwl","kwm","kwn","kwo","kwp","kwq","kwr","kws","kwt","kwu","kwv","kww","kwx","kwy","kwz","kxa","kxb","kxc","kxd","kxe","kxf","kxh","kxi","kxj","kxk","kxl","kxm","kxn","kxo","kxp","kxq","kxr","kxs","kxt","kxu","kxv","kxw","kxx","kxy","kxz","kya","kyb","kyc","kyd","kye","kyf","kyg","kyh","kyi","kyj","kyk","kyl","kym","kyn","kyo","kyp","kyq","kyr","kys","kyt","kyu","kyv","kyw","kyx","kyy","kyz","kza","kzb","kzc","kzd","kze","kzf","kzg","kzh","kzi","kzj","kzk","kzl","kzm","kzn","kzo","kzp","kzq","kzr","kzs","kzt","kzu","kzv","kzw","kzx","kzy","kzz","laa","lab","lac","lad","lae","laf","lag","lah","lai","laj","lak","lal","lam","lan","lap","laq","lar","las","lau","law","lax","lay","laz","lba","lbb","lbc","lbe","lbf","lbg","lbi","lbj","lbk","lbl","lbm","lbn","lbo","lbq","lbr","lbs","lbt","lbu","lbv","lbw","lbx","lby","lbz","lcc","lcd","lce","lcf","lch","lcl","lcm","lcp","lcq","lcs","lda","ldb","ldd","ldg","ldh","ldi","ldj","ldk","ldl","ldm","ldn","ldo","ldp","ldq","lea","leb","lec","led","lee","lef","leg","leh","lei","lej","lek","lel","lem","len","leo","lep","leq","ler","les","let","leu","lev","lew","lex","ley","lez","lfa","lfn","lga","lgb","lgg","lgh","lgi","lgk","lgl","lgm","lgn","lgq","lgr","lgt","lgu","lgz","lha","lhh","lhi","lhl","lhm","lhn","lhp","lhs","lht","lhu","lia","lib","lic","lid","lie","lif","lig","lih","lii","lij","lik","lil","lio","lip","liq","lir","lis","liu","liv","liw","lix","liy","liz","lja","lje","lji","ljl","ljp","ljw","ljx","lka","lkb","lkc","lkd","lke","lkh","lki","lkj","lkl","lkm","lkn","lko","lkr","lks","lkt","lku","lky","lla","llb","llc","lld","lle","llf","llg","llh","lli","llj","llk","lll","llm","lln","llo","llp","llq","lls","llu","llx","lma","lmb","lmc","lmd","lme","lmf","lmg","lmh","lmi","lmj","lmk","lml","lmm","lmn","lmo","lmp","lmq","lmr","lmu","lmv","lmw","lmx","lmy","lmz","lna","lnb","lnd","lng","lnh","lni","lnj","lnl","lnm","lnn","lno","lns","lnu","lnw","lnz","loa","lob","loc","loe","lof","log","loh","loi","loj","lok","lol","lom","lon","loo","lop","loq","lor","los","lot","lou","lov","low","lox","loy","loz","lpa","lpe","lpn","lpo","lpx","lra","lrc","lre","lrg","lri","lrk","lrl","lrm","lrn","lro","lrr","lrt","lrv","lrz","lsa","lsd","lse","lsg","lsh","lsi","lsl","lsm","lso","lsp","lsr","lss","lst","lsy","ltc","ltg","lth","lti","ltn","lto","lts","ltu","lua","luc","lud","lue","luf","lui","luj","luk","lul","lum","lun","luo","lup","luq","lur","lus","lut","luu","luv","luw","luy","luz","lva","lvk","lvs","lvu","lwa","lwe","lwg","lwh","lwl","lwm","lwo","lwt","lwu","lww","lya","lyg","lyn","lzh","lzl","lzn","lzz","maa","mab","mad","mae","maf","mag","mai","maj","mak","mam","man","map","maq","mas","mat","mau","mav","maw","max","maz","mba","mbb","mbc","mbd","mbe","mbf","mbh","mbi","mbj","mbk","mbl","mbm","mbn","mbo","mbp","mbq","mbr","mbs","mbt","mbu","mbv","mbw","mbx","mby","mbz","mca","mcb","mcc","mcd","mce","mcf","mcg","mch","mci","mcj","mck","mcl","mcm","mcn","mco","mcp","mcq","mcr","mcs","mct","mcu","mcv","mcw","mcx","mcy","mcz","mda","mdb","mdc","mdd","mde","mdf","mdg","mdh","mdi","mdj","mdk","mdl","mdm","mdn","mdp","mdq","mdr","mds","mdt","mdu","mdv","mdw","mdx","mdy","mdz","mea","meb","mec","med","mee","mef","meg","meh","mei","mej","mek","mel","mem","men","meo","mep","meq","mer","mes","met","meu","mev","mew","mey","mez","mfa","mfb","mfc","mfd","mfe","mff","mfg","mfh","mfi","mfj","mfk","mfl","mfm","mfn","mfo","mfp","mfq","mfr","mfs","mft","mfu","mfv","mfw","mfx","mfy","mfz","mga","mgb","mgc","mgd","mge","mgf","mgg","mgh","mgi","mgj","mgk","mgl","mgm","mgn","mgo","mgp","mgq","mgr","mgs","mgt","mgu","mgv","mgw","mgx","mgy","mgz","mha","mhb","mhc","mhd","mhe","mhf","mhg","mhh","mhi","mhj","mhk","mhl","mhm","mhn","mho","mhp","mhq","mhr","mhs","mht","mhu","mhw","mhx","mhy","mhz","mia","mib","mic","mid","mie","mif","mig","mih","mii","mij","mik","mil","mim","min","mio","mip","miq","mir","mis","mit","miu","miw","mix","miy","miz","mja","mjb","mjc","mjd","mje","mjg","mjh","mji","mjj","mjk","mjl","mjm","mjn","mjo","mjp","mjq","mjr","mjs","mjt","mju","mjv","mjw","mjx","mjy","mjz","mka","mkb","mkc","mke","mkf","mkg","mkh","mki","mkj","mkk","mkl","mkm","mkn","mko","mkp","mkq","mkr","mks","mkt","mku","mkv","mkw","mkx","mky","mkz","mla","mlb","mlc","mld","mle","mlf","mlh","mli","mlj","mlk","mll","mlm","mln","mlo","mlp","mlq","mlr","mls","mlu","mlv","mlw","mlx","mlz","mma","mmb","mmc","mmd","mme","mmf","mmg","mmh","mmi","mmj","mmk","mml","mmm","mmn","mmo","mmp","mmq","mmr","mmt","mmu","mmv","mmw","mmx","mmy","mmz","mna","mnb","mnc","mnd","mne","mnf","mng","mnh","mni","mnj","mnk","mnl","mnm","mnn","mno","mnp","mnq","mnr","mns","mnt","mnu","mnv","mnw","mnx","mny","mnz","moa","moc","mod","moe","mof","mog","moh","moi","moj","mok","mom","moo","mop","moq","mor","mos","mot","mou","mov","mow","mox","moy","moz","mpa","mpb","mpc","mpd","mpe","mpg","mph","mpi","mpj","mpk","mpl","mpm","mpn","mpo","mpp","mpq","mpr","mps","mpt","mpu","mpv","mpw","mpx","mpy","mpz","mqa","mqb","mqc","mqe","mqf","mqg","mqh","mqi","mqj","mqk","mql","mqm","mqn","mqo","mqp","mqq","mqr","mqs","mqt","mqu","mqv","mqw","mqx","mqy","mqz","mra","mrb","mrc","mrd","mre","mrf","mrg","mrh","mrj","mrk","mrl","mrm","mrn","mro","mrp","mrq","mrr","mrs","mrt","mru","mrv","mrw","mrx","mry","mrz","msb","msc","msd","mse","msf","msg","msh","msi","msj","msk","msl","msm","msn","mso","msp","msq","msr","mss","mst","msu","msv","msw","msx","msy","msz","mta","mtb","mtc","mtd","mte","mtf","mtg","mth","mti","mtj","mtk","mtl","mtm","mtn","mto","mtp","mtq","mtr","mts","mtt","mtu","mtv","mtw","mtx","mty","mua","mub","muc","mud","mue","mug","muh","mui","muj","muk","mul","mum","mun","muo","mup","muq","mur","mus","mut","muu","muv","mux","muy","muz","mva","mvb","mvd","mve","mvf","mvg","mvh","mvi","mvk","mvl","mvm","mvn","mvo","mvp","mvq","mvr","mvs","mvt","mvu","mvv","mvw","mvx","mvy","mvz","mwa","mwb","mwc","mwd","mwe","mwf","mwg","mwh","mwi","mwj","mwk","mwl","mwm","mwn","mwo","mwp","mwq","mwr","mws","mwt","mwu","mwv","mww","mwx","mwy","mwz","mxa","mxb","mxc","mxd","mxe","mxf","mxg","mxh","mxi","mxj","mxk","mxl","mxm","mxn","mxo","mxp","mxq","mxr","mxs","mxt","mxu","mxv","mxw","mxx","mxy","mxz","myb","myc","myd","mye","myf","myg","myh","myi","myj","myk","myl","mym","myn","myo","myp","myq","myr","mys","myt","myu","myv","myw","myx","myy","myz","mza","mzb","mzc","mzd","mze","mzg","mzh","mzi","mzj","mzk","mzl","mzm","mzn","mzo","mzp","mzq","mzr","mzs","mzt","mzu","mzv","mzw","mzx","mzy","mzz","naa","nab","nac","nad","nae","naf","nag","nah","nai","naj","nak","nal","nam","nan","nao","nap","naq","nar","nas","nat","naw","nax","nay","naz","nba","nbb","nbc","nbd","nbe","nbf","nbg","nbh","nbi","nbj","nbk","nbm","nbn","nbo","nbp","nbq","nbr","nbs","nbt","nbu","nbv","nbw","nbx","nby","nca","ncb","ncc","ncd","nce","ncf","ncg","nch","nci","ncj","nck","ncl","ncm","ncn","nco","ncp","ncq","ncr","ncs","nct","ncu","ncx","ncz","nda","ndb","ndc","ndd","ndf","ndg","ndh","ndi","ndj","ndk","ndl","ndm","ndn","ndp","ndq","ndr","nds","ndt","ndu","ndv","ndw","ndx","ndy","ndz","nea","neb","nec","ned","nee","nef","neg","neh","nei","nej","nek","nem","nen","neo","neq","ner","nes","net","neu","nev","new","nex","ney","nez","nfa","nfd","nfl","nfr","nfu","nga","ngb","ngc","ngd","nge","ngf","ngg","ngh","ngi","ngj","ngk","ngl","ngm","ngn","ngo","ngp","ngq","ngr","ngs","ngt","ngu","ngv","ngw","ngx","ngy","ngz","nha","nhb","nhc","nhd","nhe","nhf","nhg","nhh","nhi","nhk","nhm","nhn","nho","nhp","nhq","nhr","nht","nhu","nhv","nhw","nhx","nhy","nhz","nia","nib","nic","nid","nie","nif","nig","nih","nii","nij","nik","nil","nim","nin","nio","niq","nir","nis","nit","niu","niv","niw","nix","niy","niz","nja","njb","njd","njh","nji","njj","njl","njm","njn","njo","njr","njs","njt","nju","njx","njy","njz","nka","nkb","nkc","nkd","nke","nkf","nkg","nkh","nki","nkj","nkk","nkm","nkn","nko","nkp","nkq","nkr","nks","nkt","nku","nkv","nkw","nkx","nkz","nla","nlc","nle","nlg","nli","nlj","nlk","nll","nln","nlo","nlq","nlr","nlu","nlv","nlw","nlx","nly","nlz","nma","nmb","nmc","nmd","nme","nmf","nmg","nmh","nmi","nmj","nmk","nml","nmm","nmn","nmo","nmp","nmq","nmr","nms","nmt","nmu","nmv","nmw","nmx","nmy","nmz","nna","nnb","nnc","nnd","nne","nnf","nng","nnh","nni","nnj","nnk","nnl","nnm","nnn","nnp","nnq","nnr","nns","nnt","nnu","nnv","nnw","nnx","nny","nnz","noa","noc","nod","noe","nof","nog","noh","noi","noj","nok","nol","nom","non","noo","nop","noq","nos","not","nou","nov","now","noy","noz","npa","npb","npg","nph","npi","npl","npn","npo","nps","npu","npx","npy","nqg","nqk","nql","nqm","nqn","nqo","nqq","nqy","nra","nrb","nrc","nre","nrf","nrg","nri","nrk","nrl","nrm","nrn","nrp","nrr","nrt","nru","nrx","nrz","nsa","nsc","nsd","nse","nsf","nsg","nsh","nsi","nsk","nsl","nsm","nsn","nso","nsp","nsq","nsr","nss","nst","nsu","nsv","nsw","nsx","nsy","nsz","ntd","nte","ntg","nti","ntj","ntk","ntm","nto","ntp","ntr","nts","ntu","ntw","ntx","nty","ntz","nua","nub","nuc","nud","nue","nuf","nug","nuh","nui","nuj","nuk","nul","num","nun","nuo","nup","nuq","nur","nus","nut","nuu","nuv","nuw","nux","nuy","nuz","nvh","nvm","nvo","nwa","nwb","nwc","nwe","nwg","nwi","nwm","nwo","nwr","nwx","nwy","nxa","nxd","nxe","nxg","nxi","nxk","nxl","nxm","nxn","nxo","nxq","nxr","nxu","nxx","nyb","nyc","nyd","nye","nyf","nyg","nyh","nyi","nyj","nyk","nyl","nym","nyn","nyo","nyp","nyq","nyr","nys","nyt","nyu","nyv","nyw","nyx","nyy","nza","nzb","nzi","nzk","nzm","nzs","nzu","nzy","nzz","oaa","oac","oar","oav","obi","obk","obl","obm","obo","obr","obt","obu","oca","och","oco","ocu","oda","odk","odt","odu","ofo","ofs","ofu","ogb","ogc","oge","ogg","ogo","ogu","oht","ohu","oia","oin","ojb","ojc","ojg","ojp","ojs","ojv","ojw","oka","okb","okd","oke","okg","okh","oki","okj","okk","okl","okm","okn","oko","okr","oks","oku","okv","okx","ola","old","ole","olk","olm","olo","olr","olt","olu","oma","omb","omc","ome","omg","omi","omk","oml","omn","omo","omp","omq","omr","omt","omu","omv","omw","omx","ona","onb","one","ong","oni","onj","onk","onn","ono","onp","onr","ons","ont","onu","onw","onx","ood","oog","oon","oor","oos","opa","opk","opm","opo","opt","opy","ora","orc","ore","org","orh","orn","oro","orr","ors","ort","oru","orv","orw","orx","ory","orz","osa","osc","osi","oso","osp","ost","osu","osx","ota","otb","otd","ote","oti","otk","otl","otm","otn","oto","otq","otr","ots","ott","otu","otw","otx","oty","otz","oua","oub","oue","oui","oum","oun","ovd","owi","owl","oyb","oyd","oym","oyy","ozm","paa","pab","pac","pad","pae","paf","pag","pah","pai","pak","pal","pam","pao","pap","paq","par","pas","pat","pau","pav","paw","pax","pay","paz","pbb","pbc","pbe","pbf","pbg","pbh","pbi","pbl","pbn","pbo","pbp","pbr","pbs","pbt","pbu","pbv","pby","pbz","pca","pcb","pcc","pcd","pce","pcf","pcg","pch","pci","pcj","pck","pcl","pcm","pcn","pcp","pcr","pcw","pda","pdc","pdi","pdn","pdo","pdt","pdu","pea","peb","ped","pee","pef","peg","peh","pei","pej","pek","pel","pem","peo","pep","peq","pes","pev","pex","pey","pez","pfa","pfe","pfl","pga","pgd","pgg","pgi","pgk","pgl","pgn","pgs","pgu","pgy","pgz","pha","phd","phg","phh","phi","phk","phl","phm","phn","pho","phq","phr","pht","phu","phv","phw","pia","pib","pic","pid","pie","pif","pig","pih","pii","pij","pil","pim","pin","pio","pip","pir","pis","pit","piu","piv","piw","pix","piy","piz","pjt","pka","pkb","pkc","pkg","pkh","pkn","pko","pkp","pkr","pks","pkt","pku","pla","plb","plc","pld","ple","plf","plg","plh","plj","plk","pll","pln","plo","plp","plq","plr","pls","plt","plu","plv","plw","ply","plz","pma","pmb","pmc","pmd","pme","pmf","pmh","pmi","pmj","pmk","pml","pmm","pmn","pmo","pmq","pmr","pms","pmt","pmu","pmw","pmx","pmy","pmz","pna","pnb","pnc","pne","png","pnh","pni","pnj","pnk","pnl","pnm","pnn","pno","pnp","pnq","pnr","pns","pnt","pnu","pnv","pnw","pnx","pny","pnz","poc","pod","poe","pof","pog","poh","poi","pok","pom","pon","poo","pop","poq","pos","pot","pov","pow","pox","poy","poz","ppa","ppe","ppi","ppk","ppl","ppm","ppn","ppo","ppp","ppq","ppr","pps","ppt","ppu","pqa","pqe","pqm","pqw","pra","prb","prc","prd","pre","prf","prg","prh","pri","prk","prl","prm","prn","pro","prp","prq","prr","prs","prt","pru","prw","prx","pry","prz","psa","psc","psd","pse","psg","psh","psi","psl","psm","psn","pso","psp","psq","psr","pss","pst","psu","psw","psy","pta","pth","pti","ptn","pto","ptp","ptq","ptr","ptt","ptu","ptv","ptw","pty","pua","pub","puc","pud","pue","puf","pug","pui","puj","puk","pum","puo","pup","puq","pur","put","puu","puw","pux","puy","puz","pwa","pwb","pwg","pwi","pwm","pwn","pwo","pwr","pww","pxm","pye","pym","pyn","pys","pyu","pyx","pyy","pzn","qaa..qtz","qua","qub","quc","qud","quf","qug","quh","qui","quk","qul","qum","qun","qup","quq","qur","qus","quv","quw","qux","quy","quz","qva","qvc","qve","qvh","qvi","qvj","qvl","qvm","qvn","qvo","qvp","qvs","qvw","qvy","qvz","qwa","qwc","qwe","qwh","qwm","qws","qwt","qxa","qxc","qxh","qxl","qxn","qxo","qxp","qxq","qxr","qxs","qxt","qxu","qxw","qya","qyp","raa","rab","rac","rad","raf","rag","rah","rai","raj","rak","ral","ram","ran","rao","rap","raq","rar","ras","rat","rau","rav","raw","rax","ray","raz","rbb","rbk","rbl","rbp","rcf","rdb","rea","reb","ree","reg","rei","rej","rel","rem","ren","rer","res","ret","rey","rga","rge","rgk","rgn","rgr","rgs","rgu","rhg","rhp","ria","rie","rif","ril","rim","rin","rir","rit","riu","rjg","rji","rjs","rka","rkb","rkh","rki","rkm","rkt","rkw","rma","rmb","rmc","rmd","rme","rmf","rmg","rmh","rmi","rmk","rml","rmm","rmn","rmo","rmp","rmq","rmr","rms","rmt","rmu","rmv","rmw","rmx","rmy","rmz","rna","rnd","rng","rnl","rnn","rnp","rnr","rnw","roa","rob","roc","rod","roe","rof","rog","rol","rom","roo","rop","ror","rou","row","rpn","rpt","rri","rro","rrt","rsb","rsi","rsl","rsm","rtc","rth","rtm","rts","rtw","rub","ruc","rue","ruf","rug","ruh","rui","ruk","ruo","rup","ruq","rut","ruu","ruy","ruz","rwa","rwk","rwm","rwo","rwr","rxd","rxw","ryn","rys","ryu","rzh","saa","sab","sac","sad","sae","saf","sah","sai","saj","sak","sal","sam","sao","sap","saq","sar","sas","sat","sau","sav","saw","sax","say","saz","sba","sbb","sbc","sbd","sbe","sbf","sbg","sbh","sbi","sbj","sbk","sbl","sbm","sbn","sbo","sbp","sbq","sbr","sbs","sbt","sbu","sbv","sbw","sbx","sby","sbz","sca","scb","sce","scf","scg","sch","sci","sck","scl","scn","sco","scp","scq","scs","sct","scu","scv","scw","scx","sda","sdb","sdc","sde","sdf","sdg","sdh","sdj","sdk","sdl","sdm","sdn","sdo","sdp","sdr","sds","sdt","sdu","sdv","sdx","sdz","sea","seb","sec","sed","see","sef","seg","seh","sei","sej","sek","sel","sem","sen","seo","sep","seq","ser","ses","set","seu","sev","sew","sey","sez","sfb","sfe","sfm","sfs","sfw","sga","sgb","sgc","sgd","sge","sgg","sgh","sgi","sgj","sgk","sgl","sgm","sgn","sgo","sgp","sgr","sgs","sgt","sgu","sgw","sgx","sgy","sgz","sha","shb","shc","shd","she","shg","shh","shi","shj","shk","shl","shm","shn","sho","shp","shq","shr","shs","sht","shu","shv","shw","shx","shy","shz","sia","sib","sid","sie","sif","sig","sih","sii","sij","sik","sil","sim","sio","sip","siq","sir","sis","sit","siu","siv","siw","six","siy","siz","sja","sjb","sjd","sje","sjg","sjk","sjl","sjm","sjn","sjo","sjp","sjr","sjs","sjt","sju","sjw","ska","skb","skc","skd","ske","skf","skg","skh","ski","skj","skk","skm","skn","sko","skp","skq","skr","sks","skt","sku","skv","skw","skx","sky","skz","sla","slc","sld","sle","slf","slg","slh","sli","slj","sll","slm","sln","slp","slq","slr","sls","slt","slu","slw","slx","sly","slz","sma","smb","smc","smd","smf","smg","smh","smi","smj","smk","sml","smm","smn","smp","smq","smr","sms","smt","smu","smv","smw","smx","smy","smz","snb","snc","sne","snf","sng","snh","sni","snj","snk","snl","snm","snn","sno","snp","snq","snr","sns","snu","snv","snw","snx","sny","snz","soa","sob","soc","sod","soe","sog","soh","soi","soj","sok","sol","son","soo","sop","soq","sor","sos","sou","sov","sow","sox","soy","soz","spb","spc","spd","spe","spg","spi","spk","spl","spm","spn","spo","spp","spq","spr","sps","spt","spu","spv","spx","spy","sqa","sqh","sqj","sqk","sqm","sqn","sqo","sqq","sqr","sqs","sqt","squ","sra","srb","src","sre","srf","srg","srh","sri","srk","srl","srm","srn","sro","srq","srr","srs","srt","sru","srv","srw","srx","sry","srz","ssa","ssb","ssc","ssd","sse","ssf","ssg","ssh","ssi","ssj","ssk","ssl","ssm","ssn","sso","ssp","ssq","ssr","sss","sst","ssu","ssv","ssx","ssy","ssz","sta","stb","std","ste","stf","stg","sth","sti","stj","stk","stl","stm","stn","sto","stp","stq","str","sts","stt","stu","stv","stw","sty","sua","sub","suc","sue","sug","sui","suj","suk","sul","sum","suq","sur","sus","sut","suv","suw","sux","suy","suz","sva","svb","svc","sve","svk","svm","svr","svs","svx","swb","swc","swf","swg","swh","swi","swj","swk","swl","swm","swn","swo","swp","swq","swr","sws","swt","swu","swv","sww","swx","swy","sxb","sxc","sxe","sxg","sxk","sxl","sxm","sxn","sxo","sxr","sxs","sxu","sxw","sya","syb","syc","syd","syi","syk","syl","sym","syn","syo","syr","sys","syw","syx","syy","sza","szb","szc","szd","sze","szg","szl","szn","szp","szs","szv","szw","taa","tab","tac","tad","tae","taf","tag","tai","taj","tak","tal","tan","tao","tap","taq","tar","tas","tau","tav","taw","tax","tay","taz","tba","tbb","tbc","tbd","tbe","tbf","tbg","tbh","tbi","tbj","tbk","tbl","tbm","tbn","tbo","tbp","tbq","tbr","tbs","tbt","tbu","tbv","tbw","tbx","tby","tbz","tca","tcb","tcc","tcd","tce","tcf","tcg","tch","tci","tck","tcl","tcm","tcn","tco","tcp","tcq","tcs","tct","tcu","tcw","tcx","tcy","tcz","tda","tdb","tdc","tdd","tde","tdf","tdg","tdh","tdi","tdj","tdk","tdl","tdm","tdn","tdo","tdq","tdr","tds","tdt","tdu","tdv","tdx","tdy","tea","teb","tec","ted","tee","tef","teg","teh","tei","tek","tem","ten","teo","tep","teq","ter","tes","tet","teu","tev","tew","tex","tey","tfi","tfn","tfo","tfr","tft","tga","tgb","tgc","tgd","tge","tgf","tgg","tgh","tgi","tgj","tgn","tgo","tgp","tgq","tgr","tgs","tgt","tgu","tgv","tgw","tgx","tgy","tgz","thc","thd","the","thf","thh","thi","thk","thl","thm","thn","thp","thq","thr","ths","tht","thu","thv","thw","thx","thy","thz","tia","tic","tid","tie","tif","tig","tih","tii","tij","tik","til","tim","tin","tio","tip","tiq","tis","tit","tiu","tiv","tiw","tix","tiy","tiz","tja","tjg","tji","tjl","tjm","tjn","tjo","tjs","tju","tjw","tka","tkb","tkd","tke","tkf","tkg","tkk","tkl","tkm","tkn","tkp","tkq","tkr","tks","tkt","tku","tkv","tkw","tkx","tkz","tla","tlb","tlc","tld","tlf","tlg","tlh","tli","tlj","tlk","tll","tlm","tln","tlo","tlp","tlq","tlr","tls","tlt","tlu","tlv","tlw","tlx","tly","tma","tmb","tmc","tmd","tme","tmf","tmg","tmh","tmi","tmj","tmk","tml","tmm","tmn","tmo","tmp","tmq","tmr","tms","tmt","tmu","tmv","tmw","tmy","tmz","tna","tnb","tnc","tnd","tne","tnf","tng","tnh","tni","tnk","tnl","tnm","tnn","tno","tnp","tnq","tnr","tns","tnt","tnu","tnv","tnw","tnx","tny","tnz","tob","toc","tod","toe","tof","tog","toh","toi","toj","tol","tom","too","top","toq","tor","tos","tou","tov","tow","tox","toy","toz","tpa","tpc","tpe","tpf","tpg","tpi","tpj","tpk","tpl","tpm","tpn","tpo","tpp","tpq","tpr","tpt","tpu","tpv","tpw","tpx","tpy","tpz","tqb","tql","tqm","tqn","tqo","tqp","tqq","tqr","tqt","tqu","tqw","tra","trb","trc","trd","tre","trf","trg","trh","tri","trj","trk","trl","trm","trn","tro","trp","trq","trr","trs","trt","tru","trv","trw","trx","try","trz","tsa","tsb","tsc","tsd","tse","tsf","tsg","tsh","tsi","tsj","tsk","tsl","tsm","tsp","tsq","tsr","tss","tst","tsu","tsv","tsw","tsx","tsy","tsz","tta","ttb","ttc","ttd","tte","ttf","ttg","tth","tti","ttj","ttk","ttl","ttm","ttn","tto","ttp","ttq","ttr","tts","ttt","ttu","ttv","ttw","tty","ttz","tua","tub","tuc","tud","tue","tuf","tug","tuh","tui","tuj","tul","tum","tun","tuo","tup","tuq","tus","tut","tuu","tuv","tuw","tux","tuy","tuz","tva","tvd","tve","tvk","tvl","tvm","tvn","tvo","tvs","tvt","tvu","tvw","tvy","twa","twb","twc","twd","twe","twf","twg","twh","twl","twm","twn","two","twp","twq","twr","twt","twu","tww","twx","twy","txa","txb","txc","txe","txg","txh","txi","txj","txm","txn","txo","txq","txr","txs","txt","txu","txx","txy","tya","tye","tyh","tyi","tyj","tyl","tyn","typ","tyr","tys","tyt","tyu","tyv","tyx","tyz","tza","tzh","tzj","tzl","tzm","tzn","tzo","tzx","uam","uan","uar","uba","ubi","ubl","ubr","ubu","uby","uda","ude","udg","udi","udj","udl","udm","udu","ues","ufi","uga","ugb","uge","ugn","ugo","ugy","uha","uhn","uis","uiv","uji","uka","ukg","ukh","ukk","ukl","ukp","ukq","uks","uku","ukw","uky","ula","ulb","ulc","ule","ulf","uli","ulk","ull","ulm","uln","ulu","ulw","uma","umb","umc","umd","umg","umi","umm","umn","umo","ump","umr","ums","umu","una","und","une","ung","unk","unm","unn","unp","unr","unu","unx","unz","uok","upi","upv","ura","urb","urc","ure","urf","urg","urh","uri","urj","urk","url","urm","urn","uro","urp","urr","urt","uru","urv","urw","urx","ury","urz","usa","ush","usi","usk","usp","usu","uta","ute","utp","utr","utu","uum","uun","uur","uuu","uve","uvh","uvl","uwa","uya","uzn","uzs","vaa","vae","vaf","vag","vah","vai","vaj","val","vam","van","vao","vap","var","vas","vau","vav","vay","vbb","vbk","vec","ved","vel","vem","veo","vep","ver","vgr","vgt","vic","vid","vif","vig","vil","vin","vis","vit","viv","vka","vki","vkj","vkk","vkl","vkm","vko","vkp","vkt","vku","vlp","vls","vma","vmb","vmc","vmd","vme","vmf","vmg","vmh","vmi","vmj","vmk","vml","vmm","vmp","vmq","vmr","vms","vmu","vmv","vmw","vmx","vmy","vmz","vnk","vnm","vnp","vor","vot","vra","vro","vrs","vrt","vsi","vsl","vsv","vto","vum","vun","vut","vwa","waa","wab","wac","wad","wae","waf","wag","wah","wai","waj","wak","wal","wam","wan","wao","wap","waq","war","was","wat","wau","wav","waw","wax","way","waz","wba","wbb","wbe","wbf","wbh","wbi","wbj","wbk","wbl","wbm","wbp","wbq","wbr","wbs","wbt","wbv","wbw","wca","wci","wdd","wdg","wdj","wdk","wdu","wdy","wea","wec","wed","weg","weh","wei","wem","wen","weo","wep","wer","wes","wet","weu","wew","wfg","wga","wgb","wgg","wgi","wgo","wgu","wgw","wgy","wha","whg","whk","whu","wib","wic","wie","wif","wig","wih","wii","wij","wik","wil","wim","win","wir","wit","wiu","wiv","wiw","wiy","wja","wji","wka","wkb","wkd","wkl","wku","wkw","wky","wla","wlc","wle","wlg","wli","wlk","wll","wlm","wlo","wlr","wls","wlu","wlv","wlw","wlx","wly","wma","wmb","wmc","wmd","wme","wmh","wmi","wmm","wmn","wmo","wms","wmt","wmw","wmx","wnb","wnc","wnd","wne","wng","wni","wnk","wnm","wnn","wno","wnp","wnu","wnw","wny","woa","wob","woc","wod","woe","wof","wog","woi","wok","wom","won","woo","wor","wos","wow","woy","wpc","wra","wrb","wrd","wrg","wrh","wri","wrk","wrl","wrm","wrn","wro","wrp","wrr","wrs","wru","wrv","wrw","wrx","wry","wrz","wsa","wsg","wsi","wsk","wsr","wss","wsu","wsv","wtf","wth","wti","wtk","wtm","wtw","wua","wub","wud","wuh","wul","wum","wun","wur","wut","wuu","wuv","wux","wuy","wwa","wwb","wwo","wwr","www","wxa","wxw","wya","wyb","wyi","wym","wyr","wyy","xaa","xab","xac","xad","xae","xag","xai","xaj","xak","xal","xam","xan","xao","xap","xaq","xar","xas","xat","xau","xav","xaw","xay","xba","xbb","xbc","xbd","xbe","xbg","xbi","xbj","xbm","xbn","xbo","xbp","xbr","xbw","xbx","xby","xcb","xcc","xce","xcg","xch","xcl","xcm","xcn","xco","xcr","xct","xcu","xcv","xcw","xcy","xda","xdc","xdk","xdm","xdo","xdy","xeb","xed","xeg","xel","xem","xep","xer","xes","xet","xeu","xfa","xga","xgb","xgd","xgf","xgg","xgi","xgl","xgm","xgn","xgr","xgu","xgw","xha","xhc","xhd","xhe","xhr","xht","xhu","xhv","xia","xib","xii","xil","xin","xip","xir","xis","xiv","xiy","xjb","xjt","xka","xkb","xkc","xkd","xke","xkf","xkg","xkh","xki","xkj","xkk","xkl","xkn","xko","xkp","xkq","xkr","xks","xkt","xku","xkv","xkw","xkx","xky","xkz","xla","xlb","xlc","xld","xle","xlg","xli","xln","xlo","xlp","xls","xlu","xly","xma","xmb","xmc","xmd","xme","xmf","xmg","xmh","xmj","xmk","xml","xmm","xmn","xmo","xmp","xmq","xmr","xms","xmt","xmu","xmv","xmw","xmx","xmy","xmz","xna","xnb","xnd","xng","xnh","xni","xnk","xnn","xno","xnr","xns","xnt","xnu","xny","xnz","xoc","xod","xog","xoi","xok","xom","xon","xoo","xop","xor","xow","xpa","xpc","xpe","xpg","xpi","xpj","xpk","xpm","xpn","xpo","xpp","xpq","xpr","xps","xpt","xpu","xpy","xqa","xqt","xra","xrb","xrd","xre","xrg","xri","xrm","xrn","xrq","xrr","xrt","xru","xrw","xsa","xsb","xsc","xsd","xse","xsh","xsi","xsj","xsl","xsm","xsn","xso","xsp","xsq","xsr","xss","xsu","xsv","xsy","xta","xtb","xtc","xtd","xte","xtg","xth","xti","xtj","xtl","xtm","xtn","xto","xtp","xtq","xtr","xts","xtt","xtu","xtv","xtw","xty","xtz","xua","xub","xud","xug","xuj","xul","xum","xun","xuo","xup","xur","xut","xuu","xve","xvi","xvn","xvo","xvs","xwa","xwc","xwd","xwe","xwg","xwj","xwk","xwl","xwo","xwr","xwt","xww","xxb","xxk","xxm","xxr","xxt","xya","xyb","xyj","xyk","xyl","xyt","xyy","xzh","xzm","xzp","yaa","yab","yac","yad","yae","yaf","yag","yah","yai","yaj","yak","yal","yam","yan","yao","yap","yaq","yar","yas","yat","yau","yav","yaw","yax","yay","yaz","yba","ybb","ybd","ybe","ybh","ybi","ybj","ybk","ybl","ybm","ybn","ybo","ybx","yby","ych","ycl","ycn","ycp","yda","ydd","yde","ydg","ydk","yds","yea","yec","yee","yei","yej","yel","yen","yer","yes","yet","yeu","yev","yey","yga","ygi","ygl","ygm","ygp","ygr","ygs","ygu","ygw","yha","yhd","yhl","yhs","yia","yif","yig","yih","yii","yij","yik","yil","yim","yin","yip","yiq","yir","yis","yit","yiu","yiv","yix","yiy","yiz","yka","ykg","yki","ykk","ykl","ykm","ykn","yko","ykr","ykt","yku","yky","yla","ylb","yle","ylg","yli","yll","ylm","yln","ylo","ylr","ylu","yly","yma","ymb","ymc","ymd","yme","ymg","ymh","ymi","ymk","yml","ymm","ymn","ymo","ymp","ymq","ymr","yms","ymt","ymx","ymz","yna","ynd","yne","yng","ynh","ynk","ynl","ynn","yno","ynq","yns","ynu","yob","yog","yoi","yok","yol","yom","yon","yos","yot","yox","yoy","ypa","ypb","ypg","yph","ypk","ypm","ypn","ypo","ypp","ypz","yra","yrb","yre","yri","yrk","yrl","yrm","yrn","yro","yrs","yrw","yry","ysc","ysd","ysg","ysl","ysn","yso","ysp","ysr","yss","ysy","yta","ytl","ytp","ytw","yty","yua","yub","yuc","yud","yue","yuf","yug","yui","yuj","yuk","yul","yum","yun","yup","yuq","yur","yut","yuu","yuw","yux","yuy","yuz","yva","yvt","ywa","ywg","ywl","ywn","ywq","ywr","ywt","ywu","yww","yxa","yxg","yxl","yxm","yxu","yxy","yyr","yyu","yyz","yzg","yzk","zaa","zab","zac","zad","zae","zaf","zag","zah","zai","zaj","zak","zal","zam","zao","zap","zaq","zar","zas","zat","zau","zav","zaw","zax","zay","zaz","zbc","zbe","zbl","zbt","zbw","zca","zch","zdj","zea","zeg","zeh","zen","zga","zgb","zgh","zgm","zgn","zgr","zhb","zhd","zhi","zhn","zhw","zhx","zia","zib","zik","zil","zim","zin","zir","ziw","ziz","zka","zkb","zkd","zkg","zkh","zkk","zkn","zko","zkp","zkr","zkt","zku","zkv","zkz","zle","zlj","zlm","zln","zlq","zls","zlw","zma","zmb","zmc","zmd","zme","zmf","zmg","zmh","zmi","zmj","zmk","zml","zmm","zmn","zmo","zmp","zmq","zmr","zms","zmt","zmu","zmv","zmw","zmx","zmy","zmz","zna","znd","zne","zng","znk","zns","zoc","zoh","zom","zoo","zoq","zor","zos","zpa","zpb","zpc","zpd","zpe","zpf","zpg","zph","zpi","zpj","zpk","zpl","zpm","zpn","zpo","zpp","zpq","zpr","zps","zpt","zpu","zpv","zpw","zpx","zpy","zpz","zqe","zra","zrg","zrn","zro","zrp","zrs","zsa","zsk","zsl","zsm","zsr","zsu","zte","ztg","ztl","ztm","ztn","ztp","ztq","zts","ztt","ztu","ztx","zty","zua","zuh","zum","zun","zuy","zwa","zxx","zyb","zyg","zyj","zyn","zyp","zza","zzj"]
+;return axe.utils.validLangs=function(){"use strict";return L},commons}()})}("object"==typeof window?window:this);
\ No newline at end of file
diff --git a/tools/battor_agent/battor_connection_impl.cc b/tools/battor_agent/battor_connection_impl.cc
index 741c843..cab0fde2 100644
--- a/tools/battor_agent/battor_connection_impl.cc
+++ b/tools/battor_agent/battor_connection_impl.cc
@@ -29,11 +29,12 @@
 
 // Serial configuration parameters for the BattOr.
 const uint32_t kBattOrBitrate = 2000000;
-const device::serial::DataBits kBattOrDataBits =
-    device::serial::DataBits::EIGHT;
-const device::serial::ParityBit kBattOrParityBit =
-    device::serial::ParityBit::NONE;
-const device::serial::StopBits kBattOrStopBit = device::serial::StopBits::ONE;
+const device::mojom::SerialDataBits kBattOrDataBits =
+    device::mojom::SerialDataBits::EIGHT;
+const device::mojom::SerialParityBit kBattOrParityBit =
+    device::mojom::SerialParityBit::NONE;
+const device::mojom::SerialStopBits kBattOrStopBit =
+    device::mojom::SerialStopBits::ONE;
 const bool kBattOrCtsFlowControl = true;
 const bool kBattOrHasCtsFlowControl = true;
 // The maximum BattOr message is 50kB long.
@@ -87,7 +88,7 @@
 
   io_handler_ = CreateIoHandler();
 
-  device::serial::ConnectionOptions options;
+  device::mojom::SerialConnectionOptions options;
   options.bitrate = kBattOrBitrate;
   options.data_bits = kBattOrDataBits;
   options.parity_bit = kBattOrParityBit;
@@ -184,7 +185,7 @@
 
 void BattOrConnectionImpl::CancelReadMessage() {
   LogSerial("Canceling read due to timeout.");
-  io_handler_->CancelRead(device::serial::ReceiveError::TIMEOUT);
+  io_handler_->CancelRead(device::mojom::SerialReceiveError::TIMEOUT);
 }
 
 void BattOrConnectionImpl::Flush() {
@@ -211,9 +212,10 @@
       on_receive_buffer_filled));
 }
 
-void BattOrConnectionImpl::OnBytesRead(int bytes_read,
-                                       device::serial::ReceiveError error) {
-  if (error != device::serial::ReceiveError::NONE) {
+void BattOrConnectionImpl::OnBytesRead(
+    int bytes_read,
+    device::mojom::SerialReceiveError error) {
+  if (error != device::mojom::SerialReceiveError::NONE) {
     LogSerial(StringPrintf(
         "Read failed due to serial read failure with error code: %d.",
         static_cast<int>(error)));
@@ -341,8 +343,8 @@
 }
 
 void BattOrConnectionImpl::OnBytesSent(int bytes_sent,
-                                       device::serial::SendError error) {
-  bool success = (error == device::serial::SendError::NONE) &&
+                                       device::mojom::SerialSendError error) {
+  bool success = (error == device::mojom::SerialSendError::NONE) &&
                  (pending_write_length_ == static_cast<size_t>(bytes_sent));
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
diff --git a/tools/battor_agent/battor_connection_impl.h b/tools/battor_agent/battor_connection_impl.h
index 78ae11ea..2740bb5 100644
--- a/tools/battor_agent/battor_connection_impl.h
+++ b/tools/battor_agent/battor_connection_impl.h
@@ -63,7 +63,7 @@
 
   // Internal callback for when bytes are read. This method may trigger
   // additional reads if any newly read bytes are escape bytes.
-  void OnBytesRead(int bytes_read, device::serial::ReceiveError error);
+  void OnBytesRead(int bytes_read, device::mojom::SerialReceiveError error);
 
   void EndReadBytes(bool success,
                     BattOrMessageType type,
@@ -84,7 +84,7 @@
                                  std::vector<char>* data);
 
   // Internal callback for when bytes are sent.
-  void OnBytesSent(int bytes_sent, device::serial::SendError error);
+  void OnBytesSent(int bytes_sent, device::mojom::SerialSendError error);
 
   // Appends |str| to the serial log file if it exists.
   void LogSerial(const std::string& str);
diff --git a/tools/battor_agent/battor_connection_impl_unittest.cc b/tools/battor_agent/battor_connection_impl_unittest.cc
index 99561b5..447fdcb 100644
--- a/tools/battor_agent/battor_connection_impl_unittest.cc
+++ b/tools/battor_agent/battor_connection_impl_unittest.cc
@@ -17,8 +17,8 @@
 
 namespace {
 
-void NullWriteCallback(int, device::serial::SendError) {}
-void NullReadCallback(int, device::serial::ReceiveError) {}
+void NullWriteCallback(int, device::mojom::SerialSendError) {}
+void NullReadCallback(int, device::mojom::SerialReceiveError) {}
 
 }  // namespace
 
diff --git a/tools/battor_agent/battor_finder.cc b/tools/battor_agent/battor_finder.cc
index c47def55..79bd2c7 100644
--- a/tools/battor_agent/battor_finder.cc
+++ b/tools/battor_agent/battor_finder.cc
@@ -27,7 +27,7 @@
   std::unique_ptr<device::SerialDeviceEnumerator> serial_device_enumerator =
       device::SerialDeviceEnumerator::Create();
 
-  std::vector<device::serial::DeviceInfoPtr> devices =
+  std::vector<device::mojom::SerialDeviceInfoPtr> devices =
       serial_device_enumerator->GetDevices();
 
   std::string switch_specified_path =
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 9f7dfe10..f913faf 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -23291,6 +23291,7 @@
   <int value="280644887" label="mash"/>
   <int value="283232244" label="OmniboxUIExperimentNarrowDropdown:enabled"/>
   <int value="301869874" label="NTPPhysicalWebPageSuggestions:disabled"/>
+  <int value="303058039" label="AccountConsistency:disabled"/>
   <int value="304901781" label="NewUsbBackend:enabled"/>
   <int value="313303258" label="WebPaymentsModifiers:disabled"/>
   <int value="316182183" label="MediaDocumentDownloadButton:disabled"/>
@@ -23496,6 +23497,7 @@
   <int value="982032277" label="NTPOfflineBadge:disabled"/>
   <int value="982511393" label="NTPArticleSuggestions:disabled"/>
   <int value="983311394" label="tab-management-experiment-type"/>
+  <int value="986796748" label="AccountConsistency:enabled"/>
   <int value="988981463" label="ImageCaptureAPI:enabled"/>
   <int value="1000706989" label="AutomaticTabDiscarding:disabled"/>
   <int value="1002585107" label="emphasize-titles-in-omnibox-dropdown"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 00763a01..65c7eaa 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -8624,6 +8624,15 @@
   </summary>
 </histogram>
 
+<histogram name="Compositing.Browser.NumActivePictureLayers" units="layers">
+  <owner>paint-dev@chromium.org</owner>
+  <summary>
+    The number of PictureLayers in the active tree for each compositor frame.
+    This is logged once per frame, before the frame is drawn (in a browser
+    process).
+  </summary>
+</histogram>
+
 <histogram name="Compositing.Browser.NumRenderSurfaces" units="surfaces">
   <owner>paint-dev@chromium.org</owner>
   <summary>
@@ -8941,6 +8950,15 @@
   </summary>
 </histogram>
 
+<histogram name="Compositing.Renderer.NumActivePictureLayers" units="layers">
+  <owner>paint-dev@chromium.org</owner>
+  <summary>
+    The number of PictureLayers in the active tree for each compositor frame.
+    This is logged once per frame, before the frame is drawn (in a renderer
+    process).
+  </summary>
+</histogram>
+
 <histogram name="Compositing.Renderer.NumRenderSurfaces" units="surfaces">
   <owner>paint-dev@chromium.org</owner>
   <summary>
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index 4d4179e..678df47 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -30,6 +30,8 @@
 from core.sharding_map_generator import load_benchmark_sharding_map
 
 
+# TODO(rnephew): Remove when no tests disable using
+# expectations.PermanentlyDisableBenchmark()
 ANDROID_BOT_TO_DEVICE_TYPE_MAP = {
   'Android Swarming N5X Tester': 'Nexus 5X',
   'Android Nexus5X Perf': 'Nexus 5X',
@@ -694,6 +696,8 @@
   return True
 
 
+# TODO(rnephew): Remove when no tests disable using
+# expectations.PermanentlyDisableBenchmark()
 def ShouldBenchmarksBeScheduledViaStoryExpectations(
     benchmark, name, os_name, browser_name):
   # StoryExpectations uses finder_options.browser_type, platform.GetOSName,
@@ -785,6 +789,8 @@
       swarming_dimensions.append(get_swarming_dimension(
           dimension, device))
 
+    # TODO(rnephew): Remove when no tests disable using
+    # expectations.PermanentlyDisableBenchmark()
     if not ShouldBenchmarksBeScheduledViaStoryExpectations(
         benchmark, name, swarming_dimensions[0]['os'], browser_name):
       continue
diff --git a/tools/perf/scripts_smoke_unittest.py b/tools/perf/scripts_smoke_unittest.py
index c6baa8b..e8ae595 100644
--- a/tools/perf/scripts_smoke_unittest.py
+++ b/tools/perf/scripts_smoke_unittest.py
@@ -39,22 +39,6 @@
     self.assertIn('No benchmark named "foo"', stdout)
     self.assertNotEquals(return_code, 0)
 
-  @benchmark.Disabled('chromeos')  # crbug.com/483212
-  @benchmark.Disabled('android')   # crbug.com/641934
-  def testRunBenchmarkListListsOutBenchmarks(self):
-    return_code, stdout = self.RunPerfScript('run_benchmark list')
-    self.assertEquals(return_code, 0, stdout)
-    self.assertIn('Pass --browser to list benchmarks', stdout)
-    self.assertIn('dummy_benchmark.stable_benchmark_1', stdout)
-
-  @benchmark.Disabled('all')  # crbug.com/641934
-  def testRunBenchmarkListListsOutBenchmarksOnAndroid(self):
-    return_code, stdout = self.RunPerfScript(
-        'run_benchmark list --device=android --browser=android-chromium')
-    self.assertEquals(return_code, 0, stdout)
-    self.assertIn('Pass --browser to list benchmarks', stdout)
-    self.assertIn('dummy_benchmark.stable_benchmark_1', stdout)
-
   def testRunTrybotWithTypo(self):
     return_code, stdout = self.RunPerfScript('run_benchmark try linux octaenz')
     self.assertIn('No benchmark named "octaenz"', stdout)
diff --git a/tools/resources/OWNERS b/tools/resources/OWNERS
index fb33baa..b6a4905e 100644
--- a/tools/resources/OWNERS
+++ b/tools/resources/OWNERS
@@ -1,4 +1,3 @@
-per-file generate_resource_whitelist.*=agrieve@chromium.org
+agrieve@chromium.org
 per-file generate_resource_whitelist.*=estevenson@chromium.org
-per-file filter_resource_whitelist.*=agrieve@chromium.org
 per-file filter_resource_whitelist.*=zpeng@chromium.org
diff --git a/tools/resources/dummy.c b/tools/resources/dummy.c
new file mode 100644
index 0000000..1230b70
--- /dev/null
+++ b/tools/resources/dummy.c
@@ -0,0 +1,7 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+int main(int argc, char**argv) {
+  return 0;
+}
diff --git a/tools/resources/generate_resource_whitelist.gni b/tools/resources/generate_resource_whitelist.gni
index 33bc4b87a..d663ea2 100644
--- a/tools/resources/generate_resource_whitelist.gni
+++ b/tools/resources/generate_resource_whitelist.gni
@@ -21,17 +21,24 @@
 #     output = "$target_gen_dir/pak_whitelist.txt"
 #   }
 template("generate_resource_whitelist") {
-  action(target_name) {
+  # Wrap the shared_library in an executable so that it does not get added
+  # as a data_dep.
+  # TODO(crbug/748113): Remove once GN has a way to specify compile-only deps.
+  executable("${target_name}__exec") {
     forward_variables_from(invoker, [ "deps" ])
+    sources = [
+      "//tools/resources/dummy.c",
+    ]
+  }
+  action(target_name) {
+    deps = [
+      ":${target_name}__exec",
+    ]
     assert(is_android,
            "Resource whitelist currently implemented only on Android")
 
     script = "//tools/resources/generate_resource_whitelist.py"
 
-    inputs = [
-      invoker.input,
-    ]
-
     outputs = [
       invoker.output,
     ]
diff --git a/ui/accessibility/platform/ax_platform_node.cc b/ui/accessibility/platform/ax_platform_node.cc
index b35ecb9..93a374ab 100644
--- a/ui/accessibility/platform/ax_platform_node.cc
+++ b/ui/accessibility/platform/ax_platform_node.cc
@@ -9,15 +9,39 @@
 #include "build/build_config.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/accessibility/platform/ax_platform_node_delegate.h"
+#include "ui/accessibility/platform/ax_platform_unique_id.h"
 
 namespace ui {
 
-AXPlatformNode::AXPlatformNode() {}
+namespace {
+
+using UniqueIdMap = base::hash_map<int32_t, AXPlatformNode*>;
+// Map from each AXPlatformNode's unique id to its instance.
+base::LazyInstance<UniqueIdMap>::DestructorAtExit g_unique_id_map =
+    LAZY_INSTANCE_INITIALIZER;
+}
+
+AXPlatformNode::AXPlatformNode() : unique_id_(GetNextAXPlatformNodeUniqueId()) {
+  g_unique_id_map.Get()[unique_id_] = this;
+}
 
 AXPlatformNode::~AXPlatformNode() {
+  if (unique_id_)
+    g_unique_id_map.Get().erase(unique_id_);
 }
 
 void AXPlatformNode::Destroy() {
+  g_unique_id_map.Get().erase(unique_id_);
+  unique_id_ = 0;
+}
+
+AXPlatformNode* AXPlatformNode::GetFromUniqueId(int32_t unique_id) {
+  UniqueIdMap* unique_ids = g_unique_id_map.Pointer();
+  auto iter = unique_ids->find(unique_id);
+  if (iter != unique_ids->end())
+    return iter->second;
+
+  return nullptr;
 }
 
 }  // namespace ui
diff --git a/ui/accessibility/platform/ax_platform_node.h b/ui/accessibility/platform/ax_platform_node.h
index 5c1f26f..7204c23 100644
--- a/ui/accessibility/platform/ax_platform_node.h
+++ b/ui/accessibility/platform/ax_platform_node.h
@@ -49,6 +49,10 @@
  protected:
   AXPlatformNode();
   virtual ~AXPlatformNode();
+
+  virtual AXPlatformNode* GetFromUniqueId(int32_t unique_id);
+
+  int32_t unique_id_;
 };
 
 }  // namespace ui
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc
index 4d95f7d..25c8c227 100644
--- a/ui/accessibility/platform/ax_platform_node_win.cc
+++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -25,7 +25,6 @@
 #include "ui/accessibility/ax_tree_data.h"
 #include "ui/accessibility/platform/ax_platform_node_delegate.h"
 #include "ui/accessibility/platform/ax_platform_node_win.h"
-#include "ui/accessibility/platform/ax_platform_unique_id.h"
 #include "ui/base/win/atl_module.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 
@@ -307,34 +306,16 @@
   return ax_platform_node.Get();
 }
 
-using UniqueIdMap = base::hash_map<int32_t, AXPlatformNode*>;
-// Map from each AXPlatformNode's unique id to its instance.
-base::LazyInstance<UniqueIdMap>::DestructorAtExit g_unique_id_map =
-    LAZY_INSTANCE_INITIALIZER;
-
-// static
-AXPlatformNode* AXPlatformNodeWin::GetFromUniqueId(int32_t unique_id) {
-  UniqueIdMap* unique_ids = g_unique_id_map.Pointer();
-  auto iter = unique_ids->find(unique_id);
-  if (iter != unique_ids->end())
-    return iter->second;
-
-  return nullptr;
-}
 //
 // AXPlatformNodeWin
 //
 
-AXPlatformNodeWin::AXPlatformNodeWin()
-    : unique_id_(ui::GetNextAXPlatformNodeUniqueId()) {
-  g_unique_id_map.Get()[unique_id_] = this;
+AXPlatformNodeWin::AXPlatformNodeWin() {
 }
 
 AXPlatformNodeWin::~AXPlatformNodeWin() {
   for (ui::AXPlatformNodeRelationWin* relation : relations_)
     relation->Release();
-  if (unique_id_)
-    g_unique_id_map.Get().erase(unique_id_);
 }
 
 void AXPlatformNodeWin::CalculateRelationships() {
@@ -553,8 +534,6 @@
 void AXPlatformNodeWin::Destroy() {
   RemoveAlertTarget();
   AXPlatformNodeBase::Destroy();
-  g_unique_id_map.Get().erase(unique_id_);
-  unique_id_ = 0;
 }
 
 //
diff --git a/ui/accessibility/platform/ax_platform_node_win.h b/ui/accessibility/platform/ax_platform_node_win.h
index f6db0b8..e85a3c18 100644
--- a/ui/accessibility/platform/ax_platform_node_win.h
+++ b/ui/accessibility/platform/ax_platform_node_win.h
@@ -277,8 +277,6 @@
 
   // Clear node's current relationships and set them to the default values.
   void CalculateRelationships();
-  static AXPlatformNode* GetFromUniqueId(int32_t unique_id);
-  int32_t unique_id() const { return unique_id_; }
 
   // AXPlatformNode overrides.
   gfx::NativeViewAccessible GetNativeViewAccessible() override;
@@ -652,8 +650,6 @@
   void Dispose() override;
 
  private:
-  int32_t unique_id_;
-
   int MSAAEvent(ui::AXEvent event);
   bool IsWebAreaForPresentationalIframe();
   bool ShouldNodeHaveReadonlyStateByDefault(const AXNodeData& data) const;
diff --git a/ui/accessibility/platform/ax_platform_node_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
index 9fe0108..fbedffe1 100644
--- a/ui/accessibility/platform/ax_platform_node_win_unittest.cc
+++ b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
@@ -148,7 +148,7 @@
   void CheckIUnknownHasName(ScopedComPtr<IUnknown> unknown,
                             const wchar_t* expected_name) {
     ScopedComPtr<IAccessible2> accessible = ToIAccessible2(unknown);
-    ASSERT_NE(nullptr, accessible);
+    ASSERT_NE(nullptr, accessible.Get());
 
     ScopedBstr name;
     EXPECT_EQ(S_OK, accessible->get_accName(SELF, name.Receive()));
@@ -682,7 +682,7 @@
     ScopedComPtr<IDispatch> result;
     EXPECT_EQ(S_OK,
               root_iaccessible->get_accChild(SELF, result.GetAddressOf()));
-    EXPECT_EQ(result.Get(), root_iaccessible);
+    EXPECT_EQ(result.Get(), root_iaccessible.Get());
   }
 
   {
@@ -690,7 +690,7 @@
     ScopedVariant child1(1);
     EXPECT_EQ(S_OK,
               root_iaccessible->get_accChild(child1, result.GetAddressOf()));
-    EXPECT_EQ(result.Get(), button_iaccessible);
+    EXPECT_EQ(result.Get(), button_iaccessible.Get());
   }
 
   {
@@ -698,7 +698,7 @@
     ScopedVariant child2(2);
     EXPECT_EQ(S_OK,
               root_iaccessible->get_accChild(child2, result.GetAddressOf()));
-    EXPECT_EQ(result.Get(), checkbox_iaccessible);
+    EXPECT_EQ(result.Get(), checkbox_iaccessible.Get());
   }
 
   {
@@ -720,7 +720,7 @@
     ScopedVariant button_id_variant(button_unique_id);
     EXPECT_EQ(S_OK, root_iaccessible->get_accChild(button_id_variant,
                                                    result.GetAddressOf()));
-    EXPECT_EQ(result.Get(), button_iaccessible);
+    EXPECT_EQ(result.Get(), button_iaccessible.Get());
   }
 
   // We shouldn't be able to ask for the root node by its unique ID
@@ -741,13 +741,13 @@
   {
     ScopedComPtr<IDispatch> result;
     EXPECT_EQ(S_OK, button_iaccessible->get_accParent(result.GetAddressOf()));
-    EXPECT_EQ(result.Get(), root_iaccessible);
+    EXPECT_EQ(result.Get(), root_iaccessible.Get());
   }
 
   {
     ScopedComPtr<IDispatch> result;
     EXPECT_EQ(S_OK, checkbox_iaccessible->get_accParent(result.GetAddressOf()));
-    EXPECT_EQ(result.Get(), root_iaccessible);
+    EXPECT_EQ(result.Get(), root_iaccessible.Get());
   }
 
   {
@@ -896,7 +896,7 @@
       ToIAccessible2(GetRootIAccessible());
   ScopedComPtr<IAccessibleText> text_field;
   ia2_text_field.CopyTo(text_field.GetAddressOf());
-  ASSERT_NE(nullptr, text_field);
+  ASSERT_NE(nullptr, text_field.Get());
 
   EXPECT_HRESULT_SUCCEEDED(text_field->setSelection(0, 0, 1));
   EXPECT_HRESULT_SUCCEEDED(text_field->setSelection(0, 1, 0));
@@ -915,7 +915,7 @@
 
   ScopedComPtr<IAccessibleTable> result;
   root_obj.CopyTo(result.GetAddressOf());
-  ASSERT_NE(nullptr, result);
+  ASSERT_NE(nullptr, result.Get());
 
   ScopedComPtr<IUnknown> cell_1;
   EXPECT_EQ(S_OK, result->get_accessibleAt(1, 1, cell_1.GetAddressOf()));
@@ -942,7 +942,7 @@
 
   ScopedComPtr<IAccessibleTable> result;
   root_obj.CopyTo(result.GetAddressOf());
-  ASSERT_NE(nullptr, result);
+  ASSERT_NE(nullptr, result.Get());
 
   {
     ScopedComPtr<IUnknown> cell;
@@ -976,7 +976,7 @@
 
   ScopedComPtr<IAccessibleTable> result;
   root_obj.CopyTo(result.GetAddressOf());
-  ASSERT_NE(nullptr, result);
+  ASSERT_NE(nullptr, result.Get());
 
   long id;
   EXPECT_EQ(S_OK, result->get_childIndex(0, 0, &id));
@@ -1004,7 +1004,7 @@
 
   ScopedComPtr<IAccessibleTable> result;
   root_obj.CopyTo(result.GetAddressOf());
-  ASSERT_NE(nullptr, result);
+  ASSERT_NE(nullptr, result.Get());
 
   {
     ScopedBstr name;
@@ -1032,7 +1032,7 @@
 
   ScopedComPtr<IAccessibleTable> result;
   root_obj.CopyTo(result.GetAddressOf());
-  ASSERT_NE(nullptr, result);
+  ASSERT_NE(nullptr, result.Get());
 
   long columns_spanned;
   EXPECT_EQ(S_OK, result->get_columnExtentAt(1, 1, &columns_spanned));
@@ -1048,7 +1048,7 @@
 
   ScopedComPtr<IAccessibleTable> result;
   root_obj.CopyTo(result.GetAddressOf());
-  ASSERT_NE(nullptr, result);
+  ASSERT_NE(nullptr, result.Get());
 
   long index;
   EXPECT_EQ(S_OK, result->get_columnIndex(1, &index));
@@ -1064,7 +1064,7 @@
 
   ScopedComPtr<IAccessibleTable> result;
   root_obj.CopyTo(result.GetAddressOf());
-  ASSERT_NE(nullptr, result);
+  ASSERT_NE(nullptr, result.Get());
 
   long count;
   EXPECT_EQ(S_OK, result->get_nColumns(&count));
@@ -1078,7 +1078,7 @@
 
   ScopedComPtr<IAccessibleTable> result;
   root_obj.CopyTo(result.GetAddressOf());
-  ASSERT_NE(nullptr, result);
+  ASSERT_NE(nullptr, result.Get());
 
   long count;
   EXPECT_EQ(S_OK, result->get_nRows(&count));
@@ -1092,7 +1092,7 @@
 
   ScopedComPtr<IAccessibleTable> result;
   root_obj.CopyTo(result.GetAddressOf());
-  ASSERT_NE(nullptr, result);
+  ASSERT_NE(nullptr, result.Get());
 
   {
     ScopedBstr name;
@@ -1120,7 +1120,7 @@
 
   ScopedComPtr<IAccessibleTable> result;
   root_obj.CopyTo(result.GetAddressOf());
-  ASSERT_NE(nullptr, result);
+  ASSERT_NE(nullptr, result.Get());
 
   long rows_spanned;
   EXPECT_EQ(S_OK, result->get_rowExtentAt(0, 1, &rows_spanned));
@@ -1136,7 +1136,7 @@
 
   ScopedComPtr<IAccessibleTable> result;
   root_obj.CopyTo(result.GetAddressOf());
-  ASSERT_NE(nullptr, result);
+  ASSERT_NE(nullptr, result.Get());
 
   long index;
   EXPECT_EQ(S_OK, result->get_rowIndex(1, &index));
@@ -1152,7 +1152,7 @@
 
   ScopedComPtr<IAccessibleTable> result;
   root_obj.CopyTo(result.GetAddressOf());
-  ASSERT_NE(nullptr, result);
+  ASSERT_NE(nullptr, result.Get());
 
   long row, column, row_extents, column_extents;
   boolean is_selected;
@@ -1177,7 +1177,7 @@
 
   ScopedComPtr<IAccessibleTable2> result;
   root_obj.CopyTo(result.GetAddressOf());
-  ASSERT_NE(nullptr, result);
+  ASSERT_NE(nullptr, result.Get());
 
   {
     ScopedComPtr<IUnknown> cell;
@@ -1195,7 +1195,7 @@
   Build3X3Table();
 
   ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
-  ASSERT_NE(nullptr, cell);
+  ASSERT_NE(nullptr, cell.Get());
 
   long column_spanned;
   EXPECT_EQ(S_OK, cell->get_columnExtent(&column_spanned));
@@ -1206,7 +1206,7 @@
   Build3X3Table();
 
   ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
-  ASSERT_NE(nullptr, cell);
+  ASSERT_NE(nullptr, cell.Get());
 
   IUnknown** cell_accessibles;
 
@@ -1220,7 +1220,7 @@
   Build3X3Table();
 
   ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
-  ASSERT_NE(nullptr, cell);
+  ASSERT_NE(nullptr, cell.Get());
 
   long index;
   EXPECT_EQ(S_OK, cell->get_columnIndex(&index));
@@ -1231,7 +1231,7 @@
   Build3X3Table();
 
   ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
-  ASSERT_NE(nullptr, cell);
+  ASSERT_NE(nullptr, cell.Get());
 
   long rows_spanned;
   EXPECT_EQ(S_OK, cell->get_rowExtent(&rows_spanned));
@@ -1242,7 +1242,7 @@
   Build3X3Table();
 
   ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
-  ASSERT_NE(nullptr, cell);
+  ASSERT_NE(nullptr, cell.Get());
 
   IUnknown** cell_accessibles;
 
@@ -1258,7 +1258,7 @@
   Build3X3Table();
 
   ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
-  ASSERT_NE(nullptr, cell);
+  ASSERT_NE(nullptr, cell.Get());
 
   long index;
   EXPECT_EQ(S_OK, cell->get_rowIndex(&index));
@@ -1269,7 +1269,7 @@
   Build3X3Table();
 
   ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
-  ASSERT_NE(nullptr, cell);
+  ASSERT_NE(nullptr, cell.Get());
 
   long row, column, row_extents, column_extents;
   boolean is_selected;
@@ -1285,14 +1285,14 @@
   Build3X3Table();
 
   ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
-  ASSERT_NE(nullptr, cell);
+  ASSERT_NE(nullptr, cell.Get());
 
   ScopedComPtr<IUnknown> table;
   EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
 
   ScopedComPtr<IAccessibleTable> result;
   table.CopyTo(result.GetAddressOf());
-  ASSERT_NE(nullptr, result);
+  ASSERT_NE(nullptr, result.Get());
 
   // Check to make sure that this is the right table by checking one cell.
   ScopedComPtr<IUnknown> cell_1;
diff --git a/ui/aura/mus/window_tree_client.cc b/ui/aura/mus/window_tree_client.cc
index 9504d791..ff8bdc3 100644
--- a/ui/aura/mus/window_tree_client.cc
+++ b/ui/aura/mus/window_tree_client.cc
@@ -1373,8 +1373,31 @@
   // TODO(moshayedi): crbug.com/617222. No need to convert to ui::MouseEvent or
   // ui::TouchEvent once we have proper support for pointer events.
   std::unique_ptr<ui::Event> mapped_event = MapEvent(*event.get());
-  DispatchEventToTarget(mapped_event.get(), window);
-  ack_handler.set_handled(mapped_event->handled());
+  ui::Event* event_to_dispatch = mapped_event.get();
+// Ash wants the native events in one place (see ExtendedMouseWarpController).
+// By using the constructor that takes a MouseEvent we ensure the MouseEvent
+// has a NativeEvent that can be used to extract the pixel coordinates.
+//
+// TODO: this should really be covered by |root_location|. See 608547 for
+// details.
+#if defined(USE_OZONE)
+  std::unique_ptr<ui::MouseEvent> mapped_event_with_native;
+  if (mapped_event->type() == ui::ET_MOUSE_MOVED ||
+      mapped_event->type() == ui::ET_MOUSE_DRAGGED) {
+    mapped_event_with_native = base::MakeUnique<ui::MouseEvent>(
+        static_cast<const base::NativeEvent&>(mapped_event.get()));
+    // MouseEvent(NativeEvent) sets the root_location to location.
+    mapped_event_with_native->set_root_location_f(
+        mapped_event->AsMouseEvent()->root_location_f());
+    // |mapped_event| is now the NativeEvent. It's expected the location of the
+    // NativeEvent is the same as root_location.
+    mapped_event->AsMouseEvent()->set_location_f(
+        mapped_event->AsMouseEvent()->root_location_f());
+    event_to_dispatch = mapped_event_with_native.get();
+  }
+#endif
+  DispatchEventToTarget(event_to_dispatch, window);
+  ack_handler.set_handled(event_to_dispatch->handled());
 }
 
 void WindowTreeClient::OnPointerEventObserved(std::unique_ptr<ui::Event> event,
diff --git a/ui/aura/mus/window_tree_client_unittest.cc b/ui/aura/mus/window_tree_client_unittest.cc
index f6ba1a7..55c1921 100644
--- a/ui/aura/mus/window_tree_client_unittest.cc
+++ b/ui/aura/mus/window_tree_client_unittest.cc
@@ -724,6 +724,12 @@
   bool was_acked() const { return was_acked_; }
   const gfx::Point& last_event_location() const { return last_event_location_; }
   void set_event_id(uint32_t event_id) { event_id_ = event_id; }
+  bool last_mouse_event_had_native_event() const {
+    return last_mouse_event_had_native_event_;
+  }
+  const gfx::Point& last_native_event_location() const {
+    return last_native_event_location_;
+  }
 
   // TestWindowDelegate::
   void OnMouseEvent(ui::MouseEvent* event) override {
@@ -735,6 +741,11 @@
     else if (event->type() == ui::ET_MOUSE_RELEASED)
       got_release_ = true;
     last_event_location_ = event->location();
+    last_mouse_event_had_native_event_ = event->HasNativeEvent();
+    if (event->HasNativeEvent()) {
+      last_native_event_location_ =
+          ui::EventSystemLocationFromNative(event->native_event());
+    }
     event->SetHandled();
   }
 
@@ -765,6 +776,8 @@
   bool got_release_ = false;
   gfx::Point last_event_location_;
   uint32_t event_id_ = 0;
+  bool last_mouse_event_had_native_event_ = false;
+  gfx::Point last_native_event_location_;
 
   DISALLOW_COPY_AND_ASSIGN(InputEventBasicTestWindowDelegate);
 };
@@ -2425,9 +2438,9 @@
   uint32_t event_id = 1;
   window_delegate1.set_event_id(event_id);
   window_delegate2.set_event_id(event_id);
-  std::unique_ptr<ui::Event> ui_event(
-      new ui::MouseEvent(ui::ET_MOUSE_MOVED, event_location_in_pixels,
-                         gfx::Point(), ui::EventTimeForNow(), ui::EF_NONE, 0));
+  std::unique_ptr<ui::Event> ui_event(new ui::MouseEvent(
+      ui::ET_MOUSE_MOVED, event_location_in_pixels, event_location_in_pixels,
+      ui::EventTimeForNow(), ui::EF_NONE, 0));
   window_tree_client()->OnWindowInputEvent(
       event_id, server_id(&child1), window_tree_host.display_id(),
       ui::Event::Clone(*ui_event.get()), 0);
@@ -2438,6 +2451,13 @@
   EXPECT_FALSE(window_delegate2.got_move());
   const gfx::Point event_location_in_dip(25, 30);
   EXPECT_EQ(event_location_in_dip, window_delegate1.last_event_location());
+#if defined(USE_OZONE)
+  // For ozone there should be NativeEvent.
+  EXPECT_TRUE(window_delegate1.last_mouse_event_had_native_event());
+  // And the location of the NativeEvent should be in pixels.
+  EXPECT_EQ(event_location_in_pixels,
+            window_delegate1.last_native_event_location());
+#endif
   window_delegate1.reset();
   window_delegate2.reset();
 
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn
index 119d0fa..36db167 100644
--- a/ui/base/BUILD.gn
+++ b/ui/base/BUILD.gn
@@ -881,6 +881,7 @@
     ":ui_base_unittests_bundle_data",
     "//base",
     "//base/test:test_support",
+    "//mojo/edk/system",
     "//net",
     "//skia",
     "//testing/gmock",
diff --git a/ui/base/test/DEPS b/ui/base/test/DEPS
new file mode 100644
index 0000000..da738ce
--- /dev/null
+++ b/ui/base/test/DEPS
@@ -0,0 +1,5 @@
+specific_include_rules = {
+  "run_all_unittests\.cc": [
+    "+mojo/edk/embedder",
+  ],
+}
diff --git a/ui/base/test/run_all_unittests.cc b/ui/base/test/run_all_unittests.cc
index d778f41..af412a3 100644
--- a/ui/base/test/run_all_unittests.cc
+++ b/ui/base/test/run_all_unittests.cc
@@ -9,6 +9,7 @@
 #include "base/test/launcher/unit_test_launcher.h"
 #include "base/test/test_suite.h"
 #include "build/build_config.h"
+#include "mojo/edk/embedder/embedder.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/ui_base_paths.h"
 
@@ -107,6 +108,7 @@
 int main(int argc, char** argv) {
   UIBaseTestSuite test_suite(argc, argv);
 
+  mojo::edk::Init();
   return base::LaunchUnitTests(argc,
                                argv,
                                base::Bind(&UIBaseTestSuite::Run,
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc
index e4d00e8..468789a 100644
--- a/ui/compositor/layer.cc
+++ b/ui/compositor/layer.cc
@@ -445,14 +445,13 @@
 }
 
 void Layer::SetMaskLayer(Layer* layer_mask) {
-  // The provided mask should not have a layer mask itself.
-  DCHECK(!layer_mask ||
-         (!layer_mask->layer_mask_layer() &&
-          layer_mask->children().empty() &&
-          !layer_mask->layer_mask_back_link_));
-  DCHECK(!layer_mask_back_link_);
   if (layer_mask_ == layer_mask)
     return;
+  // The provided mask should not have a layer mask itself.
+  DCHECK(!layer_mask ||
+         (!layer_mask->layer_mask_layer() && layer_mask->children().empty() &&
+          !layer_mask->layer_mask_back_link_));
+  DCHECK(!layer_mask_back_link_);
   // We need to de-reference the currently linked object so that no problem
   // arises if the mask layer gets deleted before this object.
   if (layer_mask_)
diff --git a/ui/gl/gl_angle_util_win.cc b/ui/gl/gl_angle_util_win.cc
index 45e37ab4..291ba10 100644
--- a/ui/gl/gl_angle_util_win.cc
+++ b/ui/gl/gl_angle_util_win.cc
@@ -101,7 +101,7 @@
 
   UINT data_size = sizeof(dcomp_device.Get());
   HRESULT hr = d3d11_device->GetPrivateData(kDirectCompositionGUID, &data_size,
-                                            &dcomp_device);
+                                            dcomp_device.GetAddressOf());
   if (SUCCEEDED(hr) && dcomp_device)
     return dcomp_device;
 
diff --git a/ui/views/bubble/tray_bubble_view.cc b/ui/views/bubble/tray_bubble_view.cc
index 69bfd1d..33d429f 100644
--- a/ui/views/bubble/tray_bubble_view.cc
+++ b/ui/views/bubble/tray_bubble_view.cc
@@ -15,8 +15,7 @@
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/aura/window.h"
 #include "ui/compositor/layer.h"
-#include "ui/compositor/layer_delegate.h"
-#include "ui/compositor/paint_recorder.h"
+#include "ui/compositor/layer_owner.h"
 #include "ui/events/event.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/color_palette.h"
@@ -27,6 +26,7 @@
 #include "ui/views/bubble/bubble_frame_view.h"
 #include "ui/views/bubble/bubble_window_targeter.h"
 #include "ui/views/layout/box_layout.h"
+#include "ui/views/painter.h"
 #include "ui/views/widget/widget.h"
 #include "ui/wm/core/shadow_types.h"
 
@@ -81,54 +81,6 @@
   return false;
 }
 
-// This mask layer clips the bubble's content so that it does not overwrite the
-// rounded bubble corners.
-// TODO(miket): This does not work on Windows. Implement layer masking or
-// alternate solutions if the TrayBubbleView is needed there in the future.
-class TrayBubbleContentMask : public ui::LayerDelegate {
- public:
-  explicit TrayBubbleContentMask(int corner_radius);
-  ~TrayBubbleContentMask() override;
-
-  ui::Layer* layer() { return &layer_; }
-
-  // Overridden from LayerDelegate.
-  void OnPaintLayer(const ui::PaintContext& context) override;
-  void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
-  void OnDeviceScaleFactorChanged(float device_scale_factor) override;
-
- private:
-  ui::Layer layer_;
-  int corner_radius_;
-
-  DISALLOW_COPY_AND_ASSIGN(TrayBubbleContentMask);
-};
-
-TrayBubbleContentMask::TrayBubbleContentMask(int corner_radius)
-    : layer_(ui::LAYER_TEXTURED),
-      corner_radius_(corner_radius) {
-  layer_.set_delegate(this);
-  layer_.SetFillsBoundsOpaquely(false);
-}
-
-TrayBubbleContentMask::~TrayBubbleContentMask() {
-  layer_.set_delegate(NULL);
-}
-
-void TrayBubbleContentMask::OnPaintLayer(const ui::PaintContext& context) {
-  ui::PaintRecorder recorder(context, layer()->size());
-  cc::PaintFlags flags;
-  flags.setAlpha(255);
-  flags.setStyle(cc::PaintFlags::kFill_Style);
-  gfx::Rect rect(layer()->bounds().size());
-  recorder.canvas()->DrawRoundRect(rect, corner_radius_, flags);
-}
-
-void TrayBubbleContentMask::OnDeviceScaleFactorChanged(
-    float device_scale_factor) {
-  // Redrawing will take care of scale factor change.
-}
-
 // Custom layout for the bubble-view. Does the default box-layout if there is
 // enough height. Otherwise, makes sure the bottom rows are visible.
 class BottomAlignedBoxLayout : public BoxLayout {
@@ -166,7 +118,6 @@
 
 }  // namespace internal
 
-using internal::TrayBubbleContentMask;
 using internal::BottomAlignedBoxLayout;
 
 TrayBubbleView::Delegate::~Delegate() {}
@@ -228,8 +179,9 @@
   set_margins(gfx::Insets());
   SetPaintToLayer();
 
-  bubble_content_mask_.reset(
-      new TrayBubbleContentMask(bubble_border_->GetBorderCornerRadius()));
+  bubble_content_mask_ = views::Painter::CreatePaintedLayer(
+      views::Painter::CreateSolidRoundRectPainter(
+          SK_ColorBLACK, bubble_border_->GetBorderCornerRadius()));
 
   layout_->SetDefaultFlex(1);
   SetLayoutManager(layout_);
diff --git a/ui/views/bubble/tray_bubble_view.h b/ui/views/bubble/tray_bubble_view.h
index 592ccc3..77f6035 100644
--- a/ui/views/bubble/tray_bubble_view.h
+++ b/ui/views/bubble/tray_bubble_view.h
@@ -16,6 +16,10 @@
 #include "ui/views/mouse_watcher.h"
 #include "ui/views/views_export.h"
 
+namespace ui {
+class LayerOwner;
+}
+
 namespace views {
 class BoxLayout;
 class View;
@@ -24,10 +28,6 @@
 
 namespace views {
 
-namespace internal {
-class TrayBubbleContentMask;
-}
-
 // Specialized bubble view for bubbles associated with a tray icon (e.g. the
 // Ash status area). Mostly this handles custom anchor location and arrow and
 // border rendering. This also has its own delegate for handling mouse events
@@ -194,7 +194,7 @@
   // the latter ensures we don't leak it before passing off ownership.
   BubbleBorder* bubble_border_;
   std::unique_ptr<views::BubbleBorder> owned_bubble_border_;
-  std::unique_ptr<internal::TrayBubbleContentMask> bubble_content_mask_;
+  std::unique_ptr<ui::LayerOwner> bubble_content_mask_;
   bool is_gesture_dragging_;
 
   // True once the mouse cursor was actively moved by the user over the bubble.
diff --git a/ui/views/controls/native/native_view_host.cc b/ui/views/controls/native/native_view_host.cc
index e926db1..64160a2 100644
--- a/ui/views/controls/native/native_view_host.cc
+++ b/ui/views/controls/native/native_view_host.cc
@@ -54,6 +54,10 @@
   PreferredSizeChanged();
 }
 
+bool NativeViewHost::SetCornerRadius(int corner_radius) {
+  return native_wrapper_->SetCornerRadius(corner_radius);
+}
+
 void NativeViewHost::NativeViewDestroyed() {
   // Detach so we can clear our state and notify the native_wrapper_ to release
   // ref on the native view.
diff --git a/ui/views/controls/native/native_view_host.h b/ui/views/controls/native/native_view_host.h
index 5b018371..d838192 100644
--- a/ui/views/controls/native/native_view_host.h
+++ b/ui/views/controls/native/native_view_host.h
@@ -50,6 +50,11 @@
   // Sets a preferred size for the native view attached to this View.
   void SetPreferredSize(const gfx::Size& size);
 
+  // Sets the corner radius for clipping gfx::NativeView. Returns true on
+  // success or false if the platform doesn't support the operation.
+  // NB: This does not interact nicely with fast_resize.
+  bool SetCornerRadius(int corner_radius);
+
   // Fast resizing will move the native view and clip its visible region, this
   // will result in white areas and will not resize the content (so scrollbars
   // will be all wrong and content will flow offscreen). Only use this
@@ -70,7 +75,6 @@
     return fast_resize_at_last_layout_;
   }
 
-  // Accessor for |native_view_|.
   gfx::NativeView native_view() const { return native_view_; }
 
   void NativeViewDestroyed();
diff --git a/ui/views/controls/native/native_view_host_aura.cc b/ui/views/controls/native/native_view_host_aura.cc
index 1bb47710..40b01d9 100644
--- a/ui/views/controls/native/native_view_host_aura.cc
+++ b/ui/views/controls/native/native_view_host_aura.cc
@@ -5,13 +5,16 @@
 #include "ui/views/controls/native/native_view_host_aura.h"
 
 #include "base/logging.h"
+#include "build/build_config.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/focus_client.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_delegate.h"
 #include "ui/base/cursor/cursor.h"
 #include "ui/base/hit_test.h"
+#include "ui/compositor/paint_recorder.h"
 #include "ui/views/controls/native/native_view_host.h"
+#include "ui/views/painter.h"
 #include "ui/views/view_constants_aura.h"
 #include "ui/views/widget/widget.h"
 
@@ -95,6 +98,7 @@
   host_->native_view()->SetProperty(views::kHostViewKey,
       static_cast<View*>(host_));
   AddClippingWindow();
+  InstallMask();
 }
 
 void NativeViewHostAura::NativeViewDetaching(bool destroyed) {
@@ -132,6 +136,20 @@
   }
 }
 
+bool NativeViewHostAura::SetCornerRadius(int corner_radius) {
+#if defined(OS_WIN)
+  // Layer masks don't work on Windows. See crbug.com/713359
+  return false;
+#else
+  mask_ = views::Painter::CreatePaintedLayer(
+      views::Painter::CreateSolidRoundRectPainter(SK_ColorBLACK,
+                                                  corner_radius));
+  mask_->layer()->SetFillsBoundsOpaquely(false);
+  InstallMask();
+  return true;
+#endif
+}
+
 void NativeViewHostAura::InstallClip(int x, int y, int w, int h) {
   clip_rect_.reset(
       new gfx::Rect(host_->ConvertRectToWidget(gfx::Rect(x, y, w, h))));
@@ -187,6 +205,13 @@
   return gfx::kNullCursor;
 }
 
+void NativeViewHostAura::OnWindowBoundsChanged(aura::Window* window,
+                                               const gfx::Rect& old_bounds,
+                                               const gfx::Rect& new_bounds) {
+  if (mask_)
+    mask_->layer()->SetBounds(gfx::Rect(host_->native_view()->bounds().size()));
+}
+
 void NativeViewHostAura::OnWindowDestroying(aura::Window* window) {
   DCHECK(window == host_->native_view());
   clipping_window_delegate_->set_native_view(NULL);
@@ -234,4 +259,13 @@
     clipping_window_.parent()->RemoveChild(&clipping_window_);
 }
 
+void NativeViewHostAura::InstallMask() {
+  if (!mask_)
+    return;
+  if (host_->native_view()) {
+    mask_->layer()->SetBounds(gfx::Rect(host_->native_view()->bounds().size()));
+    host_->native_view()->layer()->SetMaskLayer(mask_->layer());
+  }
+}
+
 }  // namespace views
diff --git a/ui/views/controls/native/native_view_host_aura.h b/ui/views/controls/native/native_view_host_aura.h
index 45e8590..86770c3 100644
--- a/ui/views/controls/native/native_view_host_aura.h
+++ b/ui/views/controls/native/native_view_host_aura.h
@@ -9,6 +9,7 @@
 #include "base/macros.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_observer.h"
+#include "ui/compositor/layer_owner.h"
 #include "ui/views/controls/native/native_view_host_wrapper.h"
 #include "ui/views/views_export.h"
 
@@ -17,8 +18,8 @@
 class NativeViewHost;
 
 // Aura implementation of NativeViewHostWrapper.
-class VIEWS_EXPORT NativeViewHostAura : public NativeViewHostWrapper,
-                                        public aura::WindowObserver {
+class NativeViewHostAura : public NativeViewHostWrapper,
+                           public aura::WindowObserver {
  public:
   explicit NativeViewHostAura(NativeViewHost* host);
   ~NativeViewHostAura() override;
@@ -28,6 +29,7 @@
   void NativeViewDetaching(bool destroyed) override;
   void AddedToWidget() override;
   void RemovedFromWidget() override;
+  bool SetCornerRadius(int corner_radius) override;
   void InstallClip(int x, int y, int w, int h) override;
   bool HasInstalledClip() override;
   void UninstallClip() override;
@@ -39,12 +41,14 @@
 
  private:
   friend class NativeViewHostAuraTest;
-
   class ClippingWindowDelegate;
 
   // Overridden from aura::WindowObserver:
   void OnWindowDestroying(aura::Window* window) override;
   void OnWindowDestroyed(aura::Window* window) override;
+  void OnWindowBoundsChanged(aura::Window* window,
+                             const gfx::Rect& old_bounds,
+                             const gfx::Rect& new_bounds) override;
 
   // Reparents the native view with the clipping window existing between it and
   // its old parent, so that the fast resize path works.
@@ -54,6 +58,9 @@
   // undoes it.
   void RemoveClippingWindow();
 
+  // Sets or updates the mask layer on the native view's layer.
+  void InstallMask();
+
   // Our associated NativeViewHost.
   NativeViewHost* host_;
 
@@ -65,6 +72,9 @@
   aura::Window clipping_window_;
   std::unique_ptr<gfx::Rect> clip_rect_;
 
+  // This mask exists for the sake of SetCornerRadius().
+  std::unique_ptr<ui::LayerOwner> mask_;
+
   DISALLOW_COPY_AND_ASSIGN(NativeViewHostAura);
 };
 
diff --git a/ui/views/controls/native/native_view_host_mac.h b/ui/views/controls/native/native_view_host_mac.h
index b47d1c2..74039d86 100644
--- a/ui/views/controls/native/native_view_host_mac.h
+++ b/ui/views/controls/native/native_view_host_mac.h
@@ -15,7 +15,7 @@
 class NativeViewHost;
 
 // Mac implementation of NativeViewHostWrapper.
-class VIEWS_EXPORT NativeViewHostMac : public NativeViewHostWrapper {
+class NativeViewHostMac : public NativeViewHostWrapper {
  public:
   explicit NativeViewHostMac(NativeViewHost* host);
   ~NativeViewHostMac() override;
@@ -25,6 +25,7 @@
   void NativeViewDetaching(bool destroyed) override;
   void AddedToWidget() override;
   void RemovedFromWidget() override;
+  bool SetCornerRadius(int corner_radius) override;
   void InstallClip(int x, int y, int w, int h) override;
   bool HasInstalledClip() override;
   void UninstallClip() override;
diff --git a/ui/views/controls/native/native_view_host_mac.mm b/ui/views/controls/native/native_view_host_mac.mm
index 45a3157..cb5553b6 100644
--- a/ui/views/controls/native/native_view_host_mac.mm
+++ b/ui/views/controls/native/native_view_host_mac.mm
@@ -96,6 +96,11 @@
   NativeViewDetaching(false);
 }
 
+bool NativeViewHostMac::SetCornerRadius(int corner_radius) {
+  NOTIMPLEMENTED();
+  return false;
+}
+
 void NativeViewHostMac::InstallClip(int x, int y, int w, int h) {
   NOTIMPLEMENTED();
 }
diff --git a/ui/views/controls/native/native_view_host_wrapper.h b/ui/views/controls/native/native_view_host_wrapper.h
index 1f9330b6..d6c58dd 100644
--- a/ui/views/controls/native/native_view_host_wrapper.h
+++ b/ui/views/controls/native/native_view_host_wrapper.h
@@ -15,7 +15,7 @@
 // An interface that implemented by an object that wraps a gfx::NativeView on
 // a specific platform, used to perform platform specific operations on that
 // native view when attached, detached, moved and sized.
-class VIEWS_EXPORT NativeViewHostWrapper {
+class NativeViewHostWrapper {
  public:
   virtual ~NativeViewHostWrapper() {}
 
@@ -38,6 +38,10 @@
   // rooted at a valid Widget.
   virtual void RemovedFromWidget() = 0;
 
+  // Sets the corner radius for clipping gfx::NativeView. Returns true on
+  // success or false if the platform doesn't support the operation.
+  virtual bool SetCornerRadius(int corner_radius) = 0;
+
   // Installs a clip on the gfx::NativeView. These values are in the coordinate
   // space of the Widget, so if this method is called from ShowWidget
   // then the values need to be translated.
diff --git a/ui/views/examples/examples_main.cc b/ui/views/examples/examples_main.cc
index aca55f2..15765edf 100644
--- a/ui/views/examples/examples_main.cc
+++ b/ui/views/examples/examples_main.cc
@@ -9,11 +9,11 @@
 #include "base/files/file_path.h"
 #include "base/i18n/icu_util.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/power_monitor/power_monitor.h"
 #include "base/power_monitor/power_monitor_device_source.h"
 #include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/test/test_discardable_memory_allocator.h"
 #include "build/build_config.h"
 #include "components/viz/host/host_frame_sink_manager.h"
@@ -73,7 +73,8 @@
       &host_frame_sink_manager_, &frame_sink_manager_);
   context_factory->set_use_test_surface(false);
 
-  base::MessageLoopForUI message_loop;
+  base::test::ScopedTaskEnvironment scoped_task_environment(
+      base::test::ScopedTaskEnvironment::MainThreadType::UI);
 
   base::i18n::InitializeICU();
 
diff --git a/ui/views/painter.cc b/ui/views/painter.cc
index d9b9aee1..d50ef92 100644
--- a/ui/views/painter.cc
+++ b/ui/views/painter.cc
@@ -6,6 +6,10 @@
 
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "ui/compositor/layer.h"
+#include "ui/compositor/layer_delegate.h"
+#include "ui/compositor/layer_owner.h"
+#include "ui/compositor/paint_recorder.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/insets_f.h"
@@ -186,6 +190,40 @@
   nine_painter_->Paint(canvas, gfx::Rect(size));
 }
 
+class PaintedLayer : public ui::LayerOwner, public ui::LayerDelegate {
+ public:
+  explicit PaintedLayer(std::unique_ptr<Painter> painter);
+  ~PaintedLayer() override;
+
+  // LayerDelegate:
+  void OnPaintLayer(const ui::PaintContext& context) override;
+  void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override;
+  void OnDeviceScaleFactorChanged(float device_scale_factor) override;
+
+ private:
+  std::unique_ptr<Painter> painter_;
+
+  DISALLOW_COPY_AND_ASSIGN(PaintedLayer);
+};
+
+PaintedLayer::PaintedLayer(std::unique_ptr<Painter> painter)
+    : painter_(std::move(painter)) {
+  SetLayer(base::MakeUnique<ui::Layer>(ui::LAYER_TEXTURED));
+  layer()->set_delegate(this);
+}
+
+PaintedLayer::~PaintedLayer() {}
+
+void PaintedLayer::OnPaintLayer(const ui::PaintContext& context) {
+  ui::PaintRecorder recorder(context, layer()->size());
+  painter_->Paint(recorder.canvas(), layer()->size());
+}
+
+void PaintedLayer::OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) {
+}
+
+void PaintedLayer::OnDeviceScaleFactorChanged(float device_scale_factor) {}
+
 }  // namespace
 
 
@@ -277,4 +315,10 @@
   return base::MakeUnique<SolidFocusPainter>(color, thickness, insets);
 }
 
+// static
+std::unique_ptr<ui::LayerOwner> Painter::CreatePaintedLayer(
+    std::unique_ptr<Painter> painter) {
+  return base::MakeUnique<PaintedLayer>(std::move(painter));
+}
+
 }  // namespace views
diff --git a/ui/views/painter.h b/ui/views/painter.h
index 57b4fb0a..cd96723 100644
--- a/ui/views/painter.h
+++ b/ui/views/painter.h
@@ -24,6 +24,10 @@
 class Size;
 }
 
+namespace ui {
+class LayerOwner;
+}
+
 namespace views {
 
 class View;
@@ -89,6 +93,10 @@
       int thickness,
       const gfx::InsetsF& insets);
 
+  // Creates and returns a texture layer that is painted by |painter|.
+  static std::unique_ptr<ui::LayerOwner> CreatePaintedLayer(
+      std::unique_ptr<Painter> painter);
+
   // Returns the minimum size this painter can paint without obvious graphical
   // problems (e.g. overlapping images).
   virtual gfx::Size GetMinimumSize() const = 0;