diff --git a/DEPS b/DEPS
index 8501e3e..8b4202b 100644
--- a/DEPS
+++ b/DEPS
@@ -105,7 +105,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'fcc10da18eb533e83d8d46181819deed234ad1a3',
+  'skia_revision': '56a426a516d02fd7b7f671dcc9b924e1d69434b3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -129,7 +129,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': 'd8882193737ae167a33c1bf7a5cdb64543ad0301',
+  'pdfium_revision': '6aa2190f70a80b70af7bcfe198041756ed8c803e',
   # 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.
@@ -540,7 +540,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'c228d491eb86e4a116799d3e3a68e28c843077f5',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '3973c26575e2a3322156571ef00fb083e0a3723b',
       'condition': 'checkout_linux',
   },
 
@@ -565,7 +565,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '32e3d1e37cd6a379cc5767dc3aaa43053df9a151',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '2b138f742b74a9f8a81f7b0bdd3768019f01854c',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -1035,7 +1035,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'a5c263cc63ffc2cc189b5214074c8792067c1853',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '5795489e83adba65cb480d57e71f52bae1f5ee1b',
+    Var('webrtc_git') + '/src.git' + '@' + '58c79f66dd3afef0ec2d77053e44f26b998b84b1',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/ash/system/message_center/arc/arc_notification_content_view.cc b/ash/system/message_center/arc/arc_notification_content_view.cc
index 82f90a6..c23b5bb 100644
--- a/ash/system/message_center/arc/arc_notification_content_view.cc
+++ b/ash/system/message_center/arc/arc_notification_content_view.cc
@@ -123,6 +123,9 @@
           event_for_android_only = contains && swipe_captured_;
         }
 
+        if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN)
+          owner_->item_->CancelLongPress();
+
         if (event->type() == ui::ET_GESTURE_SCROLL_END)
           swipe_captured_ = false;
 
@@ -620,11 +623,8 @@
 
   // Make the widget active.
   if (activate) {
-    if (!GetWidget()->IsActive()) {
-      GetWidget()->widget_delegate()->set_can_activate(true);
-      GetWidget()->Activate();
-    }
-
+    GetWidget()->widget_delegate()->set_can_activate(true);
+    GetWidget()->Activate();
     surface_->FocusSurfaceWindow();
   } else {
     GetWidget()->widget_delegate()->set_can_activate(false);
diff --git a/ash/system/message_center/arc/arc_notification_item.h b/ash/system/message_center/arc/arc_notification_item.h
index 4bc69d87..6210679 100644
--- a/ash/system/message_center/arc/arc_notification_item.h
+++ b/ash/system/message_center/arc/arc_notification_item.h
@@ -83,6 +83,9 @@
 
   virtual bool IsManuallyExpandedOrCollapsed() const = 0;
 
+  // Cancel long press operation on Android side.
+  virtual void CancelLongPress() = 0;
+
   // Returns the rect for which Android wants to handle all swipe events.
   // Defaults to the empty rectangle.
   virtual gfx::Rect GetSwipeInputRect() const = 0;
diff --git a/ash/system/message_center/arc/arc_notification_item_impl.cc b/ash/system/message_center/arc/arc_notification_item_impl.cc
index 0ffd184f..fd402dbdb8 100644
--- a/ash/system/message_center/arc/arc_notification_item_impl.cc
+++ b/ash/system/message_center/arc/arc_notification_item_impl.cc
@@ -256,4 +256,8 @@
   return notification_id_;
 }
 
+void ArcNotificationItemImpl::CancelLongPress() {
+  manager_->CancelLongPress(notification_key_);
+}
+
 }  // namespace ash
diff --git a/ash/system/message_center/arc/arc_notification_item_impl.h b/ash/system/message_center/arc/arc_notification_item_impl.h
index 975fa99a..f71116f 100644
--- a/ash/system/message_center/arc/arc_notification_item_impl.h
+++ b/ash/system/message_center/arc/arc_notification_item_impl.h
@@ -51,6 +51,7 @@
   gfx::Rect GetSwipeInputRect() const override;
   const std::string& GetNotificationKey() const override;
   const std::string& GetNotificationId() const override;
+  void CancelLongPress() override;
 
  private:
   ArcNotificationManager* const manager_;
diff --git a/ash/system/message_center/arc/arc_notification_manager.cc b/ash/system/message_center/arc/arc_notification_manager.cc
index b5d66f8..dd34502 100644
--- a/ash/system/message_center/arc/arc_notification_manager.cc
+++ b/ash/system/message_center/arc/arc_notification_manager.cc
@@ -486,4 +486,18 @@
   notifications_instance->SetDoNotDisturbStatusOnAndroid(std::move(status));
 }
 
+void ArcNotificationManager::CancelLongPress(const std::string& key) {
+  auto* notifications_instance =
+      ARC_GET_INSTANCE_FOR_METHOD(instance_owner_->holder(), CancelLongPress);
+
+  // On shutdown, the ARC channel may quit earlier than notifications.
+  if (!notifications_instance) {
+    VLOG(2) << "Trying to cancel the long press operation, "
+               "but the ARC channel has already gone.";
+    return;
+  }
+
+  notifications_instance->CancelLongPress(key);
+}
+
 }  // namespace ash
diff --git a/ash/system/message_center/arc/arc_notification_manager.h b/ash/system/message_center/arc/arc_notification_manager.h
index 1a6c6a7..795567e 100644
--- a/ash/system/message_center/arc/arc_notification_manager.h
+++ b/ash/system/message_center/arc/arc_notification_manager.h
@@ -66,6 +66,7 @@
   bool IsOpeningSettingsSupported() const;
   void SendNotificationToggleExpansionOnChrome(const std::string& key);
   void SetDoNotDisturbStatusOnAndroid(bool enabled);
+  void CancelLongPress(const std::string& key);
 
  private:
   // Helper class to own MojoChannel and ConnectionHolder.
diff --git a/ash/system/message_center/arc/mock_arc_notification_item.h b/ash/system/message_center/arc/mock_arc_notification_item.h
index e85cbec2..66ba680 100644
--- a/ash/system/message_center/arc/mock_arc_notification_item.h
+++ b/ash/system/message_center/arc/mock_arc_notification_item.h
@@ -44,6 +44,7 @@
   void IncrementWindowRefCount() override {}
   void DecrementWindowRefCount() override {}
   void OnRemoteInputActivationChanged(bool activate) override {}
+  void CancelLongPress() override {}
 
   arc::mojom::ArcNotificationType GetNotificationType() const override;
   arc::mojom::ArcNotificationExpandState GetExpandState() const override;
diff --git a/ash/system/unified/unified_slider_bubble_controller.cc b/ash/system/unified/unified_slider_bubble_controller.cc
index 49716ba4..963d19c 100644
--- a/ash/system/unified/unified_slider_bubble_controller.cc
+++ b/ash/system/unified/unified_slider_bubble_controller.cc
@@ -117,7 +117,8 @@
   CreateSliderController();
 
   views::TrayBubbleView::InitParams init_params;
-  init_params.anchor_alignment = views::TrayBubbleView::ANCHOR_ALIGNMENT_BOTTOM;
+
+  init_params.anchor_alignment = tray_->GetAnchorAlignment();
   init_params.min_width = kTrayMenuWidth;
   init_params.max_width = kTrayMenuWidth;
   init_params.delegate = this;
diff --git a/base/allocator/BUILD.gn b/base/allocator/BUILD.gn
index c931d0fb..82489ba 100644
--- a/base/allocator/BUILD.gn
+++ b/base/allocator/BUILD.gn
@@ -74,7 +74,7 @@
 if (use_allocator == "tcmalloc") {
   # tcmalloc currently won't compile on Android.
   source_set("tcmalloc") {
-    tcmalloc_dir = "//third_party/tcmalloc/gperftools-2.0/chromium"
+    tcmalloc_dir = "//third_party/tcmalloc/chromium"
 
     # Don't check tcmalloc's includes. These files include various files like
     # base/foo.h and they actually refer to tcmalloc's forked copy of base
diff --git a/base/allocator/allocator_extension.cc b/base/allocator/allocator_extension.cc
index b6ddbaa..9a3d114f 100644
--- a/base/allocator/allocator_extension.cc
+++ b/base/allocator/allocator_extension.cc
@@ -7,9 +7,9 @@
 #include "base/logging.h"
 
 #if defined(USE_TCMALLOC)
-#include "third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/heap-profiler.h"
-#include "third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/malloc_extension.h"
-#include "third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/malloc_hook.h"
+#include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
+#include "third_party/tcmalloc/chromium/src/gperftools/malloc_extension.h"
+#include "third_party/tcmalloc/chromium/src/gperftools/malloc_hook.h"
 #endif
 
 namespace base {
diff --git a/base/allocator/allocator_shim_default_dispatch_to_tcmalloc.cc b/base/allocator/allocator_shim_default_dispatch_to_tcmalloc.cc
index 71e4979..878e8a7 100644
--- a/base/allocator/allocator_shim_default_dispatch_to_tcmalloc.cc
+++ b/base/allocator/allocator_shim_default_dispatch_to_tcmalloc.cc
@@ -4,8 +4,8 @@
 
 #include "base/allocator/allocator_shim.h"
 #include "base/allocator/allocator_shim_internals.h"
-#include "third_party/tcmalloc/gperftools-2.0/chromium/src/config.h"
-#include "third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/tcmalloc.h"
+#include "third_party/tcmalloc/chromium/src/config.h"
+#include "third_party/tcmalloc/chromium/src/gperftools/tcmalloc.h"
 
 namespace {
 
diff --git a/base/allocator/debugallocation_shim.cc b/base/allocator/debugallocation_shim.cc
index 7eb4504..479cfca 100644
--- a/base/allocator/debugallocation_shim.cc
+++ b/base/allocator/debugallocation_shim.cc
@@ -14,7 +14,7 @@
 #endif
 
 #if defined(TCMALLOC_FOR_DEBUGALLOCATION)
-#include "third_party/tcmalloc/gperftools-2.0/chromium/src/debugallocation.cc"
+#include "third_party/tcmalloc/chromium/src/debugallocation.cc"
 #else
-#include "third_party/tcmalloc/gperftools-2.0/chromium/src/tcmalloc.cc"
+#include "third_party/tcmalloc/chromium/src/tcmalloc.cc"
 #endif
diff --git a/base/message_loop/message_loop_unittest.cc b/base/message_loop/message_loop_unittest.cc
index c2ed61c..db4b9bf 100644
--- a/base/message_loop/message_loop_unittest.cc
+++ b/base/message_loop/message_loop_unittest.cc
@@ -2238,6 +2238,13 @@
   EXPECT_NE(slot.Get(), 11);
 }
 
+INSTANTIATE_TEST_CASE_P(
+    ,
+    MessageLoopTest,
+    ::testing::Values(TaskSchedulerAvailability::NO_TASK_SCHEDULER,
+                      TaskSchedulerAvailability::WITH_TASK_SCHEDULER),
+    MessageLoopTest::ParamInfoToString);
+
 namespace {
 
 class PostTaskOnDestroy {
@@ -2267,7 +2274,7 @@
 //  1) Not getting stuck clearing its task queue.
 //  2) DCHECKing when clearing pending tasks many times still doesn't yield an
 //     empty queue.
-TEST_P(MessageLoopTest, ExpectDeathWithStubbornPostTaskOnDestroy) {
+TEST(MessageLoopDestructionTest, ExpectDeathWithStubbornPostTaskOnDestroy) {
   std::unique_ptr<MessageLoop> loop = std::make_unique<MessageLoop>();
 
   EXPECT_DCHECK_DEATH({
@@ -2276,18 +2283,11 @@
   });
 }
 
-TEST_P(MessageLoopTest, DestroysFineWithReasonablePostTaskOnDestroy) {
+TEST(MessageLoopDestructionTest, DestroysFineWithReasonablePostTaskOnDestroy) {
   std::unique_ptr<MessageLoop> loop = std::make_unique<MessageLoop>();
 
   PostTaskOnDestroy::PostTaskWithPostingDestructor(10);
   loop.reset();
 }
 
-INSTANTIATE_TEST_CASE_P(
-    ,
-    MessageLoopTest,
-    ::testing::Values(TaskSchedulerAvailability::NO_TASK_SCHEDULER,
-                      TaskSchedulerAvailability::WITH_TASK_SCHEDULER),
-    MessageLoopTest::ParamInfoToString);
-
 }  // namespace base
diff --git a/base/message_loop/message_pump_win.cc b/base/message_loop/message_pump_win.cc
index 8dad64c..c95f85a 100644
--- a/base/message_loop/message_pump_win.cc
+++ b/base/message_loop/message_pump_win.cc
@@ -46,10 +46,6 @@
   s.should_quit = false;
   s.run_depth = state_ ? state_->run_depth + 1 : 1;
 
-  // TODO(stanisc): crbug.com/596190: Remove this code once the bug is fixed.
-  s.schedule_work_error_count = 0;
-  s.last_schedule_work_error_time = Time();
-
   RunState* previous_state = state_;
   state_ = &s;
 
@@ -118,8 +114,6 @@
   InterlockedExchange(&work_state_, READY);
   UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", MESSAGE_POST_ERROR,
                             MESSAGE_LOOP_PROBLEM_MAX);
-  state_->schedule_work_error_count++;
-  state_->last_schedule_work_error_time = Time::Now();
 }
 
 void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) {
@@ -444,8 +438,6 @@
   InterlockedExchange(&work_state_, READY);  // Clarify that we didn't succeed.
   UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", COMPLETION_POST_ERROR,
                             MESSAGE_LOOP_PROBLEM_MAX);
-  state_->schedule_work_error_count++;
-  state_->last_schedule_work_error_time = Time::Now();
 }
 
 void MessagePumpForIO::ScheduleDelayedWork(const TimeTicks& delayed_work_time) {
diff --git a/base/message_loop/message_pump_win.h b/base/message_loop/message_pump_win.h
index 8165fdb3..900fcc0 100644
--- a/base/message_loop/message_pump_win.h
+++ b/base/message_loop/message_pump_win.h
@@ -38,11 +38,6 @@
 
     // Used to count how many Run() invocations are on the stack.
     int run_depth;
-
-    // Used to help diagnose hangs.
-    // TODO(stanisc): crbug.com/596190: Remove these once the bug is fixed.
-    int schedule_work_error_count;
-    Time last_schedule_work_error_time;
   };
 
   // State used with |work_state_| variable.
diff --git a/base/process/memory_linux.cc b/base/process/memory_linux.cc
index 171753c7..21b2069 100644
--- a/base/process/memory_linux.cc
+++ b/base/process/memory_linux.cc
@@ -18,8 +18,8 @@
 #include "build/build_config.h"
 
 #if defined(USE_TCMALLOC)
-#include "third_party/tcmalloc/gperftools-2.0/chromium/src/config.h"
-#include "third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/tcmalloc.h"
+#include "third_party/tcmalloc/chromium/src/config.h"
+#include "third_party/tcmalloc/chromium/src/gperftools/tcmalloc.h"
 #endif
 
 namespace base {
diff --git a/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunner.java b/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunner.java
index 113f176..834f261 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunner.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunner.java
@@ -85,8 +85,9 @@
 
     private void validateOnlyOneClassParameterField() {
         if (getTestClass().getAnnotatedFields(ClassParameter.class).size() > 1) {
-            throw new IllegalParameterArgumentException(
-                    "%s class has more than one @ClassParameter, only one is allowed");
+            throw new IllegalParameterArgumentException(String.format(Locale.getDefault(),
+                    "%s class has more than one @ClassParameter, only one is allowed",
+                    getTestClass().getName()));
         }
     }
 
diff --git a/base/trace_event/trace_event_etw_export_win.cc b/base/trace_event/trace_event_etw_export_win.cc
index 993a222..e6d8107 100644
--- a/base/trace_event/trace_event_etw_export_win.cc
+++ b/base/trace_event/trace_event_etw_export_win.cc
@@ -61,21 +61,22 @@
 // group names or the hex representation. We only support the latter. Also, we
 // ignore the level.
 const char* const kFilteredEventGroupNames[] = {
-    "benchmark",                                       // 0x1
-    "blink",                                           // 0x2
-    "browser",                                         // 0x4
-    "cc",                                              // 0x8
-    "evdev",                                           // 0x10
-    "gpu",                                             // 0x20
-    "input",                                           // 0x40
-    "netlog",                                          // 0x80
-    "sequence_manager",                                // 0x100
-    "toplevel",                                        // 0x200
-    "v8",                                              // 0x400
-    "disabled-by-default-cc.debug",                    // 0x800
-    "disabled-by-default-cc.debug.picture",            // 0x1000
-    "disabled-by-default-toplevel.flow",               // 0x2000
-    "startup"};                                        // 0x4000
+    "benchmark",                                        // 0x1
+    "blink",                                            // 0x2
+    "browser",                                          // 0x4
+    "cc",                                               // 0x8
+    "evdev",                                            // 0x10
+    "gpu",                                              // 0x20
+    "input",                                            // 0x40
+    "netlog",                                           // 0x80
+    "sequence_manager",                                 // 0x100
+    "toplevel",                                         // 0x200
+    "v8",                                               // 0x400
+    "disabled-by-default-cc.debug",                     // 0x800
+    "disabled-by-default-cc.debug.picture",             // 0x1000
+    "disabled-by-default-toplevel.flow",                // 0x2000
+    "startup",                                          // 0x4000
+    "latency"};                                         // 0x8000
 const char kOtherEventsGroupName[] = "__OTHER_EVENTS";  // 0x2000000000000000
 const char kDisabledOtherEventsGroupName[] =
     "__DISABLED_OTHER_EVENTS";  // 0x4000000000000000
diff --git a/build/android/gradle/generate_gradle.py b/build/android/gradle/generate_gradle.py
index 566e63a..302f0a67 100755
--- a/build/android/gradle/generate_gradle.py
+++ b/build/android/gradle/generate_gradle.py
@@ -809,9 +809,9 @@
                       action='store_true',
                       help='Split projects by their gn deps rather than '
                            'combining all the dependencies of each target')
-  parser.add_argument('--full',
+  parser.add_argument('--fast',
                       action='store_true',
-                      help='Generate R.java and other ninja-generated files')
+                      help='Skip generating R.java and other generated files.')
   parser.add_argument('-j',
                       default=1000 if os.path.exists(_SRC_INTERNAL) else 50,
                       help='Value for number of parallel jobs for ninja')
@@ -962,7 +962,7 @@
     _WriteFile(os.path.join(generator.project_dir, 'local.properties'),
                _GenerateLocalProperties(sdk_path))
 
-  if args.full:
+  if not args.fast:
     zip_tuples = []
     generated_inputs = set()
     for entry in entries:
@@ -977,8 +977,9 @@
       _ExtractZips(generator.project_dir, zip_tuples)
 
   logging.warning('Generated projects for Android Studio %s', channel)
-  if not args.full:
-    logging.warning('Run with --full flag to update generated files (slow)')
+  if not args.fast:
+    logging.warning('Run with --fast flag to skip generating files (faster, '
+                    'but less correct)')
   logging.warning('For more tips: https://chromium.googlesource.com/chromium'
                   '/src.git/+/master/docs/android_studio.md')
 
diff --git a/build/android/gyp/aar.py b/build/android/gyp/aar.py
index da39e34..c2eb3ea12 100755
--- a/build/android/gyp/aar.py
+++ b/build/android/gyp/aar.py
@@ -16,6 +16,7 @@
 import zipfile
 
 from util import build_utils
+from util import md5_check
 
 sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),
                                              os.pardir, os.pardir)))
@@ -122,9 +123,17 @@
         raise Exception('android_aar_prebuilt() cached .info file is '
                         'out-of-date. Run gn gen with '
                         'update_android_aar_prebuilts=true to update it.')
-    # Clear previously extracted versions of the AAR.
-    shutil.rmtree(args.output_dir, True)
-    build_utils.ExtractAll(args.aar_file, path=args.output_dir)
+
+    def clobber():
+      # Clear previously extracted versions of the AAR if it is obsolete.
+      shutil.rmtree(args.output_dir, ignore_errors=True)
+      build_utils.ExtractAll(args.aar_file, path=args.output_dir)
+
+    with zipfile.ZipFile(args.aar_file) as zf:
+      md5_check.CallAndRecordIfStale(
+          clobber, input_paths=[args.aar_file],
+          output_paths=[
+              os.path.join(args.output_dir, n) for n in zf.namelist()])
 
   elif args.command == 'list':
     aar_info = _CreateInfo(args.aar_file)
diff --git a/build/android/gyp/javac.py b/build/android/gyp/javac.py
index 324fe5a..1425deea8 100755
--- a/build/android/gyp/javac.py
+++ b/build/android/gyp/javac.py
@@ -28,8 +28,6 @@
   'DoubleBraceInitialization',
   # TODO(crbug.com/834801): Follow steps in bug.
   'ParcelableCreator',
-  # TODO(crbug.com/834796): Follow steps in bug.
-  'OrphanedFormatString',
   # TODO(crbug.com/834790): Follow steps in bug.
   'CatchAndPrintStackTrace',
   # TODO(crbug.com/801210): Follow steps in bug.
diff --git a/build/android/gyp/util/build_utils.py b/build/android/gyp/util/build_utils.py
index 4640d80..f1764b9 100644
--- a/build/android/gyp/util/build_utils.py
+++ b/build/android/gyp/util/build_utils.py
@@ -255,6 +255,7 @@
   with zipfile.ZipFile(zip_path) as z:
     for name in z.namelist():
       if name.endswith('/'):
+        MakeDirectory(os.path.join(path, name))
         continue
       if pattern is not None:
         if not fnmatch.fnmatch(name, pattern):
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java
index 1f01dafe..0665ce9e 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java
@@ -8,8 +8,6 @@
 import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.Color;
-import android.graphics.Point;
-import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -17,6 +15,7 @@
 
 import com.google.android.libraries.feed.api.scope.FeedProcessScope;
 import com.google.android.libraries.feed.api.scope.FeedStreamScope;
+import com.google.android.libraries.feed.api.stream.ScrollListener;
 import com.google.android.libraries.feed.api.stream.Stream;
 import com.google.android.libraries.feed.host.stream.CardConfiguration;
 import com.google.android.libraries.feed.host.stream.SnackbarApi;
@@ -30,8 +29,8 @@
 import org.chromium.chrome.browser.ntp.ContextMenuManager;
 import org.chromium.chrome.browser.ntp.ContextMenuManager.TouchEnabledDelegate;
 import org.chromium.chrome.browser.ntp.NewTabPage;
-import org.chromium.chrome.browser.ntp.NewTabPage.FakeboxDelegate;
 import org.chromium.chrome.browser.ntp.NewTabPageLayout;
+import org.chromium.chrome.browser.ntp.SnapScrollHelper;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.search_engines.TemplateUrlService;
 import org.chromium.chrome.browser.suggestions.SuggestionsNavigationDelegateImpl;
@@ -48,6 +47,9 @@
 public class FeedNewTabPage
         extends NewTabPage implements TouchEnabledDelegate, NewTabPageLayout.ScrollDelegate {
     private final StreamLifecycleManager mStreamLifecycleManager;
+    private final Stream mStream;
+    private final ScrollListener mStreamScrollListener;
+    private final SnapScrollHelper mSnapScrollHelper;
 
     private FrameLayout mRootView;
     private FeedImageLoader mImageLoader;
@@ -78,7 +80,7 @@
         }
         @Override
         public int getPaddingTop() {
-            return mPadding;
+            return 0;
         }
         @Override
         public int getPaddingBottom() {
@@ -145,23 +147,46 @@
                                 new DummySnackbarApi())
                         .build();
 
-        Stream stream = streamScope.getStream();
-        mStreamLifecycleManager = new StreamLifecycleManager(stream, activity, tab);
+        mStream = streamScope.getStream();
+        mStreamLifecycleManager = new StreamLifecycleManager(mStream, activity, tab);
+        mSnapScrollHelper =
+                new SnapScrollHelper(mNewTabPageManager, mNewTabPageLayout, mStream.getView());
 
-        stream.getView().setBackgroundColor(Color.WHITE);
-        mRootView.addView(stream.getView());
+        mStream.getView().setBackgroundColor(Color.WHITE);
+        mRootView.addView(mStream.getView());
 
-        stream.setHeaderViews(Arrays.asList(mNewTabPageLayout));
+        mStream.setHeaderViews(Arrays.asList(mNewTabPageLayout));
 
         // TODO(skym): This is a work around for outstanding Feed bug.
-        stream.triggerRefresh();
+        mStream.triggerRefresh();
+
+        // Listen for layout changes on the NewTabPageView itself to catch changes in scroll
+        // position that are due to layout changes after e.g. device rotation. This contrasts with
+        // regular scrolling, which is observed through an OnScrollListener.
+        mRootView.addOnLayoutChangeListener(
+                (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
+                    mSnapScrollHelper.handleScroll();
+                });
+
+        mStreamScrollListener = new ScrollListener() {
+            @Override
+            public void onScrollStateChanged(int state) {}
+
+            @Override
+            public void onScrolled(int dx, int dy) {
+                mSnapScrollHelper.handleScroll();
+            }
+        };
+        mStream.addScrollListener(mStreamScrollListener);
     }
 
     @Override
     protected void initializeMainView(Context context) {
+        int topPadding = context.getResources().getDimensionPixelOffset(R.dimen.tab_strip_height);
         mRootView = new FrameLayout(context);
         mRootView.setLayoutParams(new FrameLayout.LayoutParams(
                 FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
+        mRootView.setPadding(0, topPadding, 0, 0);
 
         // Don't store a direct reference to the activity, because it might change later if the tab
         // is reparented.
@@ -183,6 +208,7 @@
     @Override
     public void destroy() {
         super.destroy();
+        mStream.removeScrollListener(mStreamScrollListener);
         mImageLoader.destroy();
         mStreamLifecycleManager.destroy();
     }
@@ -198,26 +224,11 @@
     }
 
     @Override
-    protected void setSearchProviderInfoOnView(boolean hasLogo, boolean isGoogle) {
-        mNewTabPageLayout.setSearchProviderInfo(hasLogo, isGoogle);
-    }
-
-    @Override
     protected void scrollToSuggestions() {
         // TODO(twellington): implement this method.
     }
 
     @Override
-    public void getSearchBoxBounds(Rect bounds, Point translation) {
-        // TODO(twellington): implement this method.
-    }
-
-    @Override
-    public void setFakeboxDelegate(FakeboxDelegate fakeboxDelegate) {
-        // TODO(twellington): implement this method.
-    }
-
-    @Override
     public boolean shouldCaptureThumbnail() {
         // TODO(twellington): add more logic to this method that also takes into account other
         // UI changes that should trigger a thumbnail capture.
@@ -241,24 +252,35 @@
 
     @Override
     public boolean isScrollViewInitialized() {
-        // TODO(twellington): implement this method.
-        return false;
+        // During startup the view may not be fully initialized, so we check to see if some basic
+        // view properties (height of the RecyclerView) are sane.
+        return mStream != null && mStream.getView().getHeight() > 0;
     }
 
     @Override
     public int getVerticalScrollOffset() {
-        // TODO(twellington): implement this method.
-        return 0;
+        // This method returns a valid vertical scroll offset only when the first header view in the
+        // Stream is visible. In all other cases, this returns 0.
+        if (!isScrollViewInitialized()) return 0;
+
+        int firstChildTop = mStream.getChildTopAt(0);
+        return firstChildTop != Stream.POSITION_NOT_KNOWN ? -firstChildTop : 0;
     }
 
     @Override
     public boolean isChildVisibleAtPosition(int position) {
-        // TODO(twellington): implement this method.
-        return false;
+        return isScrollViewInitialized() && mStream.isChildAtPositionVisible(position);
     }
 
     @Override
     public void snapScroll() {
-        // TODO(twellington): implement this method.
+        if (!isScrollViewInitialized()) return;
+
+        int initialScroll = getVerticalScrollOffset();
+        int scrollTo = mSnapScrollHelper.calculateSnapPosition(initialScroll);
+
+        // Calculating the snap position should be idempotent.
+        assert scrollTo == mSnapScrollHelper.calculateSnapPosition(scrollTo);
+        mStream.smoothScrollBy(0, scrollTo - initialScroll);
     }
 }
diff --git a/chrome/android/java/res/xml/main_preferences.xml b/chrome/android/java/res/xml/main_preferences.xml
index 6f886fb7..cfd982f4 100644
--- a/chrome/android/java/res/xml/main_preferences.xml
+++ b/chrome/android/java/res/xml/main_preferences.xml
@@ -14,7 +14,7 @@
         android:key="sign_in"
         android:order="1"
         android:title="@string/sign_in_to_chrome"/>
-    <Preference
+    <org.chromium.chrome.browser.preferences.ChromeBasePreference
         android:fragment="org.chromium.chrome.browser.preferences.SyncAndServicesPreferences"
         android:key="sync_and_services"
         android:order="2"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeSwitches.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeSwitches.java
index faf5daf..4a3fba62 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeSwitches.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeSwitches.java
@@ -189,6 +189,12 @@
     public static final String DISABLE_DIGITAL_ASSET_LINK_VERIFICATION =
             "disable-digital-asset-link-verification-for-url";
 
+    /**
+     * Forces Trusted Web Activities to show the the Disclosure Toast every time.
+     */
+    public static final String FORCE_TRUSTED_WEB_ACTIVITY_DISCLOSURE =
+            "force-trusted-web-activity-disclosure";
+
     // Prevent instantiation.
     private ChromeSwitches() {}
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityDisclosure.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityDisclosure.java
index e9c23e3d..734b40d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityDisclosure.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityDisclosure.java
@@ -6,7 +6,9 @@
 
 import android.content.Context;
 
+import org.chromium.base.CommandLine;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
 import org.chromium.ui.widget.Toast;
 
@@ -33,7 +35,9 @@
         long millisSince = now.getTime() - lastShown.getTime();
         long daysSince = TimeUnit.DAYS.convert(millisSince, TimeUnit.MILLISECONDS);
 
-        if (daysSince <= DISCLOSURE_PERIOD_DAYS) return;
+        boolean force = CommandLine.getInstance().hasSwitch(
+                ChromeSwitches.FORCE_TRUSTED_WEB_ACTIVITY_DISCLOSURE);
+        if (!force && daysSince <= DISCLOSURE_PERIOD_DAYS) return;
 
         prefs.setTrustedWebActivityLastDisclosureTime(packageName, now);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
index 8c53993..16c74b7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
@@ -420,8 +420,8 @@
      * @param hasLogo Whether the search provider has a logo.
      * @param isGoogle Whether the search provider is Google.
      */
-    protected void setSearchProviderInfoOnView(boolean hasLogo, boolean isGoogle) {
-        mNewTabPageView.setSearchProviderInfo(hasLogo, isGoogle);
+    private void setSearchProviderInfoOnView(boolean hasLogo, boolean isGoogle) {
+        mNewTabPageLayout.setSearchProviderInfo(hasLogo, isGoogle);
     }
 
     /**
@@ -443,7 +443,7 @@
      *                    to the NewTabPage view.
      */
     public void getSearchBoxBounds(Rect bounds, Point translation) {
-        mNewTabPageView.getSearchBoxBounds(bounds, translation);
+        mNewTabPageLayout.getSearchBoxBounds(bounds, translation, getView());
     }
 
     /**
@@ -493,7 +493,7 @@
      */
     public void setFakeboxDelegate(FakeboxDelegate fakeboxDelegate) {
         mFakeboxDelegate = fakeboxDelegate;
-        mNewTabPageView.setFakeboxDelegate(fakeboxDelegate);
+        if (mNewTabPageView != null) mNewTabPageView.setFakeboxDelegate(fakeboxDelegate);
         if (mFakeboxDelegate != null) {
             // The toolbar can't get the reference to the native page until its initialization is
             // finished, so we can't cache it here and transfer it to the view later. We pull that
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
index 401b58d..3d2dd1c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
@@ -19,7 +19,6 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewGroup.MarginLayoutParams;
 import android.view.ViewStub;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
@@ -267,6 +266,13 @@
     }
 
     /**
+     * @return The {@link ScrollDelegate} for this class.
+     */
+    ScrollDelegate getScrollDelegate() {
+        return mScrollDelegate;
+    }
+
+    /**
      * Sets up the hint text and event handlers for the search box text view.
      */
     private void initializeSearchBoxTextView() {
@@ -404,8 +410,9 @@
         searchBoxTop += mSearchBoxView.getPaddingTop();
 
         final int scrollY = mScrollDelegate.getVerticalScrollOffset();
+        // Use int pixel size instead of float dimension to avoid precision error on the percentage.
         final float transitionLength =
-                getResources().getDimension(R.dimen.ntp_search_box_transition_length);
+                getResources().getDimensionPixelSize(R.dimen.ntp_search_box_transition_length);
         // Tab strip height is zero on phones, nonzero on tablets.
         int tabStripHeight = getResources().getDimensionPixelSize(R.dimen.tab_strip_height);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
index 261283e..bdfba24 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
@@ -4,17 +4,14 @@
 
 package org.chromium.chrome.browser.ntp;
 
-import android.annotation.SuppressLint;
 import android.content.Context;
 import android.graphics.Canvas;
-import android.graphics.Point;
-import android.graphics.Rect;
 import android.support.v7.widget.DefaultItemAnimator;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.RecyclerView.AdapterDataObserver;
 import android.support.v7.widget.RecyclerView.ViewHolder;
 import android.util.AttributeSet;
-import android.view.MotionEvent;
+import android.view.LayoutInflater;
 import android.widget.FrameLayout;
 
 import org.chromium.base.TraceEvent;
@@ -42,21 +39,16 @@
 public class NewTabPageView extends FrameLayout {
     private static final String TAG = "NewTabPageView";
 
-    private static final long SNAP_SCROLL_DELAY_MS = 30;
-
     private NewTabPageRecyclerView mRecyclerView;
 
     private NewTabPageLayout mNewTabPageLayout;
 
     private NewTabPageManager mManager;
     private Tab mTab;
+    private SnapScrollHelper mSnapScrollHelper;
     private UiConfig mUiConfig;
-    private Runnable mSnapScrollRunnable;
     private Runnable mUpdateSearchBoxOnScrollRunnable;
 
-    private boolean mPendingSnapScroll;
-    private int mLastScrollY = -1;
-
     private boolean mNewTabPageRecyclerViewChanged;
     private int mSnapshotWidth;
     private int mSnapshotHeight;
@@ -102,7 +94,8 @@
         mRecyclerView = new NewTabPageRecyclerView(getContext());
 
         // Don't attach now, the recyclerView itself will determine when to do it.
-        mNewTabPageLayout = mRecyclerView.getAboveTheFoldView();
+        mNewTabPageLayout = (NewTabPageLayout) LayoutInflater.from(getContext())
+                                    .inflate(R.layout.new_tab_page_layout, mRecyclerView, false);
     }
 
     /**
@@ -135,7 +128,8 @@
         mNewTabPageLayout.initialize(manager, tab, tileGroupDelegate, searchProviderHasLogo,
                 searchProviderIsGoogle, mRecyclerView, mContextMenuManager, mUiConfig);
 
-        mRecyclerView.setContainsLocationBar(manager.isLocationBarShownInNTP());
+        mSnapScrollHelper = new SnapScrollHelper(mManager, mNewTabPageLayout, mRecyclerView);
+        mRecyclerView.setSnapScrollHelper(mSnapScrollHelper);
         addView(mRecyclerView);
 
         mRecyclerView.setItemAnimator(new DefaultItemAnimator() {
@@ -177,11 +171,10 @@
         OfflinePageBridge offlinePageBridge =
                 SuggestionsDependencyFactory.getInstance().getOfflinePageBridge(profile);
 
-        mSnapScrollRunnable = new SnapScrollRunnable();
         mUpdateSearchBoxOnScrollRunnable = mNewTabPageLayout::updateSearchBoxOnScroll;
 
         initializeLayoutChangeListener();
-        setSearchProviderInfo(searchProviderHasLogo, searchProviderIsGoogle);
+        mNewTabPageLayout.setSearchProviderInfo(searchProviderHasLogo, searchProviderIsGoogle);
 
         mRecyclerView.init(mUiConfig, mContextMenuManager);
 
@@ -241,7 +234,7 @@
      *                        has focus.
      */
     public void setFakeboxDelegate(FakeboxDelegate fakeboxDelegate) {
-        mRecyclerView.setFakeboxDelegate(fakeboxDelegate, mNewTabPageLayout.getSearchBoxView());
+        mRecyclerView.setFakeboxDelegate(fakeboxDelegate);
     }
 
     private void initializeLayoutChangeListener() {
@@ -250,14 +243,8 @@
         // Listen for layout changes on the NewTabPageView itself to catch changes in scroll
         // position that are due to layout changes after e.g. device rotation. This contrasts with
         // regular scrolling, which is observed through an OnScrollListener.
-        addOnLayoutChangeListener(
-                (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
-                    int scrollY = mRecyclerView.computeVerticalScrollOffset();
-                    if (mLastScrollY != scrollY) {
-                        mLastScrollY = scrollY;
-                        handleScroll();
-                    }
-                });
+        addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight,
+                                          oldBottom) -> { mSnapScrollHelper.handleScroll(); });
         TraceEvent.end(TAG + ".initializeLayoutChangeListener()");
     }
 
@@ -275,60 +262,13 @@
         mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
             @Override
             public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
-                mLastScrollY = mRecyclerView.computeVerticalScrollOffset();
-                handleScroll();
+                mSnapScrollHelper.handleScroll();
             }
         });
 
-        @SuppressLint("ClickableViewAccessibility")
-        OnTouchListener onTouchListener = (v, event) -> {
-            mRecyclerView.removeCallbacks(mSnapScrollRunnable);
-
-            if (event.getActionMasked() == MotionEvent.ACTION_CANCEL
-                    || event.getActionMasked() == MotionEvent.ACTION_UP) {
-                mPendingSnapScroll = true;
-                mRecyclerView.postDelayed(mSnapScrollRunnable, SNAP_SCROLL_DELAY_MS);
-            } else {
-                mPendingSnapScroll = false;
-            }
-            return false;
-        };
-        mRecyclerView.setOnTouchListener(onTouchListener);
         TraceEvent.end(TAG + ".setupScrollHandling()");
     }
 
-    private void handleScroll() {
-        if (mPendingSnapScroll) {
-            mRecyclerView.removeCallbacks(mSnapScrollRunnable);
-            mRecyclerView.postDelayed(mSnapScrollRunnable, SNAP_SCROLL_DELAY_MS);
-        }
-        mNewTabPageLayout.updateSearchBoxOnScroll();
-    }
-
-    /**
-     * Changes the layout depending on whether the selected search provider (e.g. Google, Bing)
-     * has a logo.
-     * @param hasLogo Whether the search provider has a logo.
-     * @param isGoogle Whether the search provider is Google.
-     */
-    public void setSearchProviderInfo(boolean hasLogo, boolean isGoogle) {
-        // Update snap scrolling for the fakebox.
-        mRecyclerView.setContainsLocationBar(mManager.isLocationBarShownInNTP());
-
-        mNewTabPageLayout.setSearchProviderInfo(hasLogo, isGoogle);
-    }
-
-    /**
-     * Get the bounds of the search box in relation to the top level NewTabPage view.
-     *
-     * @param bounds The current drawing location of the search box.
-     * @param translation The translation applied to the search box by the parent view hierarchy up
-     *                    to the NewTabPage view.
-     */
-    void getSearchBoxBounds(Rect bounds, Point translation) {
-        mNewTabPageLayout.getSearchBoxBounds(bounds, translation, this);
-    }
-
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
@@ -434,17 +374,12 @@
         return mRecyclerView.getScrollPosition();
     }
 
-    private class SnapScrollRunnable implements Runnable {
-        @Override
-        public void run() {
-            assert mPendingSnapScroll;
-            mPendingSnapScroll = false;
-
-            mRecyclerView.snapScroll();
-        }
-    }
-
     private void onDestroy() {
         mTab.getWindowAndroid().removeContextMenuCloseListener(mContextMenuManager);
     }
+
+    @VisibleForTesting
+    public SnapScrollHelper getSnapScrollHelper() {
+        return mSnapScrollHelper;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/SnapScrollHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/SnapScrollHelper.java
new file mode 100644
index 0000000..d571726
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/SnapScrollHelper.java
@@ -0,0 +1,142 @@
+// Copyright 2018 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.ntp;
+
+import android.annotation.SuppressLint;
+import android.content.res.Resources;
+import android.view.MotionEvent;
+import android.view.View;
+
+import org.chromium.base.VisibleForTesting;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ntp.NewTabPageView.NewTabPageManager;
+
+/**
+ * This class handles snap scroll for the search box on a {@link NewTabPage}.
+ */
+public class SnapScrollHelper {
+    private static final long SNAP_SCROLL_DELAY_MS = 30;
+
+    private final NewTabPageManager mManager;
+    private final NewTabPageLayout mNewTabPageLayout;
+    private final View mView;
+    private final Runnable mSnapScrollRunnable;
+    private final int mToolbarHeight;
+    private final int mSearchBoxTransitionLength;
+
+    private boolean mPendingSnapScroll;
+    private int mLastScrollY = -1;
+
+    /**
+     * @param manager The {@link NewTabPageManager} to get information about user interactions on
+     *                the {@link NewTabPage}.
+     * @param newTabPageLayout The {@link NewTabPageLayout} associated with the {@link NewTabPage}.
+     * @param view The view on which this class needs to handle snap scroll.
+     */
+    public SnapScrollHelper(NewTabPageView.NewTabPageManager manager,
+            NewTabPageLayout newTabPageLayout, View view) {
+        mManager = manager;
+        mNewTabPageLayout = newTabPageLayout;
+        mView = view;
+        mSnapScrollRunnable = new SnapScrollRunnable();
+
+        Resources res = view.getResources();
+        mToolbarHeight = res.getDimensionPixelSize(R.dimen.toolbar_height_no_shadow)
+                + res.getDimensionPixelSize(R.dimen.toolbar_progress_bar_height);
+        mSearchBoxTransitionLength =
+                res.getDimensionPixelSize(R.dimen.ntp_search_box_transition_length);
+
+        @SuppressLint("ClickableViewAccessibility")
+        View.OnTouchListener onTouchListener = (v, event) -> {
+            mView.removeCallbacks(mSnapScrollRunnable);
+
+            if (event.getActionMasked() == MotionEvent.ACTION_CANCEL
+                    || event.getActionMasked() == MotionEvent.ACTION_UP) {
+                mPendingSnapScroll = true;
+                mView.postDelayed(mSnapScrollRunnable, SNAP_SCROLL_DELAY_MS);
+            } else {
+                mPendingSnapScroll = false;
+            }
+            return false;
+        };
+        mView.setOnTouchListener(onTouchListener);
+    }
+
+    /** Update scroll offset and perform snap scroll if necessary. */
+    public void handleScroll() {
+        int scrollY = mNewTabPageLayout.getScrollDelegate().getVerticalScrollOffset();
+        if (mLastScrollY == scrollY) return;
+
+        mLastScrollY = scrollY;
+        if (mPendingSnapScroll) {
+            mView.removeCallbacks(mSnapScrollRunnable);
+            mView.postDelayed(mSnapScrollRunnable, SNAP_SCROLL_DELAY_MS);
+        }
+        mNewTabPageLayout.updateSearchBoxOnScroll();
+    }
+
+    /**
+     * @param scrollPosition The scroll position that the snap scroll calculation is based on.
+     * @return The modified scroll position that accounts for snap scroll.
+     */
+    @VisibleForTesting
+    public int calculateSnapPosition(int scrollPosition) {
+        if (mManager.isLocationBarShownInNTP()) {
+            // Snap scroll to prevent only part of the toolbar from showing.
+            scrollPosition = calculateSnapPositionForRegion(scrollPosition, 0, mToolbarHeight);
+
+            // Snap scroll to prevent resting in the middle of the omnibox transition.
+            View fakeBox = mNewTabPageLayout.getSearchBoxView();
+            int fakeBoxUpperBound = fakeBox.getTop() + fakeBox.getPaddingTop();
+            scrollPosition = calculateSnapPositionForRegion(scrollPosition,
+                    fakeBoxUpperBound - mSearchBoxTransitionLength, fakeBoxUpperBound);
+        }
+
+        return scrollPosition;
+    }
+
+    /**
+     * Calculates the position to scroll to in order to move out of a region where {@code mView}
+     * should not stay at rest.
+     * @param currentScroll the current scroll position.
+     * @param regionStart the beginning of the region to scroll out of.
+     * @param regionEnd the end of the region to scroll out of.
+     * @param flipPoint the threshold used to decide which bound of the region to scroll to.
+     * @return the position to scroll to.
+     */
+    private static int calculateSnapPositionForRegion(
+            int currentScroll, int regionStart, int regionEnd, int flipPoint) {
+        assert regionStart <= flipPoint;
+        assert flipPoint <= regionEnd;
+
+        if (currentScroll < regionStart || currentScroll > regionEnd) return currentScroll;
+
+        if (currentScroll < flipPoint) {
+            return regionStart;
+        } else {
+            return regionEnd;
+        }
+    }
+
+    /**
+     * If {@code mView} is currently scrolled to between regionStart and regionEnd, smooth scroll
+     * out of the region to the nearest edge.
+     */
+    private static int calculateSnapPositionForRegion(
+            int currentScroll, int regionStart, int regionEnd) {
+        return calculateSnapPositionForRegion(
+                currentScroll, regionStart, regionEnd, (regionStart + regionEnd) / 2);
+    }
+
+    private class SnapScrollRunnable implements Runnable {
+        @Override
+        public void run() {
+            assert mPendingSnapScroll;
+            mPendingSnapScroll = false;
+
+            mNewTabPageLayout.getScrollDelegate().snapScroll();
+        }
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerView.java
index 7d5ed73..cf30200 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerView.java
@@ -5,15 +5,11 @@
 package org.chromium.chrome.browser.ntp.cards;
 
 import android.content.Context;
-import android.content.res.Resources;
 import android.graphics.Region;
-import android.view.LayoutInflater;
-import android.view.View;
 
-import org.chromium.base.VisibleForTesting;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ntp.NewTabPage.FakeboxDelegate;
 import org.chromium.chrome.browser.ntp.NewTabPageLayout;
+import org.chromium.chrome.browser.ntp.SnapScrollHelper;
 import org.chromium.chrome.browser.suggestions.SuggestionsRecyclerView;
 import org.chromium.chrome.browser.util.ViewUtils;
 import org.chromium.ui.base.DeviceFormFactor;
@@ -24,37 +20,18 @@
  */
 public class NewTabPageRecyclerView
         extends SuggestionsRecyclerView implements NewTabPageLayout.ScrollDelegate {
-    private final int mToolbarHeight;
-    private final int mSearchBoxTransitionLength;
-
-    /** View used to calculate the position of the cards' snap point. */
-    private final NewTabPageLayout mAboveTheFoldView;
-
-    /** Whether the location bar is shown as part of the UI. */
-    private boolean mContainsLocationBar;
+    /** The helper for calculating the snap scroll offset. */
+    private SnapScrollHelper mSnapScrollHelper;
 
     /** The fake search box delegate used for determining if the url bar has focus. */
     private FakeboxDelegate mFakeboxDelegate;
 
     public NewTabPageRecyclerView(Context context) {
         super(context);
-
-        Resources res = getContext().getResources();
-        mToolbarHeight = res.getDimensionPixelSize(R.dimen.toolbar_height_no_shadow)
-                + res.getDimensionPixelSize(R.dimen.toolbar_progress_bar_height);
-        mSearchBoxTransitionLength =
-                res.getDimensionPixelSize(R.dimen.ntp_search_box_transition_length);
-
-        mAboveTheFoldView = (NewTabPageLayout) LayoutInflater.from(getContext())
-                                    .inflate(R.layout.new_tab_page_layout, this, false);
     }
 
-    public NewTabPageLayout getAboveTheFoldView() {
-        return mAboveTheFoldView;
-    }
-
-    public void setContainsLocationBar(boolean containsLocationBar) {
-        mContainsLocationBar = containsLocationBar;
+    public void setSnapScrollHelper(SnapScrollHelper snapScrollHelper) {
+        mSnapScrollHelper = snapScrollHelper;
     }
 
     /**
@@ -62,7 +39,7 @@
      * @param fakeboxDelegate The {@link FakeboxDelegate} used to determine whether the URL bar
      *                        has focus.
      */
-    public void setFakeboxDelegate(FakeboxDelegate fakeboxDelegate, View fakeBox) {
+    public void setFakeboxDelegate(FakeboxDelegate fakeboxDelegate) {
         mFakeboxDelegate = fakeboxDelegate;
     }
 
@@ -90,55 +67,6 @@
         return getLinearLayoutManager().findFirstVisibleItemPosition();
     }
 
-    /**
-     * Calculates the position to scroll to in order to move out of a region where the RecyclerView
-     * should not stay at rest.
-     * @param currentScroll the current scroll position.
-     * @param regionStart the beginning of the region to scroll out of.
-     * @param regionEnd the end of the region to scroll out of.
-     * @param flipPoint the threshold used to decide which bound of the region to scroll to.
-     * @return the position to scroll to.
-     */
-    private static int calculateSnapPositionForRegion(
-            int currentScroll, int regionStart, int regionEnd, int flipPoint) {
-        assert regionStart <= flipPoint;
-        assert flipPoint <= regionEnd;
-
-        if (currentScroll < regionStart || currentScroll > regionEnd) return currentScroll;
-
-        if (currentScroll < flipPoint) {
-            return regionStart;
-        } else {
-            return regionEnd;
-        }
-    }
-
-    /**
-     * If the RecyclerView is currently scrolled to between regionStart and regionEnd, smooth scroll
-     * out of the region to the nearest edge.
-     */
-    private static int calculateSnapPositionForRegion(
-            int currentScroll, int regionStart, int regionEnd) {
-        return calculateSnapPositionForRegion(
-                currentScroll, regionStart, regionEnd, (regionStart + regionEnd) / 2);
-    }
-
-    @VisibleForTesting
-    int calculateSnapPosition(int scrollPosition, int parentHeight) {
-        if (mContainsLocationBar) {
-            // Snap scroll to prevent only part of the toolbar from showing.
-            scrollPosition = calculateSnapPositionForRegion(scrollPosition, 0, mToolbarHeight);
-
-            // Snap scroll to prevent resting in the middle of the omnibox transition.
-            View fakeBox = mAboveTheFoldView.getSearchBoxView();
-            int fakeBoxUpperBound = fakeBox.getTop() + fakeBox.getPaddingTop();
-            scrollPosition = calculateSnapPositionForRegion(scrollPosition,
-                    fakeBoxUpperBound - mSearchBoxTransitionLength, fakeBoxUpperBound);
-        }
-
-        return scrollPosition;
-    }
-
     @Override
     public boolean gatherTransparentRegion(Region region) {
         ViewUtils.gatherTransparentRegionsForOpaqueView(this, region);
@@ -167,13 +95,12 @@
 
     @Override
     public void snapScroll() {
-        int parentHeight = ((View) getParent()).getHeight();
         int initialScroll = computeVerticalScrollOffset();
 
-        int scrollTo = calculateSnapPosition(initialScroll, parentHeight);
+        int scrollTo = mSnapScrollHelper.calculateSnapPosition(initialScroll);
 
         // Calculating the snap position should be idempotent.
-        assert scrollTo == calculateSnapPosition(scrollTo, parentHeight);
+        assert scrollTo == mSnapScrollHelper.calculateSnapPosition(scrollTo);
 
         smoothScrollBy(0, scrollTo - initialScroll);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoController.java b/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoController.java
index b82d68a..9199a3c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoController.java
@@ -10,7 +10,6 @@
 import android.content.ClipboardManager;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.os.Bundle;
 import android.provider.Settings;
@@ -20,7 +19,6 @@
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
 import android.text.style.ForegroundColorSpan;
-import android.text.style.StyleSpan;
 import android.text.style.TextAppearanceSpan;
 
 import org.chromium.base.ApiCompatibilityUtils;
@@ -30,7 +28,6 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ContentSettingsType;
 import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.instantapps.InstantAppsHandler;
 import org.chromium.chrome.browser.modaldialog.ModalDialogView;
@@ -40,25 +37,19 @@
 import org.chromium.chrome.browser.omnibox.OmniboxUrlEmphasizer;
 import org.chromium.chrome.browser.page_info.PageInfoView.ConnectionInfoParams;
 import org.chromium.chrome.browser.page_info.PageInfoView.PageInfoViewParams;
-import org.chromium.chrome.browser.page_info.PageInfoView.PermissionParams;
-import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.preferences.Preferences;
 import org.chromium.chrome.browser.preferences.PreferencesLauncher;
 import org.chromium.chrome.browser.preferences.website.ContentSetting;
-import org.chromium.chrome.browser.preferences.website.ContentSettingsResources;
 import org.chromium.chrome.browser.preferences.website.SingleWebsitePreferences;
-import org.chromium.chrome.browser.preferences.website.WebsitePreferenceBridge;
 import org.chromium.chrome.browser.ssl.SecurityStateModel;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.util.UrlUtilities;
 import org.chromium.chrome.browser.vr_shell.VrShellDelegate;
-import org.chromium.components.location.LocationUtils;
 import org.chromium.components.security_state.ConnectionSecurityLevel;
 import org.chromium.components.url_formatter.UrlFormatter;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.WebContentsObserver;
 import org.chromium.ui.base.DeviceFormFactor;
-import org.chromium.ui.base.PermissionCallback;
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.ui.widget.Toast;
 
@@ -67,14 +58,13 @@
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.text.DateFormat;
-import java.util.ArrayList;
 import java.util.Date;
-import java.util.List;
 
 /**
  * Java side of Android implementation of the page info UI.
  */
-public class PageInfoController implements ModalDialogView.Controller {
+public class PageInfoController
+        implements ModalDialogView.Controller, SystemSettingsActivityRequiredListener {
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({OPENED_FROM_MENU, OPENED_FROM_TOOLBAR, OPENED_FROM_VR})
     private @interface OpenedFromSource {}
@@ -91,30 +81,10 @@
     public static final int TRUSTED_OFFLINE_PAGE = 2;
     public static final int UNTRUSTED_OFFLINE_PAGE = 3;
 
-    /**
-     * An entry in the settings dropdown for a given permission. There are two options for each
-     * permission: Allow and Block.
-     */
-    private static final class PageInfoPermissionEntry {
-        public final String name;
-        public final int type;
-        public final ContentSetting setting;
-
-        PageInfoPermissionEntry(String name, int type, ContentSetting setting) {
-            this.name = name;
-            this.type = type;
-            this.setting = setting;
-        }
-
-        @Override
-        public String toString() {
-            return name;
-        }
-    }
-
     private final Context mContext;
     private final WindowAndroid mWindowAndroid;
     private final Tab mTab;
+    private final PermissionParamsListBuilder mPermissionParamsListBuilder;
 
     // A pointer to the C++ object for this UI.
     private long mNativePageInfoController;
@@ -140,9 +110,6 @@
     // The security level of the page (a valid ConnectionSecurityLevel).
     private int mSecurityLevel;
 
-    // Permissions available to be displayed.
-    private List<PageInfoPermissionEntry> mDisplayedPermissions;
-
     // Creation date of an offline copy, if web contents contains an offline page.
     private String mOfflinePageCreationDate;
 
@@ -197,8 +164,6 @@
             Toast.makeText(mContext, R.string.url_copied, Toast.LENGTH_SHORT).show();
         };
 
-        mDisplayedPermissions = new ArrayList<PageInfoPermissionEntry>();
-
         // Work out the URL and connection message and status visibility.
         mFullUrl = isShowingOfflinePage() ? offlinePageUrl : mTab.getOriginalUrl();
 
@@ -300,6 +265,8 @@
         }
 
         mView = new PageInfoView(mContext, viewParams);
+        mPermissionParamsListBuilder = new PermissionParamsListBuilder(
+                mContext, mWindowAndroid, mFullUrl, this, mView::setPermissions);
 
         // This needs to come after other member initialization.
         mNativePageInfoController = nativeInit(this, mTab.getWebContents());
@@ -333,19 +300,6 @@
     }
 
     /**
-     * Finds the Image resource of the icon to use for the given permission.
-     *
-     * @param permission A valid ContentSettingsType that can be displayed in the PageInfo dialog to
-     *                   retrieve the image for.
-     * @return The resource ID of the icon to use for that permission.
-     */
-    private int getImageResourceForPermission(int permission) {
-        int icon = ContentSettingsResources.getIcon(permission);
-        assert icon != 0 : "Icon requested for invalid permission: " + permission;
-        return icon;
-    }
-
-    /**
      * Whether to show a 'Details' link to the connection info popup. The link is only shown for
      * HTTPS connections.
      */
@@ -355,18 +309,6 @@
                 && mParsedUrl.getScheme().equals(UrlConstants.HTTPS_SCHEME);
     }
 
-    private boolean hasAndroidPermission(int contentSettingType) {
-        String[] androidPermissions =
-                PrefServiceBridge.getAndroidPermissionsForContentSetting(contentSettingType);
-        if (androidPermissions == null) return true;
-        for (int i = 0; i < androidPermissions.length; i++) {
-            if (!mWindowAndroid.hasPermission(androidPermissions[i])) {
-                return false;
-            }
-        }
-        return true;
-    }
-
     /**
      * Adds a new row for the given permission.
      *
@@ -376,8 +318,8 @@
      */
     @CalledByNative
     private void addPermissionSection(String name, int type, int currentSettingValue) {
-        mDisplayedPermissions.add(new PageInfoPermissionEntry(
-                name, type, ContentSetting.fromInt(currentSettingValue)));
+        mPermissionParamsListBuilder.addPermissionEntry(
+                name, type, ContentSetting.fromInt(currentSettingValue));
     }
 
     /**
@@ -385,123 +327,7 @@
      */
     @CalledByNative
     private void updatePermissionDisplay() {
-        List<PermissionParams> permissionParamsList = new ArrayList<>();
-        for (PageInfoPermissionEntry permission : mDisplayedPermissions) {
-            permissionParamsList.add(createPermissionParams(permission));
-        }
-        mView.setPermissions(permissionParamsList);
-    }
-
-    private Runnable createPermissionClickCallback(
-            Intent intentOverride, String[] androidPermissions) {
-        return () -> {
-            if (intentOverride == null && mWindowAndroid != null) {
-                // Try and immediately request missing Android permissions where possible.
-                for (int i = 0; i < androidPermissions.length; i++) {
-                    if (!mWindowAndroid.canRequestPermission(androidPermissions[i])) continue;
-
-                    // If any permissions can be requested, attempt to request them all.
-                    mWindowAndroid.requestPermissions(androidPermissions, new PermissionCallback() {
-                        @Override
-                        public void onRequestPermissionsResult(
-                                String[] permissions, int[] grantResults) {
-                            boolean allGranted = true;
-                            for (int i = 0; i < grantResults.length; i++) {
-                                if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
-                                    allGranted = false;
-                                    break;
-                                }
-                            }
-                            if (allGranted) updatePermissionDisplay();
-                        }
-                    });
-                    return;
-                }
-            }
-
-            runAfterDismiss(() -> {
-                Intent settingsIntent;
-                if (intentOverride != null) {
-                    settingsIntent = intentOverride;
-                } else {
-                    settingsIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
-                    settingsIntent.setData(Uri.parse("package:" + mContext.getPackageName()));
-                }
-                settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                mContext.startActivity(settingsIntent);
-            });
-        };
-    }
-
-    private PermissionParams createPermissionParams(PageInfoPermissionEntry permission) {
-        PermissionParams permissionParams = new PermissionParams();
-
-        permissionParams.iconResource = getImageResourceForPermission(permission.type);
-        if (permission.setting == ContentSetting.ALLOW) {
-            LocationUtils locationUtils = LocationUtils.getInstance();
-            Intent intentOverride = null;
-            String[] androidPermissions = null;
-            if (permission.type == ContentSettingsType.CONTENT_SETTINGS_TYPE_GEOLOCATION
-                    && !locationUtils.isSystemLocationSettingEnabled()) {
-                permissionParams.warningTextResource = R.string.page_info_android_location_blocked;
-                intentOverride = locationUtils.getSystemLocationSettingsIntent();
-            } else if (!hasAndroidPermission(permission.type)) {
-                permissionParams.warningTextResource =
-                        R.string.page_info_android_permission_blocked;
-                androidPermissions =
-                        PrefServiceBridge.getAndroidPermissionsForContentSetting(permission.type);
-            }
-
-            if (permissionParams.warningTextResource != 0) {
-                permissionParams.iconResource = R.drawable.exclamation_triangle;
-                permissionParams.iconTintColorResource = R.color.default_icon_color_blue;
-                permissionParams.clickCallback =
-                        createPermissionClickCallback(intentOverride, androidPermissions);
-            }
-        }
-
-        // The ads permission requires an additional static subtitle.
-        if (permission.type == ContentSettingsType.CONTENT_SETTINGS_TYPE_ADS) {
-            permissionParams.subtitleTextResource = R.string.page_info_permission_ads_subtitle;
-        }
-
-        SpannableStringBuilder builder = new SpannableStringBuilder();
-        SpannableString nameString = new SpannableString(permission.name);
-        final StyleSpan boldSpan = new StyleSpan(android.graphics.Typeface.BOLD);
-        nameString.setSpan(boldSpan, 0, nameString.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
-
-        builder.append(nameString);
-        builder.append(" – "); // en-dash.
-        String status_text = "";
-        switch (permission.setting) {
-            case ALLOW:
-                status_text = mContext.getString(R.string.page_info_permission_allowed);
-                break;
-            case BLOCK:
-                status_text = mContext.getString(R.string.page_info_permission_blocked);
-                break;
-            default:
-                assert false : "Invalid setting " + permission.setting + " for permission "
-                               + permission.type;
-        }
-        if (WebsitePreferenceBridge.isPermissionControlledByDSE(permission.type, mFullUrl, false)) {
-            status_text = statusTextForDSEPermission(permission.setting);
-        }
-        builder.append(status_text);
-        permissionParams.status = builder;
-
-        return permissionParams;
-    }
-
-    /**
-     * Returns the permission string for the Default Search Engine.
-     */
-    private String statusTextForDSEPermission(ContentSetting setting) {
-        if (setting == ContentSetting.ALLOW) {
-            return mContext.getString(R.string.page_info_dse_permission_allowed);
-        }
-
-        return mContext.getString(R.string.page_info_dse_permission_blocked);
+        mView.setPermissions(mPermissionParamsListBuilder.build());
     }
 
     /**
@@ -564,6 +390,21 @@
         mView.setConnectionInfo(connectionInfoParams);
     }
 
+    @Override
+    public void onSystemSettingsActivityRequired(Intent intentOverride) {
+        runAfterDismiss(() -> {
+            Intent settingsIntent;
+            if (intentOverride != null) {
+                settingsIntent = intentOverride;
+            } else {
+                settingsIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+                settingsIntent.setData(Uri.parse("package:" + mContext.getPackageName()));
+            }
+            settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            mContext.startActivity(settingsIntent);
+        });
+    }
+
     /**
      * Dismiss the popup, and then run a task after the animation has completed (if there is one).
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/page_info/PermissionParamsListBuilder.java b/chrome/android/java/src/org/chromium/chrome/browser/page_info/PermissionParamsListBuilder.java
new file mode 100644
index 0000000..fdf84f2
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/page_info/PermissionParamsListBuilder.java
@@ -0,0 +1,226 @@
+// Copyright 2018 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.page_info;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
+import android.text.style.StyleSpan;
+
+import org.chromium.base.Callback;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ContentSettingsType;
+import org.chromium.chrome.browser.preferences.PrefServiceBridge;
+import org.chromium.chrome.browser.preferences.website.ContentSetting;
+import org.chromium.chrome.browser.preferences.website.ContentSettingsResources;
+import org.chromium.chrome.browser.preferences.website.WebsitePreferenceBridge;
+import org.chromium.components.location.LocationUtils;
+import org.chromium.ui.base.AndroidPermissionDelegate;
+import org.chromium.ui.base.PermissionCallback;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class is a helper for PageInfoController. It contains the logic required to turn a set of
+ * permission values into PermissionParams suitable for PageInfoView to display.
+ *
+ */
+class PermissionParamsListBuilder {
+    private final List<PageInfoPermissionEntry> mEntries;
+    private final String mFullUrl;
+    private final Context mContext;
+    private final AndroidPermissionDelegate mPermissionDelegate;
+    private final SystemSettingsActivityRequiredListener mSettingsActivityRequiredListener;
+    private final Callback<List<PageInfoView.PermissionParams>> mDisplayPermissionsCallback;
+
+    /**
+     * Creates a new builder of a list of PermissionParams that can be displayed.
+     *
+     * @param context Context for accessing string resources.
+     * @param permissionDelegate Delegate for checking system permissions.
+     * @param fullUrl Full URL of the site whose permissions are being displayed.
+     * @param systemSettingsActivityRequiredListener Listener for when we need the user to enable
+     *                                               a system setting to proceed.
+     * @param displayPermissionsCallback Callback to run to display fresh permissions in response to
+     *                                   user interaction with a permission entry.
+     */
+    PermissionParamsListBuilder(Context context, AndroidPermissionDelegate permissionDelegate,
+            String fullUrl,
+            SystemSettingsActivityRequiredListener systemSettingsActivityRequiredListener,
+            Callback<List<PageInfoView.PermissionParams>> displayPermissionsCallback) {
+        mContext = context;
+        mFullUrl = fullUrl;
+        mSettingsActivityRequiredListener = systemSettingsActivityRequiredListener;
+        mPermissionDelegate = permissionDelegate;
+        mEntries = new ArrayList<>();
+        mDisplayPermissionsCallback = displayPermissionsCallback;
+    }
+
+    void addPermissionEntry(String name, int type, ContentSetting value) {
+        mEntries.add(new PageInfoPermissionEntry(name, type, value));
+    }
+
+    List<PageInfoView.PermissionParams> build() {
+        List<PageInfoView.PermissionParams> permissionParams = new ArrayList<>();
+        for (PermissionParamsListBuilder.PageInfoPermissionEntry permission : mEntries) {
+            permissionParams.add(createPermissionParams(permission));
+        }
+        return permissionParams;
+    }
+
+    private PageInfoView.PermissionParams createPermissionParams(
+            PermissionParamsListBuilder.PageInfoPermissionEntry permission) {
+        PageInfoView.PermissionParams permissionParams = new PageInfoView.PermissionParams();
+
+        permissionParams.iconResource = getImageResourceForPermission(permission.type);
+        if (permission.setting == ContentSetting.ALLOW) {
+            LocationUtils locationUtils = LocationUtils.getInstance();
+            Intent intentOverride = null;
+            String[] androidPermissions = null;
+            if (permission.type == ContentSettingsType.CONTENT_SETTINGS_TYPE_GEOLOCATION
+                    && !locationUtils.isSystemLocationSettingEnabled()) {
+                permissionParams.warningTextResource = R.string.page_info_android_location_blocked;
+                intentOverride = locationUtils.getSystemLocationSettingsIntent();
+            } else if (!hasAndroidPermission(permission.type)) {
+                permissionParams.warningTextResource =
+                        R.string.page_info_android_permission_blocked;
+                androidPermissions =
+                        PrefServiceBridge.getAndroidPermissionsForContentSetting(permission.type);
+            }
+
+            if (permissionParams.warningTextResource != 0) {
+                permissionParams.iconResource = R.drawable.exclamation_triangle;
+                permissionParams.iconTintColorResource = R.color.default_icon_color_blue;
+                permissionParams.clickCallback =
+                        createPermissionClickCallback(intentOverride, androidPermissions);
+            }
+        }
+
+        // The ads permission requires an additional static subtitle.
+        if (permission.type == ContentSettingsType.CONTENT_SETTINGS_TYPE_ADS) {
+            permissionParams.subtitleTextResource = R.string.page_info_permission_ads_subtitle;
+        }
+
+        SpannableStringBuilder builder = new SpannableStringBuilder();
+        SpannableString nameString = new SpannableString(permission.name);
+        final StyleSpan boldSpan = new StyleSpan(android.graphics.Typeface.BOLD);
+        nameString.setSpan(boldSpan, 0, nameString.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
+
+        builder.append(nameString);
+        builder.append(" – "); // en-dash.
+        String status_text = "";
+        switch (permission.setting) {
+            case ALLOW:
+                status_text = mContext.getString(R.string.page_info_permission_allowed);
+                break;
+            case BLOCK:
+                status_text = mContext.getString(R.string.page_info_permission_blocked);
+                break;
+            default:
+                assert false : "Invalid setting " + permission.setting + " for permission "
+                               + permission.type;
+        }
+        if (WebsitePreferenceBridge.isPermissionControlledByDSE(permission.type, mFullUrl, false)) {
+            status_text = statusTextForDSEPermission(permission.setting);
+        }
+        builder.append(status_text);
+        permissionParams.status = builder;
+
+        return permissionParams;
+    }
+
+    private boolean hasAndroidPermission(int contentSettingType) {
+        String[] androidPermissions =
+                PrefServiceBridge.getAndroidPermissionsForContentSetting(contentSettingType);
+        if (androidPermissions == null) return true;
+        for (int i = 0; i < androidPermissions.length; i++) {
+            if (!mPermissionDelegate.hasPermission(androidPermissions[i])) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Finds the Image resource of the icon to use for the given permission.
+     *
+     * @param permission A valid ContentSettingsType that can be displayed in the PageInfo dialog to
+     *                   retrieve the image for.
+     * @return The resource ID of the icon to use for that permission.
+     */
+    private int getImageResourceForPermission(int permission) {
+        int icon = ContentSettingsResources.getIcon(permission);
+        assert icon != 0 : "Icon requested for invalid permission: " + permission;
+        return icon;
+    }
+
+    private Runnable createPermissionClickCallback(
+            Intent intentOverride, String[] androidPermissions) {
+        return () -> {
+            if (intentOverride == null && mPermissionDelegate != null) {
+                // Try and immediately request missing Android permissions where possible.
+                for (int i = 0; i < androidPermissions.length; i++) {
+                    if (!mPermissionDelegate.canRequestPermission(androidPermissions[i])) continue;
+
+                    // If any permissions can be requested, attempt to request them all.
+                    mPermissionDelegate.requestPermissions(
+                            androidPermissions, new PermissionCallback() {
+                                @Override
+                                public void onRequestPermissionsResult(
+                                        String[] permissions, int[] grantResults) {
+                                    boolean allGranted = true;
+                                    for (int i = 0; i < grantResults.length; i++) {
+                                        if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
+                                            allGranted = false;
+                                            break;
+                                        }
+                                    }
+                                    if (allGranted) mDisplayPermissionsCallback.onResult(build());
+                                }
+                            });
+                    return;
+                }
+            }
+
+            mSettingsActivityRequiredListener.onSystemSettingsActivityRequired(intentOverride);
+        };
+    }
+
+    /**
+     * Returns the permission string for the Default Search Engine.
+     */
+    private String statusTextForDSEPermission(ContentSetting setting) {
+        if (setting == ContentSetting.ALLOW) {
+            return mContext.getString(R.string.page_info_dse_permission_allowed);
+        }
+
+        return mContext.getString(R.string.page_info_dse_permission_blocked);
+    }
+
+    /**
+     * An entry in the settings dropdown for a given permission. There are two options for each
+     * permission: Allow and Block.
+     */
+    private static final class PageInfoPermissionEntry {
+        public final String name;
+        public final int type;
+        public final ContentSetting setting;
+
+        PageInfoPermissionEntry(String name, int type, ContentSetting setting) {
+            this.name = name;
+            this.type = type;
+            this.setting = setting;
+        }
+
+        @Override
+        public String toString() {
+            return name;
+        }
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/page_info/SystemSettingsActivityRequiredListener.java b/chrome/android/java/src/org/chromium/chrome/browser/page_info/SystemSettingsActivityRequiredListener.java
new file mode 100644
index 0000000..d76ca044
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/page_info/SystemSettingsActivityRequiredListener.java
@@ -0,0 +1,14 @@
+// Copyright 2018 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.page_info;
+
+import android.content.Intent;
+
+/**
+ * Extracted to allow testing of PermissionParamsListBuilder.
+ */
+interface SystemSettingsActivityRequiredListener {
+    void onSystemSettingsActivityRequired(Intent intentOverride);
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
index d077344d..7f7d4d69 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -199,9 +199,11 @@
             }
 
             BrowserServicesMetrics.recordTwaOpened();
-            // Occasionally verification occurs in the background while there is no active Tab.
+            TrustedWebActivityDisclosure.showIfNeeded(WebappActivity.this, packageName);
+
+            // When verification occurs instantly (eg the result is cached) then it returns before
+            // there is an active tab.
             if (areTabModelsInitialized() && getActivityTab() != null) {
-                TrustedWebActivityDisclosure.showIfNeeded(WebappActivity.this, packageName);
                 mUkmRecorder.recordTwaOpened(getActivityTab().getWebContents());
             }
         }
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index 562e9a1..a4a98125 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -285,7 +285,7 @@
       <message name="IDS_SIGN_IN_TO_CHROME" desc="Title for the button to sign in to Chrome using one's Google account. [CHAR-LIMIT=27]">
         Sign in to Chrome
       </message>
-      <message name="IDS_PREFS_SYNC_AND_SERVICES" desc="Title for Settings section to manage data collection for Sync and Google services. [CHAR-LIMIT=32]">
+      <message name="IDS_PREFS_SYNC_AND_SERVICES" desc="Title for Settings section to manage data collection for Sync and Google services. [CHAR-LIMIT=40]">
         Sync and Google services
       </message>
       <message name="IDS_SIGN_IN_TO_CHROME_SUMMARY" desc="Summary for the button to sign in to Chrome, explaining benefits of signing in.">
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index cc946f7..4edc1e4 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -844,6 +844,7 @@
   "java/src/org/chromium/chrome/browser/ntp/RecentlyClosedBridge.java",
   "java/src/org/chromium/chrome/browser/ntp/RecentlyClosedTab.java",
   "java/src/org/chromium/chrome/browser/ntp/RecentlyClosedTabManager.java",
+  "java/src/org/chromium/chrome/browser/ntp/SnapScrollHelper.java",
   "java/src/org/chromium/chrome/browser/ntp/TitleUtil.java",
   "java/src/org/chromium/chrome/browser/ntp/cards/AboveTheFoldItem.java",
   "java/src/org/chromium/chrome/browser/ntp/cards/ActionItem.java",
@@ -955,9 +956,11 @@
   "java/src/org/chromium/chrome/browser/page_info/CertificateChainHelper.java",
   "java/src/org/chromium/chrome/browser/page_info/CertificateViewer.java",
   "java/src/org/chromium/chrome/browser/page_info/ConnectionInfoPopup.java",
+  "java/src/org/chromium/chrome/browser/page_info/SystemSettingsActivityRequiredListener.java",
   "java/src/org/chromium/chrome/browser/page_info/PageInfoDialog.java",
   "java/src/org/chromium/chrome/browser/page_info/PageInfoController.java",
   "java/src/org/chromium/chrome/browser/page_info/PageInfoView.java",
+  "java/src/org/chromium/chrome/browser/page_info/PermissionParamsListBuilder.java",
   "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmark.java",
   "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottle.java",
   "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksProviderIterator.java",
@@ -2194,6 +2197,7 @@
   "junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTest.java",
   "junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTrackerTest.java",
   "junit/src/org/chromium/chrome/browser/omnibox/geo/PlatformNetworksManagerTest.java",
+  "junit/src/org/chromium/chrome/browser/page_info/PermissionParamsListBuilderUnitTest.java",
   "junit/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizationsUnitTest.java",
   "junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottleTest.java",
   "junit/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderUnitTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerViewTest.java
index 5fb6dbc..ad7ebcb276 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerViewTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerViewTest.java
@@ -344,7 +344,7 @@
 
     private int getSnapPosition(int scrollPosition) {
         NewTabPageView ntpView = getNtpView();
-        return getRecyclerView().calculateSnapPosition(scrollPosition, ntpView.getHeight());
+        return ntpView.getSnapScrollHelper().calculateSnapPosition(scrollPosition);
     }
 
     private NewTabPageView getNtpView() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/TileGroupTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/TileGroupTest.java
index b7d7a2e7..6e70142 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/TileGroupTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/TileGroupTest.java
@@ -171,10 +171,10 @@
     }
 
     private TileGridLayout getTileGridLayout() {
-        ViewGroup aboveTheFoldView = getRecyclerView().getAboveTheFoldView();
-        Assert.assertNotNull("Unable to retrieve the AboveTheFold view.", aboveTheFoldView);
+        ViewGroup newTabPageLayout = mNtp.getNewTabPageLayout();
+        Assert.assertNotNull("Unable to retrieve the NewTabPageLayout.", newTabPageLayout);
 
-        TileGridLayout tileGridLayout = aboveTheFoldView.findViewById(R.id.tile_grid_layout);
+        TileGridLayout tileGridLayout = newTabPageLayout.findViewById(R.id.tile_grid_layout);
         Assert.assertNotNull("Unable to retrieve the TileGridLayout.", tileGridLayout);
         return tileGridLayout;
     }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/page_info/PermissionParamsListBuilderUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/page_info/PermissionParamsListBuilderUnitTest.java
new file mode 100644
index 0000000..0c70214
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/page_info/PermissionParamsListBuilderUnitTest.java
@@ -0,0 +1,150 @@
+// Copyright 2018 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.page_info;
+
+import static junit.framework.Assert.assertNotNull;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import android.content.Intent;
+import android.provider.Settings;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ContentSettingsType;
+import org.chromium.chrome.browser.page_info.PermissionParamsListBuilderUnitTest.ShadowWebsitePreferenceBridge;
+import org.chromium.chrome.browser.preferences.website.ContentSetting;
+import org.chromium.chrome.browser.preferences.website.WebsitePreferenceBridge;
+import org.chromium.chrome.test.util.browser.LocationSettingsTestUtil;
+import org.chromium.ui.base.AndroidPermissionDelegate;
+import org.chromium.ui.base.PermissionCallback;
+
+import java.util.List;
+
+/**
+ * Unit tests for PermissionParamsListBuilder.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, shadows = {ShadowWebsitePreferenceBridge.class})
+public class PermissionParamsListBuilderUnitTest {
+    private PermissionParamsListBuilder mPermissionParamsListBuilder;
+    private FakeSystemSettingsActivityRequiredListener mSettingsActivityRequiredListener;
+
+    @Before
+    public void setUp() throws Exception {
+        LocationSettingsTestUtil.setSystemLocationSettingEnabled(true);
+        AndroidPermissionDelegate permissionDelegate = new FakePermissionDelegate();
+        mSettingsActivityRequiredListener = new FakeSystemSettingsActivityRequiredListener();
+        mPermissionParamsListBuilder =
+                new PermissionParamsListBuilder(RuntimeEnvironment.application, permissionDelegate,
+                        "https://example.com", mSettingsActivityRequiredListener, result -> {});
+    }
+
+    @Test
+    public void addSingleEntryAndBuild() {
+        mPermissionParamsListBuilder.addPermissionEntry(
+                "Foo", ContentSettingsType.CONTENT_SETTINGS_TYPE_GEOLOCATION, ContentSetting.ALLOW);
+
+        List<PageInfoView.PermissionParams> params = mPermissionParamsListBuilder.build();
+
+        assertEquals(1, params.size());
+        PageInfoView.PermissionParams permissionParams = params.get(0);
+
+        assertEquals(R.drawable.permission_location, permissionParams.iconResource);
+
+        String expectedStatus = "Foo – "
+                + RuntimeEnvironment.application.getString(R.string.page_info_permission_allowed);
+        assertEquals(expectedStatus, permissionParams.status.toString());
+
+        assertNull(permissionParams.clickCallback);
+    }
+
+    @Test
+    public void addLocationEntryAndBuildWhenSystemLocationDisabled() {
+        LocationSettingsTestUtil.setSystemLocationSettingEnabled(false);
+        mPermissionParamsListBuilder.addPermissionEntry("Test",
+                ContentSettingsType.CONTENT_SETTINGS_TYPE_GEOLOCATION, ContentSetting.ALLOW);
+
+        List<PageInfoView.PermissionParams> params = mPermissionParamsListBuilder.build();
+
+        assertEquals(1, params.size());
+        PageInfoView.PermissionParams permissionParams = params.get(0);
+        assertEquals(
+                R.string.page_info_android_location_blocked, permissionParams.warningTextResource);
+
+        assertNotNull(permissionParams.clickCallback);
+        permissionParams.clickCallback.run();
+        assertEquals(1, mSettingsActivityRequiredListener.getCallCount());
+        assertEquals(Settings.ACTION_LOCATION_SOURCE_SETTINGS,
+                mSettingsActivityRequiredListener.getIntentOverride().getAction());
+    }
+
+    private static class FakePermissionDelegate implements AndroidPermissionDelegate {
+        @Override
+        public boolean hasPermission(String permission) {
+            return true;
+        }
+
+        @Override
+        public boolean canRequestPermission(String permission) {
+            return true;
+        }
+
+        @Override
+        public boolean isPermissionRevokedByPolicy(String permission) {
+            return false;
+        }
+
+        @Override
+        public void requestPermissions(String[] permissions, PermissionCallback callback) {}
+
+        @Override
+        public boolean handlePermissionResult(
+                int requestCode, String[] permissions, int[] grantResults) {
+            return false;
+        }
+    }
+
+    /**
+     * Allows us to stub out the static calls to native.
+     */
+    @Implements(WebsitePreferenceBridge.class)
+    public static class ShadowWebsitePreferenceBridge {
+        @Implementation
+        public static boolean isPermissionControlledByDSE(
+                @ContentSettingsType int contentSettingsType, String origin, boolean isIncognito) {
+            return false;
+        }
+    }
+
+    private static class FakeSystemSettingsActivityRequiredListener
+            implements SystemSettingsActivityRequiredListener {
+        int mCallCount = 0;
+        Intent mIntentOverride;
+
+        @Override
+        public void onSystemSettingsActivityRequired(Intent intentOverride) {
+            mCallCount++;
+            mIntentOverride = intentOverride;
+        }
+
+        public int getCallCount() {
+            return mCallCount;
+        }
+
+        Intent getIntentOverride() {
+            return mIntentOverride;
+        }
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index 6679651..dc8088f 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-69.0.3488.0_rc-r1.afdo.bz2
\ No newline at end of file
+chromeos-chrome-amd64-69.0.3489.0_rc-r1.afdo.bz2
\ No newline at end of file
diff --git a/chrome/app/BUILD.gn b/chrome/app/BUILD.gn
index 75aee9c9..ce6f796 100644
--- a/chrome/app/BUILD.gn
+++ b/chrome/app/BUILD.gn
@@ -427,6 +427,9 @@
   if (enable_extensions || is_android) {
     packaged_services += [ "//chrome/services/media_gallery_util:manifest" ]
   }
+  if (enable_simple_browser_service) {
+    packaged_services += [ "//services/content/simple_browser:manifest" ]
+  }
   if (is_win) {
     packaged_services += [
       "//chrome/services/util_win:manifest",
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 0f5bb38b..ce89280a 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -930,6 +930,8 @@
     "page_load_metrics/observers/css_scanning_page_load_metrics_observer.h",
     "page_load_metrics/observers/data_reduction_proxy_metrics_observer.cc",
     "page_load_metrics/observers/data_reduction_proxy_metrics_observer.h",
+    "page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.cc",
+    "page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.h",
     "page_load_metrics/observers/document_write_page_load_metrics_observer.cc",
     "page_load_metrics/observers/document_write_page_load_metrics_observer.h",
     "page_load_metrics/observers/from_gws_page_load_metrics_observer.cc",
@@ -4178,6 +4180,10 @@
     }
   }
 
+  if (enable_simple_browser_service) {
+    deps += [ "//services/content/simple_browser/public/mojom" ]
+  }
+
   if (enable_supervised_users) {
     sources += [
       "content_settings/content_settings_supervised_provider.cc",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index f64e3568..36855ba 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -54,6 +54,7 @@
   "+rlz",
   "+sandbox/win/src",  # The path doesn't say it, but this is the Windows sandbox.
   "+services/audio/public",
+  "+services/content/simple_browser/public",
   "+services/data_decoder/public",
   "+services/device/public",
   "+services/identity/public",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 796f243..0e63d15 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2858,6 +2858,10 @@
     {"enable-nup-printing", flag_descriptions::kEnableNupPrintingName,
      flag_descriptions::kEnableNupPrintingDescription, kOsAll,
      FEATURE_VALUE_TYPE(features::kNupPrinting)},
+    {"enable-cloud-printer-handler",
+     flag_descriptions::kCloudPrinterHandlerName,
+     flag_descriptions::kCloudPrinterHandlerDescription, kOsDesktop,
+     FEATURE_VALUE_TYPE(features::kCloudPrinterHandler)},
 #endif
 #if defined(OS_ANDROID)
     {"concurrent-background-loading-on-svelte",
diff --git a/chrome/browser/android/contextualsearch/contextual_search_delegate.cc b/chrome/browser/android/contextualsearch/contextual_search_delegate.cc
index 51f81fd..5e8df05 100644
--- a/chrome/browser/android/contextualsearch/contextual_search_delegate.cc
+++ b/chrome/browser/android/contextualsearch/contextual_search_delegate.cc
@@ -377,10 +377,8 @@
   // History.
   browser_sync::ProfileSyncService* service =
       ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
-  syncer::SyncPrefs sync_prefs(profile->GetPrefs());
   if (service == NULL || !service->CanSyncStart() ||
-      !sync_prefs.GetPreferredDataTypes(syncer::UserTypes())
-           .Has(syncer::PROXY_TABS) ||
+      !service->GetPreferredDataTypes().Has(syncer::PROXY_TABS) ||
       !service->GetActiveDataTypes().Has(syncer::HISTORY_DELETE_DIRECTIVES)) {
     return false;
   }
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index 2e6464a..993679877 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -637,8 +637,8 @@
   DCHECK(io_thread_);
   if (!network_connection_tracker_) {
     network_connection_tracker_ =
-        std::make_unique<content::NetworkConnectionTracker>(
-            base::BindRepeating(&content::GetNetworkService));
+        std::make_unique<content::NetworkConnectionTracker>();
+    network_connection_tracker_->Initialize(content::GetNetworkService());
   }
   return network_connection_tracker_.get();
 }
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 513ce73..dd3bd97 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -163,6 +163,7 @@
 #include "components/variations/variations_http_header_provider.h"
 #include "components/variations/variations_switches.h"
 #include "components/version_info/version_info.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
@@ -187,6 +188,7 @@
 #include "printing/buildflags/buildflags.h"
 #include "rlz/buildflags/buildflags.h"
 #include "services/service_manager/embedder/main_delegate.h"
+#include "services/service_manager/public/cpp/connector.h"
 #include "third_party/blink/public/common/experiments/memory_ablation_experiment.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/layout.h"
@@ -304,7 +306,10 @@
 #include "services/service_manager/runner/common/client_util.h"
 #include "ui/aura/env.h"
 #endif
-#include "services/service_manager/public/cpp/connector.h"
+
+#if BUILDFLAG(ENABLE_SIMPLE_BROWSER_SERVICE)
+#include "services/content/simple_browser/public/mojom/constants.mojom.h"
+#endif
 
 #if !defined(OS_ANDROID)
 #include "chrome/browser/component_updater/intervention_policy_database_component_installer.h"
@@ -2026,6 +2031,14 @@
                       base::TimeTicks::Now() - start_time_step3);
 #endif  // !defined(OS_ANDROID)
 
+#if BUILDFLAG(ENABLE_SIMPLE_BROWSER_SERVICE)
+  const char kLaunchSimpleBrowserSwitch[] = "launch-simple-browser";
+  if (parsed_command_line().HasSwitch(kLaunchSimpleBrowserSwitch)) {
+    content::BrowserContext::GetConnectorFor(profile_)->StartService(
+        service_manager::Identity(simple_browser::mojom::kServiceName));
+  }
+#endif  // BUILDFLAG(ENABLE_SIMPLE_BROWSER_SERVICE)
+
   return result_code_;
 }
 
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 0a19b55a..85cbd1b 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -501,6 +501,10 @@
 #include "chrome/browser/offline_pages/offline_page_url_loader_request_interceptor.h"
 #endif
 
+#if BUILDFLAG(ENABLE_SIMPLE_BROWSER_SERVICE)
+#include "services/content/simple_browser/public/mojom/constants.mojom.h"
+#endif
+
 using base::FileDescriptor;
 using content::BrowserThread;
 using content::BrowserURLHandler;
@@ -1499,6 +1503,12 @@
   return webui::LogWebUIUrl(web_ui_url);
 }
 
+bool ChromeContentBrowserClient::IsWebUIAllowedToMakeNetworkRequests(
+    const url::Origin& origin) {
+  return ChromeWebUIControllerFactory::IsWebUIAllowedToMakeNetworkRequests(
+      origin);
+}
+
 bool ChromeContentBrowserClient::IsHandledURL(const GURL& url) {
   return ProfileIOData::IsHandledURL(url);
 }
@@ -3660,6 +3670,11 @@
 #if defined(OS_CHROMEOS)
   ash_service_registry::RegisterOutOfProcessServices(services);
 #endif
+
+#if BUILDFLAG(ENABLE_SIMPLE_BROWSER_SERVICE)
+  (*services)[simple_browser::mojom::kServiceName] = base::BindRepeating(
+      []() -> base::string16 { return base::ASCIIToUTF16("Simple Browser"); });
+#endif
 }
 
 bool ChromeContentBrowserClient::ShouldTerminateOnServiceQuit(
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index 0bcbf36..e925fdb9 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -123,6 +123,7 @@
   void GetAdditionalViewSourceSchemes(
       std::vector<std::string>* additional_schemes) override;
   bool LogWebUIUrl(const GURL& web_ui_url) const override;
+  bool IsWebUIAllowedToMakeNetworkRequests(const url::Origin& origin) override;
   bool IsHandledURL(const GURL& url) override;
   bool CanCommitURL(content::RenderProcessHost* process_host,
                     const GURL& url) override;
diff --git a/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc b/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc
index 52f056f..d60ff085 100644
--- a/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc
+++ b/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc
@@ -144,6 +144,10 @@
   }
   // Only restore session cookies for the primary account in the profile.
   if (GetPrimaryAccountId() == user_email) {
+    // The refresh token has changed, so stop any ongoing actions that were
+    // based on the old refresh token.
+    Stop();
+
     // Token is loaded. Undo the flagging before token loading.
     user_manager::UserManager::Get()->SaveUserOAuthStatus(
         AccountId::FromUserEmail(user_email),
diff --git a/chrome/browser/consent_auditor/consent_auditor_factory.cc b/chrome/browser/consent_auditor/consent_auditor_factory.cc
index 4c16c5d..9967473f 100644
--- a/chrome/browser/consent_auditor/consent_auditor_factory.cc
+++ b/chrome/browser/consent_auditor/consent_auditor_factory.cc
@@ -10,7 +10,7 @@
 #include "chrome/browser/sync/user_event_service_factory.h"
 #include "chrome/common/channel_info.h"
 #include "components/browser_sync/profile_sync_service.h"
-#include "components/consent_auditor/consent_auditor.h"
+#include "components/consent_auditor/consent_auditor_impl.h"
 #include "components/consent_auditor/consent_sync_bridge.h"
 #include "components/consent_auditor/consent_sync_bridge_impl.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
@@ -69,7 +69,7 @@
         browser_sync::UserEventServiceFactory::GetForProfile(profile);
   }
 
-  return new consent_auditor::ConsentAuditor(
+  return new consent_auditor::ConsentAuditorImpl(
       profile->GetPrefs(), std::move(consent_sync_bridge), user_event_service,
       // The browser version and locale do not change runtime, so we can pass
       // them directly.
@@ -80,5 +80,5 @@
 // static
 void ConsentAuditorFactory::RegisterProfilePrefs(
     user_prefs::PrefRegistrySyncable* registry) {
-  consent_auditor::ConsentAuditor::RegisterProfilePrefs(registry);
+  consent_auditor::ConsentAuditorImpl::RegisterProfilePrefs(registry);
 }
diff --git a/chrome/browser/consent_auditor/consent_auditor_test_utils.cc b/chrome/browser/consent_auditor/consent_auditor_test_utils.cc
index 0c05226..032e3a5 100644
--- a/chrome/browser/consent_auditor/consent_auditor_test_utils.cc
+++ b/chrome/browser/consent_auditor/consent_auditor_test_utils.cc
@@ -3,16 +3,9 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/consent_auditor/consent_auditor_test_utils.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sync/user_event_service_factory.h"
 #include "components/consent_auditor/fake_consent_auditor.h"
 
 std::unique_ptr<KeyedService> BuildFakeConsentAuditor(
     content::BrowserContext* context) {
-  Profile* profile = Profile::FromBrowserContext(context);
-  std::unique_ptr<consent_auditor::FakeConsentAuditor> fake_consent_auditor =
-      std::make_unique<consent_auditor::FakeConsentAuditor>(
-          profile->GetPrefs(),
-          browser_sync::UserEventServiceFactory::GetForProfile(profile));
-  return fake_consent_auditor;
+  return std::make_unique<consent_auditor::FakeConsentAuditor>();
 }
diff --git a/chrome/browser/extensions/api/identity/identity_apitest.cc b/chrome/browser/extensions/api/identity/identity_apitest.cc
index 3091e73..574f1a83 100644
--- a/chrome/browser/extensions/api/identity/identity_apitest.cc
+++ b/chrome/browser/extensions/api/identity/identity_apitest.cc
@@ -439,7 +439,7 @@
     ProfileOAuth2TokenServiceFactory::GetInstance()->SetTestingFactory(
         context, &BuildFakeProfileOAuth2TokenService);
     GaiaCookieManagerServiceFactory::GetInstance()->SetTestingFactory(
-        context, &BuildFakeGaiaCookieManagerService);
+        context, &BuildFakeGaiaCookieManagerServiceNoFakeUrlFetcher);
 
     // Ensure that AccountFetcherService is (1) created at all and (2) created
     // early enough for it to observe the Profile initialization process and
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.cc b/chrome/browser/extensions/api/tabs/tabs_api.cc
index 3d23f6f6..f2e7c6f 100644
--- a/chrome/browser/extensions/api/tabs/tabs_api.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -265,6 +265,8 @@
 
 #if defined(OS_CHROMEOS)
 void SetLockedFullscreenState(Browser* browser, bool locked) {
+  UMA_HISTOGRAM_BOOLEAN("Extensions.LockedFullscreenStateRequest", locked);
+
   aura::Window* window = browser->window()->GetNativeWindow();
   // TRUSTED_PINNED is used here because that one locks the window fullscreen
   // without allowing the user to exit (as opposed to regular PINNED).
diff --git a/chrome/browser/extensions/chrome_extensions_browser_client.cc b/chrome/browser/extensions/chrome_extensions_browser_client.cc
index 90d8c719..535ae7fd 100644
--- a/chrome/browser/extensions/chrome_extensions_browser_client.cc
+++ b/chrome/browser/extensions/chrome_extensions_browser_client.cc
@@ -40,6 +40,7 @@
 #include "chrome/browser/sessions/session_tab_helper.h"
 #include "chrome/browser/task_manager/web_contents_tags.h"
 #include "chrome/browser/ui/bluetooth/chrome_extension_bluetooth_chooser.h"
+#include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
 #include "chrome/common/channel_info.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
@@ -532,6 +533,12 @@
       extension_id);
 }
 
+bool ChromeExtensionsBrowserClient::IsWebUIAllowedToMakeNetworkRequests(
+    const url::Origin& origin) {
+  return ChromeWebUIControllerFactory::IsWebUIAllowedToMakeNetworkRequests(
+      origin);
+}
+
 // static
 void ChromeExtensionsBrowserClient::set_did_chrome_update_for_testing(
     bool did_update) {
diff --git a/chrome/browser/extensions/chrome_extensions_browser_client.h b/chrome/browser/extensions/chrome_extensions_browser_client.h
index 1d11de87..87658e0a 100644
--- a/chrome/browser/extensions/chrome_extensions_browser_client.h
+++ b/chrome/browser/extensions/chrome_extensions_browser_client.h
@@ -151,6 +151,7 @@
   std::string GetApplicationLocale() override;
   bool IsExtensionEnabled(const std::string& extension_id,
                           content::BrowserContext* context) const override;
+  bool IsWebUIAllowedToMakeNetworkRequests(const url::Origin& origin) override;
 
   static void set_did_chrome_update_for_testing(bool did_update);
 
diff --git a/chrome/browser/extensions/scripting_permissions_modifier_unittest.cc b/chrome/browser/extensions/scripting_permissions_modifier_unittest.cc
index d315073..8e68f6e 100644
--- a/chrome/browser/extensions/scripting_permissions_modifier_unittest.cc
+++ b/chrome/browser/extensions/scripting_permissions_modifier_unittest.cc
@@ -58,22 +58,30 @@
       extension.permissions_data()->active_permissions().effective_hosts());
 }
 
+std::vector<std::string> GetScriptablePatternsAsStrings(
+    const Extension& extension) {
+  return GetPatternsAsStrings(
+      extension.permissions_data()->active_permissions().scriptable_hosts());
+}
+
+std::vector<std::string> GetExplicitPatternsAsStrings(
+    const Extension& extension) {
+  return GetPatternsAsStrings(
+      extension.permissions_data()->active_permissions().explicit_hosts());
+}
+
 scoped_refptr<const Extension> CreateExtensionWithPermissions(
-    const std::set<URLPattern>& scriptable_hosts,
-    const std::set<URLPattern>& explicit_hosts,
+    const URLPatternSet& scriptable_hosts,
+    const URLPatternSet& explicit_hosts,
     Manifest::Location location,
     const std::string& name) {
   ListBuilder scriptable_host_list;
-  for (std::set<URLPattern>::const_iterator pattern = scriptable_hosts.begin();
-       pattern != scriptable_hosts.end(); ++pattern) {
-    scriptable_host_list.Append(pattern->GetAsString());
-  }
+  for (const auto& pattern : scriptable_hosts)
+    scriptable_host_list.Append(pattern.GetAsString());
 
   ListBuilder explicit_host_list;
-  for (std::set<URLPattern>::const_iterator pattern = explicit_hosts.begin();
-       pattern != explicit_hosts.end(); ++pattern) {
-    explicit_host_list.Append(pattern->GetAsString());
-  }
+  for (const auto& pattern : explicit_hosts)
+    explicit_host_list.Append(pattern.GetAsString());
 
   DictionaryBuilder script;
   script.Set("matches", scriptable_host_list.Build())
@@ -94,31 +102,6 @@
       .Build();
 }
 
-// TODO(devlin): Implement this in terms of GetPatternsAsStrings().
-testing::AssertionResult SetsAreEqual(const std::set<URLPattern>& set1,
-                                      const std::set<URLPattern>& set2) {
-  // Take the (set1 - set2) U (set2 - set1). This is then the set of all
-  // elements which are in either set1 or set2, but not both.
-  // If the sets are equal, this is none.
-  std::set<URLPattern> difference = base::STLSetUnion<std::set<URLPattern>>(
-      base::STLSetDifference<std::set<URLPattern>>(set1, set2),
-      base::STLSetDifference<std::set<URLPattern>>(set2, set1));
-
-  std::string error;
-  for (std::set<URLPattern>::const_iterator iter = difference.begin();
-       iter != difference.end(); ++iter) {
-    if (iter->GetAsString() == "chrome://favicon/*")
-      continue;  // Grr... This is auto-added for extensions with <all_urls>
-    error = base::StringPrintf(
-        "%s\n%s contains %s and the other does not.", error.c_str(),
-        (set1.count(*iter) ? "Set1" : "Set2"), iter->GetAsString().c_str());
-  }
-
-  if (!error.empty())
-    return testing::AssertionFailure() << error;
-  return testing::AssertionSuccess();
-}
-
 class RuntimeHostPermissionsEnabledScope {
  public:
   RuntimeHostPermissionsEnabledScope() {
@@ -153,12 +136,15 @@
   for (const auto& test_case : test_cases) {
     std::string test_case_name = base::JoinString(test_case, ",");
     SCOPED_TRACE(test_case_name);
-    std::set<URLPattern> patterns;
+    URLPatternSet patterns;
     for (const auto& pattern : test_case)
-      patterns.insert(URLPattern(URLPattern::SCHEME_ALL, pattern));
+      patterns.AddPattern(URLPattern(URLPattern::SCHEME_ALL, pattern));
     scoped_refptr<const Extension> extension = CreateExtensionWithPermissions(
         patterns, patterns, Manifest::INTERNAL, test_case_name);
 
+    const std::vector<std::string> patterns_strings =
+        GetPatternsAsStrings(patterns);
+
     PermissionsUpdater(profile()).InitializePermissions(extension.get());
 
     const PermissionsData* permissions_data = extension->permissions_data();
@@ -167,62 +153,46 @@
     ASSERT_TRUE(modifier.CanAffectExtension());
 
     // By default, all permissions are granted.
-    EXPECT_TRUE(SetsAreEqual(
-        permissions_data->active_permissions().scriptable_hosts().patterns(),
-        patterns));
-    EXPECT_TRUE(SetsAreEqual(
-        permissions_data->active_permissions().explicit_hosts().patterns(),
-        patterns));
-    EXPECT_TRUE(permissions_data->withheld_permissions()
-                    .scriptable_hosts()
-                    .patterns()
-                    .empty());
-    EXPECT_TRUE(permissions_data->withheld_permissions()
-                    .explicit_hosts()
-                    .patterns()
-                    .empty());
+    EXPECT_THAT(GetScriptablePatternsAsStrings(*extension),
+                testing::UnorderedElementsAreArray(patterns_strings));
+    EXPECT_THAT(GetExplicitPatternsAsStrings(*extension),
+                testing::UnorderedElementsAreArray(patterns_strings));
+    EXPECT_TRUE(
+        permissions_data->withheld_permissions().scriptable_hosts().is_empty());
+    EXPECT_TRUE(
+        permissions_data->withheld_permissions().explicit_hosts().is_empty());
 
     // Then, withhold host permissions.
     modifier.SetWithholdHostPermissions(true);
 
-    EXPECT_TRUE(permissions_data->active_permissions()
-                    .scriptable_hosts()
-                    .patterns()
-                    .empty());
-    // Note: can't use explicit_hosts().empty() here, since chrome://favicon/
-    // will remain will still be present in explicit_hosts() (it's not really a
-    // host permission and isn't withheld). SetsAreEqual() ignores
-    // chrome://favicon in its checks.
-    EXPECT_TRUE(SetsAreEqual(
-        permissions_data->active_permissions().explicit_hosts().patterns(),
-        std::set<URLPattern>()));
+    // Note: We don't use URLPatternSet::is_empty() here, since
+    // chrome://favicon/ can still be present in the set (it's not really a
+    // host permission and isn't withheld). GetPatternsAsStrings() ignores
+    // chrome://favicon.
+    EXPECT_THAT(GetScriptablePatternsAsStrings(*extension), testing::IsEmpty());
+    EXPECT_THAT(GetExplicitPatternsAsStrings(*extension), testing::IsEmpty());
 
-    EXPECT_TRUE(SetsAreEqual(
-        permissions_data->withheld_permissions().scriptable_hosts().patterns(),
-        patterns));
-    EXPECT_TRUE(SetsAreEqual(
-        permissions_data->withheld_permissions().explicit_hosts().patterns(),
-        patterns));
+    EXPECT_THAT(
+        GetPatternsAsStrings(
+            permissions_data->withheld_permissions().scriptable_hosts()),
+        testing::UnorderedElementsAreArray(patterns_strings));
+    EXPECT_THAT(GetPatternsAsStrings(
+                    permissions_data->withheld_permissions().explicit_hosts()),
+                testing::UnorderedElementsAreArray(patterns_strings));
 
     // Finally, re-grant the withheld permissions.
     modifier.SetWithholdHostPermissions(false);
 
     // We should be back to our initial state - all requested permissions are
     // granted.
-    EXPECT_TRUE(SetsAreEqual(
-        permissions_data->active_permissions().scriptable_hosts().patterns(),
-        patterns));
-    EXPECT_TRUE(SetsAreEqual(
-        permissions_data->active_permissions().explicit_hosts().patterns(),
-        patterns));
-    EXPECT_TRUE(permissions_data->withheld_permissions()
-                    .scriptable_hosts()
-                    .patterns()
-                    .empty());
-    EXPECT_TRUE(permissions_data->withheld_permissions()
-                    .explicit_hosts()
-                    .patterns()
-                    .empty());
+    EXPECT_THAT(GetScriptablePatternsAsStrings(*extension),
+                testing::UnorderedElementsAreArray(patterns_strings));
+    EXPECT_THAT(GetExplicitPatternsAsStrings(*extension),
+                testing::UnorderedElementsAreArray(patterns_strings));
+    EXPECT_TRUE(
+        permissions_data->withheld_permissions().scriptable_hosts().is_empty());
+    EXPECT_TRUE(
+        permissions_data->withheld_permissions().explicit_hosts().is_empty());
   }
 }
 
@@ -232,54 +202,49 @@
   // Permissions can only be withheld with the appropriate feature turned on.
   auto enabled_scope = std::make_unique<RuntimeHostPermissionsEnabledScope>();
 
-  URLPattern all_hosts(URLPattern::SCHEME_ALL, "<all_urls>");
-  std::set<URLPattern> all_host_patterns;
-  all_host_patterns.insert(all_hosts);
+  URLPatternSet all_hosts_patterns(
+      {URLPattern(URLPattern::SCHEME_ALL, URLPattern::kAllUrlsPattern)});
 
   scoped_refptr<const Extension> extension = CreateExtensionWithPermissions(
-      all_host_patterns, all_host_patterns, Manifest::INTERNAL, "a");
+      all_hosts_patterns, all_hosts_patterns, Manifest::INTERNAL, "a");
   PermissionsUpdater updater(profile());
   updater.InitializePermissions(extension.get());
   const PermissionsData* permissions_data = extension->permissions_data();
 
   // By default, the extension should have all its permissions.
-  EXPECT_TRUE(SetsAreEqual(
-      permissions_data->active_permissions().scriptable_hosts().patterns(),
-      all_host_patterns));
+  EXPECT_THAT(GetEffectivePatternsAsStrings(*extension),
+              testing::UnorderedElementsAre(URLPattern::kAllUrlsPattern));
   EXPECT_TRUE(
-      permissions_data->withheld_permissions().scriptable_hosts().is_empty());
+      permissions_data->withheld_permissions().effective_hosts().is_empty());
   ScriptingPermissionsModifier modifier(profile(), extension);
   EXPECT_FALSE(modifier.HasWithheldHostPermissions());
 
   // Revoke access.
   modifier.SetWithholdHostPermissions(true);
   EXPECT_TRUE(modifier.HasWithheldHostPermissions());
-  EXPECT_TRUE(
-      permissions_data->active_permissions().scriptable_hosts().is_empty());
-  EXPECT_TRUE(SetsAreEqual(
-      permissions_data->withheld_permissions().scriptable_hosts().patterns(),
-      all_host_patterns));
+  EXPECT_THAT(GetEffectivePatternsAsStrings(*extension), testing::IsEmpty());
+  EXPECT_THAT(GetPatternsAsStrings(
+                  permissions_data->withheld_permissions().effective_hosts()),
+              testing::UnorderedElementsAre(URLPattern::kAllUrlsPattern));
 
   // Remove the switch. The extension should have permission again.
   enabled_scope.reset();
   updater.InitializePermissions(extension.get());
   EXPECT_FALSE(modifier.CanAffectExtension());
-  EXPECT_TRUE(SetsAreEqual(
-      permissions_data->active_permissions().scriptable_hosts().patterns(),
-      all_host_patterns));
+  EXPECT_THAT(GetEffectivePatternsAsStrings(*extension),
+              testing::UnorderedElementsAre(URLPattern::kAllUrlsPattern));
   EXPECT_TRUE(
-      permissions_data->withheld_permissions().scriptable_hosts().is_empty());
+      permissions_data->withheld_permissions().effective_hosts().is_empty());
 
   // Reapply the switch; the extension should go back to having permissions
   // withheld.
   enabled_scope = std::make_unique<RuntimeHostPermissionsEnabledScope>();
   updater.InitializePermissions(extension.get());
   EXPECT_TRUE(modifier.HasWithheldHostPermissions());
-  EXPECT_TRUE(
-      permissions_data->active_permissions().scriptable_hosts().is_empty());
-  EXPECT_TRUE(SetsAreEqual(
-      permissions_data->withheld_permissions().scriptable_hosts().patterns(),
-      all_host_patterns));
+  EXPECT_THAT(GetEffectivePatternsAsStrings(*extension), testing::IsEmpty());
+  EXPECT_THAT(GetPatternsAsStrings(
+                  permissions_data->withheld_permissions().effective_hosts()),
+              testing::UnorderedElementsAre(URLPattern::kAllUrlsPattern));
 }
 
 TEST_F(ScriptingPermissionsModifierUnitTest, GrantHostPermission) {
@@ -288,12 +253,11 @@
   // Permissions can only be withheld with the appropriate feature turned on.
   RuntimeHostPermissionsEnabledScope enabled_scope;
 
-  URLPattern all_hosts(URLPattern::SCHEME_ALL, "<all_urls>");
-  std::set<URLPattern> all_host_patterns;
-  all_host_patterns.insert(all_hosts);
+  URLPatternSet all_hosts_patterns(
+      {URLPattern(URLPattern::SCHEME_ALL, URLPattern::kAllUrlsPattern)});
 
   scoped_refptr<const Extension> extension = CreateExtensionWithPermissions(
-      all_host_patterns, all_host_patterns, Manifest::INTERNAL, "extension");
+      all_hosts_patterns, all_hosts_patterns, Manifest::INTERNAL, "extension");
   PermissionsUpdater(profile()).InitializePermissions(extension.get());
 
   ScriptingPermissionsModifier modifier(profile(), extension);
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 26cd8bf..eca27cb 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -198,6 +198,12 @@
 const char kCloudImportName[] = "Cloud Import";
 const char kCloudImportDescription[] = "Allows the cloud-import feature.";
 
+const char kCloudPrinterHandlerName[] = "Enable Cloud Printer Handler";
+const char kCloudPrinterHandlerDescription[] =
+    "Use the new cloud printer handler for communicating with the cloud "
+    "print server, instead of the cloud print interface in the Print "
+    "Preview WebUI.";
+
 const char kForceColorProfileSRGB[] = "sRGB";
 const char kForceColorProfileP3[] = "Display P3 D65";
 const char kForceColorProfileColorSpin[] = "Color spin with gamma 2.4";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index a740d21..eee3be3c1 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -146,6 +146,9 @@
 extern const char kCloudImportName[];
 extern const char kCloudImportDescription[];
 
+extern const char kCloudPrinterHandlerName[];
+extern const char kCloudPrinterHandlerDescription[];
+
 extern const char kForceColorProfileSRGB[];
 extern const char kForceColorProfileP3[];
 extern const char kForceColorProfileColorSpin[];
diff --git a/chrome/browser/net/network_connection_tracker_browsertest.cc b/chrome/browser/net/network_connection_tracker_browsertest.cc
index 7e28b03..38937f6b 100644
--- a/chrome/browser/net/network_connection_tracker_browsertest.cc
+++ b/chrome/browser/net/network_connection_tracker_browsertest.cc
@@ -3,20 +3,14 @@
 // found in the LICENSE file.
 
 #include "base/callback_forward.h"
-#include "base/feature_list.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
-#include "base/sequence_checker.h"
-#include "base/test/bind_test_util.h"
+#include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process_impl.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/test/base/in_process_browser_test.h"
-#include "content/public/browser/browser_context.h"
 #include "content/public/browser/network_connection_tracker.h"
-#include "content/public/browser/storage_partition.h"
 #include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/test/browser_test.h"
@@ -36,9 +30,7 @@
   explicit TestNetworkConnectionObserver(NetworkConnectionTracker* tracker)
       : num_notifications_(0),
         tracker_(tracker),
-        run_loop_(std::make_unique<base::RunLoop>()),
         connection_type_(network::mojom::ConnectionType::CONNECTION_UNKNOWN) {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     tracker_->AddNetworkConnectionObserver(this);
   }
 
@@ -48,7 +40,6 @@
 
   // NetworkConnectionObserver implementation:
   void OnConnectionChanged(network::mojom::ConnectionType type) override {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     network::mojom::ConnectionType queried_type;
     bool sync = tracker_->GetConnectionType(
         &queried_type,
@@ -58,13 +49,10 @@
 
     num_notifications_++;
     connection_type_ = type;
-    run_loop_->Quit();
+    run_loop_.Quit();
   }
 
-  void WaitForNotification() {
-    run_loop_->Run();
-    run_loop_ = std::make_unique<base::RunLoop>();
-  }
+  void WaitForNotification() { run_loop_.Run(); }
 
   size_t num_notifications() const { return num_notifications_; }
   network::mojom::ConnectionType connection_type() const {
@@ -74,21 +62,27 @@
  private:
   size_t num_notifications_;
   NetworkConnectionTracker* tracker_;
-  std::unique_ptr<base::RunLoop> run_loop_;
+  base::RunLoop run_loop_;
   network::mojom::ConnectionType connection_type_;
 
-  SEQUENCE_CHECKER(sequence_checker_);
-
   DISALLOW_COPY_AND_ASSIGN(TestNetworkConnectionObserver);
 };
 
 }  // namespace
 
-class NetworkConnectionTrackerBrowserTest : public InProcessBrowserTest {
+class NetworkConnectionTrackerBrowserTest
+    : public InProcessBrowserTest,
+      public testing::WithParamInterface<bool> {
  public:
-  NetworkConnectionTrackerBrowserTest()
-      : network_service_enabled_(
-            base::FeatureList::IsEnabled(network::features::kNetworkService)) {}
+  NetworkConnectionTrackerBrowserTest() : network_service_enabled_(GetParam()) {
+    if (network_service_enabled_) {
+      scoped_feature_list_.InitAndEnableFeature(
+          network::features::kNetworkService);
+    } else {
+      scoped_feature_list_.InitAndDisableFeature(
+          network::features::kNetworkService);
+    }
+  }
   ~NetworkConnectionTrackerBrowserTest() override {}
 
   // Simulates a network connection change.
@@ -112,11 +106,12 @@
   bool network_service_enabled() const { return network_service_enabled_; }
 
  private:
+  base::test::ScopedFeatureList scoped_feature_list_;
   const bool network_service_enabled_;
 };
 
 // Basic test to make sure NetworkConnectionTracker is set up.
-IN_PROC_BROWSER_TEST_F(NetworkConnectionTrackerBrowserTest,
+IN_PROC_BROWSER_TEST_P(NetworkConnectionTrackerBrowserTest,
                        NetworkConnectionTracker) {
 #if defined(OS_CHROMEOS) || defined(OS_MACOSX)
   // NetworkService on ChromeOS doesn't yet have a NetworkChangeManager
@@ -151,56 +146,8 @@
   EXPECT_EQ(1u, network_connection_observer.num_notifications());
 }
 
-// Simulates a network service crash, and ensures that network change manager
-// binds to the restarted network service.
-IN_PROC_BROWSER_TEST_F(NetworkConnectionTrackerBrowserTest,
-                       SimulateNetworkServiceCrash) {
-  // Out-of-process network service is not enabled, so network service's crash
-  // and restart aren't applicable.
-  if (!network_service_enabled())
-    return;
-
-  NetworkConnectionTracker* tracker =
-      g_browser_process->network_connection_tracker();
-  EXPECT_NE(nullptr, tracker);
-
-  // Issue a GetConnectionType() request to make sure NetworkService has been
-  // started up. This way, NetworkService will receive the broadcast when
-  // SimulateNetworkChange() is called.
-  base::RunLoop run_loop;
-  network::mojom::ConnectionType ignored_type;
-  bool sync = tracker->GetConnectionType(
-      &ignored_type,
-      base::BindOnce(
-          [](base::RunLoop* run_loop, network::mojom::ConnectionType type) {
-            run_loop->Quit();
-          },
-          base::Unretained(&run_loop)));
-  if (!sync)
-    run_loop.Run();
-
-  TestNetworkConnectionObserver network_connection_observer(tracker);
-  SimulateNetworkChange(network::mojom::ConnectionType::CONNECTION_3G);
-
-  network_connection_observer.WaitForNotification();
-  EXPECT_EQ(network::mojom::ConnectionType::CONNECTION_3G,
-            network_connection_observer.connection_type());
-  // Wait a bit longer to make sure only 1 notification is received and that
-  // there is no duplicate notification.
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(1u, network_connection_observer.num_notifications());
-
-  SimulateNetworkServiceCrash();
-
-  SimulateNetworkChange(network::mojom::ConnectionType::CONNECTION_2G);
-  network_connection_observer.WaitForNotification();
-  EXPECT_EQ(network::mojom::ConnectionType::CONNECTION_2G,
-            network_connection_observer.connection_type());
-
-  // Wait a bit longer to make sure only 2 notifications are received.
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_EQ(2u, network_connection_observer.num_notifications());
-}
+INSTANTIATE_TEST_CASE_P(/* no prefix */,
+                        NetworkConnectionTrackerBrowserTest,
+                        testing::Bool());
 
 }  // namespace content
diff --git a/chrome/browser/net/network_quality_tracker_browsertest.cc b/chrome/browser/net/network_quality_tracker_browsertest.cc
index 2f143ba9..94004ef6 100644
--- a/chrome/browser/net/network_quality_tracker_browsertest.cc
+++ b/chrome/browser/net/network_quality_tracker_browsertest.cc
@@ -113,6 +113,13 @@
   NetworkQualityTrackerBrowserTest()
       : network_service_enabled_(
             base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+    if (network_service_enabled_) {
+      scoped_feature_list_.InitAndEnableFeature(
+          network::features::kNetworkService);
+    } else {
+      scoped_feature_list_.InitAndDisableFeature(
+          network::features::kNetworkService);
+    }
   }
   ~NetworkQualityTrackerBrowserTest() override {}
 
@@ -147,6 +154,7 @@
   bool network_service_enabled() const { return network_service_enabled_; }
 
  private:
+  base::test::ScopedFeatureList scoped_feature_list_;
   const bool network_service_enabled_;
 };
 
diff --git a/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.cc
new file mode 100644
index 0000000..7a720fc
--- /dev/null
+++ b/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.cc
@@ -0,0 +1,60 @@
+// Copyright 2018 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/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.h"
+
+#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h"
+#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h"
+#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/web_contents.h"
+#include "url/gurl.h"
+
+DataSaverSiteBreakdownMetricsObserver::DataSaverSiteBreakdownMetricsObserver() =
+    default;
+
+DataSaverSiteBreakdownMetricsObserver::
+    ~DataSaverSiteBreakdownMetricsObserver() = default;
+
+page_load_metrics::PageLoadMetricsObserver::ObservePolicy
+DataSaverSiteBreakdownMetricsObserver::OnCommit(
+    content::NavigationHandle* navigation_handle,
+    ukm::SourceId source_id) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (!data_reduction_proxy::params::IsDataSaverSiteBreakdownUsingPLMEnabled())
+    return STOP_OBSERVING;
+
+  // This BrowserContext is valid for the lifetime of
+  // DataReductionProxyMetricsObserver. BrowserContext is always valid and
+  // non-nullptr in NavigationControllerImpl, which is a member of WebContents.
+  // A raw pointer to BrowserContext taken at this point will be valid until
+  // after WebContent's destructor. The latest that PageLoadTracker's destructor
+  // will be called is in MetricsWebContentsObserver's destructor, which is
+  // called in WebContents destructor.
+  browser_context_ = navigation_handle->GetWebContents()->GetBrowserContext();
+  committed_host_ = navigation_handle->GetURL().HostNoBrackets();
+  return CONTINUE_OBSERVING;
+}
+
+void DataSaverSiteBreakdownMetricsObserver::OnDataUseObserved(
+    int64_t received_data_length,
+    int64_t data_reduction_proxy_bytes_saved) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  data_reduction_proxy::DataReductionProxySettings*
+      data_reduction_proxy_settings =
+          DataReductionProxyChromeSettingsFactory::GetForBrowserContext(
+              browser_context_);
+  if (data_reduction_proxy_settings &&
+      data_reduction_proxy_settings->data_reduction_proxy_service()) {
+    DCHECK(!committed_host_.empty());
+    data_reduction_proxy_settings->data_reduction_proxy_service()
+        ->UpdateDataUseForHost(
+            received_data_length,
+            received_data_length + data_reduction_proxy_bytes_saved,
+            committed_host_);
+  }
+}
diff --git a/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.h b/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.h
new file mode 100644
index 0000000..c7d3f50
--- /dev/null
+++ b/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.h
@@ -0,0 +1,46 @@
+// Copyright 2018 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_PAGE_LOAD_METRICS_OBSERVERS_DATA_SAVER_SITE_BREAKDOWN_METRICS_OBSERVER_H_
+#define CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_DATA_SAVER_SITE_BREAKDOWN_METRICS_OBSERVER_H_
+
+#include <stdint.h>
+#include <string>
+
+#include "base/macros.h"
+#include "base/sequence_checker.h"
+#include "chrome/browser/page_load_metrics/page_load_metrics_observer.h"
+#include "services/metrics/public/cpp/ukm_source_id.h"
+
+namespace content {
+class BrowserContext;
+class NavigationHandle;
+}  // namespace content
+
+// Observer responsible for recording data usage per site to the data reduction
+// proxy database.
+class DataSaverSiteBreakdownMetricsObserver
+    : public page_load_metrics::PageLoadMetricsObserver {
+ public:
+  DataSaverSiteBreakdownMetricsObserver();
+  ~DataSaverSiteBreakdownMetricsObserver() override;
+
+ private:
+  ObservePolicy OnCommit(content::NavigationHandle* navigation_handle,
+                         ukm::SourceId source_id) override;
+
+  void OnDataUseObserved(int64_t received_data_length,
+                         int64_t data_reduction_proxy_bytes_saved) override;
+
+  std::string committed_host_;
+
+  // The browser context this navigation is operating in.
+  content::BrowserContext* browser_context_ = nullptr;
+
+  SEQUENCE_CHECKER(sequence_checker_);
+
+  DISALLOW_COPY_AND_ASSIGN(DataSaverSiteBreakdownMetricsObserver);
+};
+
+#endif  // CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_DATA_SAVER_SITE_BREAKDOWN_METRICS_OBSERVER_H_
diff --git a/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc
new file mode 100644
index 0000000..cf5fdc3
--- /dev/null
+++ b/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc
@@ -0,0 +1,104 @@
+// Copyright 2018 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 <stdint.h>
+#include <string>
+
+#include "base/command_line.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_feature_list.h"
+#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h"
+#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h"
+#include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h"
+#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
+#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
+#include "components/data_reduction_proxy/proto/data_store.pb.h"
+#include "components/prefs/pref_service.h"
+#include "content/public/test/browser_test_base.h"
+#include "content/public/test/browser_test_utils.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class DataSaverSiteBreakdownMetricsObserverBrowserTest
+    : public InProcessBrowserTest {
+ protected:
+  void EnableDataSaver() {
+    PrefService* prefs = browser()->profile()->GetPrefs();
+    prefs->SetBoolean(prefs::kDataSaverEnabled, true);
+    prefs->SetBoolean(data_reduction_proxy::prefs::kDataUsageReportingEnabled,
+                      true);
+    // Give the setting notification a chance to propagate.
+    base::RunLoop().RunUntilIdle();
+  }
+
+  void SetUp() override {
+    scoped_feature_list_.InitAndEnableFeature(
+        data_reduction_proxy::features::
+            kDataSaverSiteBreakdownUsingPageLoadMetrics);
+    InProcessBrowserTest::SetUp();
+  }
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    command_line->AppendSwitch(
+        data_reduction_proxy::switches::kEnableDataReductionProxy);
+  }
+
+  // Gets the data usage recorded against the host the embedded server runs on.
+  uint64_t GetDataUsage() {
+    const auto& data_usage_map =
+        DataReductionProxyChromeSettingsFactory::GetForBrowserContext(
+            browser()->profile())
+            ->data_reduction_proxy_service()
+            ->compression_stats()
+            ->DataUsageMapForTesting();
+    const auto& it =
+        data_usage_map.find(embedded_test_server()->host_port_pair().host());
+    if (it != data_usage_map.end())
+      return it->second->data_used();
+    return 0;
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(DataSaverSiteBreakdownMetricsObserverBrowserTest,
+                       NavigateToSimplePage) {
+  const struct {
+    std::string url;
+    size_t expected_min_page_size;
+    size_t expected_max_page_size;
+  } tests[] = {
+      // The range of the pages is calculated approximately from the html size
+      // and the size of the subresources it includes.
+      {"/google/google.html", 5000, 20000},
+      {"/simple.html", 100, 1000},
+      {"/media/youtube.html", 5000, 20000},
+  };
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  EnableDataSaver();
+  for (const auto& test : tests) {
+    uint64_t data_usage_before_navigation = GetDataUsage();
+    ui_test_utils::NavigateToURL(browser(),
+                                 embedded_test_server()->GetURL(test.url));
+
+    base::RunLoop().RunUntilIdle();
+    // Navigate away to force the histogram recording.
+    ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
+
+    EXPECT_LE(test.expected_min_page_size,
+              GetDataUsage() - data_usage_before_navigation);
+    EXPECT_GE(test.expected_max_page_size,
+              GetDataUsage() - data_usage_before_navigation);
+  }
+}
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc b/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc
index 11ca710..4cd8abe 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/observers/css_scanning_page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer.h"
+#include "chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.h"
@@ -118,6 +119,8 @@
     tracker->AddObserver(std::make_unique<ProtocolPageLoadMetricsObserver>());
     tracker->AddObserver(std::make_unique<TabRestorePageLoadMetricsObserver>());
     tracker->AddObserver(std::make_unique<UseCounterPageLoadMetricsObserver>());
+    tracker->AddObserver(
+        std::make_unique<DataSaverSiteBreakdownMetricsObserver>());
     std::unique_ptr<AdsPageLoadMetricsObserver> ads_observer =
         AdsPageLoadMetricsObserver::CreateIfNeeded();
     if (ads_observer)
diff --git a/chrome/browser/profiles/profile_browsertest.cc b/chrome/browser/profiles/profile_browsertest.cc
index 577f3c8..69270d03 100644
--- a/chrome/browser/profiles/profile_browsertest.cc
+++ b/chrome/browser/profiles/profile_browsertest.cc
@@ -9,8 +9,6 @@
 #include <memory>
 
 #include "base/command_line.h"
-#include "base/files/file_path.h"
-#include "base/files/file_path_watcher.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/json/json_reader.h"
@@ -37,7 +35,6 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_features.h"
-#include "chrome/common/chrome_paths.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
@@ -849,109 +846,3 @@
       net::LOAD_ONLY_FROM_CACHE);
   url_fetcher_delegate3.WaitForCompletion();
 }
-
-// Create a media cache file, and make sure it's deleted by the time the next
-// test runs.
-IN_PROC_BROWSER_TEST_F(ProfileWithoutMediaCacheBrowserTest,
-                       PRE_DeleteMediaCache) {
-  base::FilePath media_cache_path =
-      browser()->profile()->GetPath().Append(chrome::kMediaCacheDirname);
-
-  base::ScopedAllowBlockingForTesting allow_blocking;
-  EXPECT_TRUE(base::CreateDirectory(media_cache_path));
-  std::string data = "foo";
-  base::WriteFile(media_cache_path.AppendASCII("foo"), data.c_str(),
-                  data.size());
-}
-
-IN_PROC_BROWSER_TEST_F(ProfileWithoutMediaCacheBrowserTest, DeleteMediaCache) {
-  base::FilePath media_cache_path =
-      browser()->profile()->GetPath().Append(chrome::kMediaCacheDirname);
-
-  base::ScopedAllowBlockingForTesting allow_blocking;
-
-  // Wait until the file is deleted. Unfortunately, there's no way to wait until
-  // the deletion itself has run directly, so there are several possible orders
-  // of events that this code must handle:
-  //
-  // * In PRE_DeleteMediaCache, the media cache was deleted before the test
-  // completed, by the task posted on Profile creation.
-  //
-  // * In DeleteMediaCache, the media cache was deleted by the delete media
-  // cache task before starting the FilePathWatcher.
-  //
-  // * In DeleteMediaCache, the media cache was deleted by the delete media
-  // cache task after starting the FilePathWatcher.
-  //
-  // It also may be possible to get a notification of the media cache being
-  // created from the PRE_DeleteMediaCache test, so allow multiple watch events
-  // to happen.
-  while (true) {
-    base::RunLoop run_loop;
-    base::FilePathWatcher watcher;
-    EXPECT_TRUE(watcher.Watch(media_cache_path, false /* recursive */,
-                              base::BindRepeating(
-                                  [](base::RunLoop* run_loop,
-                                     const base::FilePath& path, bool error) {
-                                    EXPECT_FALSE(error);
-                                    run_loop->Quit();
-                                  },
-                                  &run_loop)));
-    if (!base::PathExists(media_cache_path))
-      return;
-    run_loop.Run();
-  }
-}
-
-// Create a media cache file, and make sure it's deleted by initializing an
-// extension browser context.
-IN_PROC_BROWSER_TEST_F(ProfileWithoutMediaCacheBrowserTest,
-                       PRE_DeleteIsolatedAppMediaCache) {
-  scoped_refptr<const extensions::Extension> app =
-      BuildTestApp(browser()->profile());
-  content::StoragePartition* extension_partition =
-      content::BrowserContext::GetStoragePartitionForSite(
-          browser()->profile(),
-          extensions::Extension::GetBaseURLFromExtensionId(app->id()));
-
-  base::FilePath extension_media_cache_path =
-      extension_partition->GetPath().Append(chrome::kMediaCacheDirname);
-
-  base::ScopedAllowBlockingForTesting allow_blocking;
-  EXPECT_TRUE(base::CreateDirectory(extension_media_cache_path));
-  std::string data = "foo";
-  base::WriteFile(extension_media_cache_path.AppendASCII("foo"), data.c_str(),
-                  data.size());
-}
-
-IN_PROC_BROWSER_TEST_F(ProfileWithoutMediaCacheBrowserTest,
-                       DeleteIsolatedAppMediaCache) {
-  scoped_refptr<const extensions::Extension> app =
-      BuildTestApp(browser()->profile());
-  content::StoragePartition* extension_partition =
-      content::BrowserContext::GetStoragePartitionForSite(
-          browser()->profile(),
-          extensions::Extension::GetBaseURLFromExtensionId(app->id()));
-
-  base::FilePath extension_media_cache_path =
-      extension_partition->GetPath().Append(chrome::kMediaCacheDirname);
-
-  // As with the DeleteMediaCache test, have to allow for a lot of different
-  // deletion orderings here.
-  base::ScopedAllowBlockingForTesting allow_blocking;
-  while (true) {
-    base::RunLoop run_loop;
-    base::FilePathWatcher watcher;
-    EXPECT_TRUE(watcher.Watch(extension_media_cache_path, false /* recursive */,
-                              base::BindRepeating(
-                                  [](base::RunLoop* run_loop,
-                                     const base::FilePath& path, bool error) {
-                                    EXPECT_FALSE(error);
-                                    run_loop->Quit();
-                                  },
-                                  &run_loop)));
-    if (!base::PathExists(extension_media_cache_path))
-      return;
-    run_loop.Run();
-  }
-}
diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc
index 626eec0..6c631999 100644
--- a/chrome/browser/profiles/profile_impl_io_data.cc
+++ b/chrome/browser/profiles/profile_impl_io_data.cc
@@ -12,8 +12,6 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/feature_list.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/metrics/field_trial.h"
@@ -21,7 +19,6 @@
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/task_scheduler/post_task.h"
-#include "base/task_scheduler/task_traits.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -115,19 +112,6 @@
   return net::CACHE_BACKEND_DEFAULT;
 }
 
-void MaybeDeleteMediaCache(const base::FilePath& media_cache_path) {
-  if (!base::FeatureList::IsEnabled(features::kUseSameCacheForMedia) ||
-      media_cache_path.empty()) {
-    return;
-  }
-  base::PostTaskWithTraits(
-      FROM_HERE,
-      {base::TaskPriority::BACKGROUND, base::MayBlock(),
-       base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
-      base::BindOnce(base::IgnoreResult(&base::DeleteFile), media_cache_path,
-                     true /* recursive */));
-}
-
 }  // namespace
 
 using content::BrowserThread;
@@ -536,8 +520,6 @@
   InitializeExtensionsRequestContext(profile_params);
 #endif
 
-  MaybeDeleteMediaCache(lazy_params_->media_cache_path);
-
   // Create a media request context based on the main context, but using a
   // media cache.  It shares the same job factory as the main context.
   StoragePartitionDescriptor details(profile_path_, false);
@@ -571,11 +553,6 @@
         protocol_handler_interceptor,
     content::ProtocolHandlerMap* protocol_handlers,
     content::URLRequestInterceptorScopedVector request_interceptors) const {
-  if (!partition_descriptor.in_memory) {
-    MaybeDeleteMediaCache(
-        partition_descriptor.path.Append(chrome::kMediaCacheDirname));
-  }
-
   // Copy most state from the main context.
   AppRequestContext* context = new AppRequestContext();
   context->CopyFrom(main_context);
diff --git a/chrome/browser/resources/print_preview/data/destination_store.js b/chrome/browser/resources/print_preview/data/destination_store.js
index c78e7b5..eaf08652 100644
--- a/chrome/browser/resources/print_preview/data/destination_store.js
+++ b/chrome/browser/resources/print_preview/data/destination_store.js
@@ -884,10 +884,10 @@
         print_preview.PrinterType.LOCAL_PRINTER,
       ];
 
-      // If the network service is enabled, request cloud printers from the
-      // handler instead of trying to directly communicate with the cloud print
-      // server, which will cause a crash. See https://crbug.com/848987.
-      if (loadTimeData.getBoolean('networkServiceEnabled'))
+      // If the cloud printer handler is enabled, request cloud printers from
+      // the handler instead of trying to directly communicate with the cloud
+      // print server. See https://crbug.com/829414.
+      if (loadTimeData.getBoolean('cloudPrinterHandlerEnabled'))
         types.push(print_preview.PrinterType.CLOUD_PRINTER);
       else
         this.startLoadCloudDestinations();
diff --git a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html
index 7117925..2a309a7a 100644
--- a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html
+++ b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html
@@ -83,7 +83,7 @@
         </iron-icon>
       </div>
       <div class="start">
-        <div role="status">[[title_]]</div>
+        <div id="status-title" role="status" inner-h-t-m-l="[[title_]]"></div>
         <div hidden="[[!showExplanation_]]">
           <span class="secondary">[[explanation_]]</span>
         </div>
diff --git a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js
index 5b54332c..8c632925 100644
--- a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js
+++ b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js
@@ -746,7 +746,7 @@
       ],
       [
         settings.ChromeCleanerCardState.CLEANUP_SUCCEEDED, {
-          title: this.i18n('chromeCleanupTitleRemoved'),
+          title: this.i18nAdvanced('chromeCleanupTitleRemoved', {tags: ['a']}),
           explanation: null,
           icon: icons.DONE,
           actionButton: null,
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_service_unittest.cc b/chrome/browser/search/one_google_bar/one_google_bar_service_unittest.cc
index 806617a..7b3d5022 100644
--- a/chrome/browser/search/one_google_bar/one_google_bar_service_unittest.cc
+++ b/chrome/browser/search/one_google_bar/one_google_bar_service_unittest.cc
@@ -19,7 +19,6 @@
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "google_apis/gaia/fake_oauth2_token_service.h"
 #include "google_apis/gaia/gaia_constants.h"
-#include "net/url_request/test_url_fetcher_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -58,7 +57,6 @@
  public:
   OneGoogleBarServiceTest()
       : signin_client_(&pref_service_),
-        fetcher_factory_(/*default_factory=*/nullptr),
         cookie_service_(&token_service_,
                         GaiaConstants::kChromeSource,
                         &signin_client_) {
@@ -66,8 +64,6 @@
     // which access prefs.
     AccountTrackerService::RegisterPrefs(pref_service_.registry());
 
-    cookie_service_.Init(&fetcher_factory_);
-
     auto loader = std::make_unique<FakeOneGoogleBarLoader>();
     loader_ = loader.get();
     service_ = std::make_unique<OneGoogleBarService>(&cookie_service_,
@@ -96,7 +92,6 @@
   sync_preferences::TestingPrefServiceSyncable pref_service_;
   TestSigninClient signin_client_;
   FakeOAuth2TokenService token_service_;
-  net::FakeURLFetcherFactory fetcher_factory_;
   FakeGaiaCookieManagerService cookie_service_;
 
   // Owned by the service.
diff --git a/chrome/browser/signin/dice_response_handler_unittest.cc b/chrome/browser/signin/dice_response_handler_unittest.cc
index 6de384d..534c0e9 100644
--- a/chrome/browser/signin/dice_response_handler_unittest.cc
+++ b/chrome/browser/signin/dice_response_handler_unittest.cc
@@ -130,7 +130,8 @@
                         &signin_error_controller_),
         cookie_service_(&token_service_,
                         GaiaConstants::kChromeSource,
-                        &signin_client_),
+                        &signin_client_,
+                        /*use_fake_url_fetcher=*/false),
         about_signin_internals_(&token_service_,
                                 &account_tracker_service_,
                                 &signin_manager_,
diff --git a/chrome/browser/signin/fake_gaia_cookie_manager_service_builder.cc b/chrome/browser/signin/fake_gaia_cookie_manager_service_builder.cc
index 65b3997..f30ff80 100644
--- a/chrome/browser/signin/fake_gaia_cookie_manager_service_builder.cc
+++ b/chrome/browser/signin/fake_gaia_cookie_manager_service_builder.cc
@@ -12,12 +12,28 @@
 #include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "google_apis/gaia/gaia_constants.h"
 
-// static
-std::unique_ptr<KeyedService> BuildFakeGaiaCookieManagerService(
-    content::BrowserContext* context) {
+namespace {
+
+std::unique_ptr<KeyedService> BuildFakeGaiaCookieManagerServiceImpl(
+    content::BrowserContext* context,
+    bool use_fake_url_fetcher) {
   Profile* profile = Profile::FromBrowserContext(context);
   return std::make_unique<FakeGaiaCookieManagerService>(
       ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
       GaiaConstants::kChromeSource,
-      ChromeSigninClientFactory::GetForProfile(profile));
+      ChromeSigninClientFactory::GetForProfile(profile), use_fake_url_fetcher);
+}
+
+}  // namespace
+
+std::unique_ptr<KeyedService> BuildFakeGaiaCookieManagerService(
+    content::BrowserContext* context) {
+  return BuildFakeGaiaCookieManagerServiceImpl(context,
+                                               /*use_fake_url_fetcher=*/true);
+}
+
+std::unique_ptr<KeyedService> BuildFakeGaiaCookieManagerServiceNoFakeUrlFetcher(
+    content::BrowserContext* context) {
+  return BuildFakeGaiaCookieManagerServiceImpl(context,
+                                               /*use_fake_url_fetcher=*/false);
 }
diff --git a/chrome/browser/signin/fake_gaia_cookie_manager_service_builder.h b/chrome/browser/signin/fake_gaia_cookie_manager_service_builder.h
index cbc53e2..be12279f 100644
--- a/chrome/browser/signin/fake_gaia_cookie_manager_service_builder.h
+++ b/chrome/browser/signin/fake_gaia_cookie_manager_service_builder.h
@@ -13,8 +13,11 @@
 class BrowserContext;
 }
 
-// Helper function to be used with KeyedService::SetTestingFactory().
+// Helper functions to be used with KeyedService::SetTestingFactory().
 std::unique_ptr<KeyedService> BuildFakeGaiaCookieManagerService(
     content::BrowserContext* context);
 
+std::unique_ptr<KeyedService> BuildFakeGaiaCookieManagerServiceNoFakeUrlFetcher(
+    content::BrowserContext* context);
+
 #endif  // CHROME_BROWSER_SIGNIN_FAKE_GAIA_COOKIE_MANAGER_SERVICE_BUILDER_H_
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 c7db3065..9c4985cf 100644
--- a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.cc
+++ b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.cc
@@ -580,6 +580,7 @@
                      GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
                          GoogleServiceAuthError::InvalidGaiaCredentialsReason::
                              CREDENTIALS_MISSING));
+    FireRefreshTokenAvailable(loading_primary_account_id_);
   }
 
 #ifndef NDEBUG
diff --git a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.h b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.h
index 0521640f..a0b69e504 100644
--- a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.h
+++ b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.h
@@ -128,6 +128,8 @@
   FRIEND_TEST_ALL_PREFIXES(MutableProfileOAuth2TokenServiceDelegateTest,
                            DelayedRevoke);
   FRIEND_TEST_ALL_PREFIXES(MutableProfileOAuth2TokenServiceDelegateTest,
+                           DiceMigrationHostedDomainPrimaryAccount);
+  FRIEND_TEST_ALL_PREFIXES(MutableProfileOAuth2TokenServiceDelegateTest,
                            ShutdownDuringRevoke);
   FRIEND_TEST_ALL_PREFIXES(MutableProfileOAuth2TokenServiceDelegateTest,
                            UpdateInvalidToken);
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 bf56d66..d7f6045 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
@@ -432,7 +432,16 @@
   EXPECT_EQ(1, start_batch_changes_);
   EXPECT_EQ(1, end_batch_changes_);
   EXPECT_EQ(1, auth_error_changed_count_);
-  ExpectOneTokensLoadedNotification();
+
+  // A"tokens loaded" notification should have been fired.
+  EXPECT_EQ(1, tokens_loaded_count_);
+
+  // As the delegate puts the primary account into the token map with an invalid
+  // token in the case of loading from an empty TB, a "token available"
+  // notification should have been fired as well.
+  EXPECT_EQ(1, token_available_count_);
+
+  ResetObserverCounts();
 
   // LoadCredentials() guarantees that the account given to it as argument
   // is in the refresh_token map.
@@ -718,14 +727,22 @@
   base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(1, tokens_loaded_count_);
-  EXPECT_EQ(0, token_available_count_);
   EXPECT_EQ(1, token_revoked_count_);
   EXPECT_EQ(1, start_batch_changes_);
   EXPECT_EQ(1, end_batch_changes_);
   EXPECT_EQ(1, auth_error_changed_count_);
+
+  // After having revoked the primary account's token during loading, the
+  // delegate should have noticed that it had no token for the primary account
+  // when the load was complete and inserted an invalid token for that account.
+  EXPECT_EQ(1, token_available_count_);
   EXPECT_TRUE(oauth2_service_delegate_->RefreshTokenIsAvailable(
       primary_account.account_id));
   EXPECT_EQ(
+      MutableProfileOAuth2TokenServiceDelegate::kInvalidRefreshToken,
+      oauth2_service_delegate_->refresh_tokens_[primary_account.account_id]
+          ->refresh_token());
+  EXPECT_EQ(
       GoogleServiceAuthError::InvalidGaiaCredentialsReason::CREDENTIALS_MISSING,
       oauth2_service_delegate_->GetAuthError(primary_account.account_id)
           .GetInvalidGaiaCredentialsReason());
diff --git a/chrome/browser/signin/signin_ui_util_unittest.cc b/chrome/browser/signin/signin_ui_util_unittest.cc
index 89250a0..45e90f4e 100644
--- a/chrome/browser/signin/signin_ui_util_unittest.cc
+++ b/chrome/browser/signin/signin_ui_util_unittest.cc
@@ -136,7 +136,7 @@
             {ProfileOAuth2TokenServiceFactory::GetInstance(),
              BuildFakeProfileOAuth2TokenService},
             {GaiaCookieManagerServiceFactory::GetInstance(),
-             BuildFakeGaiaCookieManagerService}};
+             BuildFakeGaiaCookieManagerServiceNoFakeUrlFetcher}};
   }
 
   // BrowserWithTestWindowTest:
diff --git a/chrome/browser/supervised_user/child_accounts/child_account_service_unittest.cc b/chrome/browser/supervised_user/child_accounts/child_account_service_unittest.cc
index 81c90eb..6f166ce9 100644
--- a/chrome/browser/supervised_user/child_accounts/child_account_service_unittest.cc
+++ b/chrome/browser/supervised_user/child_accounts/child_account_service_unittest.cc
@@ -13,7 +13,6 @@
 #include "components/signin/core/browser/test_signin_client.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_utils.h"
-#include "net/url_request/test_url_fetcher_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -26,7 +25,7 @@
 
 class ChildAccountServiceTest : public ::testing::Test {
  public:
-  ChildAccountServiceTest() : fake_url_fetcher_factory_(nullptr) {}
+  ChildAccountServiceTest() = default;
 
   void SetUp() override {
     ChromeSigninClientFactory::GetInstance()->SetTestingFactory(
@@ -35,13 +34,11 @@
         &profile_, &BuildFakeGaiaCookieManagerService);
     gaia_cookie_manager_service_ = static_cast<FakeGaiaCookieManagerService*>(
         GaiaCookieManagerServiceFactory::GetForProfile(&profile_));
-    gaia_cookie_manager_service_->Init(&fake_url_fetcher_factory_);
   }
 
  protected:
   content::TestBrowserThreadBundle thread_bundle_;
   TestingProfile profile_;
-  net::FakeURLFetcherFactory fake_url_fetcher_factory_;
   FakeGaiaCookieManagerService* gaia_cookie_manager_service_ = nullptr;
 };
 
diff --git a/chrome/browser/sync/profile_sync_service_factory.cc b/chrome/browser/sync/profile_sync_service_factory.cc
index c1a7621..f5435e3 100644
--- a/chrome/browser/sync/profile_sync_service_factory.cc
+++ b/chrome/browser/sync/profile_sync_service_factory.cc
@@ -28,6 +28,7 @@
 #include "chrome/browser/signin/gaia_cookie_manager_service_factory.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/signin/unified_consent_helper.h"
 #include "chrome/browser/spellchecker/spellcheck_factory.h"
 #include "chrome/browser/sync/chrome_sync_client.h"
 #include "chrome/browser/sync/sessions/sync_sessions_web_contents_router_factory.h"
@@ -184,6 +185,8 @@
           ->GetURLLoaderFactoryForBrowserProcess();
   init_params.debug_identifier = profile->GetDebugName();
   init_params.channel = chrome::GetChannel();
+  init_params.user_events_separate_pref_group =
+      IsUnifiedConsentEnabled(profile);
 
   if (!client_factory_) {
     init_params.sync_client =
diff --git a/chrome/browser/sync/test/integration/enable_disable_test.cc b/chrome/browser/sync/test/integration/enable_disable_test.cc
index ea29b99..585074d 100644
--- a/chrome/browser/sync/test/integration/enable_disable_test.cc
+++ b/chrome/browser/sync/test/integration/enable_disable_test.cc
@@ -26,6 +26,8 @@
 
 namespace {
 
+const bool kUserEventsSeparatePrefGroup = false;
+
 // Some types show up in multiple groups. This means that there are at least two
 // user selectable groups that will cause these types to become enabled. This
 // affects our tests because we cannot assume that before enabling a multi type
@@ -38,8 +40,8 @@
   ModelTypeSet multi;
   for (ModelTypeSet::Iterator si = selectable_types.First(); si.Good();
        si.Inc()) {
-    const ModelTypeSet grouped_types =
-        sync_prefs.ResolvePrefGroups(registered_types, ModelTypeSet(si.Get()));
+    const ModelTypeSet grouped_types = sync_prefs.ResolvePrefGroups(
+        registered_types, ModelTypeSet(si.Get()), kUserEventsSeparatePrefGroup);
     for (ModelTypeSet::Iterator gi = grouped_types.First(); gi.Good();
          gi.Inc()) {
       if (seen.Has(gi.Get())) {
@@ -108,7 +110,8 @@
 
   ModelTypeSet ResolveGroup(ModelType type) {
     return Difference(
-        sync_prefs_->ResolvePrefGroups(registered_types_, ModelTypeSet(type)),
+        sync_prefs_->ResolvePrefGroups(registered_types_, ModelTypeSet(type),
+                                       kUserEventsSeparatePrefGroup),
         ProxyTypes());
   }
 
diff --git a/chrome/browser/ui/autofill/local_card_migration_bubble_controller_impl.cc b/chrome/browser/ui/autofill/local_card_migration_bubble_controller_impl.cc
index 240919bb..99fd9a1 100644
--- a/chrome/browser/ui/autofill/local_card_migration_bubble_controller_impl.cc
+++ b/chrome/browser/ui/autofill/local_card_migration_bubble_controller_impl.cc
@@ -7,6 +7,7 @@
 #include <stddef.h>
 
 #include "chrome/browser/ui/autofill/local_card_migration_bubble.h"
+#include "chrome/browser/ui/autofill/popup_constants.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
@@ -21,13 +22,6 @@
 
 namespace autofill {
 
-namespace {
-// Number of seconds the bubble and icon will survive navigations, starting
-// from when the bubble is shown.
-// TODO(crbug.com/862397): Share with ManagePasswordsUIController.
-const int kSurviveNavigationSeconds = 5;
-}  // namespace
-
 // TODO(crbug.com/862405): Build a base class for this
 // and SaveCardBubbleControllerImpl.
 LocalCardMigrationBubbleControllerImpl::LocalCardMigrationBubbleControllerImpl(
@@ -117,7 +111,7 @@
 
   // Don't do anything if a navigation occurs before a user could reasonably
   // interact with the bubble.
-  if (Elapsed() < base::TimeDelta::FromSeconds(kSurviveNavigationSeconds))
+  if (Elapsed() < kCardBubbleSurviveNavigationTime)
     return;
 
   // Otherwise, get rid of the bubble and icon.
@@ -168,4 +162,4 @@
   location_bar->UpdateLocalCardMigrationIcon();
 }
 
-}  // namespace autofill
\ No newline at end of file
+}  // namespace autofill
diff --git a/chrome/browser/ui/autofill/popup_constants.h b/chrome/browser/ui/autofill/popup_constants.h
index a7a2d683..6944418 100644
--- a/chrome/browser/ui/autofill/popup_constants.h
+++ b/chrome/browser/ui/autofill/popup_constants.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_UI_AUTOFILL_POPUP_CONSTANTS_H_
 #define CHROME_BROWSER_UI_AUTOFILL_POPUP_CONSTANTS_H_
 
+#include "base/time/time.h"
 #include "build/build_config.h"
 
 namespace autofill {
@@ -17,6 +18,12 @@
 const int kPopupBorderThickness = 0;
 #endif
 
+// The time span a card bubble should be visible even if the document
+// navigates away meanwhile. This is to ensure that the user can see
+// the bubble.
+constexpr base::TimeDelta kCardBubbleSurviveNavigationTime =
+    base::TimeDelta::FromSeconds(5);
+
 }  // namespace autofill
 
 #endif  // CHROME_BROWSER_UI_AUTOFILL_POPUP_CONSTANTS_H_
diff --git a/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc b/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc
index facf9c19..016dd3a 100644
--- a/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc
+++ b/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc
@@ -10,6 +10,7 @@
 #include "chrome/browser/signin/account_tracker_service_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/ssl/security_state_tab_helper.h"
+#include "chrome/browser/ui/autofill/popup_constants.h"
 #include "chrome/browser/ui/autofill/save_card_bubble_view.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -30,15 +31,6 @@
 
 namespace autofill {
 
-namespace {
-
-// Number of seconds the bubble and icon will survive navigations, starting
-// from when the bubble is shown.
-// TODO(bondd): Share with ManagePasswordsUIController.
-const int kSurviveNavigationSeconds = 5;
-
-}  // namespace
-
 SaveCardBubbleControllerImpl::SaveCardBubbleControllerImpl(
     content::WebContents* web_contents)
     : content::WebContentsObserver(web_contents),
@@ -267,7 +259,7 @@
 
   // Don't do anything if a navigation occurs before a user could reasonably
   // interact with the bubble.
-  if (Elapsed() < base::TimeDelta::FromSeconds(kSurviveNavigationSeconds))
+  if (Elapsed() < kCardBubbleSurviveNavigationTime)
     return;
 
   // Otherwise, get rid of the bubble and icon.
diff --git a/chrome/browser/ui/autofill/save_card_bubble_controller_impl_unittest.cc b/chrome/browser/ui/autofill/save_card_bubble_controller_impl_unittest.cc
index 640222e..54bc7be0 100644
--- a/chrome/browser/ui/autofill/save_card_bubble_controller_impl_unittest.cc
+++ b/chrome/browser/ui/autofill/save_card_bubble_controller_impl_unittest.cc
@@ -475,8 +475,9 @@
   ShowLocalBubble();
 
   base::HistogramTester histogram_tester;
-  // The bubble should still stick around for up to kSurviveNavigationSeconds
-  // (5) seconds regardless of navigation.
+  // The bubble should still stick around for up to
+  // kCardBubbleSurviveNavigationTime (5 seconds) regardless of
+  // navigation.
   controller()->set_elapsed(base::TimeDelta::FromSeconds(3));
 
   controller()->SimulateNavigation();
@@ -500,8 +501,9 @@
   CloseAndReshowBubble();
 
   base::HistogramTester histogram_tester;
-  // The bubble should still stick around for up to kSurviveNavigationSeconds
-  // (5) seconds regardless of navigation.
+  // The bubble should still stick around for up to
+  // kCardBubbleSurviveNavigationTime (5 seconds) regardless of
+  // navigation.
   controller()->set_elapsed(base::TimeDelta::FromSeconds(3));
 
   controller()->SimulateNavigation();
@@ -524,8 +526,8 @@
   ShowUploadBubble();
 
   base::HistogramTester histogram_tester;
-  // The bubble should still stick around for up to kSurviveNavigationSeconds
-  // (5) seconds regardless of navigation.
+  // The bubble should still stick around for up to
+  // kCardBubbleSurviveNavigationTime (5 seconds) regardless of navigation.
   controller()->set_elapsed(base::TimeDelta::FromSeconds(3));
 
   controller()->SimulateNavigation();
@@ -548,8 +550,9 @@
   ShowUploadBubble(/*should_request_name_from_user=*/true);
 
   base::HistogramTester histogram_tester;
-  // The bubble should still stick around for up to kSurviveNavigationSeconds
-  // (5) seconds regardless of navigation.
+  // The bubble should still stick around for up to
+  // kCardBubbleSurviveNavigationTime (5 seconds) regardless of
+  // navigation.
   controller()->set_elapsed(base::TimeDelta::FromSeconds(3));
 
   controller()->SimulateNavigation();
@@ -574,8 +577,9 @@
   CloseAndReshowBubble();
 
   base::HistogramTester histogram_tester;
-  // The bubble should still stick around for up to kSurviveNavigationSeconds
-  // (5) seconds regardless of navigation.
+  // The bubble should still stick around for up to
+  // kCardBubbleSurviveNavigationTime (5 seconds) regardless of
+  // navigation.
   controller()->set_elapsed(base::TimeDelta::FromSeconds(3));
 
   controller()->SimulateNavigation();
@@ -599,8 +603,9 @@
   CloseAndReshowBubble();
 
   base::HistogramTester histogram_tester;
-  // The bubble should still stick around for up to kSurviveNavigationSeconds
-  // (5) seconds regardless of navigation.
+  // The bubble should still stick around for up to
+  // kCardBubbleSurviveNavigationTime (5 seconds) regardless of
+  // navigation.
   controller()->set_elapsed(base::TimeDelta::FromSeconds(3));
 
   controller()->SimulateNavigation();
diff --git a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h
index 0ea1f6e..014c0fa 100644
--- a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h
+++ b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h
@@ -78,7 +78,6 @@
   void UpdateManagePasswordsIconAndBubble() override;
   void UpdateSaveCreditCardIcon() override;
   void UpdateLocalCardMigrationIcon() override;
-  void UpdateFindBarIconVisibility() override;
   void UpdateBookmarkStarVisibility() override;
   void UpdateLocationBarVisibility(bool visible, bool animate) override;
   void SaveStateToContents(content::WebContents* contents) override;
diff --git a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm
index f3ee0f7..6f91c1f 100644
--- a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm
+++ b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm
@@ -206,11 +206,6 @@
   NOTIMPLEMENTED();
 }
 
-void LocationBarViewMac::UpdateFindBarIconVisibility() {
-  // TODO(crbug/651643): Implement for mac.
-  NOTIMPLEMENTED();
-}
-
 void LocationBarViewMac::UpdateBookmarkStarVisibility() {
   star_decoration_->SetVisible(IsStarEnabled());
 }
@@ -516,6 +511,10 @@
   // as update methods are migrated out of LocationBar to the
   // PageActionIconContainer interface.
   switch (type) {
+    case PageActionIconType::kFind:
+      // TODO(crbug/651643): Implement for mac.
+      NOTIMPLEMENTED();
+      break;
     case PageActionIconType::kZoom:
       UpdateZoomDecoration(/*default_zoom_changed=*/false);
       OnChanged();
diff --git a/chrome/browser/ui/cocoa/tab_contents/chrome_web_contents_view_delegate_mac.mm b/chrome/browser/ui/cocoa/tab_contents/chrome_web_contents_view_delegate_mac.mm
index 8359e7b8..169ae90 100644
--- a/chrome/browser/ui/cocoa/tab_contents/chrome_web_contents_view_delegate_mac.mm
+++ b/chrome/browser/ui/cocoa/tab_contents/chrome_web_contents_view_delegate_mac.mm
@@ -131,13 +131,6 @@
   gfx::NativeView parent_view =
       GetActiveRenderWidgetHostView()->GetNativeView();
 
-#if BUILDFLAG(MAC_VIEWS_BROWSER)
-  if (!views_mode_controller::IsViewsBrowserCocoa()) {
-    return new RenderViewContextMenuMacViews(focused_frame, params,
-                                             parent_view);
-  }
-#endif
-
   return new RenderViewContextMenuMacCocoa(focused_frame, params, parent_view);
 }
 
diff --git a/chrome/browser/ui/cocoa/view_id_util_browsertest.mm b/chrome/browser/ui/cocoa/view_id_util_browsertest.mm
index 0097133c..3526a8a 100644
--- a/chrome/browser/ui/cocoa/view_id_util_browsertest.mm
+++ b/chrome/browser/ui/cocoa/view_id_util_browsertest.mm
@@ -100,7 +100,8 @@
   test::ScopedMacViewsBrowserMode cocoa_browser_mode_{false};
 };
 
-IN_PROC_BROWSER_TEST_F(ViewIDTest, Basic) {
+// https://crbug.com/862945
+IN_PROC_BROWSER_TEST_F(ViewIDTest, DISABLED_Basic) {
   ASSERT_NO_FATAL_FAILURE(DoTest());
 }
 
diff --git a/chrome/browser/ui/find_bar/find_bar_controller.cc b/chrome/browser/ui/find_bar/find_bar_controller.cc
index 9a27ab5..81f00a4 100644
--- a/chrome/browser/ui/find_bar/find_bar_controller.cc
+++ b/chrome/browser/ui/find_bar/find_bar_controller.cc
@@ -19,7 +19,7 @@
 #include "chrome/browser/ui/find_bar/find_bar_state.h"
 #include "chrome/browser/ui/find_bar/find_bar_state_factory.h"
 #include "chrome/browser/ui/find_bar/find_tab_helper.h"
-#include "chrome/browser/ui/location_bar/location_bar.h"
+#include "chrome/browser/ui/page_action/page_action_icon_container.h"
 #include "content/public/browser/navigation_details.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/notification_details.h"
@@ -86,7 +86,8 @@
 }
 
 void FindBarController::FindBarVisibilityChanged() {
-  browser_->window()->GetLocationBar()->UpdateFindBarIconVisibility();
+  browser_->window()->GetPageActionIconContainer()->UpdatePageActionIcon(
+      PageActionIconType::kFind);
 }
 
 void FindBarController::ChangeWebContents(WebContents* contents) {
diff --git a/chrome/browser/ui/location_bar/location_bar.h b/chrome/browser/ui/location_bar/location_bar.h
index ea956e2..411ed06 100644
--- a/chrome/browser/ui/location_bar/location_bar.h
+++ b/chrome/browser/ui/location_bar/location_bar.h
@@ -55,9 +55,6 @@
   // Updates the visibility and toggled state of the local card migration icon.
   virtual void UpdateLocalCardMigrationIcon() = 0;
 
-  // Updates the visibility of the find bar image icon.
-  virtual void UpdateFindBarIconVisibility() = 0;
-
   // Updates the visibility of the bookmark star.
   virtual void UpdateBookmarkStarVisibility() = 0;
 
diff --git a/chrome/browser/ui/page_action/page_action_icon_container.h b/chrome/browser/ui/page_action/page_action_icon_container.h
index a311aa1..6e9af2f 100644
--- a/chrome/browser/ui/page_action/page_action_icon_container.h
+++ b/chrome/browser/ui/page_action/page_action_icon_container.h
@@ -8,6 +8,7 @@
 enum class PageActionIconType {
   // TODO(https://crbug.com/788051): Migrate page action icon update methods out
   // of LocationBar to this interface.
+  kFind,
   kZoom,
 };
 
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
index 65a78ad..994fad7 100644
--- a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
+++ b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
@@ -173,8 +173,6 @@
   AutofillPopupSeparatorView(AutofillPopupController* controller,
                              int line_number);
 
-  views::View* empty_ = nullptr;
-
   DISALLOW_COPY_AND_ASSIGN(AutofillPopupSeparatorView);
 };
 
@@ -374,18 +372,17 @@
 void AutofillPopupSeparatorView::CreateContent() {
   SetLayoutManager(std::make_unique<views::FillLayout>());
 
-  // In order to draw the horizontal line for the separator, create an empty
-  // view which matches the width of the parent (by using full flex) and has a
-  // height equal to the desired padding, then paint a border on the bottom.
-  empty_ = new views::View();
-  empty_->SetPreferredSize(gfx::Size(1, GetContentsVerticalPadding()));
-  empty_->SetBorder(views::CreateSolidSidedBorder(
-      /*top=*/0,
+  views::Separator* separator = new views::Separator();
+  separator->SetColor(kAutofillPopupSeparatorColor);
+  // Add some spacing between the the previous item and the separator.
+  separator->SetPreferredHeight(
+      views::MenuConfig::instance().separator_thickness);
+  separator->SetBorder(views::CreateEmptyBorder(
+      /*top=*/GetContentsVerticalPadding(),
       /*left=*/0,
-      /*bottom=*/views::MenuConfig::instance().separator_thickness,
-      /*right=*/0,
-      /*color=*/kAutofillPopupSeparatorColor));
-  AddChildView(empty_);
+      /*bottom=*/0,
+      /*right=*/0));
+  AddChildView(separator);
 }
 
 void AutofillPopupSeparatorView::RefreshStyle() {
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
index d6db8b71..c1462a5 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -812,6 +812,12 @@
     return hosted_app_button_container_->active_icon_color_;
   }
 
+  PageActionIconView* GetPageActionIcon(PageActionIconType type) {
+    return browser_view_->toolbar_button_provider()
+        ->GetPageActionIconContainerView()
+        ->GetPageActionIconView(type);
+  }
+
   ContentSettingImageView* GrantGeolocationPermission() {
     content::RenderFrameHost* frame =
         app_browser_->tab_strip_model()->GetActiveWebContents()->GetMainFrame();
@@ -879,16 +885,21 @@
             frame_header_->GetHeaderHeight());
 }
 
+// Test that the HostedAppButtonContainer is the designated toolbar button
+// provider in this window configuration.
+IN_PROC_BROWSER_TEST_P(HostedAppNonClientFrameViewAshTest,
+                       ToolbarButtonProvider) {
+  EXPECT_EQ(browser_view_->toolbar_button_provider(),
+            hosted_app_button_container_);
+}
+
 // Test that the zoom icon appears in the title bar for hosted app windows.
 IN_PROC_BROWSER_TEST_P(HostedAppNonClientFrameViewAshTest, ZoomIcon) {
   content::WebContents* web_contents =
       app_browser_->tab_strip_model()->GetActiveWebContents();
   zoom::ZoomController* zoom_controller =
       zoom::ZoomController::FromWebContents(web_contents);
-  PageActionIconView* zoom_icon =
-      browser_view_->toolbar_button_provider()
-          ->GetPageActionIconContainerView()
-          ->GetPageActionIconView(PageActionIconType::kZoom);
+  PageActionIconView* zoom_icon = GetPageActionIcon(PageActionIconType::kZoom);
 
   EXPECT_TRUE(zoom_icon);
   EXPECT_FALSE(zoom_icon->visible());
@@ -901,6 +912,18 @@
   EXPECT_TRUE(ZoomBubbleView::GetZoomBubble());
 }
 
+// Test that the find icon appears in the title bar for hosted app windows.
+IN_PROC_BROWSER_TEST_P(HostedAppNonClientFrameViewAshTest, FindIcon) {
+  PageActionIconView* find_icon = GetPageActionIcon(PageActionIconType::kFind);
+
+  EXPECT_TRUE(find_icon);
+  EXPECT_FALSE(find_icon->visible());
+
+  chrome::Find(app_browser_);
+
+  EXPECT_TRUE(find_icon->visible());
+}
+
 // Tests that the focus toolbar command focuses the app menu button in web app
 // windows.
 IN_PROC_BROWSER_TEST_P(HostedAppNonClientFrameViewAshTest,
diff --git a/chrome/browser/ui/views/frame/browser_view_layout.cc b/chrome/browser/ui/views/frame/browser_view_layout.cc
index 66ce192..bdb19d4 100644
--- a/chrome/browser/ui/views/frame/browser_view_layout.cc
+++ b/chrome/browser/ui/views/frame/browser_view_layout.cc
@@ -22,7 +22,6 @@
 #include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
 #include "chrome/browser/ui/views/frame/top_container_view.h"
 #include "chrome/browser/ui/views/infobars/infobar_container_view.h"
-#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/ui/views/tabs/tab_strip.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
 #include "components/web_modal/web_contents_modal_dialog_host.h"
@@ -216,26 +215,16 @@
   // to the Toolbar.
 
   BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser_);
-  LocationBarView* location_bar_view = browser_view->GetLocationBarView();
-
-  // Check for the presence of a visible OmniBox/location bar.
-  const bool has_location_bar =
-      browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR) &&
-      location_bar_view && location_bar_view->visible() &&
-      (!immersive_mode_controller_->IsEnabled() ||
-       immersive_mode_controller_->IsRevealed());
 
   gfx::Rect bounding_box;
-  // If the OmniBox/location bar is visible, anchor the find bar bounding box
-  // to its bottom edge.
-  if (has_location_bar) {
-    // The bounding box should be the area right below the OmniBox/location bar.
-    bounding_box = location_bar_view->ConvertRectToWidget(
-        location_bar_view->GetLocalBounds());
-    bounding_box.Inset(0, location_bar_view->height(), 0,
-                       -contents_container_->height());
-    return bounding_box;
+  if (!immersive_mode_controller_->IsEnabled() ||
+      immersive_mode_controller_->IsRevealed()) {
+    bounding_box =
+        browser_view->toolbar_button_provider()->GetFindBarBoundingBox(
+            contents_container_->height());
   }
+  if (!bounding_box.IsEmpty())
+    return bounding_box;
 
   // Otherwise, use the contents container minus any infobars and detached
   // bookmark bar from the top and a scrollbar width from the appropriate edge.
diff --git a/chrome/browser/ui/views/frame/hosted_app_button_container.cc b/chrome/browser/ui/views/frame/hosted_app_button_container.cc
index 2a70069..ecdd485a 100644
--- a/chrome/browser/ui/views/frame/hosted_app_button_container.cc
+++ b/chrome/browser/ui/views/frame/hosted_app_button_container.cc
@@ -57,6 +57,11 @@
   DISALLOW_COPY_AND_ASSIGN(HostedAppToolbarActionsBar);
 };
 
+int HorizontalPaddingBetweenItems() {
+  return views::LayoutProvider::Get()->GetDistanceMetric(
+      views::DISTANCE_RELATED_CONTROL_HORIZONTAL);
+}
+
 }  // namespace
 
 class HostedAppButtonContainer::ContentSettingsContainer
@@ -172,9 +177,10 @@
       inactive_icon_color_(inactive_icon_color),
       content_settings_container_(new ContentSettingsContainer(browser_view)),
       page_action_icon_container_view_(new PageActionIconContainerView(
-          {PageActionIconType::kZoom},
+          {PageActionIconType::kFind, PageActionIconType::kZoom},
           GetLayoutConstant(HOSTED_APP_PAGE_ACTION_ICON_SIZE),
-          browser_view->GetProfile(),
+          HorizontalPaddingBetweenItems(),
+          browser_view->browser(),
           this,
           nullptr)),
       browser_actions_container_(
@@ -184,12 +190,10 @@
                                       false /* interactive */)),
       app_menu_button_(new HostedAppMenuButton(browser_view)) {
   DCHECK(browser_view_);
-  const int kHorizontalPadding =
-      views::LayoutProvider::Get()->GetDistanceMetric(
-          views::DISTANCE_RELATED_CONTROL_HORIZONTAL);
   auto layout = std::make_unique<views::BoxLayout>(
-      views::BoxLayout::kHorizontal, gfx::Insets(0, kHorizontalPadding),
-      kHorizontalPadding);
+      views::BoxLayout::kHorizontal,
+      gfx::Insets(0, HorizontalPaddingBetweenItems()),
+      HorizontalPaddingBetweenItems());
   layout->set_cross_axis_alignment(
       views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER);
   SetLayoutManager(std::move(layout));
@@ -302,6 +306,24 @@
   return app_menu_button_;
 }
 
+gfx::Rect HostedAppButtonContainer::GetFindBarBoundingBox(
+    int contents_height) const {
+  if (!IsDrawn())
+    return gfx::Rect();
+
+  gfx::Rect anchor_bounds =
+      app_menu_button_->ConvertRectToWidget(app_menu_button_->GetLocalBounds());
+  if (base::i18n::IsRTL()) {
+    // Find bar will be left aligned so align to left edge of app menu button.
+    int widget_width = GetWidget()->GetRootView()->width();
+    return gfx::Rect(anchor_bounds.x(), anchor_bounds.bottom(),
+                     widget_width - anchor_bounds.x(), contents_height);
+  }
+  // Find bar will be right aligned so align to right edge of app menu button.
+  return gfx::Rect(0, anchor_bounds.bottom(),
+                   anchor_bounds.x() + anchor_bounds.width(), contents_height);
+}
+
 void HostedAppButtonContainer::FocusToolbar() {
   SetPaneFocus(nullptr);
 }
diff --git a/chrome/browser/ui/views/frame/hosted_app_button_container.h b/chrome/browser/ui/views/frame/hosted_app_button_container.h
index 6c70361..d1d27b0 100644
--- a/chrome/browser/ui/views/frame/hosted_app_button_container.h
+++ b/chrome/browser/ui/views/frame/hosted_app_button_container.h
@@ -90,6 +90,7 @@
   BrowserActionsContainer* GetBrowserActionsContainer() override;
   PageActionIconContainerView* GetPageActionIconContainerView() override;
   AppMenuButton* GetAppMenuButton() override;
+  gfx::Rect GetFindBarBoundingBox(int contents_height) const override;
   void FocusToolbar() override;
   views::AccessiblePaneView* GetAsAccessiblePaneView() override;
 
diff --git a/chrome/browser/ui/views/frame/test_with_browser_view.cc b/chrome/browser/ui/views/frame/test_with_browser_view.cc
index 1aa786d..71e2d0d 100644
--- a/chrome/browser/ui/views/frame/test_with_browser_view.cc
+++ b/chrome/browser/ui/views/frame/test_with_browser_view.cc
@@ -61,12 +61,11 @@
 
 }  // namespace
 
-TestWithBrowserView::TestWithBrowserView() : url_fetcher_factory_(nullptr) {}
+TestWithBrowserView::TestWithBrowserView() = default;
 
 TestWithBrowserView::TestWithBrowserView(Browser::Type browser_type,
                                          bool hosted_app)
-    : BrowserWithTestWindowTest(browser_type, hosted_app),
-      url_fetcher_factory_(nullptr) {}
+    : BrowserWithTestWindowTest(browser_type, hosted_app) {}
 
 TestWithBrowserView::~TestWithBrowserView() {
 }
@@ -113,7 +112,6 @@
   FakeGaiaCookieManagerService* gcms =
       static_cast<FakeGaiaCookieManagerService*>(
           GaiaCookieManagerServiceFactory::GetForProfile(profile));
-  gcms->Init(&url_fetcher_factory_);
   gcms->SetListAccountsResponseHttpNotFound();
   return profile;
 }
diff --git a/chrome/browser/ui/views/frame/test_with_browser_view.h b/chrome/browser/ui/views/frame/test_with_browser_view.h
index 334e4a8..eebad3b5 100644
--- a/chrome/browser/ui/views/frame/test_with_browser_view.h
+++ b/chrome/browser/ui/views/frame/test_with_browser_view.h
@@ -10,7 +10,6 @@
 #include "base/macros.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "chrome/test/views/scoped_macviews_browser_mode.h"
-#include "net/url_request/test_url_fetcher_factory.h"
 
 class BrowserView;
 
@@ -36,8 +35,6 @@
   BrowserView* browser_view_;  // Not owned.
   test::ScopedMacViewsBrowserMode views_mode_{true};
 
-  net::FakeURLFetcherFactory url_fetcher_factory_;
-
   DISALLOW_COPY_AND_ASSIGN(TestWithBrowserView);
 };
 
diff --git a/chrome/browser/ui/views/frame/toolbar_button_provider.h b/chrome/browser/ui/views/frame/toolbar_button_provider.h
index 319d884..d34fee41 100644
--- a/chrome/browser/ui/views/frame/toolbar_button_provider.h
+++ b/chrome/browser/ui/views/frame/toolbar_button_provider.h
@@ -9,6 +9,10 @@
 class BrowserActionsContainer;
 class PageActionIconContainerView;
 
+namespace gfx {
+class Rect;
+}
+
 namespace views {
 class AccessiblePaneView;
 }
@@ -26,6 +30,11 @@
   // Gets the app menu button.
   virtual AppMenuButton* GetAppMenuButton() = 0;
 
+  // Gets the area available for the find bar in widget space where
+  // |contents_height| is the amount of vertical space available, otherwise if
+  // there is no appropriate anchor point returns empty gfx::Rect.
+  virtual gfx::Rect GetFindBarBoundingBox(int contents_height) const = 0;
+
   // Gives the toolbar focus.
   virtual void FocusToolbar() = 0;
 
diff --git a/chrome/browser/ui/views/location_bar/find_bar_icon.cc b/chrome/browser/ui/views/location_bar/find_bar_icon.cc
index 22608d8..8f607658 100644
--- a/chrome/browser/ui/views/location_bar/find_bar_icon.cc
+++ b/chrome/browser/ui/views/location_bar/find_bar_icon.cc
@@ -4,12 +4,18 @@
 
 #include "chrome/browser/ui/views/location_bar/find_bar_icon.h"
 
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/find_bar/find_bar.h"
+#include "chrome/browser/ui/find_bar/find_bar_controller.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/toolbar/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
 
-FindBarIcon::FindBarIcon(PageActionIconView::Delegate* delegate)
-    : PageActionIconView(nullptr, 0, delegate) {}
+FindBarIcon::FindBarIcon(Browser* browser,
+                         PageActionIconView::Delegate* delegate)
+    : PageActionIconView(nullptr, 0, delegate), browser_(browser) {
+  DCHECK(browser_);
+}
 
 FindBarIcon::~FindBarIcon() {}
 
@@ -41,3 +47,16 @@
 const gfx::VectorIcon& FindBarIcon::GetVectorIcon() const {
   return toolbar::kFindInPageIcon;
 }
+
+bool FindBarIcon::Update() {
+  // |browser_->window()| may return nullptr because Update() is called while
+  // BrowserWindow is being constructed.
+  if (!browser_->window() || !browser_->HasFindBarController())
+    return false;
+
+  const bool was_visible = visible();
+  SetVisible(browser_->GetFindBarController()->find_bar()->IsFindBarVisible());
+  const bool visibility_changed = was_visible != visible();
+  SetActive(visible(), visibility_changed);
+  return visibility_changed;
+}
diff --git a/chrome/browser/ui/views/location_bar/find_bar_icon.h b/chrome/browser/ui/views/location_bar/find_bar_icon.h
index dfdefb3..addeb04 100644
--- a/chrome/browser/ui/views/location_bar/find_bar_icon.h
+++ b/chrome/browser/ui/views/location_bar/find_bar_icon.h
@@ -8,16 +8,19 @@
 #include "base/macros.h"
 #include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
 
+class Browser;
+
 // The find icon to show when the find bar is visible.
 class FindBarIcon : public PageActionIconView {
  public:
-  explicit FindBarIcon(PageActionIconView::Delegate* delegate);
+  FindBarIcon(Browser* browser, PageActionIconView::Delegate* delegate);
   ~FindBarIcon() override;
 
   void SetActive(bool activate, bool should_animate);
 
  protected:
   // PageActionIconView:
+  bool Update() override;
   void OnExecuting(ExecuteSource execute_source) override;
   views::BubbleDialogDelegateView* GetBubble() const override;
   const gfx::VectorIcon& GetVectorIcon() const override;
@@ -25,6 +28,8 @@
 
  private:
   DISALLOW_COPY_AND_ASSIGN(FindBarIcon);
+
+  Browser* browser_ = nullptr;
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_FIND_BAR_ICON_H_
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index 061f0b06..bd2e1ba 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -35,8 +35,6 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/content_settings/content_setting_bubble_model.h"
 #include "chrome/browser/ui/extensions/hosted_app_browser_controller.h"
-#include "chrome/browser/ui/find_bar/find_bar.h"
-#include "chrome/browser/ui/find_bar/find_bar_controller.h"
 #include "chrome/browser/ui/layout_constants.h"
 #include "chrome/browser/ui/omnibox/chrome_omnibox_client.h"
 #include "chrome/browser/ui/omnibox/omnibox_theme.h"
@@ -50,7 +48,6 @@
 #include "chrome/browser/ui/views/harmony/chrome_typography.h"
 #include "chrome/browser/ui/views/location_bar/background_with_1_px_border.h"
 #include "chrome/browser/ui/views/location_bar/content_setting_image_view.h"
-#include "chrome/browser/ui/views/location_bar/find_bar_icon.h"
 #include "chrome/browser/ui/views/location_bar/keyword_hint_view.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_layout.h"
 #include "chrome/browser/ui/views/location_bar/location_icon_view.h"
@@ -218,9 +215,17 @@
 
   SkColor icon_color = GetColor(OmniboxPart::RESULTS_ICON);
 
+  std::vector<PageActionIconType> page_action_icon_types;
+  // |browser_| may be null when LocationBarView is used for non-Browser windows
+  // such as PresentationReceiverWindowView, which do not support page actions.
+  if (browser_) {
+    page_action_icon_types = {PageActionIconType::kFind,
+                              PageActionIconType::kZoom};
+  }
   page_action_icon_container_view_ = new PageActionIconContainerView(
-      {PageActionIconType::kZoom}, GetLayoutConstant(LOCATION_BAR_ICON_SIZE),
-      profile(), this, delegate_);
+      page_action_icon_types, GetLayoutConstant(LOCATION_BAR_ICON_SIZE),
+      GetLayoutConstant(LOCATION_BAR_ELEMENT_PADDING), browser_, this,
+      delegate_);
   AddChildView(page_action_icon_container_view_);
   page_action_icon_container_view_->SetIconColor(icon_color);
 
@@ -246,7 +251,6 @@
     page_action_icons_.push_back(intent_picker_view_ =
                                      new IntentPickerView(browser_, this));
 #endif
-  page_action_icons_.push_back(find_bar_icon_ = new FindBarIcon(this));
   if (browser_) {
     page_action_icons_.push_back(
         star_view_ = new StarView(command_updater(), browser_, this));
@@ -536,7 +540,6 @@
   if (star_view_)
     add_trailing_decoration(star_view_);
   add_trailing_decoration(page_action_icon_container_view_);
-  add_trailing_decoration(find_bar_icon_);
 #if defined(OS_CHROMEOS)
   if (intent_picker_view_)
     add_trailing_decoration(intent_picker_view_);
@@ -639,14 +642,8 @@
 void LocationBarView::Update(const WebContents* contents) {
   RefreshContentSettingViews();
 
-  page_action_icon_container_view_->UpdatePageActionIcon(
-      PageActionIconType::kZoom);
-
   RefreshPageActionIconViews();
 
-  // TODO(calamity): Refactor Update to use PageActionIconView::Refresh.
-  RefreshFindBarIcon();
-
   if (star_view_) {
     // TODO(calamity): Refactor Update to use PageActionIconView::Refresh.
     UpdateBookmarkStarVisibility();
@@ -883,20 +880,6 @@
   }
 }
 
-bool LocationBarView::RefreshFindBarIcon() {
-  // |browser_| may be nullptr since some unit tests pass it in for the
-  // Browser*. |browser_->window()| may return nullptr because Update() is
-  // called while BrowserWindow is being constructed.
-  if (!find_bar_icon_ || !browser_ || !browser_->window() ||
-      !browser_->HasFindBarController()) {
-    return false;
-  }
-  const bool was_visible = find_bar_icon_->visible();
-  find_bar_icon_->SetVisible(
-      browser_->GetFindBarController()->find_bar()->IsFindBarVisible());
-  return was_visible != find_bar_icon_->visible();
-}
-
 void LocationBarView::RefreshClearAllButtonIcon() {
   const gfx::VectorIcon& icon =
       ui::MaterialDesignController::IsTouchOptimizedUiEnabled()
@@ -1065,15 +1048,6 @@
   }
 }
 
-void LocationBarView::UpdateFindBarIconVisibility() {
-  const bool visibility_changed = RefreshFindBarIcon();
-  if (visibility_changed) {
-    Layout();
-    SchedulePaint();
-  }
-  find_bar_icon_->SetActive(find_bar_icon_->visible(), visibility_changed);
-}
-
 void LocationBarView::UpdateBookmarkStarVisibility() {
   if (star_view_) {
     star_view_->SetVisible(
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h
index 88a5512b9..3c95ba4 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.h
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -37,7 +37,6 @@
 
 class CommandUpdater;
 class ContentSettingBubbleModelDelegate;
-class FindBarIcon;
 class GURL;
 class IntentPickerView;
 class KeywordHintView;
@@ -301,9 +300,6 @@
   // actions are available on the current page.
   void RefreshPageActionIconViews();
 
-  // Updates |find_bar_icon_|. Returns true if visibility changed.
-  bool RefreshFindBarIcon();
-
   // Updates the color of the icon for the "clear all" button.
   void RefreshClearAllButtonIcon();
 
@@ -343,7 +339,6 @@
   void UpdateManagePasswordsIconAndBubble() override;
   void UpdateSaveCreditCardIcon() override;
   void UpdateLocalCardMigrationIcon() override;
-  void UpdateFindBarIconVisibility() override;
   void UpdateBookmarkStarVisibility() override;
   void UpdateLocationBarVisibility(bool visible, bool animation) override;
   void SaveStateToContents(content::WebContents* contents) override;
@@ -450,9 +445,6 @@
   IntentPickerView* intent_picker_view_ = nullptr;
 #endif  // defined(OS_CHROMEOS)
 
-  // The icon displayed when the find bar is visible.
-  FindBarIcon* find_bar_icon_ = nullptr;
-
   // The star for bookmarking.  It will be null when |browser_| is null.
   StarView* star_view_ = nullptr;
 
diff --git a/chrome/browser/ui/views/page_action/page_action_icon_container_view.cc b/chrome/browser/ui/views/page_action/page_action_icon_container_view.cc
index 99a3924..06b50d0 100644
--- a/chrome/browser/ui/views/page_action/page_action_icon_container_view.cc
+++ b/chrome/browser/ui/views/page_action/page_action_icon_container_view.cc
@@ -3,7 +3,9 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/ui/views/page_action/page_action_icon_container_view.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/views/location_bar/find_bar_icon.h"
 #include "chrome/browser/ui/views/location_bar/zoom_bubble_view.h"
 #include "chrome/browser/ui/views/page_action/zoom_view.h"
 #include "ui/views/layout/box_layout.h"
@@ -11,17 +13,23 @@
 PageActionIconContainerView::PageActionIconContainerView(
     const std::vector<PageActionIconType>& types_enabled,
     int icon_size,
-    content::BrowserContext* browser_context,
-    PageActionIconView::Delegate* bubble_icon_delegate,
+    int between_icon_spacing,
+    Browser* browser,
+    PageActionIconView::Delegate* page_action_icon_delegate,
     LocationBarView::Delegate* location_bar_delegate)
     : zoom_observer_(this) {
-  SetLayoutManager(
-      std::make_unique<views::BoxLayout>(views::BoxLayout::kHorizontal));
+  SetLayoutManager(std::make_unique<views::BoxLayout>(
+      views::BoxLayout::kHorizontal, gfx::Insets(), between_icon_spacing));
 
   for (PageActionIconType type : types_enabled) {
     switch (type) {
+      case PageActionIconType::kFind:
+        find_bar_icon_ = new FindBarIcon(browser, page_action_icon_delegate);
+        page_action_icons_.push_back(find_bar_icon_);
+        break;
       case PageActionIconType::kZoom:
-        zoom_view_ = new ZoomView(location_bar_delegate, bubble_icon_delegate);
+        zoom_view_ =
+            new ZoomView(location_bar_delegate, page_action_icon_delegate);
         page_action_icons_.push_back(zoom_view_);
         break;
     }
@@ -34,8 +42,10 @@
     AddChildView(icon);
   }
 
-  zoom_observer_.Add(
-      zoom::ZoomEventManager::GetForBrowserContext(browser_context));
+  if (browser) {
+    zoom_observer_.Add(
+        zoom::ZoomEventManager::GetForBrowserContext(browser->profile()));
+  }
 }
 
 PageActionIconContainerView::~PageActionIconContainerView() {}
@@ -46,6 +56,8 @@
   // methods are migrated out of LocationBar to the PageActionIconContainer
   // interface.
   switch (type) {
+    case PageActionIconType::kFind:
+      return find_bar_icon_;
     case PageActionIconType::kZoom:
       return zoom_view_;
   }
diff --git a/chrome/browser/ui/views/page_action/page_action_icon_container_view.h b/chrome/browser/ui/views/page_action/page_action_icon_container_view.h
index 0e30d57..5f7cc9d 100644
--- a/chrome/browser/ui/views/page_action/page_action_icon_container_view.h
+++ b/chrome/browser/ui/views/page_action/page_action_icon_container_view.h
@@ -14,9 +14,8 @@
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/views/view.h"
 
-namespace context {
-class BrowserContext;
-}
+class Browser;
+class FindBarIcon;
 class ZoomView;
 
 class PageActionIconContainerView : public views::View,
@@ -26,7 +25,8 @@
   PageActionIconContainerView(
       const std::vector<PageActionIconType>& types_enabled,
       int icon_size,
-      content::BrowserContext* browser_context,
+      int between_icon_spacing,
+      Browser* browser,
       PageActionIconView::Delegate* page_action_icon_delegate,
       LocationBarView::Delegate* location_bar_delegate);
   ~PageActionIconContainerView() override;
@@ -59,6 +59,7 @@
   void OnDefaultZoomLevelChanged() override;
 
   ZoomView* zoom_view_ = nullptr;
+  FindBarIcon* find_bar_icon_ = nullptr;
   std::vector<PageActionIconView*> page_action_icons_;
 
   ScopedObserver<zoom::ZoomEventManager, zoom::ZoomEventManagerObserver>
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
index c6d555b..fbac12d 100644
--- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -716,12 +716,6 @@
     // one from the list because it is already shown in a separate button.
     std::vector<AccountInfo> accounts(dice_sync_promo_accounts_.begin() + 1,
                                       dice_sync_promo_accounts_.end());
-    if (accounts.empty()) {
-      // If there is no account to list for the submenu, directly open the
-      // sign-in page.
-      ShowViewFromMode(profiles::BUBBLE_VIEW_MODE_GAIA_SIGNIN);
-      return;
-    }
     // Display the submenu to list |accounts|.
     // Using base::Unretained(this) is safe here because |dice_accounts_menu_|
     // is owned by |ProfileChooserView|, i.e. |this|.
@@ -1200,37 +1194,20 @@
         profiles::GetPlaceholderAvatarIconResourceID());
   }
   dice_signin_button_view_ =
-      new DiceSigninButtonView(dice_promo_default_account, account_icon, this);
-  dice_signin_button_view_->SetBorder(
+      new DiceSigninButtonView(dice_promo_default_account, account_icon, this,
+                               true /* show_drop_down_arrow */);
+  views::View* signin_button_container = new views::View();
+  // Create a container for the signin button, so the special highlighting of
+  // the button won't go over the border. (DiceSigninButtonView sets a custom
+  // highlighting view with |HoverButton::SetHighlightingView|.)
+  signin_button_container->SetLayoutManager(
+      std::make_unique<views::FillLayout>());
+  signin_button_container->SetBorder(
       views::CreateEmptyBorder(gfx::Insets(kMenuEdgeMargin)));
-  view->AddChildView(dice_signin_button_view_);
+  signin_button_container->AddChildView(dice_signin_button_view_);
+  view->AddChildView(signin_button_container);
   signin_with_gaia_account_button_ = dice_signin_button_view_->signin_button();
-
-  // Create a button to sync to another account.
-  constexpr int kSmallMenuIconSize = 16;
-  std::unique_ptr<views::ImageView> switch_account_icon_view(
-      new views::ImageView());
-  switch_account_icon_view->SetImage(gfx::CreateVectorIcon(
-      kSyncSwitchAccountIcon, kSmallMenuIconSize, gfx::kChromeIconGrey));
-  // The accounts submenu is only needed when there are additional accounts to
-  // list, i.e. when there is more than 1 account (the first account has it's
-  // own button).
-  std::unique_ptr<views::ImageView> submenu_arrow_icon_view;
-  if (dice_sync_promo_accounts_.size() > 1) {
-    constexpr int kSubmenuArrowSize = 12;
-    submenu_arrow_icon_view = std::make_unique<views::ImageView>();
-    submenu_arrow_icon_view->SetImage(gfx::CreateVectorIcon(
-        kUserMenuRightArrowIcon, kSubmenuArrowSize, gfx::kChromeIconGrey));
-    // Make sure that the arrow is flipped in RTL mode.
-    submenu_arrow_icon_view->EnableCanvasFlippingForRTLUI(true);
-  }
-  LOG(ERROR) << "----------- use secondary icon";
-  sync_to_another_account_button_ = new HoverButton(
-      this, std::move(switch_account_icon_view),
-      l10n_util::GetStringUTF16(
-          IDS_PROFILES_DICE_SIGNIN_WITH_ANOTHER_ACCOUNT_BUTTON),
-      base::string16() /* subtitle */, std::move(submenu_arrow_icon_view));
-  view->AddChildView(sync_to_another_account_button_);
+  sync_to_another_account_button_ = dice_signin_button_view_->drop_down_arrow();
   return view;
 }
 
diff --git a/chrome/browser/ui/views/tabs/new_tab_button.cc b/chrome/browser/ui/views/tabs/new_tab_button.cc
index 0b832ef..d54e7246 100644
--- a/chrome/browser/ui/views/tabs/new_tab_button.cc
+++ b/chrome/browser/ui/views/tabs/new_tab_button.cc
@@ -46,7 +46,6 @@
 namespace {
 
 constexpr int kDistanceBetweenIcons = 6;
-
 constexpr int kStrokeThickness = 1;
 
 sk_sp<SkDrawLooper> CreateShadowDrawLooper(SkColor color) {
@@ -105,6 +104,19 @@
     SetFocusPainter(nullptr);
     focus_ring_ = views::FocusRing::Install(this);
   }
+
+  // In newer material UI, the button is placed vertically exactly in the
+  // center of the tabstrip.  In older UI, the new tab button is placed at a
+  // fixed distance from the bottom of the tabstrip.
+  const int extra_vertical_space =
+      GetLayoutConstant(TAB_HEIGHT) -
+      GetLayoutConstant(TABSTRIP_TOOLBAR_OVERLAP) -
+      GetLayoutSize(NEW_TAB_BUTTON, is_incognito_).height();
+  constexpr int kNewTabButtonBottomOffset = 4;
+  const int top = MD::IsNewerMaterialUi()
+                      ? (extra_vertical_space / 2)
+                      : (extra_vertical_space - kNewTabButtonBottomOffset);
+  SetBorder(views::CreateEmptyBorder(gfx::Insets(top, 0, 0, 0)));
 }
 
 NewTabButton::~NewTabButton() {
@@ -113,26 +125,6 @@
 }
 
 // static
-int NewTabButton::GetTopOffset() {
-  // We're only interested in the button's height which doesn't change based
-  // on incognito or not, so we used `is_incognito=false`.
-  const int extra_vertical_space =
-      GetLayoutConstant(TAB_HEIGHT) -
-      GetLayoutConstant(TABSTRIP_TOOLBAR_OVERLAP) -
-      GetLayoutSize(NEW_TAB_BUTTON, false /* is_incognito */).height();
-
-  // In newer material UI, the button is placed vertically exactly in the
-  // center of the tabstrip.
-  if (MD::IsNewerMaterialUi())
-    return extra_vertical_space / 2;
-
-  // In the non-touch-optimized UI, the new tab button is placed at a fixed
-  // distance from the bottom of the tabstrip.
-  constexpr int kNewTabButtonBottomOffset = 4;
-  return extra_vertical_space - kNewTabButtonBottomOffset;
-}
-
-// static
 void NewTabButton::ShowPromoForLastActiveBrowser() {
   BrowserView* browser = static_cast<BrowserView*>(
       BrowserList::GetInstance()->GetLastActive()->window());
@@ -199,8 +191,8 @@
 }
 
 void NewTabButton::AddInkDropLayer(ui::Layer* ink_drop_layer) {
-  DCHECK(ink_drop_layer->bounds().size() == GetVisibleBounds().size());
-  DCHECK(ink_drop_container_->bounds().size() == GetVisibleBounds().size());
+  DCHECK(ink_drop_layer->bounds().size() == GetContentsBounds().size());
+  DCHECK(ink_drop_container_->bounds().size() == GetContentsBounds().size());
   ink_drop_container_->AddInkDropLayer(ink_drop_layer);
   InstallInkDropMask(ink_drop_layer);
 }
@@ -212,17 +204,18 @@
 
 std::unique_ptr<views::InkDropRipple> NewTabButton::CreateInkDropRipple()
     const {
+  const gfx::Rect contents_bounds = GetContentsBounds();
   return std::make_unique<views::FloodFillInkDropRipple>(
-      GetContentsBounds().size(), gfx::Insets(),
-      GetInkDropCenterBasedOnLastEvent(), GetInkDropBaseColor(),
-      ink_drop_visible_opacity());
+      contents_bounds.size(), gfx::Insets(),
+      GetInkDropCenterBasedOnLastEvent() - contents_bounds.OffsetFromOrigin(),
+      GetInkDropBaseColor(), ink_drop_visible_opacity());
 }
 
 std::unique_ptr<views::InkDropHighlight> NewTabButton::CreateInkDropHighlight()
     const {
-  const gfx::Rect bounds = GetContentsBounds();
+  const gfx::Rect bounds(GetContentsBounds().size());
   auto highlight = CreateDefaultInkDropHighlight(
-      gfx::RectF(GetMirroredRect(bounds)).CenterPoint(), bounds.size());
+      gfx::RectF(bounds).CenterPoint(), bounds.size());
   highlight->set_visible_opacity(0.1f);
   return highlight;
 }
@@ -234,7 +227,7 @@
 
 std::unique_ptr<views::InkDrop> NewTabButton::CreateInkDrop() {
   std::unique_ptr<views::InkDropImpl> ink_drop =
-      std::make_unique<views::InkDropImpl>(this, GetVisibleBounds().size());
+      std::make_unique<views::InkDropImpl>(this, GetContentsBounds().size());
   ink_drop->SetAutoHighlightMode(views::InkDropImpl::AutoHighlightMode::NONE);
   ink_drop->SetShowHighlightOnHover(true);
   UpdateInkDropBaseColor();
@@ -243,14 +236,13 @@
 
 std::unique_ptr<views::InkDropMask> NewTabButton::CreateInkDropMask() const {
   return std::make_unique<views::RoundRectInkDropMask>(
-      GetVisibleBounds().size(), gfx::Insets(), GetCornerRadius());
+      GetContentsBounds().size(), gfx::Insets(), GetCornerRadius());
 }
 
 void NewTabButton::PaintButtonContents(gfx::Canvas* canvas) {
   gfx::ScopedCanvas scoped_canvas(canvas);
-  const int visible_height =
-      GetLayoutSize(NEW_TAB_BUTTON, is_incognito_).height();
-  canvas->Translate(gfx::Vector2d(0, height() - visible_height));
+  const gfx::Rect contents_bounds = GetContentsBounds();
+  canvas->Translate(contents_bounds.OffsetFromOrigin());
   const float scale = canvas->image_scale();
   const bool pressed = state() == views::Button::STATE_PRESSED;
   const SkColor stroke_color =
@@ -264,11 +256,11 @@
 
   // Fill.
   SkPath fill, stroke;
-  const bool is_touch_ui = MD::GetMode() == MD::MATERIAL_TOUCH_OPTIMIZED;
   if (!MD::IsRefreshUi()) {
-    fill = is_touch_ui ? GetTouchOptimizedButtonPath(0, scale, false, true)
-                       : GetNonTouchOptimizedButtonPath(0, visible_height,
-                                                        scale, false, true);
+    fill = MD::IsTouchOptimizedUiEnabled()
+               ? GetTouchOptimizedButtonPath(0, scale, false, true)
+               : GetNonTouchOptimizedButtonPath(0, contents_bounds.height(),
+                                                scale, false, true);
     PaintFill(pressed, scale, fill, canvas);
 
     // Stroke.
@@ -290,7 +282,7 @@
           plus_icon_offset, paint_flags);
     }
 
-    if (is_touch_ui) {
+    if (!MD::IsRefreshUi()) {
       // Draw stroke.
       // In the touch-optimized UI design, the new tab button is rendered flat,
       // regardless of whether pressed or not (i.e. we don't emulate a pushed
@@ -338,12 +330,14 @@
     if (plus_icon_.isNull())
       InitButtonIcons();
 
-    const gfx::Rect ink_drop_bounds(gfx::Point(0, GetTopOffset()),
-                                    GetVisibleBounds().size());
-    ink_drop_container_->SetBoundsRect(ink_drop_bounds);
+    // TODO(pkasting): Instead of setting this bounds rect, maybe have the
+    // container match the view bounds, then undo the coordinate transforms in
+    // the ink drop creation methods above.
+    const gfx::Rect contents_bounds = GetContentsBounds();
+    ink_drop_container_->SetBoundsRect(contents_bounds);
 
     SkPath path;
-    path.addOval(gfx::RectToSkRect(ink_drop_bounds));
+    path.addOval(gfx::RectToSkRect(contents_bounds));
     focus_ring_->SetPath(path);
   }
 }
@@ -358,8 +352,15 @@
   UpdateInkDropBaseColor();
 }
 
+gfx::Size NewTabButton::CalculatePreferredSize() const {
+  gfx::Size size = GetLayoutSize(NEW_TAB_BUTTON, is_incognito_);
+  const auto insets = GetInsets();
+  size.Enlarge(insets.width(), insets.height());
+  return size;
+}
+
 void NewTabButton::OnBoundsChanged(const gfx::Rect& previous_bounds) {
-  const gfx::Size ink_drop_size = GetVisibleBounds().size();
+  const gfx::Size ink_drop_size = GetContentsBounds().size();
   GetInkDrop()->HostSizeChanged(ink_drop_size);
   UpdateInkDropMaskLayerSize(ink_drop_size);
 }
@@ -368,9 +369,12 @@
   DCHECK(mask);
 
   SkPath border;
+  const gfx::Point contents_origin = GetContentsBounds().origin();
   const float scale = GetWidget()->GetCompositor()->device_scale_factor();
-  GetBorderPath(GetTopOffset() * scale, scale,
+  // TODO(pkasting): Fitts' Law horizontally when appropriate.
+  GetBorderPath(contents_origin.y() * scale, scale,
                 tab_strip_->SizeTabButtonToTopOfTabStrip(), &border);
+  border.offset(contents_origin.x(), 0);
   mask->addPath(border, SkMatrix::MakeScale(1 / scale));
   return true;
 }
@@ -392,38 +396,29 @@
   return is_incognito_ && MD::GetMode() == MD::MATERIAL_TOUCH_OPTIMIZED;
 }
 
-gfx::Rect NewTabButton::GetVisibleBounds() const {
-  // TODO(pkasting): This is correct but inefficient for newer material UI.
-  SkPath border;
-  GetBorderPath(GetTopOffset(), 1.0f /* scale */, false, &border);
-  gfx::Rect rect = gfx::ToEnclosingRect(gfx::SkRectToRectF(border.getBounds()));
-  ConvertRectToScreen(this, &rect);
-  return rect;
-}
-
 int NewTabButton::GetCornerRadius() const {
   return ChromeLayoutProvider::Get()->GetCornerRadiusMetric(
-      views::EMPHASIS_MAXIMUM, GetLayoutSize(NEW_TAB_BUTTON, is_incognito_));
+      views::EMPHASIS_MAXIMUM, GetContentsBounds().size());
 }
 
 void NewTabButton::GetBorderPath(float button_y,
                                  float scale,
                                  bool extend_to_top,
                                  SkPath* path) const {
-  const int button_height =
-      GetLayoutSize(NEW_TAB_BUTTON, is_incognito_).height();
+  const gfx::Rect contents_bounds = GetContentsBounds();
 
   if (MD::IsRefreshUi()) {
-    path->addRect(0, extend_to_top ? 0 : button_y, width() * scale,
-                  button_y + button_height * scale);
+    path->addRect(0, extend_to_top ? 0 : button_y,
+                  contents_bounds.width() * scale,
+                  button_y + contents_bounds.height() * scale);
     return;
   }
 
   *path =
       MD::IsTouchOptimizedUiEnabled()
           ? GetTouchOptimizedButtonPath(button_y, scale, extend_to_top, false)
-          : GetNonTouchOptimizedButtonPath(button_y, button_height, scale,
-                                           extend_to_top, false);
+          : GetNonTouchOptimizedButtonPath(button_y, contents_bounds.height(),
+                                           scale, extend_to_top, false);
 }
 
 void NewTabButton::PaintFill(bool pressed,
@@ -461,7 +456,7 @@
       // background should never be mirrored. Mirror it here to compensate.
       float x_scale = 1.0f;
       int x = GetMirroredX() + background_offset_.x();
-      const gfx::Size size(GetLayoutSize(NEW_TAB_BUTTON, is_incognito_));
+      const gfx::Size size = GetContentsBounds().size();
       if (base::i18n::IsRTL()) {
         x_scale = -1.0f;
         // Offset by |width| such that the same region is painted as if there
@@ -470,7 +465,7 @@
       }
 
       const bool succeeded = canvas->InitPaintFlagsForTiling(
-          *tp->GetImageSkiaNamed(bg_id), x, GetTopOffset() + offset_y,
+          *tp->GetImageSkiaNamed(bg_id), x, GetContentsBounds().y() + offset_y,
           x_scale * scale, scale, 0, 0, &flags);
       DCHECK(succeeded);
     } else {
diff --git a/chrome/browser/ui/views/tabs/new_tab_button.h b/chrome/browser/ui/views/tabs/new_tab_button.h
index 835ae77..a2d01dfa 100644
--- a/chrome/browser/ui/views/tabs/new_tab_button.h
+++ b/chrome/browser/ui/views/tabs/new_tab_button.h
@@ -35,10 +35,6 @@
     background_offset_ = offset;
   }
 
-  // Returns the offset from the top of the tabstrip at which the new tab
-  // button's visible region begins.
-  static int GetTopOffset();
-
   // Retrieves the last active BrowserView instance to display the NewTabPromo.
   static void ShowPromoForLastActiveBrowser();
 
@@ -79,6 +75,7 @@
   void PaintButtonContents(gfx::Canvas* canvas) override;
   void Layout() override;
   void OnThemeChanged() override;
+  gfx::Size CalculatePreferredSize() const override;
   void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
 
   // views::MaskedTargeterDelegate:
@@ -90,12 +87,6 @@
   // Returns whether this button should draw an incognito icon.
   bool ShouldDrawIncognitoIcon() const;
 
-  // Returns the gfx::Rect around the visible portion of the New Tab Button.
-  // Note: This is different than the rect around the entire New Tab Button as
-  // it extends to the top of the tabstrip for Fitts' Law interaction in a
-  // maximized window. Used for anchoring the NewTabPromo.
-  gfx::Rect GetVisibleBounds() const;
-
   // Returns the radius to use for the button corners (in newer material UI).
   int GetCornerRadius() const;
 
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index 0b3ded13..7868c06 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -1489,8 +1489,6 @@
   // So we get enter/exit on children to switch stacked layout on and off.
   set_notify_enter_exit_on_child(true);
 
-  new_tab_button_bounds_.set_size(GetLayoutSize(NEW_TAB_BUTTON, IsIncognito()));
-  new_tab_button_bounds_.Inset(0, 0, 0, -NewTabButton::GetTopOffset());
   new_tab_button_ = new NewTabButton(this, this);
   new_tab_button_->SetTooltipText(
       l10n_util::GetStringUTF16(IDS_TOOLTIP_NEW_TAB));
@@ -1502,6 +1500,8 @@
       std::make_unique<views::ViewTargeter>(new_tab_button_));
   AddChildView(new_tab_button_);
 
+  new_tab_button_bounds_.set_size(new_tab_button_->GetPreferredSize());
+
   if (drop_indicator_width == 0) {
     // Direction doesn't matter, both images are the same size.
     gfx::ImageSkia* drop_image = GetDropArrowImage(true);
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc
index b35eda3..5c54273 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -710,6 +710,19 @@
   return app_menu_button_;
 }
 
+gfx::Rect ToolbarView::GetFindBarBoundingBox(int contents_height) const {
+  if (!browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR))
+    return gfx::Rect();
+
+  if (!location_bar_->IsDrawn())
+    return gfx::Rect();
+
+  gfx::Rect bounds =
+      location_bar_->ConvertRectToWidget(location_bar_->GetLocalBounds());
+  return gfx::Rect(bounds.x(), bounds.bottom(), bounds.width(),
+                   contents_height);
+}
+
 void ToolbarView::FocusToolbar() {
   SetPaneFocus(nullptr);
 }
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h
index 160db31..6f7c6fe 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -196,6 +196,7 @@
   BrowserActionsContainer* GetBrowserActionsContainer() override;
   PageActionIconContainerView* GetPageActionIconContainerView() override;
   AppMenuButton* GetAppMenuButton() override;
+  gfx::Rect GetFindBarBoundingBox(int contents_height) const override;
   void FocusToolbar() override;
   views::AccessiblePaneView* GetAsAccessiblePaneView() override;
 
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 6d6c12f..97eb43c 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -780,6 +780,26 @@
   return base::Singleton<ChromeWebUIControllerFactory>::get();
 }
 
+// static
+bool ChromeWebUIControllerFactory::IsWebUIAllowedToMakeNetworkRequests(
+    const url::Origin& origin) {
+  // Whitelist to work around exceptional cases.
+  //
+  // If you are adding a new host to this list, please file a corresponding bug
+  // to track its removal. See https://crbug.com/829412 for the metabug.
+  return
+#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
+      // https://crbug.com/829414
+      origin.host() == chrome::kChromeUIPrintHost ||
+#endif
+      // https://crbug.com/831812
+      origin.host() == chrome::kChromeUISyncConfirmationHost ||
+      // https://crbug.com/831813
+      origin.host() == chrome::kChromeUIInspectHost ||
+      // https://crbug.com/859345
+      origin.host() == chrome::kChromeUIDownloadsHost;
+}
+
 ChromeWebUIControllerFactory::ChromeWebUIControllerFactory() {
 }
 
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.h b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.h
index 462f37a6..b0a3fa7 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.h
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.h
@@ -18,10 +18,21 @@
 class RefCountedMemory;
 }
 
+namespace url {
+class Origin;
+}
+
 class ChromeWebUIControllerFactory : public content::WebUIControllerFactory {
  public:
   static ChromeWebUIControllerFactory* GetInstance();
 
+  // http://crbug.com/829412
+  // Renderers with WebUI bindings shouldn't make http(s) requests for security
+  // reasons (e.g. to avoid malicious responses being able to run code in
+  // priviliged renderers). Fix these webui's to make requests through C++
+  // code instead.
+  static bool IsWebUIAllowedToMakeNetworkRequests(const url::Origin& origin);
+
   // content::WebUIControllerFactory:
   content::WebUI::TypeID GetWebUIType(content::BrowserContext* browser_context,
                                       const GURL& url) const override;
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 e9dc187..7ce766e 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -16,6 +16,7 @@
 #include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/containers/flat_map.h"
+#include "base/feature_list.h"
 #include "base/i18n/number_formatting.h"
 #include "base/json/json_reader.h"
 #include "base/lazy_instance.h"
@@ -48,6 +49,7 @@
 #include "chrome/browser/ui/webui/print_preview/printer_handler.h"
 #include "chrome/browser/ui/webui/print_preview/sticky_settings.h"
 #include "chrome/common/buildflags.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/cloud_print/cloud_print_constants.h"
 #include "chrome/common/crash_keys.h"
@@ -74,7 +76,6 @@
 #include "printing/backend/print_backend_consts.h"
 #include "printing/buildflags/buildflags.h"
 #include "printing/print_settings.h"
-#include "services/network/public/cpp/features.h"
 #include "third_party/icu/source/i18n/unicode/ulocdata.h"
 
 #if defined(OS_CHROMEOS)
@@ -1113,7 +1114,7 @@
       preview_web_contents()->GetBrowserContext());
   PrefService* prefs = profile->GetPrefs();
   if (prefs->GetBoolean(prefs::kCloudPrintSubmitEnabled) &&
-      !base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+      !base::FeatureList::IsEnabled(features::kCloudPrinterHandler)) {
     FireWebUIListener(
         "use-cloud-print",
         base::Value(GURL(cloud_devices::GetCloudPrintURL()).spec()),
@@ -1283,10 +1284,9 @@
     return local_printer_handler_.get();
   }
   if (printer_type == PrinterType::kCloudPrinter) {
-    // This printer handler is currently an empty implementation to prevent
-    // crashes when the network service flag is enabled. Ensure it is never
-    // created otherwise.
-    CHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
+    // This printer handler is currently experimental. Ensure it is never
+    // created unless the flag is enabled.
+    CHECK(base::FeatureList::IsEnabled(features::kCloudPrinterHandler));
     if (!cloud_printer_handler_)
       cloud_printer_handler_ = PrinterHandler::CreateForCloudPrinters();
     return cloud_printer_handler_.get();
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
index 2eb7fa8c..4d571af9 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
@@ -50,7 +50,6 @@
 #include "printing/buildflags/buildflags.h"
 #include "printing/page_size_margins.h"
 #include "printing/print_job_constants.h"
-#include "services/network/public/cpp/features.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/ui_base_features.h"
 #include "ui/gfx/geometry/rect.h"
@@ -422,9 +421,10 @@
       base::FeatureList::IsEnabled(features::kNupPrinting);
   source->AddBoolean("pagesPerSheetEnabled", nup_printing_enabled);
 
-  bool network_service_enabled =
-      base::FeatureList::IsEnabled(network::features::kNetworkService);
-  source->AddBoolean("networkServiceEnabled", network_service_enabled);
+  bool cloud_printer_handler_enabled =
+      base::FeatureList::IsEnabled(features::kCloudPrinterHandler);
+  source->AddBoolean("cloudPrinterHandlerEnabled",
+                     cloud_printer_handler_enabled);
 }
 
 void SetupPrintPreviewPlugin(content::WebUIDataSource* source) {
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index c36abac..9a21e268 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -45,6 +45,7 @@
     "ENABLE_NATIVE_NOTIFICATIONS=$enable_native_notifications",
     "ENABLE_SERVICE_DISCOVERY=$enable_service_discovery",
     "ENABLE_SESSION_SERVICE=$enable_session_service",
+    "ENABLE_SIMPLE_BROWSER_SERVICE=$enable_simple_browser_service",
     "ENABLE_SUPERVISED_USERS=$enable_supervised_users",
     "ENABLE_WAYLAND_SERVER=$enable_wayland_server",
     "PGO_BUILD=$pgo_build",
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 079f3612..4f7e84bd 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -459,6 +459,12 @@
 #endif
 
 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
+// If enabled, Print Preview will use the CloudPrinterHandler instead of the
+// cloud print interface to communicate with the cloud print server. This
+// prevents Print Preview from making direct network requests. See
+// https://crbug.com/829414.
+const base::Feature kCloudPrinterHandler{"CloudPrinterHandler",
+                                         base::FEATURE_DISABLED_BY_DEFAULT};
 // Enables the new Print Preview UI.
 const base::Feature kNewPrintPreview{"NewPrintPreview",
                                      base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index cb5af2e..7089b26 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -246,6 +246,7 @@
 #endif
 
 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
+extern const base::Feature kCloudPrinterHandler;
 extern const base::Feature kNewPrintPreview;
 extern const base::Feature kNupPrinting;
 #endif
diff --git a/chrome/common/features.gni b/chrome/common/features.gni
index 363848f2..3ab61c4 100644
--- a/chrome/common/features.gni
+++ b/chrome/common/features.gni
@@ -5,6 +5,7 @@
 import("//build/config/chrome_build.gni")
 import("//build/config/chromecast_build.gni")
 import("//build/config/compiler/compiler.gni")
+import("//build/config/dcheck_always_on.gni")
 import("//build/config/features.gni")
 import("//build/config/linux/gtk/gtk.gni")
 import("//device/vr/buildflags/buildflags.gni")
@@ -53,6 +54,11 @@
   # Android stores them separately on the Java side.
   enable_session_service = !is_android && !is_chromecast
 
+  # Enables embedding of the simple_browser service, a lightweight browser
+  # application which consumes the Content Service. Useful primarily for
+  # developer testing.
+  enable_simple_browser_service = is_chromeos && (is_debug || dcheck_always_on)
+
   enable_supervised_users = !is_chromecast
 
   # Indicates if Wayland display server support is enabled.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index c7f5a11..5567e39 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -641,6 +641,7 @@
       "../browser/ntp_snippets/content_suggestions_service_factory_browsertest.cc",
       "../browser/ntp_tiles/ntp_tiles_browsertest.cc",
       "../browser/page_load_metrics/observers/ads_page_load_metrics_observer_browsertest.cc",
+      "../browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc",
       "../browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer_browsertest.cc",
       "../browser/page_load_metrics/observers/multi_tab_loading_page_load_metrics_observer_browsertest.cc",
       "../browser/page_load_metrics/observers/security_state_page_load_metrics_observer_browsertest.cc",
diff --git a/chrome/test/base/test_browser_window.h b/chrome/test/base/test_browser_window.h
index c78fa1ca..baa3a78 100644
--- a/chrome/test/base/test_browser_window.h
+++ b/chrome/test/base/test_browser_window.h
@@ -177,7 +177,6 @@
     void UpdateManagePasswordsIconAndBubble() override {}
     void UpdateSaveCreditCardIcon() override {}
     void UpdateLocalCardMigrationIcon() override {}
-    void UpdateFindBarIconVisibility() override {}
     void UpdateBookmarkStarVisibility() override {}
     void UpdateLocationBarVisibility(bool visible, bool animate) override {}
     void SaveStateToContents(content::WebContents* contents) override {}
diff --git a/chrome/test/data/webui/settings/chrome_cleanup_page_test.js b/chrome/test/data/webui/settings/chrome_cleanup_page_test.js
index 0393044..e383918 100644
--- a/chrome/test/data/webui/settings/chrome_cleanup_page_test.js
+++ b/chrome/test/data/webui/settings/chrome_cleanup_page_test.js
@@ -437,6 +437,10 @@
 
     const actionButton = chromeCleanupPage.$$('#action-button');
     assertFalse(!!actionButton);
+
+    const title = chromeCleanupPage.$$('#status-title');
+    assertTrue(!!title);
+    assertTrue(!!title.querySelector('a'));
   });
 
   test('logsUploadingOnScanOffered', function() {
diff --git a/chrome/utility/BUILD.gn b/chrome/utility/BUILD.gn
index 1740a6d7..307e550 100644
--- a/chrome/utility/BUILD.gn
+++ b/chrome/utility/BUILD.gn
@@ -197,6 +197,13 @@
   if (is_android || enable_extensions) {
     deps += [ "//chrome/services/media_gallery_util:lib" ]
   }
+
+  if (enable_simple_browser_service) {
+    deps += [
+      "//services/content/simple_browser",
+      "//services/content/simple_browser/public/mojom",
+    ]
+  }
 }
 
 if (!is_android) {
diff --git a/chrome/utility/DEPS b/chrome/utility/DEPS
index eb50738..b5e28ce 100644
--- a/chrome/utility/DEPS
+++ b/chrome/utility/DEPS
@@ -30,6 +30,7 @@
   "+extensions/common",
   "+extensions/buildflags",
   "+media",
+  "+services/content/simple_browser",
   "+services/network/public",
   "+services/network/url_request_context_builder_mojo.h",
   "+services/proxy_resolver",
diff --git a/chrome/utility/chrome_content_utility_client.cc b/chrome/utility/chrome_content_utility_client.cc
index 2d46f25..41d4652 100644
--- a/chrome/utility/chrome_content_utility_client.cc
+++ b/chrome/utility/chrome_content_utility_client.cc
@@ -86,6 +86,11 @@
 #include "chrome/services/file_util/public/mojom/constants.mojom.h"  // nogncheck
 #endif
 
+#if BUILDFLAG(ENABLE_SIMPLE_BROWSER_SERVICE)
+#include "services/content/simple_browser/public/mojom/constants.mojom.h"
+#include "services/content/simple_browser/simple_browser_service.h"
+#endif
+
 namespace {
 
 base::LazyInstance<ChromeContentUtilityClient::NetworkBinderCreationCallback>::
@@ -261,6 +266,17 @@
   // TODO(jamescook): Figure out why we have to do this when not using mash.
   mash_service_factory_->RegisterOutOfProcessServices(services);
 #endif
+
+#if BUILDFLAG(ENABLE_SIMPLE_BROWSER_SERVICE)
+  {
+    service_manager::EmbeddedServiceInfo service_info;
+    service_info.factory =
+        base::BindRepeating([]() -> std::unique_ptr<service_manager::Service> {
+          return std::make_unique<simple_browser::SimpleBrowserService>();
+        });
+    services->emplace(simple_browser::mojom::kServiceName, service_info);
+  }
+#endif
 }
 
 void ChromeContentUtilityClient::RegisterNetworkBinders(
diff --git a/chromecast/browser/cast_gesture_dispatcher.cc b/chromecast/browser/cast_gesture_dispatcher.cc
index 2805679f..6cf35266 100644
--- a/chromecast/browser/cast_gesture_dispatcher.cc
+++ b/chromecast/browser/cast_gesture_dispatcher.cc
@@ -48,16 +48,14 @@
     return;
   }
 
+  // Already dispatched, don't send further progress events.
+  if (dispatched_back_) {
+    return;
+  }
+
   delegate_->GestureProgress(GestureType::GO_BACK, touch_location);
   VLOG(1) << "swipe gesture continue, elapsed time: "
           << current_swipe_time_.Elapsed().InMilliseconds() << "ms";
-
-  if (!dispatched_back_ && touch_location.x() >= horizontal_threshold_) {
-    dispatched_back_ = true;
-    delegate_->ConsumeGesture(GestureType::GO_BACK);
-    VLOG(1) << "swipe gesture complete, elapsed time: "
-            << current_swipe_time_.Elapsed().InMilliseconds() << "ms";
-  }
 }
 
 void CastGestureDispatcher::HandleSideSwipeEnd(
@@ -71,10 +69,25 @@
   if (!delegate_->CanHandleGesture(GestureType::GO_BACK)) {
     return;
   }
-  if (!dispatched_back_ && touch_location.x() < horizontal_threshold_) {
+
+  // Already dispatched, don't send further events until the next begin.
+  if (dispatched_back_) {
+    return;
+  }
+
+  // Finger lifted before horizontal threshold met, cancel the gesture.
+  if (touch_location.x() < horizontal_threshold_) {
     VLOG(1) << "swipe gesture cancelled";
     delegate_->CancelGesture(GestureType::GO_BACK, touch_location);
+    return;
   }
+
+  // Finger lifted after horizontal threshold, let the consumer know we have a
+  // back gesture.
+  dispatched_back_ = true;
+  delegate_->ConsumeGesture(GestureType::GO_BACK);
+  VLOG(1) << "swipe gesture complete, elapsed time: "
+          << current_swipe_time_.Elapsed().InMilliseconds() << "ms";
 }
 
 void CastGestureDispatcher::HandleTapDownGesture(
diff --git a/chromecast/browser/cast_gesture_dispatcher_test.cc b/chromecast/browser/cast_gesture_dispatcher_test.cc
index c05106b6..f9945377 100644
--- a/chromecast/browser/cast_gesture_dispatcher_test.cc
+++ b/chromecast/browser/cast_gesture_dispatcher_test.cc
@@ -54,14 +54,59 @@
   CastGestureDispatcher dispatcher(&delegate);
   EXPECT_CALL(delegate, CanHandleGesture(Eq(GestureType::GO_BACK)))
       .WillRepeatedly(Return(true));
+  EXPECT_CALL(delegate, GestureProgress(Eq(GestureType::GO_BACK),
+                                        Eq(kOngoingBackGesturePoint1)));
   EXPECT_CALL(delegate, ConsumeGesture(Eq(GestureType::GO_BACK)))
       .WillRepeatedly(Return(true));
+  dispatcher.CanHandleSwipe(CastSideSwipeOrigin::LEFT);
+  dispatcher.HandleSideSwipeBegin(CastSideSwipeOrigin::LEFT, kLeftSidePoint);
+  dispatcher.HandleSideSwipeContinue(CastSideSwipeOrigin::LEFT,
+                                     kOngoingBackGesturePoint1);
+  dispatcher.HandleSideSwipeEnd(CastSideSwipeOrigin::LEFT,
+                                kValidBackGestureEndPoint);
+}
+
+// Verify that if the finger is not lifted, that's not a back gesture.
+TEST(CastGestureDispatcherTest, VerifyNoDispatchOnNoLift) {
+  MockCastContentWindowDelegate delegate;
+  CastGestureDispatcher dispatcher(&delegate);
+  EXPECT_CALL(delegate, CanHandleGesture(Eq(GestureType::GO_BACK)))
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(delegate, ConsumeGesture(Eq(GestureType::GO_BACK))).Times(0);
   EXPECT_CALL(delegate, GestureProgress(Eq(GestureType::GO_BACK),
                                         Eq(kValidBackGestureEndPoint)));
+  EXPECT_CALL(delegate,
+              GestureProgress(Eq(GestureType::GO_BACK), Eq(kPastTheEndPoint1)));
   dispatcher.CanHandleSwipe(CastSideSwipeOrigin::LEFT);
   dispatcher.HandleSideSwipeBegin(CastSideSwipeOrigin::LEFT, kLeftSidePoint);
   dispatcher.HandleSideSwipeContinue(CastSideSwipeOrigin::LEFT,
                                      kValidBackGestureEndPoint);
+  dispatcher.HandleSideSwipeContinue(CastSideSwipeOrigin::LEFT,
+                                     kPastTheEndPoint1);
+}
+
+// Verify that no continue events are dispatched after the end.
+TEST(CastGestureDispatcherTest, VerifyNoContinueAfterEnd) {
+  MockCastContentWindowDelegate delegate;
+  CastGestureDispatcher dispatcher(&delegate);
+  EXPECT_CALL(delegate, CanHandleGesture(Eq(GestureType::GO_BACK)))
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(delegate, GestureProgress(Eq(GestureType::GO_BACK),
+                                        Eq(kOngoingBackGesturePoint1)));
+  EXPECT_CALL(delegate, ConsumeGesture(Eq(GestureType::GO_BACK)))
+      .WillOnce(Return(true));
+  EXPECT_CALL(delegate,
+              GestureProgress(Eq(GestureType::GO_BACK), Eq(kPastTheEndPoint1)))
+      .Times(0);
+
+  dispatcher.CanHandleSwipe(CastSideSwipeOrigin::LEFT);
+  dispatcher.HandleSideSwipeBegin(CastSideSwipeOrigin::LEFT, kLeftSidePoint);
+  dispatcher.HandleSideSwipeContinue(CastSideSwipeOrigin::LEFT,
+                                     kOngoingBackGesturePoint1);
+  dispatcher.HandleSideSwipeEnd(CastSideSwipeOrigin::LEFT,
+                                kValidBackGestureEndPoint);
+  dispatcher.HandleSideSwipeContinue(CastSideSwipeOrigin::LEFT,
+                                     kPastTheEndPoint1);
 }
 
 // Verify that multiple 'continue' events still only lead to one back
@@ -75,8 +120,6 @@
                                         Eq(kValidBackGestureEndPoint)));
   EXPECT_CALL(delegate,
               GestureProgress(Eq(GestureType::GO_BACK), Eq(kPastTheEndPoint1)));
-  EXPECT_CALL(delegate,
-              GestureProgress(Eq(GestureType::GO_BACK), Eq(kPastTheEndPoint2)));
   EXPECT_CALL(delegate, ConsumeGesture(Eq(GestureType::GO_BACK)))
       .WillRepeatedly(Return(true));
   dispatcher.CanHandleSwipe(CastSideSwipeOrigin::LEFT);
@@ -85,8 +128,7 @@
                                      kValidBackGestureEndPoint);
   dispatcher.HandleSideSwipeContinue(CastSideSwipeOrigin::LEFT,
                                      kPastTheEndPoint1);
-  dispatcher.HandleSideSwipeContinue(CastSideSwipeOrigin::LEFT,
-                                     kPastTheEndPoint2);
+  dispatcher.HandleSideSwipeEnd(CastSideSwipeOrigin::LEFT, kPastTheEndPoint2);
 }
 
 // Verify that if the delegate says it doesn't handle back that we won't try to
@@ -100,6 +142,7 @@
   dispatcher.HandleSideSwipeBegin(CastSideSwipeOrigin::LEFT, kLeftSidePoint);
   dispatcher.HandleSideSwipeContinue(CastSideSwipeOrigin::LEFT,
                                      kValidBackGestureEndPoint);
+  dispatcher.HandleSideSwipeEnd(CastSideSwipeOrigin::LEFT, kPastTheEndPoint2);
 }
 
 // Verify that a not-left gesture doesn't lead to a swipe.
@@ -121,10 +164,14 @@
       .WillRepeatedly(Return(true));
   EXPECT_CALL(delegate, GestureProgress(Eq(GestureType::GO_BACK),
                                         Eq(kOngoingBackGesturePoint1)));
+  EXPECT_CALL(delegate, CancelGesture(Eq(GestureType::GO_BACK),
+                                      Eq(kOngoingBackGesturePoint2)));
   dispatcher.CanHandleSwipe(CastSideSwipeOrigin::LEFT);
   dispatcher.HandleSideSwipeBegin(CastSideSwipeOrigin::LEFT, kLeftSidePoint);
   dispatcher.HandleSideSwipeContinue(CastSideSwipeOrigin::LEFT,
                                      kOngoingBackGesturePoint1);
+  dispatcher.HandleSideSwipeEnd(CastSideSwipeOrigin::LEFT,
+                                kOngoingBackGesturePoint2);
 }
 
 // Verify that if the gesture ends before going far enough, that's also not a
diff --git a/components/arc/common/notifications.mojom b/components/arc/common/notifications.mojom
index ae384ec..8f5aa7b9 100644
--- a/components/arc/common/notifications.mojom
+++ b/components/arc/common/notifications.mojom
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// Next MinVersion: 19
+// Next MinVersion: 20
 
 module arc.mojom;
 
@@ -186,7 +186,7 @@
   OpenMessageCenter@6();
 };
 
-// Next Method ID: 8
+// Next Method ID: 9
 // TODO(lhchavez): Migrate all request/response messages to Mojo.
 interface NotificationsInstance {
   // DEPRECATED: Please use Init@5 instead.
@@ -223,7 +223,13 @@
   [MinVersion=17]
   OpenNotificationSnoozeSettings@6(string key);
 
-  // Set the Do-Not-Disturb status on Android side from Chrome side.
+  // Sets the Do-Not-Disturb status on Android side from Chrome side.
   [MinVersion=18]
   SetDoNotDisturbStatusOnAndroid@7(ArcDoNotDisturbStatus status);
+
+  // Cancels the long-press operation even during touching the view. This should
+  // be called when the on-going gesture is recognized not as a normal touch
+  // event but as a scroll event, and the on-going touch should be cancelled.
+  [MinVersion=19]
+  CancelLongPress@8(string key);
 };
diff --git a/components/arc/test/fake_notifications_instance.cc b/components/arc/test/fake_notifications_instance.cc
index 98abfdd92..092810e 100644
--- a/components/arc/test/fake_notifications_instance.cc
+++ b/components/arc/test/fake_notifications_instance.cc
@@ -35,6 +35,8 @@
   latest_do_not_disturb_status_ = std::move(status);
 }
 
+void FakeNotificationsInstance::CancelLongPress(const std::string& key) {}
+
 void FakeNotificationsInstance::InitDeprecated(
     mojom::NotificationsHostPtr host_ptr) {
   Init(std::move(host_ptr), base::DoNothing());
diff --git a/components/arc/test/fake_notifications_instance.h b/components/arc/test/fake_notifications_instance.h
index 9eddbdd6..6a40bd4 100644
--- a/components/arc/test/fake_notifications_instance.h
+++ b/components/arc/test/fake_notifications_instance.h
@@ -32,6 +32,7 @@
   void OpenNotificationSnoozeSettings(const std::string& key) override;
   void SetDoNotDisturbStatusOnAndroid(
       mojom::ArcDoNotDisturbStatusPtr status) override;
+  void CancelLongPress(const std::string& key) override;
 
   const std::vector<std::pair<std::string, mojom::ArcNotificationEvent>>&
   events() const;
diff --git a/components/autofill/core/browser/form_data_importer.cc b/components/autofill/core/browser/form_data_importer.cc
index fa2e83b..d6cb0c5 100644
--- a/components/autofill/core/browser/form_data_importer.cc
+++ b/components/autofill/core/browser/form_data_importer.cc
@@ -131,7 +131,8 @@
     // not match a masked server card. We can offer to upload either kind.
     credit_card_save_manager_->AttemptToOfferCardUploadSave(
         submitted_form, *imported_credit_card,
-        offering_upload_of_local_credit_card_);
+        imported_credit_card_record_type_ ==
+            ImportedCreditCardRecordType::LOCAL_CARD);
   }
 }
 
@@ -172,6 +173,9 @@
   // - ImportCreditCard may update an existing card, or fill
   //   |imported_credit_card| with an extracted card. See .h for details of
   //   |should_return_local_card|.
+  // Reset |imported_credit_card_record_type_| every time we import data from
+  // form no matter whether ImportCreditCard() is called or not.
+  imported_credit_card_record_type_ = ImportedCreditCardRecordType::NO_CARD;
   bool cc_import = false;
   if (credit_card_autofill_enabled) {
     cc_import = ImportCreditCard(submitted_form, should_return_local_card,
@@ -313,9 +317,6 @@
     bool should_return_local_card,
     std::unique_ptr<CreditCard>* imported_credit_card) {
   DCHECK(!*imported_credit_card);
-  // Reset |offering_upload_of_local_credit_card_| every time a new credit card
-  // is imported.
-  offering_upload_of_local_credit_card_ = false;
 
   // The candidate for credit card import. There are many ways for the candidate
   // to be rejected (see everywhere this function returns false, below).
@@ -342,6 +343,9 @@
   }
   AutofillMetrics::LogSubmittedCardStateMetric(
       AutofillMetrics::HAS_CARD_NUMBER_AND_EXPIRATION_DATE);
+  // Can import one valid card per form. Start by treating it as NEW_CARD, but
+  // overwrite this type if we discover it is already a local or server card.
+  imported_credit_card_record_type_ = ImportedCreditCardRecordType::NEW_CARD;
 
   // Attempt to merge with an existing credit card. Don't present a prompt if we
   // have already saved this card number, unless |should_return_local_card| is
@@ -355,13 +359,14 @@
     CreditCard card_copy(*card);
     if (card_copy.UpdateFromImportedCard(candidate_credit_card, app_locale_)) {
       personal_data_manager_->UpdateCreditCard(card_copy);
+      // Mark that the credit card imported from the submitted form is
+      // already a local card.
+      imported_credit_card_record_type_ =
+          ImportedCreditCardRecordType::LOCAL_CARD;
       // If we should not return the local card, return that we merged it,
       // without setting |imported_credit_card|.
       if (!should_return_local_card)
         return true;
-      // Mark that the credit card potentially being offered to upload is
-      // already a local card.
-      offering_upload_of_local_credit_card_ = true;
 
       break;
     }
@@ -375,6 +380,9 @@
   for (const CreditCard* card :
        personal_data_manager_->GetServerCreditCards()) {
     if (candidate_credit_card.HasSameNumberAs(*card)) {
+      // Mark that the imported credit card is a server card.
+      imported_credit_card_record_type_ =
+          ImportedCreditCardRecordType::SERVER_CARD;
       // Record metric on whether expiration dates matched.
       if (candidate_credit_card.expiration_month() ==
               card->expiration_month() &&
diff --git a/components/autofill/core/browser/form_data_importer.h b/components/autofill/core/browser/form_data_importer.h
index 0009ffb..a47d19a 100644
--- a/components/autofill/core/browser/form_data_importer.h
+++ b/components/autofill/core/browser/form_data_importer.h
@@ -25,6 +25,18 @@
 // Owned by AutofillManager.
 class FormDataImporter {
  public:
+  // Record type of the credit card imported from the form, if one exists.
+  enum ImportedCreditCardRecordType {
+    // No card was successfully imported from the form.
+    NO_CARD,
+    // The imported card is already stored locally on the device.
+    LOCAL_CARD,
+    // The imported card is already known to be a server card (either masked or
+    // unmasked).
+    SERVER_CARD,
+    // The imported card is not currently stored with the browser.
+    NEW_CARD,
+  };
   // The parameters should outlive the FormDataImporter.
   FormDataImporter(AutofillClient* client,
                    payments::PaymentsClient* payments_client,
@@ -109,9 +121,10 @@
   // May be NULL.  NULL indicates OTR.
   PersonalDataManager* personal_data_manager_;
 
-  // For metrics, to be passed to |credit_card_save_manager_|. Notes if the
-  // credit card being offered for upload is already a locally-saved card.
-  bool offering_upload_of_local_credit_card_ = false;
+  // Represents the type of the imported credit card from the submitted form.
+  // It will be used to determine whether to offer Upstream or card migration.
+  // Will be passed to |credit_card_save_manager_| for metrics.
+  ImportedCreditCardRecordType imported_credit_card_record_type_;
 
   std::string app_locale_;
 
@@ -124,14 +137,32 @@
                            AllowDuplicateMaskedServerCardIfFlagEnabled);
   FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest, DontDuplicateFullServerCard);
   FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest, DontDuplicateMaskedServerCard);
+  FRIEND_TEST_ALL_PREFIXES(
+      FormDataImporterTest,
+      ImportFormData_ImportCreditCardRecordType_FullServerCard);
   FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
-                           ImportCreditCard_TrackOfferingUploadOfLocalCard);
+                           ImportFormData_ImportCreditCardRecordType_LocalCard);
+  FRIEND_TEST_ALL_PREFIXES(
+      FormDataImporterTest,
+      ImportFormData_ImportCreditCardRecordType_MaskedServerCard);
   FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
-                           ImportCreditCard_TrackOfferingUploadOfNewCard);
+                           ImportFormData_ImportCreditCardRecordType_NewCard);
+  FRIEND_TEST_ALL_PREFIXES(
+      FormDataImporterTest,
+      ImportFormData_ImportCreditCardRecordType_NoCard_ExpiredCard);
+  FRIEND_TEST_ALL_PREFIXES(
+      FormDataImporterTest,
+      ImportFormData_ImportCreditCardRecordType_NoCard_InvalidCardNumber);
+  FRIEND_TEST_ALL_PREFIXES(
+      FormDataImporterTest,
+      ImportFormData_ImportCreditCardRecordType_NoCard_NoCardOnForm);
   FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
                            ImportFormData_OneAddressCreditCardDisabled);
   FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
                            ImportFormData_OneAddressOneCreditCard);
+  FRIEND_TEST_ALL_PREFIXES(
+      FormDataImporterTest,
+      ImportFormData_SecondImportResetsCreditCardRecordType);
   FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
                            ImportFormData_AddressesDisabledOneCreditCard);
   FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
diff --git a/components/autofill/core/browser/form_data_importer_unittest.cc b/components/autofill/core/browser/form_data_importer_unittest.cc
index 206db166..9001c9f9 100644
--- a/components/autofill/core/browser/form_data_importer_unittest.cc
+++ b/components/autofill/core/browser/form_data_importer_unittest.cc
@@ -2043,8 +2043,9 @@
   EXPECT_EQ(0, credit_card.Compare(*results[0]));
 }
 
-// Ensures that |offering_upload_of_local_credit_card_| is set correctly.
-TEST_F(FormDataImporterTest, ImportCreditCard_TrackOfferingUploadOfLocalCard) {
+// Ensures that |imported_credit_card_record_type_| is set and reset correctly.
+TEST_F(FormDataImporterTest,
+       ImportFormData_SecondImportResetsCreditCardRecordType) {
   // Start with a single valid credit card stored via the preferences.
   CreditCard saved_credit_card(base::GenerateGUID(), "https://www.example.com");
   test::SetCreditCardInfo(&saved_credit_card, "Biggie Smalls",
@@ -2067,14 +2068,18 @@
   form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
                                          0 /* source_id */);
   std::unique_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(ImportCreditCard(form_structure, true, &imported_credit_card));
+  EXPECT_TRUE(form_data_importer_->ImportFormData(
+      form_structure, /*profile_autofill_enabled=*/true,
+      /*credit_card_autofill_enabled=*/true,
+      /*should_return_local_card=*/true, &imported_credit_card));
   ASSERT_TRUE(imported_credit_card);
-  // |offering_upload_of_local_credit_card_| should be true because upload was
+  // |imported_credit_card_record_type_| should be LOCAL_CARD because upload was
   // offered and the card is a local card already on the device.
-  ASSERT_TRUE(form_data_importer_->offering_upload_of_local_credit_card_);
+  ASSERT_TRUE(form_data_importer_->imported_credit_card_record_type_ ==
+              FormDataImporter::ImportedCreditCardRecordType::LOCAL_CARD);
 
   // Second form is filled with a new card so
-  // |offering_upload_of_local_credit_card_| should be reset.
+  // |imported_credit_card_record_type_| should be reset.
   // Simulate a form submission with a new card.
   FormData form2;
   AddFullCreditCardForm(&form2, "Biggie Smalls", "4012888888881881", "01",
@@ -2084,15 +2089,57 @@
   form_structure2.DetermineHeuristicTypes(nullptr /* ukm_service */,
                                           0 /* source_id */);
   std::unique_ptr<CreditCard> imported_credit_card2;
-  EXPECT_TRUE(ImportCreditCard(form_structure2, true, &imported_credit_card2));
+  EXPECT_TRUE(form_data_importer_->ImportFormData(
+      form_structure2, /*profile_autofill_enabled=*/true,
+      /*credit_card_autofill_enabled=*/true,
+      /*should_return_local_card=*/true, &imported_credit_card2));
   ASSERT_TRUE(imported_credit_card2);
-  // |offering_upload_of_local_credit_card_| should be false because user use a
-  // new card for upload.
-  ASSERT_FALSE(form_data_importer_->offering_upload_of_local_credit_card_);
+  // |imported_credit_card_record_type_| should be NEW_CARD because the imported
+  // card is not already on the device.
+  ASSERT_TRUE(form_data_importer_->imported_credit_card_record_type_ ==
+              FormDataImporter::ImportedCreditCardRecordType::NEW_CARD);
+
+  // Third form is an address form and set |credit_card_autofill_enabled| to be
+  // false so that the ImportCreditCard won't be called.
+  // |imported_credit_card_record_type_| should still be reset even if
+  // ImportCreditCard is not called. Simulate a form submission with no card.
+  FormData form3;
+  FormFieldData field;
+  test::CreateTestFormField("First name:", "first_name", "George", "text",
+                            &field);
+  form3.fields.push_back(field);
+  test::CreateTestFormField("Last name:", "last_name", "Washington", "text",
+                            &field);
+  form3.fields.push_back(field);
+  test::CreateTestFormField("Email:", "email", "bogus@example.com", "text",
+                            &field);
+  form3.fields.push_back(field);
+  test::CreateTestFormField("Address:", "address1", "21 Laussat St", "text",
+                            &field);
+  form3.fields.push_back(field);
+  test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
+  form3.fields.push_back(field);
+  test::CreateTestFormField("State:", "state", "California", "text", &field);
+  form3.fields.push_back(field);
+  test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
+  form3.fields.push_back(field);
+  FormStructure form_structure3(form3);
+  form_structure3.DetermineHeuristicTypes(nullptr /* ukm_service */,
+                                          0 /* source_id */);
+  std::unique_ptr<CreditCard> imported_credit_card3;
+  EXPECT_TRUE(form_data_importer_->ImportFormData(
+      form_structure3, /*profile_autofill_enabled=*/true,
+      /*credit_card_autofill_enabled=*/false,
+      /*should_return_local_card=*/true, &imported_credit_card3));
+  // |imported_credit_card_record_type_| should be NO_CARD because no valid card
+  // was imported from the form.
+  ASSERT_TRUE(form_data_importer_->imported_credit_card_record_type_ ==
+              FormDataImporter::ImportedCreditCardRecordType::NO_CARD);
 }
 
-// Ensures that |offering_upload_of_local_credit_card_| is set correctly.
-TEST_F(FormDataImporterTest, ImportCreditCard_TrackOfferingUploadOfNewCard) {
+// Ensures that |imported_credit_card_record_type_| is set correctly.
+TEST_F(FormDataImporterTest,
+       ImportFormData_ImportCreditCardRecordType_NewCard) {
   // Simulate a form submission with a new credit card.
   FormData form;
   AddFullCreditCardForm(&form, "Biggie Smalls", "4111 1111 1111 1111", "01",
@@ -2102,11 +2149,207 @@
   form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
                                          0 /* source_id */);
   std::unique_ptr<CreditCard> imported_credit_card;
-  EXPECT_TRUE(ImportCreditCard(form_structure, true, &imported_credit_card));
+  EXPECT_TRUE(form_data_importer_->ImportFormData(
+      form_structure, /*profile_autofill_enabled=*/true,
+      /*credit_card_autofill_enabled=*/true,
+      /*should_return_local_card=*/true, &imported_credit_card));
   ASSERT_TRUE(imported_credit_card);
-  // |offering_upload_of_local_credit_card_| should be false because upload was
-  // offered but the card is NOT a local card already on the device.
-  ASSERT_FALSE(form_data_importer_->offering_upload_of_local_credit_card_);
+  // |imported_credit_card_record_type_| should be NEW_CARD because the imported
+  // card is not already on the device.
+  ASSERT_TRUE(form_data_importer_->imported_credit_card_record_type_ ==
+              FormDataImporter::ImportedCreditCardRecordType::NEW_CARD);
+}
+
+// Ensures that |imported_credit_card_record_type_| is set correctly.
+TEST_F(FormDataImporterTest,
+       ImportFormData_ImportCreditCardRecordType_LocalCard) {
+  // Start with a single valid credit card stored via the preferences.
+  CreditCard saved_credit_card(base::GenerateGUID(), "https://www.example.com");
+  test::SetCreditCardInfo(&saved_credit_card, "Biggie Smalls",
+                          "4111 1111 1111 1111" /* Visa */, "01", "2999", "");
+  personal_data_manager_->AddCreditCard(saved_credit_card);
+
+  WaitForOnPersonalDataChanged();
+
+  const std::vector<CreditCard*>& results =
+      personal_data_manager_->GetCreditCards();
+  ASSERT_EQ(1U, results.size());
+  EXPECT_EQ(0, saved_credit_card.Compare(*results[0]));
+
+  // Simulate a form submission with the same card.
+  FormData form;
+  AddFullCreditCardForm(&form, "Biggie Smalls", "4111 1111 1111 1111", "01",
+                        "2999");
+
+  FormStructure form_structure(form);
+  form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
+                                         0 /* source_id */);
+  std::unique_ptr<CreditCard> imported_credit_card;
+  EXPECT_TRUE(form_data_importer_->ImportFormData(
+      form_structure, /*profile_autofill_enabled=*/true,
+      /*credit_card_autofill_enabled=*/true,
+      /*should_return_local_card=*/true, &imported_credit_card));
+  ASSERT_TRUE(imported_credit_card);
+  // |imported_credit_card_record_type_| should be LOCAL_CARD because upload was
+  // offered and the card is a local card already on the device.
+  ASSERT_TRUE(form_data_importer_->imported_credit_card_record_type_ ==
+              FormDataImporter::ImportedCreditCardRecordType::LOCAL_CARD);
+}
+
+// Ensures that |imported_credit_card_record_type_| is set correctly.
+TEST_F(FormDataImporterTest,
+       ImportFormData_ImportCreditCardRecordType_MaskedServerCard) {
+  // Add a masked server card.
+  std::vector<CreditCard> server_cards;
+  server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "a123"));
+  test::SetCreditCardInfo(&server_cards.back(), "Biggie Smalls",
+                          "1111" /* Visa */, "01", "2999", "");
+  server_cards.back().SetNetworkForMaskedCard(kVisaCard);
+  test::SetServerCreditCards(autofill_table_, server_cards);
+
+  // Make sure everything is set up correctly.
+  personal_data_manager_->Refresh();
+  WaitForOnPersonalDataChanged();
+  EXPECT_EQ(1U, personal_data_manager_->GetCreditCards().size());
+
+  // Simulate a form submission with the same masked server card.
+  FormData form;
+  AddFullCreditCardForm(&form, "Biggie Smalls", "4111 1111 1111 1111", "01",
+                        "2999");
+
+  FormStructure form_structure(form);
+  form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
+                                         0 /* source_id */);
+  std::unique_ptr<CreditCard> imported_credit_card;
+  EXPECT_FALSE(form_data_importer_->ImportFormData(
+      form_structure, /*profile_autofill_enabled=*/true,
+      /*credit_card_autofill_enabled=*/true,
+      /*should_return_local_card=*/true, &imported_credit_card));
+  ASSERT_FALSE(imported_credit_card);
+  // |imported_credit_card_record_type_| should be SERVER_CARD.
+  ASSERT_TRUE(form_data_importer_->imported_credit_card_record_type_ ==
+              FormDataImporter::ImportedCreditCardRecordType::SERVER_CARD);
+}
+
+// Ensures that |imported_credit_card_record_type_| is set correctly.
+TEST_F(FormDataImporterTest,
+       ImportFormData_ImportCreditCardRecordType_FullServerCard) {
+  // Add a full server card.
+  std::vector<CreditCard> server_cards;
+  server_cards.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "c789"));
+  test::SetCreditCardInfo(&server_cards.back(), "Biggie Smalls",
+                          "378282246310005" /* American Express */, "04",
+                          "2999", "1");
+  test::SetServerCreditCards(autofill_table_, server_cards);
+
+  // Make sure everything is set up correctly.
+  personal_data_manager_->Refresh();
+  WaitForOnPersonalDataChanged();
+  EXPECT_EQ(1U, personal_data_manager_->GetCreditCards().size());
+
+  // Simulate a form submission with the same full server card.
+  FormData form;
+  AddFullCreditCardForm(&form, "Biggie Smalls", "378282246310005", "04",
+                        "2999");
+
+  FormStructure form_structure(form);
+  form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
+                                         0 /* source_id */);
+  std::unique_ptr<CreditCard> imported_credit_card;
+  EXPECT_FALSE(form_data_importer_->ImportFormData(
+      form_structure, /*profile_autofill_enabled=*/true,
+      /*credit_card_autofill_enabled=*/true,
+      /*should_return_local_card=*/true, &imported_credit_card));
+  ASSERT_FALSE(imported_credit_card);
+  // |imported_credit_card_record_type_| should be SERVER_CARD.
+  ASSERT_TRUE(form_data_importer_->imported_credit_card_record_type_ ==
+              FormDataImporter::ImportedCreditCardRecordType::SERVER_CARD);
+}
+
+// Ensures that |imported_credit_card_record_type_| is set correctly.
+TEST_F(FormDataImporterTest,
+       ImportFormData_ImportCreditCardRecordType_NoCard_InvalidCardNumber) {
+  // Simulate a form submission using a credit card with an invalid card number.
+  FormData form;
+  AddFullCreditCardForm(&form, "Biggie Smalls", "4111 1111 1111 1112", "01",
+                        "2999");
+
+  FormStructure form_structure(form);
+  form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
+                                         0 /* source_id */);
+  std::unique_ptr<CreditCard> imported_credit_card;
+  EXPECT_FALSE(form_data_importer_->ImportFormData(
+      form_structure, /*profile_autofill_enabled=*/true,
+      /*credit_card_autofill_enabled=*/true,
+      /*should_return_local_card=*/true, &imported_credit_card));
+  ASSERT_FALSE(imported_credit_card);
+  // |imported_credit_card_record_type_| should be NO_CARD because no valid card
+  // was successfully imported from the form.
+  ASSERT_TRUE(form_data_importer_->imported_credit_card_record_type_ ==
+              FormDataImporter::ImportedCreditCardRecordType::NO_CARD);
+}
+
+// Ensures that |imported_credit_card_record_type_| is set correctly.
+TEST_F(FormDataImporterTest,
+       ImportFormData_ImportCreditCardRecordType_NoCard_ExpiredCard) {
+  // Simulate a form submission with an expired credit card.
+  FormData form;
+  AddFullCreditCardForm(&form, "Biggie Smalls", "4111 1111 1111 1111", "01",
+                        "1999");
+
+  FormStructure form_structure(form);
+  form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
+                                         0 /* source_id */);
+  std::unique_ptr<CreditCard> imported_credit_card;
+  EXPECT_FALSE(form_data_importer_->ImportFormData(
+      form_structure, /*profile_autofill_enabled=*/true,
+      /*credit_card_autofill_enabled=*/true,
+      /*should_return_local_card=*/true, &imported_credit_card));
+  ASSERT_FALSE(imported_credit_card);
+  // |imported_credit_card_record_type_| should be NO_CARD because no valid card
+  // was successfully imported from the form.
+  ASSERT_TRUE(form_data_importer_->imported_credit_card_record_type_ ==
+              FormDataImporter::ImportedCreditCardRecordType::NO_CARD);
+}
+
+// Ensures that |imported_credit_card_record_type_| is set correctly.
+TEST_F(FormDataImporterTest,
+       ImportFormData_ImportCreditCardRecordType_NoCard_NoCardOnForm) {
+  // Simulate a form submission with no credit card on form.
+  FormData form;
+  FormFieldData field;
+  test::CreateTestFormField("First name:", "first_name", "George", "text",
+                            &field);
+  form.fields.push_back(field);
+  test::CreateTestFormField("Last name:", "last_name", "Washington", "text",
+                            &field);
+  form.fields.push_back(field);
+  test::CreateTestFormField("Email:", "email", "bogus@example.com", "text",
+                            &field);
+  form.fields.push_back(field);
+  test::CreateTestFormField("Address:", "address1", "21 Laussat St", "text",
+                            &field);
+  form.fields.push_back(field);
+  test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
+  form.fields.push_back(field);
+  test::CreateTestFormField("State:", "state", "California", "text", &field);
+  form.fields.push_back(field);
+  test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
+  form.fields.push_back(field);
+
+  FormStructure form_structure(form);
+  form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
+                                         0 /* source_id */);
+  std::unique_ptr<CreditCard> imported_credit_card;
+  EXPECT_TRUE(form_data_importer_->ImportFormData(
+      form_structure, /*profile_autofill_enabled=*/true,
+      /*credit_card_autofill_enabled=*/true,
+      /*should_return_local_card=*/true, &imported_credit_card));
+  ASSERT_FALSE(imported_credit_card);
+  // |imported_credit_card_record_type_| should be NO_CARD because the form
+  // doesn't have credit card section.
+  ASSERT_TRUE(form_data_importer_->imported_credit_card_record_type_ ==
+              FormDataImporter::ImportedCreditCardRecordType::NO_CARD);
 }
 
 // ImportFormData tests (both addresses and credit cards).
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc
index 6a77a91c..87729c1 100644
--- a/components/browser_sync/profile_sync_service.cc
+++ b/components/browser_sync/profile_sync_service.cc
@@ -196,6 +196,8 @@
       sync_service_url_(
           syncer::GetSyncServiceURL(*base::CommandLine::ForCurrentProcess(),
                                     init_params.channel)),
+      user_events_separate_pref_group_(
+          init_params.user_events_separate_pref_group),
       signin_scoped_device_id_callback_(
           init_params.signin_scoped_device_id_callback),
       network_time_update_callback_(
@@ -1452,7 +1454,8 @@
 
   const syncer::ModelTypeSet registered_types = GetRegisteredDataTypes();
   // Will only enable those types that are registered and preferred.
-  sync_prefs_.SetPreferredDataTypes(registered_types, chosen_types);
+  sync_prefs_.SetPreferredDataTypes(registered_types, chosen_types,
+                                    user_events_separate_pref_group_);
 
   // Now reconfigure the DTM.
   ReconfigureDatatypeManager();
@@ -1490,7 +1493,8 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   const syncer::ModelTypeSet registered_types = GetRegisteredDataTypes();
   const syncer::ModelTypeSet preferred_types =
-      Union(sync_prefs_.GetPreferredDataTypes(registered_types),
+      Union(sync_prefs_.GetPreferredDataTypes(registered_types,
+                                              user_events_separate_pref_group_),
             syncer::ControlTypes());
   const syncer::ModelTypeSet enforced_types =
       Intersection(GetDataTypesFromPreferenceProviders(), registered_types);
diff --git a/components/browser_sync/profile_sync_service.h b/components/browser_sync/profile_sync_service.h
index 24ac43e..52386eb9e 100644
--- a/components/browser_sync/profile_sync_service.h
+++ b/components/browser_sync/profile_sync_service.h
@@ -219,6 +219,7 @@
     std::string debug_identifier;
     version_info::Channel channel = version_info::Channel::UNKNOWN;
     syncer::RepeatingModelTypeStoreFactory model_type_store_factory;
+    bool user_events_separate_pref_group = false;
 
    private:
     DISALLOW_COPY_AND_ASSIGN(InitParams);
@@ -642,6 +643,10 @@
   // This specifies where to find the sync server.
   const GURL sync_service_url_;
 
+  // Whether USER_EVENTS model type has a separate pref group instead of
+  // being bundled with the TYPED_URLS model type.
+  const bool user_events_separate_pref_group_;
+
   // A utility object containing logic and state relating to encryption. It is
   // never null.
   std::unique_ptr<syncer::SyncServiceCrypto> crypto_;
diff --git a/components/consent_auditor/BUILD.gn b/components/consent_auditor/BUILD.gn
index a0633416..b11c6d0d 100644
--- a/components/consent_auditor/BUILD.gn
+++ b/components/consent_auditor/BUILD.gn
@@ -10,6 +10,8 @@
   sources = [
     "consent_auditor.cc",
     "consent_auditor.h",
+    "consent_auditor_impl.cc",
+    "consent_auditor_impl.h",
     "consent_sync_bridge.h",
     "consent_sync_bridge_impl.cc",
     "consent_sync_bridge_impl.h",
@@ -48,7 +50,7 @@
 source_set("unit_tests") {
   testonly = true
   sources = [
-    "consent_auditor_unittest.cc",
+    "consent_auditor_impl_unittest.cc",
     "consent_sync_bridge_impl_unittest.cc",
   ]
 
diff --git a/components/consent_auditor/consent_auditor.cc b/components/consent_auditor/consent_auditor.cc
index 643292f9..2d33d93f 100644
--- a/components/consent_auditor/consent_auditor.cc
+++ b/components/consent_auditor/consent_auditor.cc
@@ -4,226 +4,10 @@
 
 #include "components/consent_auditor/consent_auditor.h"
 
-#include <memory>
-
-#include "base/metrics/histogram_macros.h"
-#include "base/values.h"
-#include "components/consent_auditor/pref_names.h"
-#include "components/prefs/pref_registry_simple.h"
-#include "components/prefs/pref_service.h"
-#include "components/prefs/scoped_user_pref_update.h"
-#include "components/sync/driver/sync_driver_switches.h"
-#include "components/sync/model/model_type_sync_bridge.h"
-#include "components/sync/user_events/user_event_service.h"
-
-using sync_pb::UserConsentTypes;
-using sync_pb::UserConsentSpecifics;
-using sync_pb::UserEventSpecifics;
-
 namespace consent_auditor {
 
-namespace {
-
-const char kLocalConsentDescriptionKey[] = "description";
-const char kLocalConsentConfirmationKey[] = "confirmation";
-const char kLocalConsentVersionKey[] = "version";
-const char kLocalConsentLocaleKey[] = "locale";
-
-bool IsSeparateConsentTypeEnabled() {
-  return base::FeatureList::IsEnabled(switches::kSyncUserConsentSeparateType);
-}
-
-UserEventSpecifics::UserConsent::Feature FeatureToUserEventProtoEnum(
-    consent_auditor::Feature feature) {
-  switch (feature) {
-    case consent_auditor::Feature::CHROME_SYNC:
-      return UserEventSpecifics::UserConsent::CHROME_SYNC;
-    case consent_auditor::Feature::PLAY_STORE:
-      return UserEventSpecifics::UserConsent::PLAY_STORE;
-    case consent_auditor::Feature::BACKUP_AND_RESTORE:
-      return UserEventSpecifics::UserConsent::BACKUP_AND_RESTORE;
-    case consent_auditor::Feature::GOOGLE_LOCATION_SERVICE:
-      return UserEventSpecifics::UserConsent::GOOGLE_LOCATION_SERVICE;
-    case consent_auditor::Feature::CHROME_UNIFIED_CONSENT:
-      return UserEventSpecifics::UserConsent::CHROME_UNIFIED_CONSENT;
-  }
-  NOTREACHED();
-  return UserEventSpecifics::UserConsent::FEATURE_UNSPECIFIED;
-}
-
-UserConsentTypes::ConsentStatus StatusToProtoEnum(
-    consent_auditor::ConsentStatus status) {
-  switch (status) {
-    case consent_auditor::ConsentStatus::NOT_GIVEN:
-      return UserConsentTypes::NOT_GIVEN;
-    case consent_auditor::ConsentStatus::GIVEN:
-      return UserConsentTypes::GIVEN;
-  }
-  NOTREACHED();
-  return UserConsentTypes::CONSENT_STATUS_UNSPECIFIED;
-}
-
-UserConsentSpecifics::Feature FeatureToUserConsentProtoEnum(
-    consent_auditor::Feature feature) {
-  switch (feature) {
-    case consent_auditor::Feature::CHROME_SYNC:
-      return UserConsentSpecifics::CHROME_SYNC;
-    case consent_auditor::Feature::PLAY_STORE:
-      return UserConsentSpecifics::PLAY_STORE;
-    case consent_auditor::Feature::BACKUP_AND_RESTORE:
-      return UserConsentSpecifics::BACKUP_AND_RESTORE;
-    case consent_auditor::Feature::GOOGLE_LOCATION_SERVICE:
-      return UserConsentSpecifics::GOOGLE_LOCATION_SERVICE;
-    case consent_auditor::Feature::CHROME_UNIFIED_CONSENT:
-      return UserConsentSpecifics::CHROME_UNIFIED_CONSENT;
-  }
-  NOTREACHED();
-  return UserConsentSpecifics::FEATURE_UNSPECIFIED;
-}
-
-}  // namespace
-
-ConsentAuditor::ConsentAuditor(
-    PrefService* pref_service,
-    std::unique_ptr<syncer::ConsentSyncBridge> consent_sync_bridge,
-    syncer::UserEventService* user_event_service,
-    const std::string& app_version,
-    const std::string& app_locale)
-    : pref_service_(pref_service),
-      consent_sync_bridge_(std::move(consent_sync_bridge)),
-      user_event_service_(user_event_service),
-      app_version_(app_version),
-      app_locale_(app_locale) {
-  if (IsSeparateConsentTypeEnabled()) {
-    DCHECK(consent_sync_bridge_ && !user_event_service_);
-  } else {
-    DCHECK(user_event_service_ && !consent_sync_bridge_);
-  }
-  DCHECK(pref_service_);
-}
+ConsentAuditor::ConsentAuditor() {}
 
 ConsentAuditor::~ConsentAuditor() {}
 
-void ConsentAuditor::Shutdown() {
-  user_event_service_ = nullptr;
-}
-
-// static
-void ConsentAuditor::RegisterProfilePrefs(PrefRegistrySimple* registry) {
-  registry->RegisterDictionaryPref(prefs::kLocalConsentsDictionary);
-}
-
-void ConsentAuditor::RecordGaiaConsent(
-    const std::string& account_id,
-    Feature feature,
-    const std::vector<int>& description_grd_ids,
-    int confirmation_grd_id,
-    ConsentStatus status) {
-  DCHECK(!account_id.empty()) << "No signed-in account specified.";
-
-  if (!base::FeatureList::IsEnabled(switches::kSyncUserConsentEvents))
-    return;
-
-  DCHECK_LE(feature, consent_auditor::Feature::FEATURE_LAST);
-
-  switch (status) {
-    case ConsentStatus::GIVEN:
-      UMA_HISTOGRAM_ENUMERATION(
-          "Privacy.ConsentAuditor.ConsentGiven.Feature", feature,
-          static_cast<int>(consent_auditor::Feature::FEATURE_LAST) + 1);
-      break;
-    case ConsentStatus::NOT_GIVEN:
-      UMA_HISTOGRAM_ENUMERATION(
-          "Privacy.ConsentAuditor.ConsentNotGiven.Feature", feature,
-          static_cast<int>(consent_auditor::Feature::FEATURE_LAST) + 1);
-      break;
-  }
-
-  if (IsSeparateConsentTypeEnabled()) {
-    // TODO(msramek): Pass in the actual account id.
-    std::unique_ptr<sync_pb::UserConsentSpecifics> specifics =
-        ConstructUserConsentSpecifics(account_id, feature, description_grd_ids,
-                                      confirmation_grd_id, status);
-    consent_sync_bridge_->RecordConsent(std::move(specifics));
-  } else {
-    // TODO(msramek): Pass in the actual account id.
-    std::unique_ptr<sync_pb::UserEventSpecifics> specifics =
-        ConstructUserEventSpecifics(account_id, feature, description_grd_ids,
-                                    confirmation_grd_id, status);
-    user_event_service_->RecordUserEvent(std::move(specifics));
-  }
-}
-
-std::unique_ptr<sync_pb::UserEventSpecifics>
-ConsentAuditor::ConstructUserEventSpecifics(
-    const std::string& account_id,
-    Feature feature,
-    const std::vector<int>& description_grd_ids,
-    int confirmation_grd_id,
-    ConsentStatus status) {
-  DCHECK(!IsSeparateConsentTypeEnabled());
-
-  auto specifics = std::make_unique<sync_pb::UserEventSpecifics>();
-  specifics->set_event_time_usec(
-      base::Time::Now().since_origin().InMicroseconds());
-  auto* consent = specifics->mutable_user_consent();
-  consent->set_account_id(account_id);
-  consent->set_feature(FeatureToUserEventProtoEnum(feature));
-  for (int id : description_grd_ids) {
-    consent->add_description_grd_ids(id);
-  }
-  consent->set_confirmation_grd_id(confirmation_grd_id);
-  consent->set_locale(app_locale_);
-  consent->set_status(StatusToProtoEnum(status));
-  return specifics;
-}
-
-std::unique_ptr<sync_pb::UserConsentSpecifics>
-ConsentAuditor::ConstructUserConsentSpecifics(
-    const std::string& account_id,
-    Feature feature,
-    const std::vector<int>& description_grd_ids,
-    int confirmation_grd_id,
-    ConsentStatus status) {
-  DCHECK(IsSeparateConsentTypeEnabled());
-
-  auto specifics = std::make_unique<sync_pb::UserConsentSpecifics>();
-  specifics->set_client_consent_time_usec(
-      base::Time::Now().since_origin().InMicroseconds());
-  specifics->set_account_id(account_id);
-  specifics->set_feature(FeatureToUserConsentProtoEnum(feature));
-  for (int id : description_grd_ids) {
-    specifics->add_description_grd_ids(id);
-  }
-  specifics->set_confirmation_grd_id(confirmation_grd_id);
-  specifics->set_locale(app_locale_);
-  specifics->set_status(StatusToProtoEnum(status));
-  return specifics;
-}
-
-void ConsentAuditor::RecordLocalConsent(const std::string& feature,
-                                        const std::string& description_text,
-                                        const std::string& confirmation_text) {
-  DictionaryPrefUpdate consents_update(pref_service_,
-                                       prefs::kLocalConsentsDictionary);
-  base::DictionaryValue* consents = consents_update.Get();
-  DCHECK(consents);
-
-  base::DictionaryValue record;
-  record.SetKey(kLocalConsentDescriptionKey, base::Value(description_text));
-  record.SetKey(kLocalConsentConfirmationKey, base::Value(confirmation_text));
-  record.SetKey(kLocalConsentVersionKey, base::Value(app_version_));
-  record.SetKey(kLocalConsentLocaleKey, base::Value(app_locale_));
-
-  consents->SetKey(feature, std::move(record));
-}
-
-base::WeakPtr<syncer::ModelTypeControllerDelegate>
-ConsentAuditor::GetControllerDelegateOnUIThread() {
-  if (consent_sync_bridge_) {
-    return consent_sync_bridge_->GetControllerDelegateOnUIThread();
-  }
-  return base::WeakPtr<syncer::ModelTypeControllerDelegate>();
-}
-
 }  // namespace consent_auditor
diff --git a/components/consent_auditor/consent_auditor.h b/components/consent_auditor/consent_auditor.h
index ef00767..ff90f01 100644
--- a/components/consent_auditor/consent_auditor.h
+++ b/components/consent_auditor/consent_auditor.h
@@ -11,22 +11,12 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "components/consent_auditor/consent_sync_bridge.h"
 #include "components/keyed_service/core/keyed_service.h"
 
 namespace syncer {
 class ModelTypeControllerDelegate;
-class UserEventService;
 }
 
-namespace sync_pb {
-class UserConsentSpecifics;
-class UserEventSpecifics;
-}
-
-class PrefService;
-class PrefRegistrySimple;
-
 namespace consent_auditor {
 
 // Feature for which a consent moment is to be recorded.
@@ -57,19 +47,9 @@
 // fully launched.
 class ConsentAuditor : public KeyedService {
  public:
-  ConsentAuditor(PrefService* pref_service,
-                 std::unique_ptr<syncer::ConsentSyncBridge> consent_sync_bridge,
-                 syncer::UserEventService* user_event_service,
-                 const std::string& app_version,
-                 const std::string& app_locale);
+  ConsentAuditor();
   ~ConsentAuditor() override;
 
-  // KeyedService:
-  void Shutdown() override;
-
-  // Registers the preferences needed by this service.
-  static void RegisterProfilePrefs(PrefRegistrySimple* registry);
-
   // Records a consent for |feature| for the signed-in GAIA account with
   // the ID |account_id| (as defined in AccountInfo).
   // Consent text consisted of strings with |consent_grd_ids|, and the UI
@@ -79,41 +59,21 @@
                                  Feature feature,
                                  const std::vector<int>& description_grd_ids,
                                  int confirmation_grd_id,
-                                 ConsentStatus status);
+                                 ConsentStatus status) = 0;
 
   // Records that the user consented to a |feature|. The user was presented with
   // |description_text| and accepted it by interacting |confirmation_text|
   // (e.g. clicking on a button; empty if not applicable).
   // Returns true if successful.
-  void RecordLocalConsent(const std::string& feature,
-                          const std::string& description_text,
-                          const std::string& confirmation_text);
+  virtual void RecordLocalConsent(const std::string& feature,
+                                  const std::string& description_text,
+                                  const std::string& confirmation_text) = 0;
 
   // Returns the underlying Sync integration point.
-  base::WeakPtr<syncer::ModelTypeControllerDelegate>
-  GetControllerDelegateOnUIThread();
+  virtual base::WeakPtr<syncer::ModelTypeControllerDelegate>
+  GetControllerDelegateOnUIThread() = 0;
 
  private:
-  std::unique_ptr<sync_pb::UserEventSpecifics> ConstructUserEventSpecifics(
-      const std::string& account_id,
-      Feature feature,
-      const std::vector<int>& description_grd_ids,
-      int confirmation_grd_id,
-      ConsentStatus status);
-
-  std::unique_ptr<sync_pb::UserConsentSpecifics> ConstructUserConsentSpecifics(
-      const std::string& account_id,
-      Feature feature,
-      const std::vector<int>& description_grd_ids,
-      int confirmation_grd_id,
-      ConsentStatus status);
-
-  PrefService* pref_service_;
-  std::unique_ptr<syncer::ConsentSyncBridge> consent_sync_bridge_;
-  syncer::UserEventService* user_event_service_;
-  std::string app_version_;
-  std::string app_locale_;
-
   DISALLOW_COPY_AND_ASSIGN(ConsentAuditor);
 };
 
diff --git a/components/consent_auditor/consent_auditor_impl.cc b/components/consent_auditor/consent_auditor_impl.cc
new file mode 100644
index 0000000..913319d
--- /dev/null
+++ b/components/consent_auditor/consent_auditor_impl.cc
@@ -0,0 +1,230 @@
+// Copyright 2018 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/consent_auditor/consent_auditor_impl.h"
+
+#include <memory>
+
+#include "base/metrics/histogram_macros.h"
+#include "base/values.h"
+#include "components/consent_auditor/pref_names.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/scoped_user_pref_update.h"
+#include "components/sync/driver/sync_driver_switches.h"
+#include "components/sync/model/model_type_sync_bridge.h"
+#include "components/sync/user_events/user_event_service.h"
+
+using sync_pb::UserConsentTypes;
+using sync_pb::UserConsentSpecifics;
+using sync_pb::UserEventSpecifics;
+
+namespace consent_auditor {
+
+namespace {
+
+const char kLocalConsentDescriptionKey[] = "description";
+const char kLocalConsentConfirmationKey[] = "confirmation";
+const char kLocalConsentVersionKey[] = "version";
+const char kLocalConsentLocaleKey[] = "locale";
+
+bool IsSeparateConsentTypeEnabled() {
+  return base::FeatureList::IsEnabled(switches::kSyncUserConsentSeparateType);
+}
+
+UserEventSpecifics::UserConsent::Feature FeatureToUserEventProtoEnum(
+    consent_auditor::Feature feature) {
+  switch (feature) {
+    case consent_auditor::Feature::CHROME_SYNC:
+      return UserEventSpecifics::UserConsent::CHROME_SYNC;
+    case consent_auditor::Feature::PLAY_STORE:
+      return UserEventSpecifics::UserConsent::PLAY_STORE;
+    case consent_auditor::Feature::BACKUP_AND_RESTORE:
+      return UserEventSpecifics::UserConsent::BACKUP_AND_RESTORE;
+    case consent_auditor::Feature::GOOGLE_LOCATION_SERVICE:
+      return UserEventSpecifics::UserConsent::GOOGLE_LOCATION_SERVICE;
+    case consent_auditor::Feature::CHROME_UNIFIED_CONSENT:
+      return UserEventSpecifics::UserConsent::CHROME_UNIFIED_CONSENT;
+  }
+  NOTREACHED();
+  return UserEventSpecifics::UserConsent::FEATURE_UNSPECIFIED;
+}
+
+UserConsentTypes::ConsentStatus StatusToProtoEnum(
+    consent_auditor::ConsentStatus status) {
+  switch (status) {
+    case consent_auditor::ConsentStatus::NOT_GIVEN:
+      return UserConsentTypes::NOT_GIVEN;
+    case consent_auditor::ConsentStatus::GIVEN:
+      return UserConsentTypes::GIVEN;
+  }
+  NOTREACHED();
+  return UserConsentTypes::CONSENT_STATUS_UNSPECIFIED;
+}
+
+UserConsentSpecifics::Feature FeatureToUserConsentProtoEnum(
+    consent_auditor::Feature feature) {
+  switch (feature) {
+    case consent_auditor::Feature::CHROME_SYNC:
+      return UserConsentSpecifics::CHROME_SYNC;
+    case consent_auditor::Feature::PLAY_STORE:
+      return UserConsentSpecifics::PLAY_STORE;
+    case consent_auditor::Feature::BACKUP_AND_RESTORE:
+      return UserConsentSpecifics::BACKUP_AND_RESTORE;
+    case consent_auditor::Feature::GOOGLE_LOCATION_SERVICE:
+      return UserConsentSpecifics::GOOGLE_LOCATION_SERVICE;
+    case consent_auditor::Feature::CHROME_UNIFIED_CONSENT:
+      return UserConsentSpecifics::CHROME_UNIFIED_CONSENT;
+  }
+  NOTREACHED();
+  return UserConsentSpecifics::FEATURE_UNSPECIFIED;
+}
+
+}  // namespace
+
+ConsentAuditorImpl::ConsentAuditorImpl(
+    PrefService* pref_service,
+    std::unique_ptr<syncer::ConsentSyncBridge> consent_sync_bridge,
+    syncer::UserEventService* user_event_service,
+    const std::string& app_version,
+    const std::string& app_locale)
+    : pref_service_(pref_service),
+      consent_sync_bridge_(std::move(consent_sync_bridge)),
+      user_event_service_(user_event_service),
+      app_version_(app_version),
+      app_locale_(app_locale) {
+  if (IsSeparateConsentTypeEnabled()) {
+    DCHECK(consent_sync_bridge_ && !user_event_service_);
+  } else {
+    DCHECK(user_event_service_ && !consent_sync_bridge_);
+  }
+  DCHECK(pref_service_);
+}
+
+ConsentAuditorImpl::~ConsentAuditorImpl() {}
+
+void ConsentAuditorImpl::Shutdown() {
+  user_event_service_ = nullptr;
+}
+
+// static
+void ConsentAuditorImpl::RegisterProfilePrefs(PrefRegistrySimple* registry) {
+  registry->RegisterDictionaryPref(prefs::kLocalConsentsDictionary);
+}
+
+void ConsentAuditorImpl::RecordGaiaConsent(
+    const std::string& account_id,
+    Feature feature,
+    const std::vector<int>& description_grd_ids,
+    int confirmation_grd_id,
+    ConsentStatus status) {
+  DCHECK(!account_id.empty()) << "No signed-in account specified.";
+
+  if (!base::FeatureList::IsEnabled(switches::kSyncUserConsentEvents))
+    return;
+
+  DCHECK_LE(feature, consent_auditor::Feature::FEATURE_LAST);
+
+  switch (status) {
+    case ConsentStatus::GIVEN:
+      UMA_HISTOGRAM_ENUMERATION(
+          "Privacy.ConsentAuditor.ConsentGiven.Feature", feature,
+          static_cast<int>(consent_auditor::Feature::FEATURE_LAST) + 1);
+      break;
+    case ConsentStatus::NOT_GIVEN:
+      UMA_HISTOGRAM_ENUMERATION(
+          "Privacy.ConsentAuditor.ConsentNotGiven.Feature", feature,
+          static_cast<int>(consent_auditor::Feature::FEATURE_LAST) + 1);
+      break;
+  }
+
+  if (IsSeparateConsentTypeEnabled()) {
+    // TODO(msramek): Pass in the actual account id.
+    std::unique_ptr<sync_pb::UserConsentSpecifics> specifics =
+        ConstructUserConsentSpecifics(account_id, feature, description_grd_ids,
+                                      confirmation_grd_id, status);
+    consent_sync_bridge_->RecordConsent(std::move(specifics));
+  } else {
+    // TODO(msramek): Pass in the actual account id.
+    std::unique_ptr<sync_pb::UserEventSpecifics> specifics =
+        ConstructUserEventSpecifics(account_id, feature, description_grd_ids,
+                                    confirmation_grd_id, status);
+    user_event_service_->RecordUserEvent(std::move(specifics));
+  }
+}
+
+std::unique_ptr<sync_pb::UserEventSpecifics>
+ConsentAuditorImpl::ConstructUserEventSpecifics(
+    const std::string& account_id,
+    Feature feature,
+    const std::vector<int>& description_grd_ids,
+    int confirmation_grd_id,
+    ConsentStatus status) {
+  DCHECK(!IsSeparateConsentTypeEnabled());
+
+  auto specifics = std::make_unique<sync_pb::UserEventSpecifics>();
+  specifics->set_event_time_usec(
+      base::Time::Now().since_origin().InMicroseconds());
+  auto* consent = specifics->mutable_user_consent();
+  consent->set_account_id(account_id);
+  consent->set_feature(FeatureToUserEventProtoEnum(feature));
+  for (int id : description_grd_ids) {
+    consent->add_description_grd_ids(id);
+  }
+  consent->set_confirmation_grd_id(confirmation_grd_id);
+  consent->set_locale(app_locale_);
+  consent->set_status(StatusToProtoEnum(status));
+  return specifics;
+}
+
+std::unique_ptr<sync_pb::UserConsentSpecifics>
+ConsentAuditorImpl::ConstructUserConsentSpecifics(
+    const std::string& account_id,
+    Feature feature,
+    const std::vector<int>& description_grd_ids,
+    int confirmation_grd_id,
+    ConsentStatus status) {
+  DCHECK(IsSeparateConsentTypeEnabled());
+
+  auto specifics = std::make_unique<sync_pb::UserConsentSpecifics>();
+  specifics->set_client_consent_time_usec(
+      base::Time::Now().since_origin().InMicroseconds());
+  specifics->set_account_id(account_id);
+  specifics->set_feature(FeatureToUserConsentProtoEnum(feature));
+  for (int id : description_grd_ids) {
+    specifics->add_description_grd_ids(id);
+  }
+  specifics->set_confirmation_grd_id(confirmation_grd_id);
+  specifics->set_locale(app_locale_);
+  specifics->set_status(StatusToProtoEnum(status));
+  return specifics;
+}
+
+void ConsentAuditorImpl::RecordLocalConsent(
+    const std::string& feature,
+    const std::string& description_text,
+    const std::string& confirmation_text) {
+  DictionaryPrefUpdate consents_update(pref_service_,
+                                       prefs::kLocalConsentsDictionary);
+  base::DictionaryValue* consents = consents_update.Get();
+  DCHECK(consents);
+
+  base::DictionaryValue record;
+  record.SetKey(kLocalConsentDescriptionKey, base::Value(description_text));
+  record.SetKey(kLocalConsentConfirmationKey, base::Value(confirmation_text));
+  record.SetKey(kLocalConsentVersionKey, base::Value(app_version_));
+  record.SetKey(kLocalConsentLocaleKey, base::Value(app_locale_));
+
+  consents->SetKey(feature, std::move(record));
+}
+
+base::WeakPtr<syncer::ModelTypeControllerDelegate>
+ConsentAuditorImpl::GetControllerDelegateOnUIThread() {
+  if (consent_sync_bridge_) {
+    return consent_sync_bridge_->GetControllerDelegateOnUIThread();
+  }
+  return base::WeakPtr<syncer::ModelTypeControllerDelegate>();
+}
+
+}  // namespace consent_auditor
diff --git a/components/consent_auditor/consent_auditor_impl.h b/components/consent_auditor/consent_auditor_impl.h
new file mode 100644
index 0000000..acad016
--- /dev/null
+++ b/components/consent_auditor/consent_auditor_impl.h
@@ -0,0 +1,102 @@
+// Copyright 2018 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_CONSENT_AUDITOR_CONSENT_AUDITOR_IMPL_H_
+#define COMPONENTS_CONSENT_AUDITOR_CONSENT_AUDITOR_IMPL_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "components/consent_auditor/consent_auditor.h"
+#include "components/consent_auditor/consent_sync_bridge.h"
+#include "components/keyed_service/core/keyed_service.h"
+
+namespace syncer {
+class ModelTypeControllerDelegate;
+class UserEventService;
+}  // namespace syncer
+
+namespace sync_pb {
+class UserConsentSpecifics;
+class UserEventSpecifics;
+}  // namespace sync_pb
+
+class PrefService;
+class PrefRegistrySimple;
+
+namespace consent_auditor {
+
+// TODO(vitaliii): Delete user-event-related code once USER_CONSENTS type is
+// fully launched.
+class ConsentAuditorImpl : public ConsentAuditor {
+ public:
+  ConsentAuditorImpl(
+      PrefService* pref_service,
+      std::unique_ptr<syncer::ConsentSyncBridge> consent_sync_bridge,
+      syncer::UserEventService* user_event_service,
+      const std::string& app_version,
+      const std::string& app_locale);
+  ~ConsentAuditorImpl() override;
+
+  // KeyedService (through ConsentAuditor) implementation.
+  void Shutdown() override;
+
+  // Registers the preferences needed by this service.
+  static void RegisterProfilePrefs(PrefRegistrySimple* registry);
+
+  // Consent auditor implementation.
+
+  // Records a consent for |feature| for the signed-in GAIA account with
+  // the ID |account_id| (as defined in AccountInfo).
+  // Consent text consisted of strings with |consent_grd_ids|, and the UI
+  // element the user clicked had the ID |confirmation_grd_id|.
+  // Whether the consent was GIVEN or NOT_GIVEN is passed as |status|.
+  void RecordGaiaConsent(const std::string& account_id,
+                         Feature feature,
+                         const std::vector<int>& description_grd_ids,
+                         int confirmation_grd_id,
+                         ConsentStatus status) override;
+
+  // Records that the user consented to a |feature|. The user was presented with
+  // |description_text| and accepted it by interacting |confirmation_text|
+  // (e.g. clicking on a button; empty if not applicable).
+  // Returns true if successful.
+  void RecordLocalConsent(const std::string& feature,
+                          const std::string& description_text,
+                          const std::string& confirmation_text) override;
+
+  // Returns the underlying Sync integration point.
+  base::WeakPtr<syncer::ModelTypeControllerDelegate>
+  GetControllerDelegateOnUIThread() override;
+
+ private:
+  std::unique_ptr<sync_pb::UserEventSpecifics> ConstructUserEventSpecifics(
+      const std::string& account_id,
+      Feature feature,
+      const std::vector<int>& description_grd_ids,
+      int confirmation_grd_id,
+      ConsentStatus status);
+
+  std::unique_ptr<sync_pb::UserConsentSpecifics> ConstructUserConsentSpecifics(
+      const std::string& account_id,
+      Feature feature,
+      const std::vector<int>& description_grd_ids,
+      int confirmation_grd_id,
+      ConsentStatus status);
+
+  PrefService* pref_service_;
+  std::unique_ptr<syncer::ConsentSyncBridge> consent_sync_bridge_;
+  syncer::UserEventService* user_event_service_;
+  std::string app_version_;
+  std::string app_locale_;
+
+  DISALLOW_COPY_AND_ASSIGN(ConsentAuditorImpl);
+};
+
+}  // namespace consent_auditor
+
+#endif  // COMPONENTS_CONSENT_AUDITOR_CONSENT_AUDITOR_IMPL_H_
diff --git a/components/consent_auditor/consent_auditor_unittest.cc b/components/consent_auditor/consent_auditor_impl_unittest.cc
similarity index 91%
rename from components/consent_auditor/consent_auditor_unittest.cc
rename to components/consent_auditor/consent_auditor_impl_unittest.cc
index 3648427..ddb10716 100644
--- a/components/consent_auditor/consent_auditor_unittest.cc
+++ b/components/consent_auditor/consent_auditor_impl_unittest.cc
@@ -1,8 +1,8 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
+// Copyright 2018 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/consent_auditor/consent_auditor.h"
+#include "components/consent_auditor/consent_auditor_impl.h"
 
 #include <map>
 #include <memory>
@@ -104,25 +104,25 @@
 
 }  // namespace
 
-class ConsentAuditorTest : public testing::Test {
+class ConsentAuditorImplTest : public testing::Test {
  public:
   void SetUp() override {
     pref_service_ = std::make_unique<TestingPrefServiceSimple>();
     user_event_service_ = std::make_unique<syncer::FakeUserEventService>();
-    ConsentAuditor::RegisterProfilePrefs(pref_service_->registry());
+    ConsentAuditorImpl::RegisterProfilePrefs(pref_service_->registry());
     app_version_ = kCurrentAppVersion;
     app_locale_ = kCurrentAppLocale;
-    BuildConsentAuditor();
+    BuildConsentAuditorImpl();
   }
 
   // TODO(vitaliii): Add a real builder class instead.
-  void BuildConsentAuditor() {
-    consent_auditor_ = std::make_unique<ConsentAuditor>(
+  void BuildConsentAuditorImpl() {
+    consent_auditor_ = std::make_unique<ConsentAuditorImpl>(
         pref_service_.get(), std::move(consent_sync_bridge_),
         user_event_service_.get(), app_version_, app_locale_);
   }
 
-  // These have no effect before |BuildConsentAuditor|.
+  // These have no effect before |BuildConsentAuditorImpl|.
   void SetAppVersion(const std::string& new_app_version) {
     app_version_ = new_app_version;
   }
@@ -150,14 +150,14 @@
     }
   }
 
-  ConsentAuditor* consent_auditor() { return consent_auditor_.get(); }
+  ConsentAuditorImpl* consent_auditor() { return consent_auditor_.get(); }
   PrefService* pref_service() const { return pref_service_.get(); }
   syncer::FakeUserEventService* user_event_service() {
     return user_event_service_.get();
   }
 
  private:
-  std::unique_ptr<ConsentAuditor> consent_auditor_;
+  std::unique_ptr<ConsentAuditorImpl> consent_auditor_;
 
   std::unique_ptr<TestingPrefServiceSimple> pref_service_;
   std::unique_ptr<syncer::FakeUserEventService> user_event_service_;
@@ -168,10 +168,10 @@
   variations::testing::VariationParamsManager params_manager_;
 };
 
-TEST_F(ConsentAuditorTest, LocalConsentPrefRepresentation) {
+TEST_F(ConsentAuditorImplTest, LocalConsentPrefRepresentation) {
   SetAppVersion(kCurrentAppVersion);
   SetAppLocale(kCurrentAppLocale);
-  BuildConsentAuditor();
+  BuildConsentAuditorImpl();
 
   // No consents are written at first.
   EXPECT_FALSE(pref_service()->HasPrefPath(prefs::kLocalConsentsDictionary));
@@ -223,7 +223,7 @@
   SetAppLocale(kFeature2NewAppLocale);
   // We rebuild consent auditor to emulate restarting Chrome. This is the only
   // way to change app version or app locale.
-  BuildConsentAuditor();
+  BuildConsentAuditorImpl();
 
   consent_auditor()->RecordLocalConsent("feature2", kFeature2NewDescription,
                                         kFeature2NewConfirmation);
@@ -238,7 +238,7 @@
   EXPECT_EQ(2u, consents->size());
 }
 
-TEST_F(ConsentAuditorTest, RecordingEnabled) {
+TEST_F(ConsentAuditorImplTest, RecordingEnabled) {
   SetIsSeparateConsentTypeEnabledFeature(false);
 
   consent_auditor()->RecordGaiaConsent(kAccountId, Feature::CHROME_SYNC, {}, 0,
@@ -247,7 +247,7 @@
   EXPECT_EQ(1U, events.size());
 }
 
-TEST_F(ConsentAuditorTest, RecordingDisabled) {
+TEST_F(ConsentAuditorImplTest, RecordingDisabled) {
   SetIsSeparateConsentTypeEnabledFeature(false);
 
   base::test::ScopedFeatureList scoped_feature_list;
@@ -258,12 +258,12 @@
   EXPECT_EQ(0U, events.size());
 }
 
-TEST_F(ConsentAuditorTest, RecordGaiaConsentAsUserEvent) {
+TEST_F(ConsentAuditorImplTest, RecordGaiaConsentAsUserEvent) {
   SetIsSeparateConsentTypeEnabledFeature(false);
   SetConsentSyncBridge(nullptr);
   SetAppVersion(kCurrentAppVersion);
   SetAppLocale(kCurrentAppLocale);
-  BuildConsentAuditor();
+  BuildConsentAuditorImpl();
 
   std::vector<int> kDescriptionMessageIds = {12, 37, 42};
   int kConfirmationMessageId = 47;
@@ -289,7 +289,7 @@
   EXPECT_EQ(kCurrentAppLocale, consent.locale());
 }
 
-TEST_F(ConsentAuditorTest, RecordGaiaConsentAsUserConsent) {
+TEST_F(ConsentAuditorImplTest, RecordGaiaConsentAsUserConsent) {
   SetIsSeparateConsentTypeEnabledFeature(true);
 
   auto wrapped_fake_bridge = std::make_unique<FakeConsentSyncBridge>();
@@ -300,7 +300,7 @@
   SetUserEventService(nullptr);
   SetAppVersion(kCurrentAppVersion);
   SetAppLocale(kCurrentAppLocale);
-  BuildConsentAuditor();
+  BuildConsentAuditorImpl();
 
   std::vector<int> kDescriptionMessageIds = {12, 37, 42};
   int kConfirmationMessageId = 47;
@@ -330,17 +330,17 @@
   EXPECT_EQ(kCurrentAppLocale, consent.locale());
 }
 
-TEST_F(ConsentAuditorTest, ShouldReturnNoSyncDelegateWhenNoBridge) {
+TEST_F(ConsentAuditorImplTest, ShouldReturnNoSyncDelegateWhenNoBridge) {
   SetIsSeparateConsentTypeEnabledFeature(false);
   SetConsentSyncBridge(nullptr);
-  BuildConsentAuditor();
+  BuildConsentAuditorImpl();
 
   // There is no bridge (i.e. separate sync type for consents is disabled),
   // thus, there should be no delegate as well.
   EXPECT_EQ(nullptr, consent_auditor()->GetControllerDelegateOnUIThread());
 }
 
-TEST_F(ConsentAuditorTest, ShouldReturnSyncDelegateWhenBridgePresent) {
+TEST_F(ConsentAuditorImplTest, ShouldReturnSyncDelegateWhenBridgePresent) {
   SetIsSeparateConsentTypeEnabledFeature(true);
   auto fake_bridge = std::make_unique<FakeConsentSyncBridge>();
 
@@ -352,7 +352,7 @@
 
   SetConsentSyncBridge(std::move(fake_bridge));
   SetUserEventService(nullptr);
-  BuildConsentAuditor();
+  BuildConsentAuditorImpl();
 
   // There is a bridge (i.e. separate sync type for consents is enabled), thus,
   // there should be a delegate as well.
diff --git a/components/consent_auditor/fake_consent_auditor.cc b/components/consent_auditor/fake_consent_auditor.cc
index 2adee70..fd99e13 100644
--- a/components/consent_auditor/fake_consent_auditor.cc
+++ b/components/consent_auditor/fake_consent_auditor.cc
@@ -8,14 +8,7 @@
 
 namespace consent_auditor {
 
-FakeConsentAuditor::FakeConsentAuditor(
-    PrefService* pref_service,
-    syncer::UserEventService* user_event_service)
-    : ConsentAuditor(pref_service,
-                     /*consent_sync_bridge=*/nullptr,
-                     user_event_service,
-                     /*app_version=*/std::string(),
-                     /*app_locale=*/std::string()) {}
+FakeConsentAuditor::FakeConsentAuditor() {}
 
 FakeConsentAuditor::~FakeConsentAuditor() {}
 
@@ -32,4 +25,17 @@
   recorded_statuses_.push_back(status);
 }
 
+void FakeConsentAuditor::RecordLocalConsent(
+    const std::string& feature,
+    const std::string& description_text,
+    const std::string& confirmation_text) {
+  NOTIMPLEMENTED();
+}
+
+base::WeakPtr<syncer::ModelTypeControllerDelegate>
+FakeConsentAuditor::GetControllerDelegateOnUIThread() {
+  NOTIMPLEMENTED();
+  return nullptr;
+}
+
 }  // namespace consent_auditor
diff --git a/components/consent_auditor/fake_consent_auditor.h b/components/consent_auditor/fake_consent_auditor.h
index 56a37ce..82310e8 100644
--- a/components/consent_auditor/fake_consent_auditor.h
+++ b/components/consent_auditor/fake_consent_auditor.h
@@ -10,26 +10,26 @@
 #include "base/macros.h"
 #include "components/consent_auditor/consent_auditor.h"
 
-namespace syncer {
-class UserEventService;
-}
-
-class PrefService;
-
 namespace consent_auditor {
 
 class FakeConsentAuditor : public ConsentAuditor {
  public:
-  FakeConsentAuditor(PrefService* pref_service,
-                     syncer::UserEventService* user_event_service);
+  FakeConsentAuditor();
   ~FakeConsentAuditor() override;
 
+  // ConsentAuditor implementation.
   void RecordGaiaConsent(const std::string& account_id,
                          consent_auditor::Feature feature,
                          const std::vector<int>& description_grd_ids,
                          int confirmation_grd_id,
                          consent_auditor::ConsentStatus status) override;
+  void RecordLocalConsent(const std::string& feature,
+                          const std::string& description_text,
+                          const std::string& confirmation_text) override;
+  base::WeakPtr<syncer::ModelTypeControllerDelegate>
+  GetControllerDelegateOnUIThread() override;
 
+  // Methods for fake.
   const std::string& account_id() const { return account_id_; }
 
   const std::vector<std::vector<int>>& recorded_id_vectors() {
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_use_observer.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_use_observer.cc
index ffb0b2d..f61dd41 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_use_observer.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_data_use_observer.cc
@@ -12,6 +12,7 @@
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
+#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
 #include "components/data_reduction_proxy/core/common/lofi_decider.h"
 #include "components/data_use_measurement/core/data_use.h"
 #include "components/data_use_measurement/core/data_use_ascriber.h"
@@ -63,7 +64,8 @@
     : data_reduction_proxy_io_data_(data_reduction_proxy_io_data),
       data_use_ascriber_(data_use_ascriber) {
   DCHECK(data_reduction_proxy_io_data_);
-  data_use_ascriber_->AddObserver(this);
+  if (!data_reduction_proxy::params::IsDataSaverSiteBreakdownUsingPLMEnabled())
+    data_use_ascriber_->AddObserver(this);
 }
 
 DataReductionProxyDataUseObserver::~DataReductionProxyDataUseObserver() {
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_features.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_features.cc
index 3b007a4b..75e628b 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_features.cc
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_features.cc
@@ -44,5 +44,11 @@
 const base::Feature kDogfood{"DataReductionProxyDogfood",
                              base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Enables recording of the site-breakdown metrics using the page load metrics
+// harness, and disables the observer for data use ascriber.
+const base::Feature kDataSaverSiteBreakdownUsingPageLoadMetrics{
+    "DataSaverSiteBreakdownUsingPageLoadMetrics",
+    base::FEATURE_DISABLED_BY_DEFAULT};
+
 }  // namespace features
 }  // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_features.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_features.h
index d9711e1..6682513 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_features.h
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_features.h
@@ -16,6 +16,7 @@
 extern const base::Feature kMissingViaHeaderShortDuration;
 extern const base::Feature kDataReductionProxyRobustConnection;
 extern const base::Feature kDogfood;
+extern const base::Feature kDataSaverSiteBreakdownUsingPageLoadMetrics;
 
 }  // namespace features
 }  // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
index 574c7117..a8ed2fe 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
@@ -407,6 +407,12 @@
   return GURL(secure_proxy_check_url);
 }
 
+bool IsDataSaverSiteBreakdownUsingPLMEnabled() {
+  return base::FeatureList::IsEnabled(
+      data_reduction_proxy::features::
+          kDataSaverSiteBreakdownUsingPageLoadMetrics);
+}
+
 }  // namespace params
 
 DataReductionProxyParams::DataReductionProxyParams() {
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
index a40d20b..978b73d 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
@@ -147,6 +147,10 @@
 // Returns the experiment parameter name to disable missing via header bypasses.
 const char* GetMissingViaBypassParamName();
 
+// Returns if site-breakdown metrics should be recorded using the page load
+// metrics harness.
+bool IsDataSaverSiteBreakdownUsingPLMEnabled();
+
 // Returns the experiment parameter name to discard the cached result for canary
 // check probe.
 const char* GetDiscardCanaryCheckResultParam();
diff --git a/components/exo/pointer.cc b/components/exo/pointer.cc
index 9484e59d..08ec41d2 100644
--- a/components/exo/pointer.cc
+++ b/components/exo/pointer.cc
@@ -155,6 +155,10 @@
 }
 
 void Pointer::SetCursorType(ui::CursorType cursor_type) {
+  // Early out if the pointer doesn't have a surface in focus.
+  if (!focus_surface_)
+    return;
+
   if (cursor_ == cursor_type)
     return;
   cursor_ = cursor_type;
diff --git a/components/exo/pointer_unittest.cc b/components/exo/pointer_unittest.cc
index f1a2d38..9056fea 100644
--- a/components/exo/pointer_unittest.cc
+++ b/components/exo/pointer_unittest.cc
@@ -226,6 +226,38 @@
   pointer.reset();
 }
 
+TEST_F(MAYBE_PointerTest, SetCursorTypeOutsideOfSurface) {
+  std::unique_ptr<Surface> surface(new Surface);
+  std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get()));
+  gfx::Size buffer_size(10, 10);
+  std::unique_ptr<Buffer> buffer(
+      new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
+  surface->Attach(buffer.get());
+  surface->Commit();
+
+  MockPointerDelegate delegate;
+  std::unique_ptr<Pointer> pointer(new Pointer(&delegate));
+  ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
+
+  EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface.get()))
+      .WillRepeatedly(testing::Return(true));
+  generator.MoveMouseTo(surface->window()->GetBoundsInScreen().origin() -
+                        gfx::Vector2d(1, 1));
+
+  pointer->SetCursorType(ui::CursorType::kIBeam);
+  RunAllPendingInMessageLoop();
+
+  EXPECT_EQ(nullptr, pointer->root_surface());
+  aura::client::CursorClient* cursor_client = aura::client::GetCursorClient(
+      shell_surface->GetWidget()->GetNativeWindow()->GetRootWindow());
+  // The cursor type shouldn't be the specified one, since the pointer is
+  // located outside of the surface.
+  EXPECT_NE(ui::CursorType::kIBeam, cursor_client->GetCursor().native_type());
+
+  EXPECT_CALL(delegate, OnPointerDestroying(pointer.get()));
+  pointer.reset();
+}
+
 TEST_F(MAYBE_PointerTest, SetCursorAndSetCursorType) {
   std::unique_ptr<Surface> surface(new Surface);
   std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get()));
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index babf479..0cbfea89 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -885,7 +885,7 @@
 
       This controls DNS prefetching, TCP and SSL preconnection and prerendering of web pages.
 
-      If you set this preference to 'always', 'never', or 'WiFi only', users cannot change or override this setting in <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph>.
+      If you set this policy, users cannot change or override this setting in <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph>.
 
       If this policy is left not set, network prediction will be enabled but the user will be able to change it.''',
     },
diff --git a/components/search/OWNERS b/components/search/OWNERS
index bad91db..b15621a5 100644
--- a/components/search/OWNERS
+++ b/components/search/OWNERS
@@ -1,3 +1,4 @@
+mathp@chromium.org
 treib@chromium.org
 sfiera@chromium.org
 
diff --git a/components/search_provider_logos/logo_service_impl_unittest.cc b/components/search_provider_logos/logo_service_impl_unittest.cc
index 4e53a588..9ea86f4b 100644
--- a/components/search_provider_logos/logo_service_impl_unittest.cc
+++ b/components/search_provider_logos/logo_service_impl_unittest.cc
@@ -281,16 +281,13 @@
 // signing in/out.
 class SigninHelper {
  public:
-  SigninHelper(base::test::ScopedTaskEnvironment* task_environment,
-               net::FakeURLFetcherFactory* fetcher_factory)
+  explicit SigninHelper(base::test::ScopedTaskEnvironment* task_environment)
       : task_environment_(task_environment),
         signin_client_(&pref_service_),
         cookie_service_(&token_service_, "test_source", &signin_client_) {
     // GaiaCookieManagerService calls static methods of AccountTrackerService
     // which access prefs.
     AccountTrackerService::RegisterPrefs(pref_service_.registry());
-
-    cookie_service_.Init(fetcher_factory);
   }
 
   GaiaCookieManagerService* cookie_service() { return &cookie_service_; }
@@ -325,8 +322,7 @@
         shared_factory_(
             base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
                 &test_url_loader_factory_)),
-        fake_url_fetcher_factory_(nullptr),
-        signin_helper_(&task_environment_, &fake_url_fetcher_factory_),
+        signin_helper_(&task_environment_),
         use_gray_background_(false) {
     test_url_loader_factory_.SetInterceptor(base::BindRepeating(
         &LogoServiceImplTest::CapturingInterceptor, base::Unretained(this)));
@@ -395,14 +391,11 @@
   base::SimpleTestClock test_clock_;
   NiceMock<MockLogoCache>* logo_cache_;
 
-  // There is a bit of transition pain here: |fake_url_fetcher_factory_| is used
-  // for signin_helper,  while |test_url_loader_factory_| is used for
-  // logo_service_.
+  // Used for mocking |logo_service_| URLs.
   network::TestURLLoaderFactory test_url_loader_factory_;
   scoped_refptr<network::SharedURLLoaderFactory> shared_factory_;
   std::unique_ptr<LogoServiceImpl> logo_service_;
 
-  net::FakeURLFetcherFactory fake_url_fetcher_factory_;
   SigninHelper signin_helper_;
 
   GURL latest_url_;
diff --git a/components/signin/core/browser/account_investigator_unittest.cc b/components/signin/core/browser/account_investigator_unittest.cc
index ba93a3e..aef935b 100644
--- a/components/signin/core/browser/account_investigator_unittest.cc
+++ b/components/signin/core/browser/account_investigator_unittest.cc
@@ -23,7 +23,6 @@
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/google_service_auth_error.h"
-#include "net/url_request/test_url_fetcher_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using base::HistogramTester;
@@ -44,13 +43,13 @@
         gaia_cookie_manager_service_(nullptr,
                                      GaiaConstants::kChromeSource,
                                      &signin_client_),
-        investigator_(&gaia_cookie_manager_service_, &prefs_, &signin_manager_),
-        fake_url_fetcher_factory_(nullptr) {
+        investigator_(&gaia_cookie_manager_service_,
+                      &prefs_,
+                      &signin_manager_) {
     AccountTrackerService::RegisterPrefs(prefs_.registry());
     AccountInvestigator::RegisterPrefs(prefs_.registry());
     SigninManagerBase::RegisterProfilePrefs(prefs_.registry());
     account_tracker_service_.Initialize(&signin_client_);
-    gaia_cookie_manager_service_.Init(&fake_url_fetcher_factory_);
   }
 
   ~AccountInvestigatorTest() override { investigator_.Shutdown(); }
@@ -161,7 +160,6 @@
   FakeSigninManager signin_manager_;
   FakeGaiaCookieManagerService gaia_cookie_manager_service_;
   AccountInvestigator investigator_;
-  net::FakeURLFetcherFactory fake_url_fetcher_factory_;
   std::map<ReportingType, std::string> suffix_ = {
       {ReportingType::PERIODIC, "_Periodic"},
       {ReportingType::ON_CHANGE, "_OnChange"}};
diff --git a/components/signin/core/browser/account_reconcilor_unittest.cc b/components/signin/core/browser/account_reconcilor_unittest.cc
index e873581..42e98f09 100644
--- a/components/signin/core/browser/account_reconcilor_unittest.cc
+++ b/components/signin/core/browser/account_reconcilor_unittest.cc
@@ -238,13 +238,6 @@
   }
   base::HistogramTester* histogram_tester() { return &histogram_tester_; }
 
-  void SetFakeResponse(const std::string& url,
-                       const std::string& data,
-                       net::HttpStatusCode code,
-                       net::URLRequestStatus::Status status) {
-    url_fetcher_factory_.SetFakeResponse(GURL(url), data, code, status);
-  }
-
   MockAccountReconcilor* GetMockReconcilor();
   MockAccountReconcilor* GetMockReconcilor(
       std::unique_ptr<signin::AccountReconcilorDelegate> delegate);
@@ -282,7 +275,6 @@
   FakeGaiaCookieManagerService cookie_manager_service_;
   FakeSigninManagerForTesting signin_manager_;
   std::unique_ptr<MockAccountReconcilor> mock_reconcilor_;
-  net::FakeURLFetcherFactory url_fetcher_factory_;
   base::HistogramTester histogram_tester_;
   GURL get_check_connection_info_url_;
 
@@ -315,14 +307,13 @@
                               GaiaConstants::kChromeSource,
                               &test_signin_client_),
 #if defined(OS_CHROMEOS)
-      signin_manager_(&test_signin_client_, &account_tracker_),
+      signin_manager_(&test_signin_client_, &account_tracker_) {
 #else
       signin_manager_(&test_signin_client_,
                       &token_service_,
                       &account_tracker_,
-                      &cookie_manager_service_),
+                      &cookie_manager_service_) {
 #endif
-      url_fetcher_factory_(nullptr) {
   AccountTrackerService::RegisterPrefs(pref_service_.registry());
   SigninManagerBase::RegisterProfilePrefs(pref_service_.registry());
   SigninManagerBase::RegisterPrefs(pref_service_.registry());
@@ -333,7 +324,6 @@
           GaiaConstants::kChromeSource);
 
   account_tracker_.Initialize(&test_signin_client_);
-  cookie_manager_service_.Init(&url_fetcher_factory_);
   cookie_manager_service_.SetListAccountsResponseHttpNotFound();
   signin_manager_.Initialize(nullptr);
 
diff --git a/components/signin/core/browser/fake_gaia_cookie_manager_service.cc b/components/signin/core/browser/fake_gaia_cookie_manager_service.cc
index ed87b82..2289d9eb 100644
--- a/components/signin/core/browser/fake_gaia_cookie_manager_service.cc
+++ b/components/signin/core/browser/fake_gaia_cookie_manager_service.cc
@@ -9,21 +9,23 @@
 #include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_urls.h"
+#include "net/url_request/test_url_fetcher_factory.h"
 
 FakeGaiaCookieManagerService::FakeGaiaCookieManagerService(
     OAuth2TokenService* token_service,
     const std::string& source,
-    SigninClient* client)
-    : GaiaCookieManagerService(token_service, source, client),
-      url_fetcher_factory_(nullptr) {}
-
-void FakeGaiaCookieManagerService::Init(
-    net::FakeURLFetcherFactory* url_fetcher_factory) {
-  url_fetcher_factory_ = url_fetcher_factory;
+    SigninClient* client,
+    bool use_fake_url_fetcher)
+    : GaiaCookieManagerService(token_service, source, client) {
+  if (use_fake_url_fetcher) {
+    url_fetcher_factory_ = std::make_unique<net::FakeURLFetcherFactory>(
+        /*default_factory=*/nullptr);
+  }
 }
 
+FakeGaiaCookieManagerService::~FakeGaiaCookieManagerService() = default;
+
 void FakeGaiaCookieManagerService::SetListAccountsResponseHttpNotFound() {
-  DCHECK(url_fetcher_factory_);
   url_fetcher_factory_->SetFakeResponse(
       GaiaUrls::GetInstance()->ListAccountsURLWithSource(
           GaiaConstants::kChromeSource),
@@ -31,7 +33,6 @@
 }
 
 void FakeGaiaCookieManagerService::SetListAccountsResponseWebLoginRequired() {
-  DCHECK(url_fetcher_factory_);
   url_fetcher_factory_->SetFakeResponse(
       GaiaUrls::GetInstance()->ListAccountsURLWithSource(
           GaiaConstants::kChromeSource),
@@ -40,8 +41,6 @@
 
 void FakeGaiaCookieManagerService::SetListAccountsResponseWithParams(
     const std::vector<CookieParams>& params) {
-  DCHECK(url_fetcher_factory_);
-
   std::vector<std::string> response_body;
   for (const auto& param : params) {
     std::string response_part = base::StringPrintf(
diff --git a/components/signin/core/browser/fake_gaia_cookie_manager_service.h b/components/signin/core/browser/fake_gaia_cookie_manager_service.h
index a4b0620..c2550fc 100644
--- a/components/signin/core/browser/fake_gaia_cookie_manager_service.h
+++ b/components/signin/core/browser/fake_gaia_cookie_manager_service.h
@@ -9,7 +9,10 @@
 
 #include "base/macros.h"
 #include "components/signin/core/browser/gaia_cookie_manager_service.h"
-#include "net/url_request/test_url_fetcher_factory.h"
+
+namespace net {
+class FakeURLFetcherFactory;
+}
 
 class FakeGaiaCookieManagerService : public GaiaCookieManagerService {
  public:
@@ -24,9 +27,9 @@
 
   FakeGaiaCookieManagerService(OAuth2TokenService* token_service,
                                const std::string& source,
-                               SigninClient* client);
-
-  void Init(net::FakeURLFetcherFactory* url_fetcher_factory);
+                               SigninClient* client,
+                               bool use_fake_url_fetcher = true);
+  ~FakeGaiaCookieManagerService() override;
 
   void SetListAccountsResponseHttpNotFound();
   void SetListAccountsResponseWebLoginRequired();
@@ -49,7 +52,7 @@
   std::string GetDefaultSourceForRequest() override;
 
   // Provide a fake response for calls to /ListAccounts.
-  net::FakeURLFetcherFactory* url_fetcher_factory_;
+  std::unique_ptr<net::FakeURLFetcherFactory> url_fetcher_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeGaiaCookieManagerService);
 };
diff --git a/components/signin/core/browser/signin_manager_unittest.cc b/components/signin/core/browser/signin_manager_unittest.cc
index 1ae77c52..f38e025f 100644
--- a/components/signin/core/browser/signin_manager_unittest.cc
+++ b/components/signin/core/browser/signin_manager_unittest.cc
@@ -29,7 +29,6 @@
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "net/cookies/cookie_monster.h"
-#include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "net/url_request/url_request_status.h"
@@ -85,11 +84,9 @@
         cookie_manager_service_(&token_service_,
                                 GaiaConstants::kChromeSource,
                                 &test_signin_client_),
-        url_fetcher_factory_(nullptr),
         account_consistency_(signin::AccountConsistencyMethod::kDisabled) {
     test_signin_client_.SetURLRequestContext(
         new net::TestURLRequestContextGetter(loop_.task_runner()));
-    cookie_manager_service_.Init(&url_fetcher_factory_);
     AccountFetcherService::RegisterPrefs(user_prefs_.registry());
     AccountTrackerService::RegisterPrefs(user_prefs_.registry());
     SigninManagerBase::RegisterProfilePrefs(user_prefs_.registry());
@@ -172,7 +169,6 @@
   AccountTrackerService account_tracker_;
   FakeGaiaCookieManagerService cookie_manager_service_;
   FakeAccountFetcherService account_fetcher_;
-  net::FakeURLFetcherFactory url_fetcher_factory_;
   std::unique_ptr<SigninManager> manager_;
   TestSigninManagerObserver test_observer_;
   std::vector<std::string> oauth_tokens_fetched_;
diff --git a/components/sync/base/sync_prefs.cc b/components/sync/base/sync_prefs.cc
index d261d9b..f9455ee 100644
--- a/components/sync/base/sync_prefs.cc
+++ b/components/sync/base/sync_prefs.cc
@@ -16,6 +16,54 @@
 
 namespace syncer {
 
+namespace {
+// Groups of prefs that always have the same value as a "master" pref.
+// For example, the APPS group has {APP_NOTIFICATIONS, APP_SETTINGS}
+// (as well as APPS, but that is implied), so
+//   pref_groups_[APPS] =       { APP_NOTIFICATIONS,
+//                                          APP_SETTINGS }
+//   pref_groups_[EXTENSIONS] = { EXTENSION_SETTINGS }
+// etc.
+using PrefGroupsMap = std::map<ModelType, ModelTypeSet>;
+PrefGroupsMap ComputePrefGroups(bool user_events_separate_pref_group) {
+  PrefGroupsMap pref_groups;
+  pref_groups[APPS].Put(APP_NOTIFICATIONS);
+  pref_groups[APPS].Put(APP_SETTINGS);
+  pref_groups[APPS].Put(APP_LIST);
+  pref_groups[APPS].Put(ARC_PACKAGE);
+  pref_groups[APPS].Put(READING_LIST);
+
+  pref_groups[AUTOFILL].Put(AUTOFILL_PROFILE);
+  pref_groups[AUTOFILL].Put(AUTOFILL_WALLET_DATA);
+  pref_groups[AUTOFILL].Put(AUTOFILL_WALLET_METADATA);
+
+  pref_groups[EXTENSIONS].Put(EXTENSION_SETTINGS);
+
+  pref_groups[PREFERENCES].Put(DICTIONARY);
+  pref_groups[PREFERENCES].Put(PRIORITY_PREFERENCES);
+  pref_groups[PREFERENCES].Put(SEARCH_ENGINES);
+
+  pref_groups[TYPED_URLS].Put(HISTORY_DELETE_DIRECTIVES);
+  pref_groups[TYPED_URLS].Put(SESSIONS);
+  pref_groups[TYPED_URLS].Put(FAVICON_IMAGES);
+  pref_groups[TYPED_URLS].Put(FAVICON_TRACKING);
+
+  if (!user_events_separate_pref_group) {
+    pref_groups[TYPED_URLS].Put(USER_EVENTS);
+  }
+
+  pref_groups[PROXY_TABS].Put(SESSIONS);
+  pref_groups[PROXY_TABS].Put(FAVICON_IMAGES);
+  pref_groups[PROXY_TABS].Put(FAVICON_TRACKING);
+
+  // TODO(zea): Put favicons in the bookmarks group as well once it handles
+  // those favicons.
+
+  return pref_groups;
+}
+
+}  // namespace
+
 SessionSyncPrefs::~SessionSyncPrefs() {}
 
 CryptoSyncPrefs::~CryptoSyncPrefs() {}
@@ -24,7 +72,6 @@
 
 SyncPrefs::SyncPrefs(PrefService* pref_service) : pref_service_(pref_service) {
   DCHECK(pref_service);
-  RegisterPrefGroups();
   // Watch the preference that indicates sync is managed so we can take
   // appropriate action.
   pref_sync_managed_.Init(
@@ -220,7 +267,8 @@
 }
 
 ModelTypeSet SyncPrefs::GetPreferredDataTypes(
-    ModelTypeSet registered_types) const {
+    ModelTypeSet registered_types,
+    bool user_events_separate_pref_group) const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (pref_service_->GetBoolean(prefs::kSyncKeepEverythingSynced)) {
@@ -234,13 +282,16 @@
       preferred_types.Put(it.Get());
     }
   }
-  return ResolvePrefGroups(registered_types, preferred_types);
+  return ResolvePrefGroups(registered_types, preferred_types,
+                           user_events_separate_pref_group);
 }
 
 void SyncPrefs::SetPreferredDataTypes(ModelTypeSet registered_types,
-                                      ModelTypeSet preferred_types) {
+                                      ModelTypeSet preferred_types,
+                                      bool user_events_separate_pref_group) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  preferred_types = ResolvePrefGroups(registered_types, preferred_types);
+  preferred_types = ResolvePrefGroups(registered_types, preferred_types,
+                                      user_events_separate_pref_group);
   DCHECK(registered_types.HasAll(preferred_types));
   for (ModelTypeSet::Iterator i = registered_types.First(); i.Good(); i.Inc()) {
     SetDataTypePreferred(i.Get(), preferred_types.Has(i.Get()));
@@ -396,37 +447,6 @@
   pref_service_->SetBoolean(prefs::kSyncManaged, is_managed);
 }
 
-void SyncPrefs::RegisterPrefGroups() {
-  pref_groups_[APPS].Put(APP_NOTIFICATIONS);
-  pref_groups_[APPS].Put(APP_SETTINGS);
-  pref_groups_[APPS].Put(APP_LIST);
-  pref_groups_[APPS].Put(ARC_PACKAGE);
-  pref_groups_[APPS].Put(READING_LIST);
-
-  pref_groups_[AUTOFILL].Put(AUTOFILL_PROFILE);
-  pref_groups_[AUTOFILL].Put(AUTOFILL_WALLET_DATA);
-  pref_groups_[AUTOFILL].Put(AUTOFILL_WALLET_METADATA);
-
-  pref_groups_[EXTENSIONS].Put(EXTENSION_SETTINGS);
-
-  pref_groups_[PREFERENCES].Put(DICTIONARY);
-  pref_groups_[PREFERENCES].Put(PRIORITY_PREFERENCES);
-  pref_groups_[PREFERENCES].Put(SEARCH_ENGINES);
-
-  pref_groups_[TYPED_URLS].Put(HISTORY_DELETE_DIRECTIVES);
-  pref_groups_[TYPED_URLS].Put(SESSIONS);
-  pref_groups_[TYPED_URLS].Put(FAVICON_IMAGES);
-  pref_groups_[TYPED_URLS].Put(FAVICON_TRACKING);
-  pref_groups_[TYPED_URLS].Put(USER_EVENTS);
-
-  pref_groups_[PROXY_TABS].Put(SESSIONS);
-  pref_groups_[PROXY_TABS].Put(FAVICON_IMAGES);
-  pref_groups_[PROXY_TABS].Put(FAVICON_TRACKING);
-
-  // TODO(zea): Put favicons in the bookmarks group as well once it handles
-  // those favicons.
-}
-
 // static
 void SyncPrefs::RegisterDataTypePreferredPref(
     user_prefs::PrefRegistrySyncable* registry,
@@ -467,13 +487,16 @@
   pref_service_->SetBoolean(pref_name, is_preferred);
 }
 
-ModelTypeSet SyncPrefs::ResolvePrefGroups(ModelTypeSet registered_types,
-                                          ModelTypeSet types) const {
+ModelTypeSet SyncPrefs::ResolvePrefGroups(
+    ModelTypeSet registered_types,
+    ModelTypeSet types,
+    bool user_events_separate_pref_group) const {
   ModelTypeSet types_with_groups = types;
-  for (PrefGroupsMap::const_iterator i = pref_groups_.begin();
-       i != pref_groups_.end(); ++i) {
-    if (types.Has(i->first))
-      types_with_groups.PutAll(i->second);
+  for (const auto& pref_group :
+       ComputePrefGroups(user_events_separate_pref_group)) {
+    if (types.Has(pref_group.first)) {
+      types_with_groups.PutAll(pref_group.second);
+    }
   }
   types_with_groups.RetainAll(registered_types);
   return types_with_groups;
diff --git a/components/sync/base/sync_prefs.h b/components/sync/base/sync_prefs.h
index 932dc83..7d91804 100644
--- a/components/sync/base/sync_prefs.h
+++ b/components/sync/base/sync_prefs.h
@@ -140,15 +140,31 @@
   // The returned set is guaranteed to be a subset of
   // |registered_types|.  Returns |registered_types| directly if
   // HasKeepEverythingSynced() is true.
-  ModelTypeSet GetPreferredDataTypes(ModelTypeSet registered_types) const;
+  // |user_events_separate_pref_group| is true when USER_EVENTS model type has
+  // a separate pref group instead of being bundled with the TYPED_URLS. This
+  // is used when Unified Consent is enabled.
+  //
+  // TODO(https://crbug.com/862983): |user_events_separate_pref_group| is only
+  // temporary and should removed once Unified Consent feature is is launched.
+  ModelTypeSet GetPreferredDataTypes(
+      ModelTypeSet registered_types,
+      bool user_events_separate_pref_group) const;
+
   // |preferred_types| should be a subset of |registered_types|.  All
   // types in |preferred_types| are marked preferred, and all types in
   // |registered_types| \ |preferred_types| are marked not preferred.
   // Changes are still made to the prefs even if
   // HasKeepEverythingSynced() is true, but won't be visible until
   // SetKeepEverythingSynced(false) is called.
+  // |user_events_separate_pref_group| is true when USER_EVENTS model type has
+  // a separate pref group instead of being bundled with the TYPED_URLS. This
+  // is used when Unified Consent is enabled.
+  //
+  // TODO(https://crbug.com/862983): |user_events_separate_pref_group| is only
+  // temporary and should removed once Unified Consent feature is is launched.
   void SetPreferredDataTypes(ModelTypeSet registered_types,
-                             ModelTypeSet preferred_types);
+                             ModelTypeSet preferred_types,
+                             bool user_events_separate_pref_group);
 
   // This pref is set outside of sync.
   bool IsManaged() const;
@@ -231,11 +247,10 @@
   // Returns a ModelTypeSet based on |types| expanded to include pref groups
   // (see |pref_groups_|), but as a subset of |registered_types|.
   ModelTypeSet ResolvePrefGroups(ModelTypeSet registered_types,
-                                 ModelTypeSet types) const;
+                                 ModelTypeSet types,
+                                 bool user_events_separate_pref_group) const;
 
  private:
-  void RegisterPrefGroups();
-
   static void RegisterDataTypePreferredPref(
       user_prefs::PrefRegistrySyncable* prefs,
       ModelType type,
@@ -256,16 +271,6 @@
 
   bool local_sync_enabled_;
 
-  // Groups of prefs that always have the same value as a "master" pref.
-  // For example, the APPS group has {APP_NOTIFICATIONS, APP_SETTINGS}
-  // (as well as APPS, but that is implied), so
-  //   pref_groups_[APPS] =       { APP_NOTIFICATIONS,
-  //                                          APP_SETTINGS }
-  //   pref_groups_[EXTENSIONS] = { EXTENSION_SETTINGS }
-  // etc.
-  using PrefGroupsMap = std::map<ModelType, ModelTypeSet>;
-  PrefGroupsMap pref_groups_;
-
   SEQUENCE_CHECKER(sequence_checker_);
 
   DISALLOW_COPY_AND_ASSIGN(SyncPrefs);
diff --git a/components/sync/base/sync_prefs_unittest.cc b/components/sync/base/sync_prefs_unittest.cc
index af32ae4..c4c92f0 100644
--- a/components/sync/base/sync_prefs_unittest.cc
+++ b/components/sync/base/sync_prefs_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "components/sync/base/sync_prefs.h"
 
+#include <memory>
+
 #include "base/command_line.h"
 #include "base/message_loop/message_loop.h"
 #include "components/prefs/pref_notifier_impl.h"
@@ -23,50 +25,149 @@
 
 class SyncPrefsTest : public testing::Test {
  protected:
-  void SetUp() override {
+  SyncPrefsTest() {
     SyncPrefs::RegisterProfilePrefs(pref_service_.registry());
+    sync_prefs_ = std::make_unique<SyncPrefs>(&pref_service_);
   }
 
-  sync_preferences::TestingPrefServiceSyncable pref_service_;
-
- private:
   base::MessageLoop loop_;
+  sync_preferences::TestingPrefServiceSyncable pref_service_;
+  std::unique_ptr<SyncPrefs> sync_prefs_;
 };
 
-TEST_F(SyncPrefsTest, Basic) {
-  SyncPrefs sync_prefs(&pref_service_);
+// Verify that invalidation versions are persisted and loaded correctly.
+TEST_F(SyncPrefsTest, InvalidationVersions) {
+  std::map<ModelType, int64_t> versions;
+  versions[BOOKMARKS] = 10;
+  versions[SESSIONS] = 20;
+  versions[PREFERENCES] = 30;
 
-  EXPECT_FALSE(sync_prefs.IsFirstSetupComplete());
-  sync_prefs.SetFirstSetupComplete();
-  EXPECT_TRUE(sync_prefs.IsFirstSetupComplete());
+  sync_prefs_->UpdateInvalidationVersions(versions);
 
-  EXPECT_TRUE(sync_prefs.IsSyncRequested());
-  sync_prefs.SetSyncRequested(false);
-  EXPECT_FALSE(sync_prefs.IsSyncRequested());
-  sync_prefs.SetSyncRequested(true);
-  EXPECT_TRUE(sync_prefs.IsSyncRequested());
+  std::map<ModelType, int64_t> versions2;
+  sync_prefs_->GetInvalidationVersions(&versions2);
 
-  EXPECT_EQ(base::Time(), sync_prefs.GetLastSyncedTime());
-  const base::Time& now = base::Time::Now();
-  sync_prefs.SetLastSyncedTime(now);
-  EXPECT_EQ(now, sync_prefs.GetLastSyncedTime());
-
-  EXPECT_TRUE(sync_prefs.HasKeepEverythingSynced());
-  sync_prefs.SetKeepEverythingSynced(false);
-  EXPECT_FALSE(sync_prefs.HasKeepEverythingSynced());
-  sync_prefs.SetKeepEverythingSynced(true);
-  EXPECT_TRUE(sync_prefs.HasKeepEverythingSynced());
-
-  EXPECT_TRUE(sync_prefs.GetEncryptionBootstrapToken().empty());
-  sync_prefs.SetEncryptionBootstrapToken("token");
-  EXPECT_EQ("token", sync_prefs.GetEncryptionBootstrapToken());
+  EXPECT_EQ(versions.size(), versions2.size());
+  for (auto map_iter : versions2) {
+    EXPECT_EQ(versions[map_iter.first], map_iter.second);
+  }
 }
 
-TEST_F(SyncPrefsTest, DefaultTypes) {
-  SyncPrefs sync_prefs(&pref_service_);
-  sync_prefs.SetKeepEverythingSynced(false);
+TEST_F(SyncPrefsTest, ShortPollInterval) {
+  EXPECT_TRUE(sync_prefs_->GetShortPollInterval().is_zero());
 
-  ModelTypeSet preferred_types = sync_prefs.GetPreferredDataTypes(UserTypes());
+  sync_prefs_->SetShortPollInterval(base::TimeDelta::FromMinutes(30));
+
+  EXPECT_FALSE(sync_prefs_->GetShortPollInterval().is_zero());
+  EXPECT_EQ(sync_prefs_->GetShortPollInterval().InMinutes(), 30);
+}
+
+TEST_F(SyncPrefsTest, LongPollInterval) {
+  EXPECT_TRUE(sync_prefs_->GetLongPollInterval().is_zero());
+
+  sync_prefs_->SetLongPollInterval(base::TimeDelta::FromMinutes(60));
+
+  EXPECT_FALSE(sync_prefs_->GetLongPollInterval().is_zero());
+  EXPECT_EQ(sync_prefs_->GetLongPollInterval().InMinutes(), 60);
+}
+
+class MockSyncPrefObserver : public SyncPrefObserver {
+ public:
+  MOCK_METHOD1(OnSyncManagedPrefChange, void(bool));
+};
+
+TEST_F(SyncPrefsTest, ObservedPrefs) {
+  StrictMock<MockSyncPrefObserver> mock_sync_pref_observer;
+  InSequence dummy;
+  EXPECT_CALL(mock_sync_pref_observer, OnSyncManagedPrefChange(true));
+  EXPECT_CALL(mock_sync_pref_observer, OnSyncManagedPrefChange(false));
+
+  EXPECT_FALSE(sync_prefs_->IsManaged());
+
+  sync_prefs_->AddSyncPrefObserver(&mock_sync_pref_observer);
+
+  sync_prefs_->SetManagedForTest(true);
+  EXPECT_TRUE(sync_prefs_->IsManaged());
+  sync_prefs_->SetManagedForTest(false);
+  EXPECT_FALSE(sync_prefs_->IsManaged());
+
+  sync_prefs_->RemoveSyncPrefObserver(&mock_sync_pref_observer);
+}
+
+TEST_F(SyncPrefsTest, ClearPreferences) {
+  EXPECT_FALSE(sync_prefs_->IsFirstSetupComplete());
+  EXPECT_EQ(base::Time(), sync_prefs_->GetLastSyncedTime());
+  EXPECT_TRUE(sync_prefs_->GetEncryptionBootstrapToken().empty());
+
+  sync_prefs_->SetFirstSetupComplete();
+  sync_prefs_->SetLastSyncedTime(base::Time::Now());
+  sync_prefs_->SetEncryptionBootstrapToken("token");
+
+  EXPECT_TRUE(sync_prefs_->IsFirstSetupComplete());
+  EXPECT_NE(base::Time(), sync_prefs_->GetLastSyncedTime());
+  EXPECT_EQ("token", sync_prefs_->GetEncryptionBootstrapToken());
+
+  sync_prefs_->ClearPreferences();
+
+  EXPECT_FALSE(sync_prefs_->IsFirstSetupComplete());
+  EXPECT_EQ(base::Time(), sync_prefs_->GetLastSyncedTime());
+  EXPECT_TRUE(sync_prefs_->GetEncryptionBootstrapToken().empty());
+}
+
+// -----------------------------------------------------------------------------
+// Test that manipulate preferred data types.
+// -----------------------------------------------------------------------------
+
+class SyncPrefsDataTypesTest : public SyncPrefsTest,
+                               public testing::WithParamInterface<bool> {
+ protected:
+  SyncPrefsDataTypesTest() : user_events_separate_pref_group_(GetParam()) {}
+
+  ModelTypeSet GetPreferredDataTypes(ModelTypeSet registered_types) {
+    return sync_prefs_->GetPreferredDataTypes(registered_types,
+                                              user_events_separate_pref_group_);
+  }
+
+  void SetPreferredDataTypes(ModelTypeSet registered_types,
+                             ModelTypeSet preferred_types) {
+    return sync_prefs_->SetPreferredDataTypes(registered_types, preferred_types,
+                                              user_events_separate_pref_group_);
+  }
+
+  const bool user_events_separate_pref_group_;
+};
+
+TEST_P(SyncPrefsDataTypesTest, Basic) {
+  EXPECT_FALSE(sync_prefs_->IsFirstSetupComplete());
+  sync_prefs_->SetFirstSetupComplete();
+  EXPECT_TRUE(sync_prefs_->IsFirstSetupComplete());
+
+  EXPECT_TRUE(sync_prefs_->IsSyncRequested());
+  sync_prefs_->SetSyncRequested(false);
+  EXPECT_FALSE(sync_prefs_->IsSyncRequested());
+  sync_prefs_->SetSyncRequested(true);
+  EXPECT_TRUE(sync_prefs_->IsSyncRequested());
+
+  EXPECT_EQ(base::Time(), sync_prefs_->GetLastSyncedTime());
+  const base::Time& now = base::Time::Now();
+  sync_prefs_->SetLastSyncedTime(now);
+  EXPECT_EQ(now, sync_prefs_->GetLastSyncedTime());
+
+  EXPECT_TRUE(sync_prefs_->HasKeepEverythingSynced());
+  sync_prefs_->SetKeepEverythingSynced(false);
+  EXPECT_FALSE(sync_prefs_->HasKeepEverythingSynced());
+  sync_prefs_->SetKeepEverythingSynced(true);
+  EXPECT_TRUE(sync_prefs_->HasKeepEverythingSynced());
+
+  EXPECT_TRUE(sync_prefs_->GetEncryptionBootstrapToken().empty());
+  sync_prefs_->SetEncryptionBootstrapToken("token");
+  EXPECT_EQ("token", sync_prefs_->GetEncryptionBootstrapToken());
+}
+
+TEST_P(SyncPrefsDataTypesTest, DefaultTypes) {
+  sync_prefs_->SetKeepEverythingSynced(false);
+
+  ModelTypeSet preferred_types = GetPreferredDataTypes(UserTypes());
   EXPECT_EQ(AlwaysPreferredUserTypes(), preferred_types);
 
   // Simulate an upgrade to delete directives + proxy tabs support. None of the
@@ -79,14 +180,14 @@
   registered_types.Remove(HISTORY_DELETE_DIRECTIVES);
 
   // Enable all other types.
-  sync_prefs.SetPreferredDataTypes(registered_types, registered_types);
+  SetPreferredDataTypes(registered_types, registered_types);
 
   // Manually enable typed urls (to simulate the old world).
   pref_service_.SetBoolean(prefs::kSyncTypedUrls, true);
 
   // Proxy tabs should not be enabled (since sessions wasn't), but history
   // delete directives should (since typed urls was).
-  preferred_types = sync_prefs.GetPreferredDataTypes(UserTypes());
+  preferred_types = GetPreferredDataTypes(UserTypes());
   EXPECT_FALSE(preferred_types.Has(PROXY_TABS));
   EXPECT_TRUE(preferred_types.Has(HISTORY_DELETE_DIRECTIVES));
 
@@ -95,35 +196,31 @@
   // delete directives are not enabled.
   pref_service_.SetBoolean(prefs::kSyncTypedUrls, false);
   pref_service_.SetBoolean(prefs::kSyncSessions, true);
-  preferred_types = sync_prefs.GetPreferredDataTypes(UserTypes());
+  preferred_types = GetPreferredDataTypes(UserTypes());
   EXPECT_TRUE(preferred_types.Has(PROXY_TABS));
   EXPECT_FALSE(preferred_types.Has(HISTORY_DELETE_DIRECTIVES));
 }
 
-TEST_F(SyncPrefsTest, PreferredTypesKeepEverythingSynced) {
-  SyncPrefs sync_prefs(&pref_service_);
-
-  EXPECT_TRUE(sync_prefs.HasKeepEverythingSynced());
+TEST_P(SyncPrefsDataTypesTest, PreferredTypesKeepEverythingSynced) {
+  EXPECT_TRUE(sync_prefs_->HasKeepEverythingSynced());
 
   const ModelTypeSet user_types = UserTypes();
-  EXPECT_EQ(user_types, sync_prefs.GetPreferredDataTypes(user_types));
+  EXPECT_EQ(user_types, GetPreferredDataTypes(user_types));
   const ModelTypeSet user_visible_types = UserSelectableTypes();
   for (ModelTypeSet::Iterator it = user_visible_types.First(); it.Good();
        it.Inc()) {
     ModelTypeSet preferred_types;
     preferred_types.Put(it.Get());
-    sync_prefs.SetPreferredDataTypes(user_types, preferred_types);
-    EXPECT_EQ(user_types, sync_prefs.GetPreferredDataTypes(user_types));
+    SetPreferredDataTypes(user_types, preferred_types);
+    EXPECT_EQ(user_types, GetPreferredDataTypes(user_types));
   }
 }
 
-TEST_F(SyncPrefsTest, PreferredTypesNotKeepEverythingSynced) {
-  SyncPrefs sync_prefs(&pref_service_);
-
-  sync_prefs.SetKeepEverythingSynced(false);
+TEST_P(SyncPrefsDataTypesTest, PreferredTypesNotKeepEverythingSynced) {
+  sync_prefs_->SetKeepEverythingSynced(false);
 
   const ModelTypeSet user_types = UserTypes();
-  EXPECT_NE(user_types, sync_prefs.GetPreferredDataTypes(user_types));
+  EXPECT_NE(user_types, GetPreferredDataTypes(user_types));
   const ModelTypeSet user_visible_types = UserSelectableTypes();
   for (ModelTypeSet::Iterator it = user_visible_types.First(); it.Good();
        it.Inc()) {
@@ -155,7 +252,9 @@
       expected_preferred_types.Put(SESSIONS);
       expected_preferred_types.Put(FAVICON_IMAGES);
       expected_preferred_types.Put(FAVICON_TRACKING);
-      expected_preferred_types.Put(USER_EVENTS);
+      if (!user_events_separate_pref_group_) {
+        expected_preferred_types.Put(USER_EVENTS);
+      }
     }
     if (it.Get() == PROXY_TABS) {
       expected_preferred_types.Put(SESSIONS);
@@ -165,125 +264,40 @@
 
     expected_preferred_types.PutAll(AlwaysPreferredUserTypes());
 
-    sync_prefs.SetPreferredDataTypes(user_types, preferred_types);
-    EXPECT_EQ(expected_preferred_types,
-              sync_prefs.GetPreferredDataTypes(user_types));
+    SetPreferredDataTypes(user_types, preferred_types);
+    EXPECT_EQ(expected_preferred_types, GetPreferredDataTypes(user_types));
   }
 }
 
-class MockSyncPrefObserver : public SyncPrefObserver {
- public:
-  MOCK_METHOD1(OnSyncManagedPrefChange, void(bool));
-};
-
-TEST_F(SyncPrefsTest, ObservedPrefs) {
-  SyncPrefs sync_prefs(&pref_service_);
-
-  StrictMock<MockSyncPrefObserver> mock_sync_pref_observer;
-  InSequence dummy;
-  EXPECT_CALL(mock_sync_pref_observer, OnSyncManagedPrefChange(true));
-  EXPECT_CALL(mock_sync_pref_observer, OnSyncManagedPrefChange(false));
-
-  EXPECT_FALSE(sync_prefs.IsManaged());
-
-  sync_prefs.AddSyncPrefObserver(&mock_sync_pref_observer);
-
-  sync_prefs.SetManagedForTest(true);
-  EXPECT_TRUE(sync_prefs.IsManaged());
-  sync_prefs.SetManagedForTest(false);
-  EXPECT_FALSE(sync_prefs.IsManaged());
-
-  sync_prefs.RemoveSyncPrefObserver(&mock_sync_pref_observer);
-}
-
-TEST_F(SyncPrefsTest, ClearPreferences) {
-  SyncPrefs sync_prefs(&pref_service_);
-
-  EXPECT_FALSE(sync_prefs.IsFirstSetupComplete());
-  EXPECT_EQ(base::Time(), sync_prefs.GetLastSyncedTime());
-  EXPECT_TRUE(sync_prefs.GetEncryptionBootstrapToken().empty());
-
-  sync_prefs.SetFirstSetupComplete();
-  sync_prefs.SetLastSyncedTime(base::Time::Now());
-  sync_prefs.SetEncryptionBootstrapToken("token");
-
-  EXPECT_TRUE(sync_prefs.IsFirstSetupComplete());
-  EXPECT_NE(base::Time(), sync_prefs.GetLastSyncedTime());
-  EXPECT_EQ("token", sync_prefs.GetEncryptionBootstrapToken());
-
-  sync_prefs.ClearPreferences();
-
-  EXPECT_FALSE(sync_prefs.IsFirstSetupComplete());
-  EXPECT_EQ(base::Time(), sync_prefs.GetLastSyncedTime());
-  EXPECT_TRUE(sync_prefs.GetEncryptionBootstrapToken().empty());
-}
-
 // Device info should always be enabled.
-TEST_F(SyncPrefsTest, DeviceInfo) {
-  SyncPrefs sync_prefs(&pref_service_);
-  EXPECT_TRUE(sync_prefs.GetPreferredDataTypes(UserTypes()).Has(DEVICE_INFO));
-  sync_prefs.SetKeepEverythingSynced(true);
-  EXPECT_TRUE(sync_prefs.GetPreferredDataTypes(UserTypes()).Has(DEVICE_INFO));
-  sync_prefs.SetKeepEverythingSynced(false);
-  EXPECT_TRUE(sync_prefs.GetPreferredDataTypes(UserTypes()).Has(DEVICE_INFO));
-  sync_prefs.SetPreferredDataTypes(
+TEST_P(SyncPrefsDataTypesTest, DeviceInfo) {
+  EXPECT_TRUE(GetPreferredDataTypes(UserTypes()).Has(DEVICE_INFO));
+  sync_prefs_->SetKeepEverythingSynced(true);
+  EXPECT_TRUE(GetPreferredDataTypes(UserTypes()).Has(DEVICE_INFO));
+  sync_prefs_->SetKeepEverythingSynced(false);
+  EXPECT_TRUE(GetPreferredDataTypes(UserTypes()).Has(DEVICE_INFO));
+  SetPreferredDataTypes(
       /*registered_types=*/ModelTypeSet(DEVICE_INFO),
       /*preferred_types=*/ModelTypeSet());
-  EXPECT_TRUE(sync_prefs.GetPreferredDataTypes(UserTypes()).Has(DEVICE_INFO));
+  EXPECT_TRUE(GetPreferredDataTypes(UserTypes()).Has(DEVICE_INFO));
 }
 
 // User Consents should always be enabled.
-TEST_F(SyncPrefsTest, UserConsents) {
-  SyncPrefs sync_prefs(&pref_service_);
-  EXPECT_TRUE(sync_prefs.GetPreferredDataTypes(UserTypes()).Has(USER_CONSENTS));
-  sync_prefs.SetKeepEverythingSynced(true);
-  EXPECT_TRUE(sync_prefs.GetPreferredDataTypes(UserTypes()).Has(USER_CONSENTS));
-  sync_prefs.SetKeepEverythingSynced(false);
-  EXPECT_TRUE(sync_prefs.GetPreferredDataTypes(UserTypes()).Has(USER_CONSENTS));
-  sync_prefs.SetPreferredDataTypes(
+TEST_P(SyncPrefsDataTypesTest, UserConsents) {
+  EXPECT_TRUE(GetPreferredDataTypes(UserTypes()).Has(USER_CONSENTS));
+  sync_prefs_->SetKeepEverythingSynced(true);
+  EXPECT_TRUE(GetPreferredDataTypes(UserTypes()).Has(USER_CONSENTS));
+  sync_prefs_->SetKeepEverythingSynced(false);
+  EXPECT_TRUE(GetPreferredDataTypes(UserTypes()).Has(USER_CONSENTS));
+  SetPreferredDataTypes(
       /*registered_types=*/ModelTypeSet(USER_CONSENTS),
       /*preferred_types=*/ModelTypeSet());
-  EXPECT_TRUE(sync_prefs.GetPreferredDataTypes(UserTypes()).Has(USER_CONSENTS));
+  EXPECT_TRUE(GetPreferredDataTypes(UserTypes()).Has(USER_CONSENTS));
 }
 
-// Verify that invalidation versions are persisted and loaded correctly.
-TEST_F(SyncPrefsTest, InvalidationVersions) {
-  std::map<ModelType, int64_t> versions;
-  versions[BOOKMARKS] = 10;
-  versions[SESSIONS] = 20;
-  versions[PREFERENCES] = 30;
-
-  SyncPrefs sync_prefs(&pref_service_);
-  sync_prefs.UpdateInvalidationVersions(versions);
-
-  std::map<ModelType, int64_t> versions2;
-  sync_prefs.GetInvalidationVersions(&versions2);
-
-  EXPECT_EQ(versions.size(), versions2.size());
-  for (auto map_iter : versions2) {
-    EXPECT_EQ(versions[map_iter.first], map_iter.second);
-  }
-}
-
-TEST_F(SyncPrefsTest, ShortPollInterval) {
-  SyncPrefs sync_prefs(&pref_service_);
-  EXPECT_TRUE(sync_prefs.GetShortPollInterval().is_zero());
-
-  sync_prefs.SetShortPollInterval(base::TimeDelta::FromMinutes(30));
-
-  EXPECT_FALSE(sync_prefs.GetShortPollInterval().is_zero());
-  EXPECT_EQ(sync_prefs.GetShortPollInterval().InMinutes(), 30);
-}
-
-TEST_F(SyncPrefsTest, LongPollInterval) {
-  SyncPrefs sync_prefs(&pref_service_);
-  EXPECT_TRUE(sync_prefs.GetLongPollInterval().is_zero());
-
-  sync_prefs.SetLongPollInterval(base::TimeDelta::FromMinutes(60));
-
-  EXPECT_FALSE(sync_prefs.GetLongPollInterval().is_zero());
-  EXPECT_EQ(sync_prefs.GetLongPollInterval().InMinutes(), 60);
-}
+INSTANTIATE_TEST_CASE_P(,
+                        SyncPrefsDataTypesTest,
+                        ::testing::Values(false, true));
 
 }  // namespace
 
diff --git a/components/sync/driver/glue/sync_backend_host_core.cc b/components/sync/driver/glue/sync_backend_host_core.cc
index a7d527c..b3af3f5 100644
--- a/components/sync/driver/glue/sync_backend_host_core.cc
+++ b/components/sync/driver/glue/sync_backend_host_core.cc
@@ -65,7 +65,7 @@
       weak_ptr_factory_(this) {
   DCHECK(backend);
   // This is constructed on the UI thread but used from the sync thread.
-  thread_checker_.DetachFromThread();
+  DETACH_FROM_SEQUENCE(sequence_checker_);
 }
 
 SyncBackendHostCore::~SyncBackendHostCore() {
@@ -75,7 +75,7 @@
 bool SyncBackendHostCore::OnMemoryDump(
     const base::trace_event::MemoryDumpArgs& args,
     base::trace_event::ProcessMemoryDump* pmd) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!sync_manager_)
     return false;
   sync_manager_->OnMemoryDump(pmd);
@@ -84,14 +84,14 @@
 
 void SyncBackendHostCore::OnSyncCycleCompleted(
     const SyncCycleSnapshot& snapshot) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   host_.Call(FROM_HERE,
              &SyncBackendHostImpl::HandleSyncCycleCompletedOnFrontendLoop,
              snapshot);
 }
 
 void SyncBackendHostCore::DoRefreshTypes(ModelTypeSet types) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   sync_manager_->RefreshTypes(types);
 }
 
@@ -100,7 +100,7 @@
     const WeakHandle<DataTypeDebugInfoListener>& debug_info_listener,
     bool success,
     const ModelTypeSet restored_types) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!success) {
     DoDestroySyncManager();
@@ -170,7 +170,7 @@
 }
 
 void SyncBackendHostCore::OnConnectionStatusChange(ConnectionStatus status) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   host_.Call(FROM_HERE,
              &SyncBackendHostImpl::HandleConnectionStatusChangeOnFrontendLoop,
              status);
@@ -179,7 +179,7 @@
 void SyncBackendHostCore::OnCommitCountersUpdated(
     ModelType type,
     const CommitCounters& counters) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   host_.Call(
       FROM_HERE,
       &SyncBackendHostImpl::HandleDirectoryCommitCountersUpdatedOnFrontendLoop,
@@ -189,7 +189,7 @@
 void SyncBackendHostCore::OnUpdateCountersUpdated(
     ModelType type,
     const UpdateCounters& counters) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   host_.Call(
       FROM_HERE,
       &SyncBackendHostImpl::HandleDirectoryUpdateCountersUpdatedOnFrontendLoop,
@@ -199,7 +199,7 @@
 void SyncBackendHostCore::OnStatusCountersUpdated(
     ModelType type,
     const StatusCounters& counters) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   host_.Call(
       FROM_HERE,
       &SyncBackendHostImpl::HandleDirectoryStatusCountersUpdatedOnFrontendLoop,
@@ -208,21 +208,21 @@
 
 void SyncBackendHostCore::OnActionableError(
     const SyncProtocolError& sync_error) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   host_.Call(FROM_HERE,
              &SyncBackendHostImpl::HandleActionableErrorEventOnFrontendLoop,
              sync_error);
 }
 
 void SyncBackendHostCore::OnMigrationRequested(ModelTypeSet types) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   host_.Call(FROM_HERE,
              &SyncBackendHostImpl::HandleMigrationRequestedOnFrontendLoop,
              types);
 }
 
 void SyncBackendHostCore::OnProtocolEvent(const ProtocolEvent& event) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (forward_protocol_events_) {
     std::unique_ptr<ProtocolEvent> event_clone(event.Clone());
     host_.Call(FROM_HERE,
@@ -232,13 +232,13 @@
 }
 
 void SyncBackendHostCore::DoOnInvalidatorStateChange(InvalidatorState state) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   sync_manager_->SetInvalidatorEnabled(state == INVALIDATIONS_ENABLED);
 }
 
 void SyncBackendHostCore::DoOnIncomingInvalidation(
     const ObjectIdInvalidationMap& invalidation_map) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   ObjectIdSet ids = invalidation_map.GetObjectIds();
   for (const invalidation::ObjectId& object_id : ids) {
@@ -274,7 +274,7 @@
 }
 
 void SyncBackendHostCore::DoInitialize(SyncEngine::InitParams params) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Blow away the partial or corrupt sync data folder before doing any more
   // initialization, if necessary.
@@ -338,7 +338,7 @@
 
 void SyncBackendHostCore::DoUpdateCredentials(
     const SyncCredentials& credentials) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // UpdateCredentials can be called during backend initialization, possibly
   // when backend initialization has failed but hasn't notified the UI thread
   // yet. In that case, the sync manager may have been destroyed on the sync
@@ -349,7 +349,7 @@
 }
 
 void SyncBackendHostCore::DoInvalidateCredentials() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (sync_manager_) {
     sync_manager_->InvalidateCredentials();
   }
@@ -360,20 +360,20 @@
 }
 
 void SyncBackendHostCore::DoStartSyncing(base::Time last_poll_time) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   sync_manager_->StartSyncingNormally(last_poll_time);
 }
 
 void SyncBackendHostCore::DoSetEncryptionPassphrase(
     const std::string& passphrase,
     bool is_explicit) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   sync_manager_->GetEncryptionHandler()->SetEncryptionPassphrase(passphrase,
                                                                  is_explicit);
 }
 
 void SyncBackendHostCore::DoInitialProcessControlTypes() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   DVLOG(1) << "Initilalizing Control Types";
 
@@ -411,12 +411,12 @@
 
 void SyncBackendHostCore::DoSetDecryptionPassphrase(
     const std::string& passphrase) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   sync_manager_->GetEncryptionHandler()->SetDecryptionPassphrase(passphrase);
 }
 
 void SyncBackendHostCore::DoEnableEncryptEverything() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   sync_manager_->GetEncryptionHandler()->EnableEncryptEverything();
 }
 
@@ -442,7 +442,7 @@
 }
 
 void SyncBackendHostCore::DoShutdown(ShutdownReason reason) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   DoDestroySyncManager();
 
@@ -456,7 +456,7 @@
 }
 
 void SyncBackendHostCore::DoDestroySyncManager() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
       this);
   if (sync_manager_) {
@@ -471,13 +471,13 @@
 void SyncBackendHostCore::DoPurgeDisabledTypes(const ModelTypeSet& to_purge,
                                                const ModelTypeSet& to_journal,
                                                const ModelTypeSet& to_unapply) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   sync_manager_->PurgeDisabledTypes(to_purge, to_journal, to_unapply);
 }
 
 void SyncBackendHostCore::DoConfigureSyncer(
     ModelTypeConfigurer::ConfigureParams params) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!params.ready_task.is_null());
   DCHECK(!params.retry_callback.is_null());
 
@@ -497,7 +497,7 @@
 void SyncBackendHostCore::DoFinishConfigureDataTypes(
     ModelTypeSet types_to_config,
     const base::Callback<void(ModelTypeSet, ModelTypeSet)>& ready_task) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Update the enabled types for the bridge and sync manager.
   ModelSafeRoutingInfo routing_info;
@@ -517,13 +517,13 @@
 
 void SyncBackendHostCore::DoRetryConfiguration(
     const base::Closure& retry_callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   host_.Call(FROM_HERE, &SyncBackendHostImpl::RetryConfigurationOnFrontendLoop,
              retry_callback);
 }
 
 void SyncBackendHostCore::SendBufferedProtocolEventsAndEnableForwarding() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   forward_protocol_events_ = true;
 
   if (sync_manager_) {
@@ -542,12 +542,12 @@
 }
 
 void SyncBackendHostCore::DisableProtocolEventForwarding() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   forward_protocol_events_ = false;
 }
 
 void SyncBackendHostCore::EnableDirectoryTypeDebugInfoForwarding() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(sync_manager_);
 
   forward_type_info_ = true;
@@ -558,7 +558,7 @@
 }
 
 void SyncBackendHostCore::DisableDirectoryTypeDebugInfoForwarding() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(sync_manager_);
 
   if (!forward_type_info_)
@@ -571,7 +571,7 @@
 }
 
 void SyncBackendHostCore::StartSavingChanges() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!save_changes_timer_);
   save_changes_timer_ = std::make_unique<base::RepeatingTimer>();
   save_changes_timer_->Start(
@@ -580,13 +580,13 @@
 }
 
 void SyncBackendHostCore::SaveChanges() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   sync_manager_->SaveChanges();
 }
 
 void SyncBackendHostCore::DoClearServerData(
     const base::Closure& frontend_callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   const base::Closure callback =
       base::Bind(&SyncBackendHostCore::ClearServerDataDone,
                  weak_ptr_factory_.GetWeakPtr(), frontend_callback);
@@ -596,7 +596,7 @@
 void SyncBackendHostCore::DoOnCookieJarChanged(bool account_mismatch,
                                                bool empty_jar,
                                                const base::Closure& callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   sync_manager_->OnCookieJarChanged(account_mismatch, empty_jar);
   if (!callback.is_null()) {
     host_.Call(FROM_HERE,
@@ -606,14 +606,14 @@
 }
 
 bool SyncBackendHostCore::HasUnsyncedItemsForTest() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(sync_manager_);
   return sync_manager_->HasUnsyncedItemsForTest();
 }
 
 void SyncBackendHostCore::ClearServerDataDone(
     const base::Closure& frontend_callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   host_.Call(FROM_HERE, &SyncBackendHostImpl::ClearServerDataDoneOnFrontendLoop,
              frontend_callback);
 }
diff --git a/components/sync/driver/glue/sync_backend_host_core.h b/components/sync/driver/glue/sync_backend_host_core.h
index f0d4d978..a3b306c5 100644
--- a/components/sync/driver/glue/sync_backend_host_core.h
+++ b/components/sync/driver/glue/sync_backend_host_core.h
@@ -15,8 +15,7 @@
 #include "base/callback_forward.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_checker.h"
+#include "base/sequence_checker.h"
 #include "base/timer/timer.h"
 #include "base/trace_event/memory_dump_provider.h"
 #include "components/invalidation/public/invalidation.h"
@@ -237,7 +236,7 @@
   std::map<ModelType, int64_t> last_invalidation_versions_;
 
   // Checks that we are on the sync thread.
-  base::ThreadChecker thread_checker_;
+  SEQUENCE_CHECKER(sequence_checker_);
 
   base::WeakPtrFactory<SyncBackendHostCore> weak_ptr_factory_;
 
diff --git a/components/sync/driver/glue/sync_backend_host_impl.cc b/components/sync/driver/glue/sync_backend_host_impl.cc
index f0325e8..7830d31 100644
--- a/components/sync/driver/glue/sync_backend_host_impl.cc
+++ b/components/sync/driver/glue/sync_backend_host_impl.cc
@@ -12,7 +12,6 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/task_runner_util.h"
-#include "base/threading/thread_task_runner_handle.h"
 #include "components/invalidation/public/invalidation_service.h"
 #include "components/invalidation/public/object_id_invalidation_map.h"
 #include "components/sync/base/experiments.h"
@@ -76,7 +75,7 @@
 }
 
 void SyncBackendHostImpl::TriggerRefresh(const ModelTypeSet& types) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   sync_task_runner_->PostTask(
       FROM_HERE,
       base::Bind(&SyncBackendHostCore::DoRefreshTypes, core_, types));
@@ -116,7 +115,7 @@
 
 void SyncBackendHostImpl::SetEncryptionPassphrase(const std::string& passphrase,
                                                   bool is_explicit) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   sync_task_runner_->PostTask(
       FROM_HERE, base::Bind(&SyncBackendHostCore::DoSetEncryptionPassphrase,
                             core_, passphrase, is_explicit));
@@ -124,14 +123,14 @@
 
 void SyncBackendHostImpl::SetDecryptionPassphrase(
     const std::string& passphrase) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   sync_task_runner_->PostTask(
       FROM_HERE, base::Bind(&SyncBackendHostCore::DoSetDecryptionPassphrase,
                             core_, passphrase));
 }
 
 void SyncBackendHostImpl::StopSyncingForShutdown() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Stop getting messages from the sync thread.
   weak_ptr_factory_.InvalidateWeakPtrs();
@@ -315,7 +314,7 @@
     const WeakHandle<DataTypeDebugInfoListener> debug_info_listener,
     std::unique_ptr<ModelTypeConnector> model_type_connector,
     const std::string& cache_guid) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   model_type_connector_ = std::move(model_type_connector);
 
@@ -339,7 +338,7 @@
 }
 
 void SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   host_->OnEngineInitialized(ModelTypeSet(), WeakHandle<JsBackend>(),
                              WeakHandle<DataTypeDebugInfoListener>(), "",
                              false);
@@ -347,7 +346,7 @@
 
 void SyncBackendHostImpl::HandleSyncCycleCompletedOnFrontendLoop(
     const SyncCycleSnapshot& snapshot) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Process any changes to the datatypes we're syncing.
   // TODO(sync): add support for removing types.
@@ -365,13 +364,13 @@
 
 void SyncBackendHostImpl::HandleActionableErrorEventOnFrontendLoop(
     const SyncProtocolError& sync_error) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   host_->OnActionableError(sync_error);
 }
 
 void SyncBackendHostImpl::HandleMigrationRequestedOnFrontendLoop(
     ModelTypeSet types) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   host_->OnMigrationNeededForTypes(types);
 }
 
@@ -394,46 +393,46 @@
 
 void SyncBackendHostImpl::HandleConnectionStatusChangeOnFrontendLoop(
     ConnectionStatus status) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DVLOG(1) << "Connection status changed: " << ConnectionStatusToString(status);
   host_->OnConnectionStatusChange(status);
 }
 
 void SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop(
     std::unique_ptr<ProtocolEvent> event) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   host_->OnProtocolEvent(*event);
 }
 
 void SyncBackendHostImpl::HandleDirectoryCommitCountersUpdatedOnFrontendLoop(
     ModelType type,
     const CommitCounters& counters) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   host_->OnDirectoryTypeCommitCounterUpdated(type, counters);
 }
 
 void SyncBackendHostImpl::HandleDirectoryUpdateCountersUpdatedOnFrontendLoop(
     ModelType type,
     const UpdateCounters& counters) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   host_->OnDirectoryTypeUpdateCounterUpdated(type, counters);
 }
 
 void SyncBackendHostImpl::HandleDirectoryStatusCountersUpdatedOnFrontendLoop(
     ModelType type,
     const StatusCounters& counters) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   host_->OnDatatypeStatusCounterUpdated(type, counters);
 }
 
 void SyncBackendHostImpl::UpdateInvalidationVersions(
     const std::map<ModelType, int64_t>& invalidation_versions) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   sync_prefs_->UpdateInvalidationVersions(invalidation_versions);
 }
 
 void SyncBackendHostImpl::ClearServerData(const base::Closure& callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   sync_task_runner_->PostTask(
       FROM_HERE,
       base::Bind(&SyncBackendHostCore::DoClearServerData, core_, callback));
@@ -442,7 +441,7 @@
 void SyncBackendHostImpl::OnCookieJarChanged(bool account_mismatch,
                                              bool empty_jar,
                                              const base::Closure& callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   sync_task_runner_->PostTask(
       FROM_HERE, base::Bind(&SyncBackendHostCore::DoOnCookieJarChanged, core_,
                             account_mismatch, empty_jar, callback));
@@ -450,13 +449,13 @@
 
 void SyncBackendHostImpl::ClearServerDataDoneOnFrontendLoop(
     const base::Closure& frontend_callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   frontend_callback.Run();
 }
 
 void SyncBackendHostImpl::OnCookieJarChangedDoneOnFrontendLoop(
     const base::Closure& callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   callback.Run();
 }
 
diff --git a/components/sync/driver/glue/sync_backend_host_impl.h b/components/sync/driver/glue/sync_backend_host_impl.h
index 724fa157..e451b53 100644
--- a/components/sync/driver/glue/sync_backend_host_impl.h
+++ b/components/sync/driver/glue/sync_backend_host_impl.h
@@ -17,7 +17,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "base/threading/thread_checker.h"
+#include "base/sequence_checker.h"
 #include "components/invalidation/public/invalidation_handler.h"
 #include "components/sync/base/extensions_activity.h"
 #include "components/sync/base/model_type.h"
@@ -230,7 +230,7 @@
   bool invalidation_handler_registered_ = false;
 
   // Checks that we're on the same thread this was constructed on (UI thread).
-  base::ThreadChecker thread_checker_;
+  SEQUENCE_CHECKER(sequence_checker_);
 
   base::WeakPtrFactory<SyncBackendHostImpl> weak_ptr_factory_;
 
diff --git a/components/sync/driver/sync_service_crypto.cc b/components/sync/driver/sync_service_crypto.cc
index 0652608..34c6acd 100644
--- a/components/sync/driver/sync_service_crypto.cc
+++ b/components/sync/driver/sync_service_crypto.cc
@@ -120,19 +120,19 @@
 SyncServiceCrypto::~SyncServiceCrypto() = default;
 
 base::Time SyncServiceCrypto::GetExplicitPassphraseTime() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return cached_explicit_passphrase_time_;
 }
 
 bool SyncServiceCrypto::IsUsingSecondaryPassphrase() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return cached_passphrase_type_ ==
              PassphraseType::FROZEN_IMPLICIT_PASSPHRASE ||
          cached_passphrase_type_ == PassphraseType::CUSTOM_PASSPHRASE;
 }
 
 void SyncServiceCrypto::EnableEncryptEverything() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(IsEncryptEverythingAllowed());
   DCHECK(engine_);
 
@@ -143,14 +143,14 @@
 }
 
 bool SyncServiceCrypto::IsEncryptEverythingEnabled() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(engine_);
   return encrypt_everything_ || encryption_pending_;
 }
 
 void SyncServiceCrypto::SetEncryptionPassphrase(const std::string& passphrase,
                                                 bool is_explicit) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // This should only be called when the engine has been initialized.
   DCHECK(engine_);
   DCHECK(data_type_manager_);
@@ -189,7 +189,7 @@
 }
 
 bool SyncServiceCrypto::SetDecryptionPassphrase(const std::string& passphrase) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(data_type_manager_);
 
   if (!data_type_manager_->IsNigoriEnabled()) {
@@ -226,23 +226,23 @@
 }
 
 PassphraseType SyncServiceCrypto::GetPassphraseType() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return cached_passphrase_type_;
 }
 
 bool SyncServiceCrypto::IsEncryptEverythingAllowed() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return encrypt_everything_allowed_;
 }
 
 void SyncServiceCrypto::SetEncryptEverythingAllowed(bool allowed) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(allowed || !engine_ || !IsEncryptEverythingEnabled());
   encrypt_everything_allowed_ = allowed;
 }
 
 ModelTypeSet SyncServiceCrypto::GetEncryptedDataTypes() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(encrypted_types_.Has(PASSWORDS));
   // We may be called during the setup process before we're
   // initialized.  In this case, we default to the sensitive types.
@@ -252,7 +252,7 @@
 void SyncServiceCrypto::OnPassphraseRequired(
     PassphraseRequiredReason reason,
     const sync_pb::EncryptedData& pending_keys) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Update our cache of the cryptographer's pending keys.
   cached_pending_keys_ = pending_keys;
@@ -274,7 +274,7 @@
 }
 
 void SyncServiceCrypto::OnPassphraseAccepted() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Clear our cache of the cryptographer's pending keys.
   cached_pending_keys_.clear_blob();
@@ -297,7 +297,7 @@
 void SyncServiceCrypto::OnBootstrapTokenUpdated(
     const std::string& bootstrap_token,
     BootstrapTokenType type) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(sync_prefs_);
   if (type == PASSPHRASE_BOOTSTRAP_TOKEN) {
     sync_prefs_->SetEncryptionBootstrapToken(bootstrap_token);
@@ -308,7 +308,7 @@
 
 void SyncServiceCrypto::OnEncryptedTypesChanged(ModelTypeSet encrypted_types,
                                                 bool encrypt_everything) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   encrypted_types_ = encrypted_types;
   encrypt_everything_ = encrypt_everything;
   DCHECK(encrypt_everything_allowed_ || !encrypt_everything_);
@@ -322,7 +322,7 @@
 }
 
 void SyncServiceCrypto::OnEncryptionComplete() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DVLOG(1) << "Encryption complete";
   if (encryption_pending_ && encrypt_everything_) {
     encryption_pending_ = false;
@@ -334,13 +334,13 @@
 
 void SyncServiceCrypto::OnCryptographerStateChanged(
     Cryptographer* cryptographer) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // Do nothing.
 }
 
 void SyncServiceCrypto::OnPassphraseTypeChanged(PassphraseType type,
                                                 base::Time passphrase_time) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DVLOG(1) << "Passphrase type changed to " << PassphraseTypeToString(type);
   cached_passphrase_type_ = type;
   cached_explicit_passphrase_time_ = passphrase_time;
@@ -349,7 +349,7 @@
 
 void SyncServiceCrypto::OnLocalSetPassphraseEncryption(
     const SyncEncryptionHandler::NigoriState& nigori_state) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!base::FeatureList::IsEnabled(
           switches::kSyncClearDataOnPassphraseEncryption)) {
     return;
@@ -367,7 +367,7 @@
 }
 
 void SyncServiceCrypto::BeginConfigureCatchUpBeforeClear() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(data_type_manager_);
   DCHECK(!saved_nigori_state_);
   DCHECK(can_configure_data_types_.Run());
@@ -380,14 +380,14 @@
 
 std::unique_ptr<SyncEncryptionHandler::Observer>
 SyncServiceCrypto::GetEncryptionObserverProxy() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return std::make_unique<SyncEncryptionObserverProxy>(
       weak_factory_.GetWeakPtr(), base::SequencedTaskRunnerHandle::Get());
 }
 
 std::unique_ptr<SyncEncryptionHandler::NigoriState>
 SyncServiceCrypto::TakeSavedNigoriState() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return std::move(saved_nigori_state_);
 }
 
diff --git a/components/sync/driver/sync_service_crypto.h b/components/sync/driver/sync_service_crypto.h
index 7e322e2..066ea6e3 100644
--- a/components/sync/driver/sync_service_crypto.h
+++ b/components/sync/driver/sync_service_crypto.h
@@ -10,6 +10,7 @@
 
 #include "base/callback.h"
 #include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
 #include "components/sync/base/model_type.h"
 #include "components/sync/engine/sync_encryption_handler.h"
 #include "components/sync/engine/sync_engine.h"
@@ -157,7 +158,8 @@
   // first set (if available).
   base::Time cached_explicit_passphrase_time_;
 
-  base::ThreadChecker thread_checker_;
+  SEQUENCE_CHECKER(sequence_checker_);
+
   base::WeakPtrFactory<SyncServiceCrypto> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(SyncServiceCrypto);
diff --git a/components/sync/engine/sync_backend_registrar.cc b/components/sync/engine/sync_backend_registrar.cc
index e0aa9737..f8086aa 100644
--- a/components/sync/engine/sync_backend_registrar.cc
+++ b/components/sync/engine/sync_backend_registrar.cc
@@ -28,7 +28,7 @@
 }
 
 void SyncBackendRegistrar::RegisterNonBlockingType(ModelType type) {
-  DCHECK(ui_thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   base::AutoLock lock(lock_);
   // There may have been a previously successful sync of a type when passive,
   // which is now NonBlocking. We're not sure what order these two sets of types
@@ -78,7 +78,7 @@
 }
 
 void SyncBackendRegistrar::AddRestoredNonBlockingType(ModelType type) {
-  DCHECK(ui_thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   base::AutoLock lock(lock_);
   DCHECK(non_blocking_types_.Has(type));
   DCHECK(routing_info_.find(type) == routing_info_.end());
@@ -87,7 +87,7 @@
 }
 
 bool SyncBackendRegistrar::IsNigoriEnabled() const {
-  DCHECK(ui_thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   base::AutoLock lock(lock_);
   return routing_info_.find(NIGORI) != routing_info_.end();
 }
@@ -139,7 +139,7 @@
 }
 
 void SyncBackendRegistrar::RequestWorkerStopOnUIThread() {
-  DCHECK(ui_thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   base::AutoLock lock(lock_);
   for (const auto& kv : workers_) {
     kv.second->RequestStop();
@@ -172,7 +172,9 @@
 void SyncBackendRegistrar::DeactivateDataType(ModelType type) {
   DVLOG(1) << "Deactivate: " << ModelTypeToString(type);
 
-  DCHECK(ui_thread_checker_.CalledOnValidThread() || IsControlType(type));
+  if (!IsControlType(type)) {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  }
   base::AutoLock lock(lock_);
 
   routing_info_.erase(type);
diff --git a/components/sync/engine/sync_backend_registrar.h b/components/sync/engine/sync_backend_registrar.h
index 23bbb677..88791bf 100644
--- a/components/sync/engine/sync_backend_registrar.h
+++ b/components/sync/engine/sync_backend_registrar.h
@@ -15,8 +15,8 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/sequence_checker.h"
 #include "base/synchronization/lock.h"
-#include "base/threading/thread_checker.h"
 #include "components/sync/base/model_type.h"
 #include "components/sync/engine/model_safe_worker.h"
 #include "components/sync/engine/sync_manager.h"
@@ -143,7 +143,7 @@
   const std::string name_;
 
   // Checker for the UI thread (where this object is constructed).
-  base::ThreadChecker ui_thread_checker_;
+  SEQUENCE_CHECKER(sequence_checker_);
 
   // Protects all variables below.
   mutable base::Lock lock_;
diff --git a/components/sync/engine_impl/debug_info_event_listener.cc b/components/sync/engine_impl/debug_info_event_listener.cc
index 820f08b..237798e 100644
--- a/components/sync/engine_impl/debug_info_event_listener.cc
+++ b/components/sync/engine_impl/debug_info_event_listener.cc
@@ -20,7 +20,7 @@
 
 void DebugInfoEventListener::OnSyncCycleCompleted(
     const SyncCycleSnapshot& snapshot) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   sync_pb::DebugEventInfo event_info;
   sync_pb::SyncCycleCompletedEventInfo* sync_completed_event_info =
       event_info.mutable_sync_cycle_completed_event_info();
@@ -54,31 +54,31 @@
     const WeakHandle<DataTypeDebugInfoListener>& debug_listener,
     bool success,
     ModelTypeSet restored_types) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   CreateAndAddEvent(sync_pb::SyncEnums::INITIALIZATION_COMPLETE);
 }
 
 void DebugInfoEventListener::OnConnectionStatusChange(ConnectionStatus status) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   CreateAndAddEvent(sync_pb::SyncEnums::CONNECTION_STATUS_CHANGE);
 }
 
 void DebugInfoEventListener::OnPassphraseRequired(
     PassphraseRequiredReason reason,
     const sync_pb::EncryptedData& pending_keys) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   CreateAndAddEvent(sync_pb::SyncEnums::PASSPHRASE_REQUIRED);
 }
 
 void DebugInfoEventListener::OnPassphraseAccepted() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   CreateAndAddEvent(sync_pb::SyncEnums::PASSPHRASE_ACCEPTED);
 }
 
 void DebugInfoEventListener::OnBootstrapTokenUpdated(
     const std::string& bootstrap_token,
     BootstrapTokenType type) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (type == PASSPHRASE_BOOTSTRAP_TOKEN) {
     CreateAndAddEvent(sync_pb::SyncEnums::BOOTSTRAP_TOKEN_UPDATED);
     return;
@@ -90,18 +90,18 @@
 void DebugInfoEventListener::OnEncryptedTypesChanged(
     ModelTypeSet encrypted_types,
     bool encrypt_everything) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   CreateAndAddEvent(sync_pb::SyncEnums::ENCRYPTED_TYPES_CHANGED);
 }
 
 void DebugInfoEventListener::OnEncryptionComplete() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   CreateAndAddEvent(sync_pb::SyncEnums::ENCRYPTION_COMPLETE);
 }
 
 void DebugInfoEventListener::OnCryptographerStateChanged(
     Cryptographer* cryptographer) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   cryptographer_has_pending_keys_ = cryptographer->has_pending_keys();
   cryptographer_ready_ = cryptographer->is_ready();
 }
@@ -109,7 +109,7 @@
 void DebugInfoEventListener::OnPassphraseTypeChanged(
     PassphraseType type,
     base::Time explicit_passphrase_time) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   CreateAndAddEvent(sync_pb::SyncEnums::PASSPHRASE_TYPE_CHANGED);
 }
 
@@ -118,7 +118,7 @@
 
 void DebugInfoEventListener::OnActionableError(
     const SyncProtocolError& sync_error) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   CreateAndAddEvent(sync_pb::SyncEnums::ACTIONABLE_ERROR);
 }
 
@@ -127,7 +127,7 @@
 void DebugInfoEventListener::OnProtocolEvent(const ProtocolEvent& event) {}
 
 void DebugInfoEventListener::OnNudgeFromDatatype(ModelType datatype) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   sync_pb::DebugEventInfo event_info;
   event_info.set_nudging_datatype(
       GetSpecificsFieldNumberFromModelType(datatype));
@@ -135,7 +135,7 @@
 }
 
 void DebugInfoEventListener::GetDebugInfo(sync_pb::DebugInfo* debug_info) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_LE(events_.size(), kMaxEntries);
 
   for (DebugEventInfoQueue::const_iterator iter = events_.begin();
@@ -151,7 +151,7 @@
 }
 
 void DebugInfoEventListener::ClearDebugInfo() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_LE(events_.size(), kMaxEntries);
 
   events_.clear();
@@ -159,13 +159,13 @@
 }
 
 base::WeakPtr<DataTypeDebugInfoListener> DebugInfoEventListener::GetWeakPtr() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return weak_ptr_factory_.GetWeakPtr();
 }
 
 void DebugInfoEventListener::OnDataTypeConfigureComplete(
     const std::vector<DataTypeConfigurationStats>& configuration_stats) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   for (size_t i = 0; i < configuration_stats.size(); ++i) {
     DCHECK(ProtocolTypes().Has(configuration_stats[i].model_type));
@@ -236,7 +236,7 @@
 
 void DebugInfoEventListener::CreateAndAddEvent(
     sync_pb::SyncEnums::SingletonDebugEventType type) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   sync_pb::DebugEventInfo event_info;
   event_info.set_singleton_event(type);
   AddEventToQueue(event_info);
@@ -244,7 +244,7 @@
 
 void DebugInfoEventListener::AddEventToQueue(
     const sync_pb::DebugEventInfo& event_info) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (events_.size() >= kMaxEntries) {
     DVLOG(1) << "DebugInfoEventListener::AddEventToQueue Dropping an old event "
              << "because of full queue";
diff --git a/components/sync/engine_impl/debug_info_event_listener.h b/components/sync/engine_impl/debug_info_event_listener.h
index 6022e3f..4999688 100644
--- a/components/sync/engine_impl/debug_info_event_listener.h
+++ b/components/sync/engine_impl/debug_info_event_listener.h
@@ -12,6 +12,7 @@
 #include "base/containers/circular_deque.h"
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
+#include "base/sequence_checker.h"
 #include "components/sync/base/model_type.h"
 #include "components/sync/base/weak_handle.h"
 #include "components/sync/engine/cycle/sync_cycle_snapshot.h"
@@ -107,7 +108,7 @@
   // Cryptographer is initialized and does not have pending keys.
   bool cryptographer_ready_;
 
-  base::ThreadChecker thread_checker_;
+  SEQUENCE_CHECKER(sequence_checker_);
 
   base::WeakPtrFactory<DebugInfoEventListener> weak_ptr_factory_;
 
diff --git a/components/sync/engine_impl/model_type_worker.cc b/components/sync/engine_impl/model_type_worker.cc
index 0e88984d..481b569 100644
--- a/components/sync/engine_impl/model_type_worker.cc
+++ b/components/sync/engine_impl/model_type_worker.cc
@@ -77,13 +77,13 @@
 }
 
 ModelType ModelTypeWorker::GetModelType() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return type_;
 }
 
 void ModelTypeWorker::UpdateCryptographer(
     std::unique_ptr<Cryptographer> cryptographer) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(cryptographer);
   cryptographer_ = std::move(cryptographer);
   UpdateEncryptionKeyName();
@@ -93,19 +93,19 @@
 
 // UpdateHandler implementation.
 bool ModelTypeWorker::IsInitialSyncEnded() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return model_type_state_.initial_sync_done();
 }
 
 void ModelTypeWorker::GetDownloadProgress(
     sync_pb::DataTypeProgressMarker* progress_marker) const {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   progress_marker->CopyFrom(model_type_state_.progress_marker());
 }
 
 void ModelTypeWorker::GetDataTypeContext(
     sync_pb::DataTypeContext* context) const {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   context->CopyFrom(model_type_state_.type_context());
 }
 
@@ -114,7 +114,7 @@
     const sync_pb::DataTypeContext& mutated_context,
     const SyncEntityList& applicable_updates,
     StatusController* status) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // TODO(rlarocque): Handle data type context conflicts.
   *model_type_state_.mutable_type_context() = mutated_context;
@@ -197,7 +197,7 @@
 }
 
 void ModelTypeWorker::ApplyUpdates(StatusController* status) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // This should only ever be called after one PassiveApplyUpdates.
   DCHECK(model_type_state_.initial_sync_done());
   // Download cycle is done, pass all updates to the processor.
@@ -205,7 +205,7 @@
 }
 
 void ModelTypeWorker::PassiveApplyUpdates(StatusController* status) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // This should only be called at the end of the very first download cycle.
   DCHECK(!model_type_state_.initial_sync_done());
   // Indicate to the processor that the initial download is done. The initial
@@ -247,7 +247,7 @@
 }
 
 void ModelTypeWorker::NudgeForCommit() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   has_local_changes_ = true;
   NudgeIfReadyToCommit();
 }
@@ -260,7 +260,7 @@
 // CommitContributor implementation.
 std::unique_ptr<CommitContribution> ModelTypeWorker::GetContribution(
     size_t max_entries) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(model_type_state_.initial_sync_done());
   // Early return if type is not ready to commit (initial sync isn't done or
   // cryptographer has pending keys).
@@ -298,7 +298,7 @@
 }
 
 void ModelTypeWorker::OnCommitResponse(CommitResponseDataList* response_list) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Send the responses back to the model thread. It needs to know which
   // items have been successfully committed so it can save that information in
diff --git a/components/sync/engine_impl/model_type_worker.h b/components/sync/engine_impl/model_type_worker.h
index b17f258d..9898710 100644
--- a/components/sync/engine_impl/model_type_worker.h
+++ b/components/sync/engine_impl/model_type_worker.h
@@ -14,8 +14,8 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
 #include "base/synchronization/waitable_event.h"
-#include "base/threading/thread_checker.h"
 #include "components/sync/base/cancelation_observer.h"
 #include "components/sync/base/cryptographer.h"
 #include "components/sync/base/model_type.h"
@@ -211,7 +211,8 @@
   // shutdown.
   CancelationSignal* cancelation_signal_;
 
-  base::ThreadChecker thread_checker_;
+  SEQUENCE_CHECKER(sequence_checker_);
+
   base::WeakPtrFactory<ModelTypeWorker> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ModelTypeWorker);
diff --git a/components/sync/engine_impl/net/server_connection_manager.cc b/components/sync/engine_impl/net/server_connection_manager.cc
index 0d24168..a40ec6a9 100644
--- a/components/sync/engine_impl/net/server_connection_manager.cc
+++ b/components/sync/engine_impl/net/server_connection_manager.cc
@@ -154,7 +154,7 @@
 }
 
 bool ServerConnectionManager::SetAuthToken(const std::string& auth_token) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!auth_token.empty() && (previously_invalidated_token != auth_token)) {
     auth_token_.assign(auth_token);
@@ -176,7 +176,7 @@
 }
 
 void ServerConnectionManager::InvalidateAndClearAuthToken() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // Copy over the token to previous invalid token.
   if (!auth_token_.empty()) {
     previously_invalidated_token.assign(auth_token_);
@@ -197,14 +197,14 @@
 }
 
 void ServerConnectionManager::NotifyStatusChanged() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (auto& observer : listeners_)
     observer.OnServerConnectionEvent(ServerConnectionEvent(server_status_));
 }
 
 bool ServerConnectionManager::PostBufferWithCachedAuth(
     PostBufferParams* params) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   string path =
       MakeSyncServerPath(proto_sync_path(), MakeSyncQueryString(client_id_));
   bool result = PostBufferToPath(params, path, auth_token());
@@ -215,7 +215,7 @@
 bool ServerConnectionManager::PostBufferToPath(PostBufferParams* params,
                                                const string& path,
                                                const string& auth_token) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (auth_token.empty()) {
     params->response.server_status = HttpResponse::SYNC_AUTH_ERROR;
@@ -253,13 +253,13 @@
 
 void ServerConnectionManager::AddListener(
     ServerConnectionEventListener* listener) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   listeners_.AddObserver(listener);
 }
 
 void ServerConnectionManager::RemoveListener(
     ServerConnectionEventListener* listener) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   listeners_.RemoveObserver(listener);
 }
 
diff --git a/components/sync/engine_impl/net/server_connection_manager.h b/components/sync/engine_impl/net/server_connection_manager.h
index 531ffe521..dd2eb4f38 100644
--- a/components/sync/engine_impl/net/server_connection_manager.h
+++ b/components/sync/engine_impl/net/server_connection_manager.h
@@ -14,9 +14,9 @@
 #include "base/atomicops.h"
 #include "base/macros.h"
 #include "base/observer_list.h"
+#include "base/sequence_checker.h"
 #include "base/strings/string_util.h"
 #include "base/synchronization/lock.h"
-#include "base/threading/thread_checker.h"
 #include "components/sync/base/cancelation_observer.h"
 #include "components/sync/syncable/syncable_id.h"
 
@@ -170,7 +170,7 @@
   void RemoveListener(ServerConnectionEventListener* listener);
 
   inline HttpResponse::ServerConnectionCode server_status() const {
-    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     return server_status_;
   }
 
@@ -181,7 +181,7 @@
   virtual std::unique_ptr<Connection> MakeConnection();
 
   void set_client_id(const std::string& client_id) {
-    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     DCHECK(client_id_.empty());
     client_id_.assign(client_id);
   }
@@ -194,7 +194,7 @@
   bool HasInvalidAuthToken() { return auth_token_.empty(); }
 
   const std::string auth_token() const {
-    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     return auth_token_;
   }
 
@@ -248,7 +248,7 @@
 
   HttpResponse::ServerConnectionCode server_status_;
 
-  base::ThreadChecker thread_checker_;
+  SEQUENCE_CHECKER(sequence_checker_);
 
   CancelationSignal* const cancelation_signal_;
 
diff --git a/components/sync/engine_impl/sync_manager_impl.cc b/components/sync/engine_impl/sync_manager_impl.cc
index b1cb538..1a860f2e 100644
--- a/components/sync/engine_impl/sync_manager_impl.cc
+++ b/components/sync/engine_impl/sync_manager_impl.cc
@@ -86,7 +86,7 @@
 }
 
 SyncManagerImpl::~SyncManagerImpl() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!initialized_);
 }
 
@@ -167,7 +167,7 @@
     ModelTypeSet to_download,
     const base::Closure& ready_task,
     const base::Closure& retry_task) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!ready_task.is_null());
   DCHECK(initialized_);
 
@@ -187,7 +187,7 @@
 
 void SyncManagerImpl::Init(InitArgs* args) {
   DCHECK(!initialized_);
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(args->post_factory);
   DCHECK(!args->short_poll_interval.is_zero());
   DCHECK(!args->long_poll_interval.is_zero());
@@ -379,12 +379,12 @@
 void SyncManagerImpl::StartSyncingNormally(
     base::Time last_poll_time) {
   // Start the sync scheduler.
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   scheduler_->Start(SyncScheduler::NORMAL_MODE, last_poll_time);
 }
 
 void SyncManagerImpl::StartConfiguration() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   scheduler_->Start(SyncScheduler::CONFIGURATION_MODE, base::Time());
 }
 
@@ -447,7 +447,7 @@
 void SyncManagerImpl::PurgeDisabledTypes(ModelTypeSet to_purge,
                                          ModelTypeSet to_journal,
                                          ModelTypeSet to_unapply) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(initialized_);
   DVLOG(1) << "Purging disabled types:\n\t"
            << "types to purge: " << ModelTypeSetToString(to_purge) << "\n\t"
@@ -459,7 +459,7 @@
 }
 
 void SyncManagerImpl::UpdateCredentials(const SyncCredentials& credentials) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(initialized_);
   DCHECK(!credentials.account_id.empty());
   DCHECK(!credentials.scope_set.empty());
@@ -475,22 +475,22 @@
 }
 
 void SyncManagerImpl::InvalidateCredentials() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   connection_manager_->SetAuthToken(std::string());
 }
 
 void SyncManagerImpl::AddObserver(SyncManager::Observer* observer) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   observers_.AddObserver(observer);
 }
 
 void SyncManagerImpl::RemoveObserver(SyncManager::Observer* observer) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   observers_.RemoveObserver(observer);
 }
 
 void SyncManagerImpl::ShutdownOnSyncThread() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Prevent any in-flight method calls from running.  Also
   // invalidates |weak_handle_this_| and |change_observer_|.
@@ -544,7 +544,7 @@
 
 void SyncManagerImpl::OnNetworkChanged(
     net::NetworkChangeNotifier::ConnectionType type) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!observing_network_connectivity_changes_) {
     DVLOG(1) << "Network change dropped.";
     return;
@@ -555,7 +555,7 @@
 
 void SyncManagerImpl::OnServerConnectionEvent(
     const ServerConnectionEvent& event) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (event.connection_code == HttpResponse::SERVER_CONNECTION_OK) {
     for (auto& observer : observers_) {
       observer.OnConnectionStatusChange(CONNECTION_OK);
@@ -767,22 +767,22 @@
 }
 
 void SyncManagerImpl::NudgeForInitialDownload(ModelType type) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   scheduler_->ScheduleInitialSyncNudge(type);
 }
 
 void SyncManagerImpl::NudgeForCommit(ModelType type) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   RequestNudgeForDataTypes(FROM_HERE, ModelTypeSet(type));
 }
 
 void SyncManagerImpl::NudgeForRefresh(ModelType type) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   RefreshTypes(ModelTypeSet(type));
 }
 
 void SyncManagerImpl::OnSyncCycleEvent(const SyncCycleEvent& event) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // Only send an event if this is due to a cycle ending and this cycle
   // concludes a canonical "sync" process; that is, based on what is known
   // locally we are "all happy" and up to date.  There may be new changes on
@@ -837,7 +837,7 @@
 }
 
 void SyncManagerImpl::SetInvalidatorEnabled(bool invalidator_enabled) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   DVLOG(1) << "Invalidator enabled state is now: " << invalidator_enabled;
   allstatus_.SetNotificationsEnabled(invalidator_enabled);
@@ -847,7 +847,7 @@
 void SyncManagerImpl::OnIncomingInvalidation(
     ModelType type,
     std::unique_ptr<InvalidationInterface> invalidation) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   allstatus_.IncrementNotificationsReceived();
   scheduler_->ScheduleInvalidationNudge(type, std::move(invalidation),
@@ -855,7 +855,7 @@
 }
 
 void SyncManagerImpl::RefreshTypes(ModelTypeSet types) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (types.Empty()) {
     LOG(WARNING) << "Sync received refresh request with no types specified.";
   } else {
@@ -877,7 +877,7 @@
 }
 
 ModelTypeConnector* SyncManagerImpl::GetModelTypeConnector() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return model_type_registry_.get();
 }
 
@@ -971,7 +971,7 @@
 }
 
 void SyncManagerImpl::ClearServerData(const base::Closure& callback) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   scheduler_->Start(SyncScheduler::CLEAR_SERVER_DATA_MODE, base::Time());
   ClearParams params(callback);
   scheduler_->ScheduleClearServerData(params);
@@ -979,7 +979,7 @@
 
 void SyncManagerImpl::OnCookieJarChanged(bool account_mismatch,
                                          bool empty_jar) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   cycle_context_->set_cookie_jar_mismatch(account_mismatch);
   cycle_context_->set_cookie_jar_empty(empty_jar);
 }
diff --git a/components/sync/engine_impl/sync_manager_impl.h b/components/sync/engine_impl/sync_manager_impl.h
index 4071fcb..d92be22 100644
--- a/components/sync/engine_impl/sync_manager_impl.h
+++ b/components/sync/engine_impl/sync_manager_impl.h
@@ -15,6 +15,7 @@
 #include "base/callback_forward.h"
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
+#include "base/sequence_checker.h"
 #include "components/sync/base/cryptographer.h"
 #include "components/sync/base/time.h"
 #include "components/sync/engine/sync_manager.h"
@@ -237,7 +238,7 @@
 
   const std::string name_;
 
-  base::ThreadChecker thread_checker_;
+  SEQUENCE_CHECKER(sequence_checker_);
 
   // Thread-safe handle used by
   // HandleCalculateChangesChangeEventFromSyncApi(), which can be
diff --git a/components/sync/engine_impl/sync_manager_impl_unittest.cc b/components/sync/engine_impl/sync_manager_impl_unittest.cc
index bb1ae7b..8001939 100644
--- a/components/sync/engine_impl/sync_manager_impl_unittest.cc
+++ b/components/sync/engine_impl/sync_manager_impl_unittest.cc
@@ -1121,7 +1121,7 @@
   }
 
   void SimulateInvalidatorEnabledForTest(bool is_enabled) {
-    DCHECK(sync_manager_.thread_checker_.CalledOnValidThread());
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sync_manager_.sequence_checker_);
     sync_manager_.SetInvalidatorEnabled(is_enabled);
   }
 
diff --git a/components/sync/test/engine/fake_model_worker.cc b/components/sync/test/engine/fake_model_worker.cc
index 4f48864e..d9868271 100644
--- a/components/sync/test/engine/fake_model_worker.cc
+++ b/components/sync/test/engine/fake_model_worker.cc
@@ -15,22 +15,22 @@
   // multi-threaded test; since ModelSafeWorkers are
   // RefCountedThreadSafe, they could theoretically be destroyed from
   // a different thread.
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
 void FakeModelWorker::ScheduleWork(base::OnceClosure work) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // Simply do the work on the current thread.
   std::move(work).Run();
 }
 
 ModelSafeGroup FakeModelWorker::GetModelSafeGroup() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return group_;
 }
 
 bool FakeModelWorker::IsOnModelSequence() {
-  return thread_checker_.CalledOnValidThread();
+  return sequence_checker_.CalledOnValidSequence();
 }
 
 }  // namespace syncer
diff --git a/components/sync/test/engine/fake_model_worker.h b/components/sync/test/engine/fake_model_worker.h
index 42624ffe..dd013741 100644
--- a/components/sync/test/engine/fake_model_worker.h
+++ b/components/sync/test/engine/fake_model_worker.h
@@ -28,7 +28,8 @@
   void ScheduleWork(base::OnceClosure work) override;
 
   const ModelSafeGroup group_;
-  base::ThreadChecker thread_checker_;
+
+  base::SequenceChecker sequence_checker_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeModelWorker);
 };
diff --git a/components/sync_bookmarks/bookmark_change_processor.cc b/components/sync_bookmarks/bookmark_change_processor.cc
index 0898ac26..644bd9a6 100644
--- a/components/sync_bookmarks/bookmark_change_processor.cc
+++ b/components/sync_bookmarks/bookmark_change_processor.cc
@@ -61,7 +61,7 @@
 }
 
 void BookmarkChangeProcessor::StartImpl() {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!bookmark_model_);
   bookmark_model_ = sync_client_->GetBookmarkModel();
   DCHECK(bookmark_model_->loaded());
@@ -559,7 +559,7 @@
     const syncer::BaseTransaction* trans,
     int64_t model_version,
     const syncer::ImmutableChangeRecordList& changes) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // A note about ordering.  Sync backend is responsible for ordering the change
   // records in the following order:
   //
diff --git a/components/sync_bookmarks/bookmark_change_processor.h b/components/sync_bookmarks/bookmark_change_processor.h
index f1a5b9d0..bfbd55c 100644
--- a/components/sync_bookmarks/bookmark_change_processor.h
+++ b/components/sync_bookmarks/bookmark_change_processor.h
@@ -13,7 +13,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
-#include "base/threading/thread_checker.h"
+#include "base/sequence_checker.h"
 #include "components/bookmarks/browser/bookmark_model_observer.h"
 #include "components/bookmarks/browser/bookmark_node.h"
 #include "components/sync/model/change_processor.h"
@@ -238,7 +238,7 @@
   // Returns false if |node| should not be synced.
   bool CanSyncNode(const bookmarks::BookmarkNode* node);
 
-  base::ThreadChecker thread_checker_;
+  SEQUENCE_CHECKER(sequence_checker_);
 
   // The bookmark model we are processing changes from.  Non-null when
   // |running_| is true.
diff --git a/components/unified_consent/unified_consent_service.cc b/components/unified_consent/unified_consent_service.cc
index 89511092..80f0a99 100644
--- a/components/unified_consent/unified_consent_service.cc
+++ b/components/unified_consent/unified_consent_service.cc
@@ -29,6 +29,7 @@
   DCHECK(identity_manager_);
   DCHECK(sync_service_);
   identity_manager_->AddObserver(this);
+  sync_service_->AddObserver(this);
 
   if (GetMigrationState() == MigrationState::NOT_INITIALIZED)
     MigrateProfileToUnifiedConsent();
@@ -83,6 +84,7 @@
 
 void UnifiedConsentService::Shutdown() {
   identity_manager_->RemoveObserver(this);
+  sync_service_->RemoveObserver(this);
 }
 
 void UnifiedConsentService::OnPrimaryAccountCleared(
@@ -109,6 +111,11 @@
   }
 }
 
+void UnifiedConsentService::OnStateChanged(syncer::SyncService* sync) {
+  if (IsUnifiedConsentGiven())
+    EnableAllSyncDataTypesIfPossible();
+}
+
 void UnifiedConsentService::OnUnifiedConsentGivenPrefChanged() {
   bool enabled = pref_service_->GetBoolean(prefs::kUnifiedConsentGiven);
 
@@ -130,10 +137,9 @@
   if (GetMigrationState() != MigrationState::COMPLETED)
     MarkMigrationComplete();
 
-  // Enable all sync data types.
-  pref_service_->SetBoolean(autofill::prefs::kAutofillWalletImportEnabled,
-                            true);
-  sync_service_->OnUserChoseDatatypes(true, syncer::UserSelectableTypes());
+  // Enable all sync data types if possible, otherwise they will be enabled with
+  // |OnStateChanged| once sync is active;
+  EnableAllSyncDataTypesIfPossible();
 
   // Enable all non-personalized services.
   pref_service_->SetBoolean(prefs::kUrlKeyedAnonymizedDataCollectionEnabled,
@@ -149,6 +155,14 @@
   service_client_->SetNetworkPredictionEnabled(true);
 }
 
+void UnifiedConsentService::EnableAllSyncDataTypesIfPossible() {
+  if (sync_service_->GetState() != syncer::SyncService::State::ACTIVE)
+    return;
+  pref_service_->SetBoolean(autofill::prefs::kAutofillWalletImportEnabled,
+                            true);
+  sync_service_->OnUserChoseDatatypes(true, syncer::UserSelectableTypes());
+}
+
 void UnifiedConsentService::MigrateProfileToUnifiedConsent() {
   DCHECK_EQ(GetMigrationState(), MigrationState::NOT_INITIALIZED);
   DCHECK(!IsUnifiedConsentGiven());
diff --git a/components/unified_consent/unified_consent_service.h b/components/unified_consent/unified_consent_service.h
index 80256fc..f2bd639 100644
--- a/components/unified_consent/unified_consent_service.h
+++ b/components/unified_consent/unified_consent_service.h
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/observer_list.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "components/sync/driver/sync_service_observer.h"
 #include "services/identity/public/cpp/identity_manager.h"
 
 namespace user_prefs {
@@ -38,7 +39,8 @@
 // A browser-context keyed service that is used to manage the user consent
 // when UnifiedConsent feature is enabled.
 class UnifiedConsentService : public KeyedService,
-                              public identity::IdentityManager::Observer {
+                              public identity::IdentityManager::Observer,
+                              public syncer::SyncServiceObserver {
  public:
   UnifiedConsentService(UnifiedConsentServiceClient* service_client,
                         PrefService* pref_service,
@@ -72,11 +74,17 @@
       const AccountInfo& previous_primary_account_info) override;
 
  private:
+  // syncer::SyncServiceObserver:
+  void OnStateChanged(syncer::SyncService* sync) override;
+
   // Called when |prefs::kUnifiedConsentGiven| pref value changes.
   // When set to true, it enables syncing of all data types and it enables all
   // non-personalized services. Otherwise it does nothing.
   void OnUnifiedConsentGivenPrefChanged();
 
+  // Enables all sync data types if sync is active.
+  void EnableAllSyncDataTypesIfPossible();
+
   // Called when the unified consent service is created to resolve
   // inconsistencies with sync-related prefs.
   void MigrateProfileToUnifiedConsent();
diff --git a/components/unified_consent/unified_consent_service_unittest.cc b/components/unified_consent/unified_consent_service_unittest.cc
index 689c0735..f4cb701 100644
--- a/components/unified_consent/unified_consent_service_unittest.cc
+++ b/components/unified_consent/unified_consent_service_unittest.cc
@@ -22,6 +22,30 @@
 class TestSyncService : public syncer::FakeSyncService {
  public:
   int GetDisableReasons() const override { return DISABLE_REASON_NONE; }
+  bool IsFirstSetupComplete() const override { return true; }
+  bool IsSyncActive() const override { return engine_initialized_; }
+  bool IsEngineInitialized() const override { return engine_initialized_; }
+  void AddObserver(syncer::SyncServiceObserver* observer) override {
+    observer_ = observer;
+  }
+  void OnUserChoseDatatypes(bool sync_everything,
+                            syncer::ModelTypeSet chosen_types) override {
+    is_syncing_everything_ = sync_everything;
+  }
+
+  void SetEngineInitialized(bool engine_initialized) {
+    engine_initialized_ = engine_initialized;
+  }
+  void FireStateChanged() {
+    if (observer_)
+      observer_->OnStateChanged(this);
+  }
+  bool IsSyncingEverything() { return is_syncing_everything_; }
+
+ private:
+  syncer::SyncServiceObserver* observer_ = nullptr;
+  bool engine_initialized_ = true;
+  bool is_syncing_everything_ = false;
 };
 
 class UnifiedConsentServiceTest : public testing::Test,
@@ -117,6 +141,33 @@
   EXPECT_TRUE(search_suggest_enabled_);
 }
 
+TEST_F(UnifiedConsentServiceTest, EnableUnfiedConsent_SyncNotActive) {
+  CreateConsentService();
+  identity_test_environment_.SetPrimaryAccount("testaccount");
+  EXPECT_FALSE(pref_service_.GetBoolean(prefs::kUnifiedConsentGiven));
+  EXPECT_FALSE(sync_service_.IsSyncingEverything());
+
+  // Make sure sync is not active.
+  sync_service_.SetEngineInitialized(false);
+  EXPECT_FALSE(sync_service_.IsEngineInitialized());
+  EXPECT_NE(sync_service_.GetState(), syncer::SyncService::State::ACTIVE);
+
+  // Opt into unified consent.
+  consent_service_->SetUnifiedConsentGiven(true);
+  EXPECT_TRUE(consent_service_->IsUnifiedConsentGiven());
+
+  // Couldn't sync everything because sync is not active.
+  EXPECT_FALSE(sync_service_.IsSyncingEverything());
+
+  // Initalize sync engine and therefore activate sync.
+  sync_service_.SetEngineInitialized(true);
+  EXPECT_EQ(sync_service_.GetState(), syncer::SyncService::State::ACTIVE);
+  sync_service_.FireStateChanged();
+
+  // UnifiedConsentService starts syncing everything.
+  EXPECT_TRUE(sync_service_.IsSyncingEverything());
+}
+
 #if !defined(OS_CHROMEOS)
 TEST_F(UnifiedConsentServiceTest, Migration_SyncingEverything) {
   // Create inconsistent state.
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 5361ebd5..c81e294 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -1078,6 +1078,8 @@
     "media/audible_metrics.h",
     "media/audio_input_stream_broker.cc",
     "media/audio_input_stream_broker.h",
+    "media/audio_log_factory.cc",
+    "media/audio_log_factory.h",
     "media/audio_loopback_stream_broker.cc",
     "media/audio_loopback_stream_broker.h",
     "media/audio_muting_session.cc",
@@ -1122,8 +1124,6 @@
     "media/media_web_contents_observer.h",
     "media/midi_host.cc",
     "media/midi_host.h",
-    "media/mojo_audio_logging_adapter.cc",
-    "media/mojo_audio_logging_adapter.h",
     "media/session/audio_focus_delegate.h",
     "media/session/audio_focus_delegate_android.cc",
     "media/session/audio_focus_delegate_android.h",
diff --git a/content/browser/background_fetch/background_fetch_context.cc b/content/browser/background_fetch/background_fetch_context.cc
index 59ecbe3..76b68620 100644
--- a/content/browser/background_fetch/background_fetch_context.cc
+++ b/content/browser/background_fetch/background_fetch_context.cc
@@ -36,11 +36,9 @@
   // Although this lives only on the IO thread, it is constructed on UI thread.
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(service_worker_context_);
+
   data_manager_ = std::make_unique<BackgroundFetchDataManager>(
-      browser_context, service_worker_context, cache_storage_context,
-      base::BindRepeating(&BackgroundFetchContext::AbandonFetches,
-                          weak_factory_.GetWeakPtr(),
-                          blink::mojom::kInvalidServiceWorkerRegistrationId));
+      browser_context_, service_worker_context, cache_storage_context);
   scheduler_ = std::make_unique<BackgroundFetchScheduler>(data_manager_.get());
   delegate_proxy_.SetClickEventDispatcher(base::BindRepeating(
       &BackgroundFetchContext::DispatchClickEvent, weak_factory_.GetWeakPtr()));
@@ -209,6 +207,11 @@
                                       std::move(callback));
 }
 
+void BackgroundFetchContext::OnServiceWorkerDatabaseCorrupted(
+    int64_t service_worker_registration_id) {
+  AbandonFetches(service_worker_registration_id);
+}
+
 void BackgroundFetchContext::AbandonFetches(
     int64_t service_worker_registration_id) {
   // Abandon all active fetches associated with this service worker.
diff --git a/content/browser/background_fetch/background_fetch_context.h b/content/browser/background_fetch/background_fetch_context.h
index 4e0ea21..66efef5 100644
--- a/content/browser/background_fetch/background_fetch_context.h
+++ b/content/browser/background_fetch/background_fetch_context.h
@@ -116,6 +116,8 @@
   // BackgroundFetchDataManagerObserver implementation.
   void OnUpdatedUI(const BackgroundFetchRegistrationId& registration_id,
                    const std::string& title) override;
+  void OnServiceWorkerDatabaseCorrupted(
+      int64_t service_worker_registration_id) override;
 
   // ServiceWorkerContextCoreObserver implementation.
   void OnRegistrationDeleted(int64_t registration_id,
diff --git a/content/browser/background_fetch/background_fetch_data_manager.cc b/content/browser/background_fetch/background_fetch_data_manager.cc
index 833cce06..c326cdc 100644
--- a/content/browser/background_fetch/background_fetch_data_manager.cc
+++ b/content/browser/background_fetch/background_fetch_data_manager.cc
@@ -63,16 +63,13 @@
 BackgroundFetchDataManager::BackgroundFetchDataManager(
     BrowserContext* browser_context,
     scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
-    scoped_refptr<CacheStorageContextImpl> cache_storage_context,
-    const base::RepeatingClosure& abandon_fetches_callback)
+    scoped_refptr<CacheStorageContextImpl> cache_storage_context)
     : service_worker_context_(std::move(service_worker_context)),
       cache_storage_context_(std::move(cache_storage_context)),
-      abandon_fetches_callback_(abandon_fetches_callback),
       weak_ptr_factory_(this) {
   // Constructed on the UI thread, then used on the IO thread.
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(browser_context);
-  DCHECK(abandon_fetches_callback_);
 
   // Store the blob storage context for the given |browser_context|.
   blob_storage_context_ =
diff --git a/content/browser/background_fetch/background_fetch_data_manager.h b/content/browser/background_fetch/background_fetch_data_manager.h
index a757dbf..5611929 100644
--- a/content/browser/background_fetch/background_fetch_data_manager.h
+++ b/content/browser/background_fetch/background_fetch_data_manager.h
@@ -78,8 +78,7 @@
   BackgroundFetchDataManager(
       BrowserContext* browser_context,
       scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
-      scoped_refptr<CacheStorageContextImpl> cache_storage_context,
-      const base::RepeatingClosure& abandon_fetches_callback);
+      scoped_refptr<CacheStorageContextImpl> cache_storage_context);
 
   ~BackgroundFetchDataManager() override;
 
@@ -162,10 +161,6 @@
     return observers_;
   }
 
-  const base::RepeatingClosure& abandon_fetches_callback() {
-    return abandon_fetches_callback_;
-  }
-
   // BackgroundFetchScheduler::RequestProvider implementation:
   void PopNextRequest(const BackgroundFetchRegistrationId& registration_id,
                       NextRequestCallback callback) override;
@@ -237,11 +232,6 @@
   // the browser is shutdown first.
   std::set<std::string> ref_counted_unique_ids_;
 
-  // This is called to abandon all ongoing fetches. It will also mark these
-  // fetches for deletion, which will be cleaned up by the Cleanup task
-  // subsequently.
-  base::RepeatingClosure abandon_fetches_callback_;
-
   base::WeakPtrFactory<BackgroundFetchDataManager> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(BackgroundFetchDataManager);
diff --git a/content/browser/background_fetch/background_fetch_data_manager_observer.h b/content/browser/background_fetch/background_fetch_data_manager_observer.h
index 78a47dd..12981a8 100644
--- a/content/browser/background_fetch/background_fetch_data_manager_observer.h
+++ b/content/browser/background_fetch/background_fetch_data_manager_observer.h
@@ -19,6 +19,10 @@
   virtual void OnUpdatedUI(const BackgroundFetchRegistrationId& registration_id,
                            const std::string& title) = 0;
 
+  // Called if corrupted data is found in the Service Worker database.
+  virtual void OnServiceWorkerDatabaseCorrupted(
+      int64_t service_worker_registration_id) = 0;
+
   virtual ~BackgroundFetchDataManagerObserver() {}
 };
 
diff --git a/content/browser/background_fetch/background_fetch_data_manager_unittest.cc b/content/browser/background_fetch/background_fetch_data_manager_unittest.cc
index cab30b6..f932b9a3 100644
--- a/content/browser/background_fetch/background_fetch_data_manager_unittest.cc
+++ b/content/browser/background_fetch/background_fetch_data_manager_unittest.cc
@@ -479,6 +479,8 @@
   MOCK_METHOD2(OnUpdatedUI,
                void(const BackgroundFetchRegistrationId& registration,
                     const std::string& title));
+  MOCK_METHOD1(OnServiceWorkerDatabaseCorrupted,
+               void(int64_t service_worker_registration_id));
 
  protected:
   void DidGetRegistration(
@@ -1365,6 +1367,8 @@
 
   std::vector<ServiceWorkerFetchRequest> requests(2u);
   BackgroundFetchOptions options;
+  options.title = kInitialTitle;
+  options.download_total = 42u;
   blink::mojom::BackgroundFetchError error;
   // Register a Background Fetch.
   BackgroundFetchRegistrationId registration_id(
@@ -1372,6 +1376,8 @@
 
   CreateRegistration(registration_id, requests, options, SkBitmap(), &error);
   ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
+  UpdateRegistrationUI(registration_id, kUpdatedTitle, &error);
+  ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
   {
     std::vector<BackgroundFetchInitializationData> data =
         GetInitializationData();
@@ -1380,6 +1386,9 @@
     EXPECT_EQ(data[0].registration_id, registration_id);
     EXPECT_EQ(data[0].registration.unique_id, kExampleUniqueId);
     EXPECT_EQ(data[0].registration.developer_id, kExampleDeveloperId);
+    EXPECT_EQ(data[0].options.title, kInitialTitle);
+    EXPECT_EQ(data[0].options.download_total, 42u);
+    EXPECT_EQ(data[0].ui_title, kUpdatedTitle);
     EXPECT_EQ(data[0].num_requests, requests.size());
     EXPECT_EQ(data[0].num_completed_requests, 0u);
     EXPECT_TRUE(data[0].active_fetch_guids.empty());
diff --git a/content/browser/background_fetch/background_fetch_test_data_manager.cc b/content/browser/background_fetch/background_fetch_test_data_manager.cc
index d3804b5..b081be6b 100644
--- a/content/browser/background_fetch/background_fetch_test_data_manager.cc
+++ b/content/browser/background_fetch/background_fetch_test_data_manager.cc
@@ -42,8 +42,7 @@
     bool mock_fill_response)
     : BackgroundFetchDataManager(browser_context,
                                  service_worker_context,
-                                 nullptr /* cache_storage_context */,
-                                 base::DoNothing()),
+                                 nullptr /* cache_storage_context */),
       browser_context_(browser_context),
       storage_partition_(storage_partition),
       mock_fill_response_(mock_fill_response) {}
diff --git a/content/browser/background_fetch/storage/database_task.cc b/content/browser/background_fetch/storage/database_task.cc
index 06582f8..62a5a758 100644
--- a/content/browser/background_fetch/storage/database_task.cc
+++ b/content/browser/background_fetch/storage/database_task.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "content/browser/background_fetch/background_fetch_data_manager.h"
+#include "content/browser/background_fetch/background_fetch_data_manager_observer.h"
 #include "content/browser/background_fetch/storage/database_helpers.h"
 #include "content/public/browser/browser_thread.h"
 
@@ -55,6 +56,11 @@
   insert_result.first->second->Start();  // Start the subtask.
 }
 
+void DatabaseTask::AbandonFetches(int64_t service_worker_registration_id) {
+  for (auto& observer : data_manager()->observers())
+    observer.OnServiceWorkerDatabaseCorrupted(service_worker_registration_id);
+}
+
 ServiceWorkerContextWrapper* DatabaseTask::service_worker_context() {
   DCHECK(data_manager()->service_worker_context());
   return data_manager()->service_worker_context();
diff --git a/content/browser/background_fetch/storage/database_task.h b/content/browser/background_fetch/storage/database_task.h
index 177e977b..f0eeae1a 100644
--- a/content/browser/background_fetch/storage/database_task.h
+++ b/content/browser/background_fetch/storage/database_task.h
@@ -76,6 +76,9 @@
   void AddDatabaseTask(std::unique_ptr<DatabaseTask> task);
   void AddSubTask(std::unique_ptr<DatabaseTask> task);
 
+  // Abandon all fetches for a given service worker.
+  void AbandonFetches(int64_t service_worker_registration_id);
+
   ServiceWorkerContextWrapper* service_worker_context();
 
   CacheStorageManager* cache_manager();
diff --git a/content/browser/background_fetch/storage/delete_registration_task.cc b/content/browser/background_fetch/storage/delete_registration_task.cc
index f046dde..d9e08ae 100644
--- a/content/browser/background_fetch/storage/delete_registration_task.cc
+++ b/content/browser/background_fetch/storage/delete_registration_task.cc
@@ -94,7 +94,7 @@
     } else {
       // Service worker database has been corrupted. Abandon all fetches.
       error_ = blink::mojom::BackgroundFetchError::STORAGE_ERROR;
-      data_manager()->abandon_fetches_callback().Run();
+      AbandonFetches(service_worker_registration_id_);
       std::move(done_closure).Run();
     }
   } else {
diff --git a/content/browser/background_fetch/storage/get_initialization_data_task.cc b/content/browser/background_fetch/storage/get_initialization_data_task.cc
index 40f8c65c..40d3975 100644
--- a/content/browser/background_fetch/storage/get_initialization_data_task.cc
+++ b/content/browser/background_fetch/storage/get_initialization_data_task.cc
@@ -5,9 +5,11 @@
 #include "content/browser/background_fetch/storage/get_initialization_data_task.h"
 
 #include "base/barrier_closure.h"
+#include "base/strings/utf_string_conversions.h"
 #include "content/browser/background_fetch/background_fetch.pb.h"
 #include "content/browser/background_fetch/storage/database_helpers.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "third_party/blink/public/common/manifest/manifest.h"
 #include "url/origin.h"
 
 namespace content {
@@ -61,6 +63,46 @@
   DISALLOW_COPY_AND_ASSIGN(InitializationSubTask);
 };
 
+// Fills the BackgroundFetchInitializationData with the most recent UI title.
+class GetTitleTask : public InitializationSubTask {
+ public:
+  GetTitleTask(DatabaseTaskHost* host,
+               const SubTaskInit& sub_task_init,
+               base::OnceClosure done_closure)
+      : InitializationSubTask(host, sub_task_init, std::move(done_closure)),
+        weak_factory_(this) {}
+
+  ~GetTitleTask() override = default;
+
+  void Start() override {
+    service_worker_context()->GetRegistrationUserData(
+        sub_task_init().service_worker_registration_id,
+        {TitleKey(sub_task_init().unique_id)},
+        base::BindOnce(&GetTitleTask::DidGetTitle, weak_factory_.GetWeakPtr()));
+  }
+
+ private:
+  void DidGetTitle(const std::vector<std::string>& data,
+                   blink::ServiceWorkerStatusCode status) {
+    switch (ToDatabaseStatus(status)) {
+      case DatabaseStatus::kFailed:
+        *sub_task_init().error =
+            blink::mojom::BackgroundFetchError::STORAGE_ERROR;
+        FinishTask();
+        return;
+      case DatabaseStatus::kNotFound:
+      case DatabaseStatus::kOk:
+        break;
+    }
+
+    if (!data.empty())
+      sub_task_init().initialization_data->ui_title = data.front();
+    FinishTask();
+  }
+
+  base::WeakPtrFactory<GetTitleTask> weak_factory_;  // Keep as last.
+};
+
 // Fills the BackgroundFetchInitializationData with the number of completed
 // requests.
 class GetCompletedRequestsTask : public InitializationSubTask {
@@ -76,7 +118,7 @@
   void Start() override {
     service_worker_context()->GetRegistrationUserDataByKeyPrefix(
         sub_task_init().service_worker_registration_id,
-        {CompletedRequestKeyPrefix(sub_task_init().unique_id)},
+        CompletedRequestKeyPrefix(sub_task_init().unique_id),
         base::BindOnce(&GetCompletedRequestsTask::DidGetCompletedRequests,
                        weak_factory_.GetWeakPtr()));
   }
@@ -118,7 +160,7 @@
   void Start() override {
     service_worker_context()->GetRegistrationUserDataByKeyPrefix(
         sub_task_init().service_worker_registration_id,
-        {ActiveRequestKeyPrefix(sub_task_init().unique_id)},
+        ActiveRequestKeyPrefix(sub_task_init().unique_id),
         base::BindOnce(&GetActiveRequestsTask::DidGetActiveRequests,
                        weak_factory_.GetWeakPtr()));
   }
@@ -234,8 +276,34 @@
     // Total number of requests.
     sub_task_init().initialization_data->num_requests = metadata.num_fetches();
 
-    // TODO(rayankans): Fill BackgroundFetchOptions and the icon after it is
-    // persisted.
+    // Fill BackgroundFetchOptions.
+    auto& options = sub_task_init().initialization_data->options;
+    options.title = metadata.options().title();
+    options.download_total = metadata.options().download_total();
+    options.icons.reserve(metadata.options().icons_size());
+    for (const auto& icon : metadata.options().icons()) {
+      blink::Manifest::ImageResource ir;
+      ir.src = GURL(icon.src());
+      ir.type = base::ASCIIToUTF16(icon.type());
+
+      ir.sizes.reserve(icon.sizes_size());
+      for (const auto& size : icon.sizes())
+        ir.sizes.emplace_back(size.width(), size.height());
+
+      ir.purpose.reserve(icon.purpose_size());
+      for (auto purpose : icon.purpose()) {
+        switch (purpose) {
+          case proto::BackgroundFetchOptions_ImageResource_Purpose_ANY:
+            ir.purpose.push_back(blink::Manifest::ImageResource::Purpose::ANY);
+            break;
+          case proto::BackgroundFetchOptions_ImageResource_Purpose_BADGE:
+            ir.purpose.push_back(
+                blink::Manifest::ImageResource::Purpose::BADGE);
+            break;
+        }
+      }
+    }
+
     FinishTask();
   }
 
@@ -257,14 +325,14 @@
   ~FillBackgroundFetchInitializationDataTask() override = default;
 
   void Start() override {
-    // We need 3 queries to get the initialization data. These are wrapped
+    // We need 4 queries to get the initialization data. These are wrapped
     // in a BarrierClosure to avoid querying them serially.
     // 1. Metadata
     // 2. Active Requests
     // 3. Completed Requests
-    // TODO(rayankans): 4. UI Title
+    // 4. UI Title
     base::RepeatingClosure barrier_closure = base::BarrierClosure(
-        3u,
+        4u,
         base::BindOnce(&FillBackgroundFetchInitializationDataTask::FinishTask,
                        weak_factory_.GetWeakPtr()));
     AddSubTask(std::make_unique<FillFromMetadataTask>(this, sub_task_init(),
@@ -273,6 +341,8 @@
                                                           barrier_closure));
     AddSubTask(std::make_unique<GetActiveRequestsTask>(this, sub_task_init(),
                                                        barrier_closure));
+    AddSubTask(
+        std::make_unique<GetTitleTask>(this, sub_task_init(), barrier_closure));
   }
 
  private:
diff --git a/content/browser/background_fetch/storage/get_initialization_data_task.h b/content/browser/background_fetch/storage/get_initialization_data_task.h
index 42c722e..380323e6 100644
--- a/content/browser/background_fetch/storage/get_initialization_data_task.h
+++ b/content/browser/background_fetch/storage/get_initialization_data_task.h
@@ -37,6 +37,9 @@
   size_t num_requests;
   size_t num_completed_requests;
   std::vector<std::string> active_fetch_guids;
+  // The most recent title. This can be different from |options.title| if the
+  // developer called `updateUI` on the BackgroundFetchUpdateEvent.
+  std::string ui_title;
 
   DISALLOW_COPY_AND_ASSIGN(BackgroundFetchInitializationData);
 };
diff --git a/content/browser/background_fetch/storage/get_settled_fetches_task.cc b/content/browser/background_fetch/storage/get_settled_fetches_task.cc
index 99a4c94e..ff470f12 100644
--- a/content/browser/background_fetch/storage/get_settled_fetches_task.cc
+++ b/content/browser/background_fetch/storage/get_settled_fetches_task.cc
@@ -82,7 +82,7 @@
       // Service worker database has been corrupted. Abandon fetches.
       error_ = blink::mojom::BackgroundFetchError::STORAGE_ERROR;
       background_fetch_succeeded_ = false;
-      data_manager()->abandon_fetches_callback().Run();
+      AbandonFetches(registration_id_.service_worker_registration_id());
       break;
     }
     if (!completed_requests_.back().succeeded())
diff --git a/content/browser/background_fetch/storage/mark_registration_for_deletion_task.cc b/content/browser/background_fetch/storage/mark_registration_for_deletion_task.cc
index 99cb7d12..5e39f044 100644
--- a/content/browser/background_fetch/storage/mark_registration_for_deletion_task.cc
+++ b/content/browser/background_fetch/storage/mark_registration_for_deletion_task.cc
@@ -78,7 +78,7 @@
                        weak_factory_.GetWeakPtr()));
   } else {
     // Service worker database has been corrupted. Abandon fetches.
-    data_manager()->abandon_fetches_callback().Run();
+    AbandonFetches(registration_id_.service_worker_registration_id());
     std::move(callback_).Run(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
     Finished();  // Destroys |this|.
     return;
diff --git a/content/browser/background_fetch/storage/start_next_pending_request_task.cc b/content/browser/background_fetch/storage/start_next_pending_request_task.cc
index 4d06d4e..f9538d11 100644
--- a/content/browser/background_fetch/storage/start_next_pending_request_task.cc
+++ b/content/browser/background_fetch/storage/start_next_pending_request_task.cc
@@ -61,7 +61,7 @@
 
   if (!pending_request_.ParseFromString(data.front())) {
     // Service Worker database has been corrupted. Abandon fetches.
-    data_manager()->abandon_fetches_callback().Run();
+    AbandonFetches(service_worker_registration_id_);
     std::move(callback_).Run(nullptr /* request */);
     Finished();  // Destroys |this|.
     return;
@@ -93,7 +93,7 @@
       // We already stored the active request.
       if (!active_request_.ParseFromString(data.front())) {
         // Service worker database has been corrupted. Abandon fetches.
-        data_manager()->abandon_fetches_callback().Run();
+        AbandonFetches(service_worker_registration_id_);
         std::move(callback_).Run(nullptr /* request */);
         Finished();
         return;
diff --git a/content/browser/browser_context.cc b/content/browser/browser_context.cc
index 6793401c..47d76e8 100644
--- a/content/browser/browser_context.cc
+++ b/content/browser/browser_context.cc
@@ -398,6 +398,12 @@
     return;
   browser_context->was_notify_will_be_destroyed_called_ = true;
 
+  // Subclasses of BrowserContext may expect there to be no more
+  // RenderProcessHosts using them by the time this function returns. We
+  // therefore explicitly tear down embedded Content Service instances now to
+  // ensure that all their WebContents (and therefore RPHs) are torn down too.
+  browser_context->RemoveUserData(kContentServiceDelegateKey);
+
   // Service Workers must shutdown before the browser context is destroyed,
   // since they keep render process hosts alive and the codebase assumes that
   // render process hosts die before their profile (browser context) dies.
diff --git a/content/browser/browser_side_navigation_browsertest.cc b/content/browser/browser_side_navigation_browsertest.cc
index 3054b8ca..b4cf78fe 100644
--- a/content/browser/browser_side_navigation_browsertest.cc
+++ b/content/browser/browser_side_navigation_browsertest.cc
@@ -35,6 +35,7 @@
 #include "content/shell/browser/shell_download_manager_delegate.h"
 #include "content/shell/browser/shell_network_delegate.h"
 #include "content/test/content_browser_test_utils_internal.h"
+#include "content/test/did_commit_provisional_load_interceptor.h"
 #include "ipc/ipc_security_test_util.h"
 #include "net/base/filename_util.h"
 #include "net/base/load_flags.h"
@@ -47,6 +48,96 @@
 
 namespace content {
 
+namespace {
+
+class InterceptAndCancelDidCommitProvisionalLoad
+    : public DidCommitProvisionalLoadInterceptor {
+ public:
+  explicit InterceptAndCancelDidCommitProvisionalLoad(WebContents* web_contents)
+      : DidCommitProvisionalLoadInterceptor(web_contents) {}
+  ~InterceptAndCancelDidCommitProvisionalLoad() override {}
+
+  void Wait(size_t number_of_messages) {
+    while (intercepted_messages_.size() < number_of_messages) {
+      loop_.reset(new base::RunLoop);
+      loop_->Run();
+    }
+  }
+
+  const std::vector<::FrameHostMsg_DidCommitProvisionalLoad_Params>&
+  intercepted_messages() const {
+    return intercepted_messages_;
+  }
+
+  std::vector<::service_manager::mojom::InterfaceProviderRequest>&
+  intercepted_requests() {
+    return intercepted_requests_;
+  }
+
+ protected:
+  bool WillDispatchDidCommitProvisionalLoad(
+      RenderFrameHost* render_frame_host,
+      ::FrameHostMsg_DidCommitProvisionalLoad_Params* params,
+      service_manager::mojom::InterfaceProviderRequest*
+          interface_provider_request) override {
+    intercepted_messages_.push_back(*params);
+    intercepted_requests_.push_back(std::move(*interface_provider_request));
+    if (loop_)
+      loop_->Quit();
+    // Do not send the message to the RenderFrameHostImpl.
+    return false;
+  }
+
+  std::vector<::FrameHostMsg_DidCommitProvisionalLoad_Params>
+      intercepted_messages_;
+  std::vector<::service_manager::mojom::InterfaceProviderRequest>
+      intercepted_requests_;
+  std::unique_ptr<base::RunLoop> loop_;
+};
+
+// Record every WebContentsObserver's event related to navigation. The goal is
+// to check these events happen and happen in the expected right order.
+class NavigationRecorder : public WebContentsObserver {
+ public:
+  NavigationRecorder(WebContents* web_contents)
+      : WebContentsObserver(web_contents) {}
+
+  // WebContentsObserver implementation.
+  void DidStartNavigation(NavigationHandle* navigation_handle) override {
+    records_.push_back("start " + navigation_handle->GetURL().path());
+    WakeUp();
+  }
+  void ReadyToCommitNavigation(NavigationHandle* navigation_handle) override {
+    records_.push_back("ready-to-commit " + navigation_handle->GetURL().path());
+    WakeUp();
+  }
+  void DidFinishNavigation(NavigationHandle* navigation_handle) override {
+    records_.push_back("did-commit " + navigation_handle->GetURL().path());
+    WakeUp();
+  }
+
+  void WaitForEvents(size_t numbers_of_events) {
+    while (records_.size() < numbers_of_events) {
+      loop_.reset(new base::RunLoop);
+      loop_->Run();
+      loop_.reset();
+    }
+  }
+
+  const std::vector<std::string> records() { return records_; }
+
+ private:
+  void WakeUp() {
+    if (loop_)
+      loop_->Quit();
+  }
+
+  std::unique_ptr<base::RunLoop> loop_;
+  std::vector<std::string> records_;
+};
+
+}  // namespace
+
 // Test with BrowserSideNavigation enabled (aka PlzNavigate).
 // If you don't need a custom embedded test server, please use the next class
 // below (BrowserSideNavigationBrowserTest), it will automatically start the
@@ -927,4 +1018,86 @@
   EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
 }
 
+// This test reproduces the following race condition:
+// 1) A first navigation starts, the headers are received, the navigation
+//    reaches ready-to-commit. It is sent to the renderer to be committed.
+// 2) In the meantime, a second navigation reaches ready-to-commit in the
+//    browser.
+// 3) Before the renderer gets notified of the new navigation, the
+//    first navigation is committed.
+// 4) The browser gets notified of the commit of the first navigation. This
+//    should not destroy the NavigationRequest corresponding to the second
+//    navigation.
+IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
+                       RaceNewNavigationCommitWhileOldOneFinishesLoading) {
+  // Start the test with an initial document.
+  GURL main_url(embedded_test_server()->GetURL("/simple_page.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+  RenderFrameHostImpl* render_frame_host = static_cast<RenderFrameHostImpl*>(
+      shell()->web_contents()->GetMainFrame());
+
+  NavigationRecorder recorder(shell()->web_contents());
+  // Note: These two pages contain an image that will never load. The goal is to
+  // prevent RenderFrameHostImpl::DidStopLoading() to be called since it will
+  // cancel any pending navigation.
+  GURL page_1(embedded_test_server()->GetURL("/infinite_load_1.html"));
+  GURL page_2(embedded_test_server()->GetURL("/infinite_load_2.html"));
+  // Intercept and cancel any FrameMsgHost_DidCommitProvisionalLoad events.
+  InterceptAndCancelDidCommitProvisionalLoad interceptor(
+      shell()->web_contents());
+
+  // 1) Navigate to page_1.
+  shell()->LoadURL(page_1);
+
+  // 2) The browser receives the response's headers. The navigation commits in
+  //    the browser.
+  recorder.WaitForEvents(2);
+  EXPECT_EQ(2u, recorder.records().size());
+  EXPECT_STREQ("start /infinite_load_1.html", recorder.records()[0].c_str());
+  EXPECT_STREQ("ready-to-commit /infinite_load_1.html",
+               recorder.records()[1].c_str());
+
+  // 3) Wait for the renderer to receive the response's body, but do not notify
+  //    the browser of it right now. It is delayed in 6).
+  interceptor.Wait(1);
+  EXPECT_EQ(1u, interceptor.intercepted_messages().size());
+
+  // 4) In the meantime, the browser starts a navigation to page_2.
+  shell()->LoadURL(page_2);
+
+  // 5) The response's headers are received, the navigation reaches
+  // ready-to-commit in the browser. This should not delete the ongoing
+  // NavigationRequest.
+  recorder.WaitForEvents(4);
+  EXPECT_EQ(4u, recorder.records().size());
+  EXPECT_STREQ("start /infinite_load_2.html", recorder.records()[2].c_str());
+  EXPECT_STREQ("ready-to-commit /infinite_load_2.html",
+               recorder.records()[3].c_str());
+
+  // 6) The browser receives the first DidCommitProvisionalLoad message. This
+  //    should not delete the second navigation. This is the end of the first
+  //    navigation.
+  render_frame_host->DidCommitProvisionalLoadForTesting(
+      std::make_unique<::FrameHostMsg_DidCommitProvisionalLoad_Params>(
+          interceptor.intercepted_messages()[0]),
+      std::move(interceptor.intercepted_requests()[0]));
+  recorder.WaitForEvents(5);
+  EXPECT_EQ(5u, recorder.records().size());
+  EXPECT_STREQ("did-commit /infinite_load_1.html",
+               recorder.records()[4].c_str());
+
+  // 7) Wait for the renderer to receive the second response's body. This is the
+  //    end of the second navigation.
+  interceptor.Wait(2);
+  EXPECT_EQ(2u, interceptor.intercepted_messages().size());
+  render_frame_host->DidCommitProvisionalLoadForTesting(
+      std::make_unique<::FrameHostMsg_DidCommitProvisionalLoad_Params>(
+          interceptor.intercepted_messages()[1]),
+      std::move(interceptor.intercepted_requests()[1]));
+  recorder.WaitForEvents(6);
+  EXPECT_EQ(6u, recorder.records().size());
+  EXPECT_STREQ("did-commit /infinite_load_2.html",
+               recorder.records()[5].c_str());
+}
+
 }  // namespace content
diff --git a/content/browser/content_service_delegate_impl.cc b/content/browser/content_service_delegate_impl.cc
index b4de792..fa67d58 100644
--- a/content/browser/content_service_delegate_impl.cc
+++ b/content/browser/content_service_delegate_impl.cc
@@ -30,8 +30,13 @@
 
  private:
   // content::ViewDelegate:
+  gfx::NativeView GetNativeView() override {
+    return web_contents_->GetNativeView();
+  }
+
   void Navigate(const GURL& url) override {
     NavigationController::LoadURLParams params(url);
+    params.transition_type = ui::PAGE_TRANSITION_AUTO_TOPLEVEL;
     web_contents_->GetController().LoadURLWithParams(params);
   }
 
diff --git a/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
index afb3c77..9211fd39 100644
--- a/content/browser/frame_host/navigation_controller_impl_browsertest.cc
+++ b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -6672,7 +6672,7 @@
 
  private:
   // DidCommitProvisionalLoadInterceptor:
-  void WillDispatchDidCommitProvisionalLoad(
+  bool WillDispatchDidCommitProvisionalLoad(
       RenderFrameHost* render_frame_host,
       ::FrameHostMsg_DidCommitProvisionalLoad_Params* params,
       service_manager::mojom::InterfaceProviderRequest*
@@ -6681,6 +6681,7 @@
       did_trigger_history_navigation_ = true;
       web_contents()->GetController().GoBack();
     }
+    return true;
   }
 
   bool did_trigger_history_navigation_;
diff --git a/content/browser/frame_host/navigation_controller_impl_unittest.cc b/content/browser/frame_host/navigation_controller_impl_unittest.cc
index 8bbec4f..6a50990 100644
--- a/content/browser/frame_host/navigation_controller_impl_unittest.cc
+++ b/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -5330,7 +5330,14 @@
   controller.LoadURLWithParams(params);
   int entry_id = controller.GetPendingEntry()->GetUniqueID();
 
+  NavigationRequest* request =
+      main_test_rfh()->frame_tree_node()->navigation_request();
+  CHECK(request);
+
   main_test_rfh()->PrepareForCommit();
+  main_test_rfh()->SimulateCommitProcessed(
+      request->navigation_handle()->GetNavigationId(),
+      true /* was_successful */);
   main_test_rfh()->SendNavigate(entry_id, true, url1);
 
   EXPECT_TRUE(observer.is_main_frame());
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index d42c8c0b..0db1cb0 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -1607,9 +1607,9 @@
   }
 
   navigation_handle_->ReadyToCommitNavigation(render_frame_host, true);
-  render_frame_host->FailedNavigation(common_params_, request_params_,
-                                      has_stale_copy_in_cache_, net_error_,
-                                      error_page_content);
+  render_frame_host->FailedNavigation(
+      navigation_handle_->GetNavigationId(), common_params_, request_params_,
+      has_stale_copy_in_cache_, net_error_, error_page_content);
 }
 
 void NavigationRequest::CommitNavigation() {
@@ -1650,8 +1650,9 @@
     associated_site_instance_id_.reset();
   }
   render_frame_host->CommitNavigation(
-      response_.get(), std::move(url_loader_client_endpoints_), common_params_,
-      request_params_, is_view_source_, std::move(subresource_loader_params_),
+      navigation_handle_->GetNavigationId(), response_.get(),
+      std::move(url_loader_client_endpoints_), common_params_, request_params_,
+      is_view_source_, std::move(subresource_loader_params_),
       std::move(subresource_overrides_), devtools_navigation_token_);
 
   // Give SpareRenderProcessHostManager a heads-up about the most recently used
diff --git a/content/browser/frame_host/navigator_impl_unittest.cc b/content/browser/frame_host/navigator_impl_unittest.cc
index 3f560d4..78c1a044 100644
--- a/content/browser/frame_host/navigator_impl_unittest.cc
+++ b/content/browser/frame_host/navigator_impl_unittest.cc
@@ -117,17 +117,20 @@
   EXPECT_EQ(NavigationRequest::STARTED, request->state());
   ASSERT_TRUE(GetLoaderForNavigationRequest(request));
   EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
+  int64_t navigation_id = request->navigation_handle()->GetNavigationId();
 
   // Have the current RenderFrameHost commit the navigation.
   scoped_refptr<network::ResourceResponse> response(
       new network::ResourceResponse);
   GetLoaderForNavigationRequest(request)->CallOnResponseStarted(response,
                                                                 nullptr);
-  EXPECT_TRUE(main_test_rfh()->navigation_request());
   EXPECT_TRUE(main_test_rfh()->is_loading());
   EXPECT_FALSE(node->navigation_request());
 
   // Commit the navigation.
+  main_test_rfh()->SimulateCommitProcessed(navigation_id,
+                                           true /* was_successful */);
+  EXPECT_TRUE(main_test_rfh()->navigation_request());
   main_test_rfh()->SendNavigate(entry_id, true, kUrl);
   EXPECT_TRUE(main_test_rfh()->is_active());
   EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl),
@@ -178,7 +181,6 @@
 
   // Have the current RenderFrameHost commit the navigation
   navigation->ReadyToCommit();
-  EXPECT_TRUE(main_test_rfh()->navigation_request());
   EXPECT_TRUE(main_test_rfh()->is_loading());
   EXPECT_FALSE(node->navigation_request());
 
@@ -231,9 +233,6 @@
   if (AreAllSitesIsolatedForTesting()) {
     EXPECT_EQ(navigation->GetFinalRenderFrameHost(),
               GetSpeculativeRenderFrameHost(node));
-    EXPECT_TRUE(GetSpeculativeRenderFrameHost(node)->navigation_request());
-  } else {
-    EXPECT_TRUE(main_test_rfh()->navigation_request());
   }
   EXPECT_FALSE(node->navigation_request());
 
@@ -444,6 +443,7 @@
 
   // Receive the beforeUnload ACK.
   main_test_rfh()->SendBeforeUnloadACK(true);
+  int64_t navigation_id = main_request->navigation_handle()->GetNavigationId();
   EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
 
   scoped_refptr<network::ResourceResponse> response(
@@ -451,9 +451,12 @@
   GetLoaderForNavigationRequest(main_request)
       ->CallOnResponseStarted(response, nullptr);
   EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
-  EXPECT_TRUE(speculative_rfh->navigation_request());
   EXPECT_FALSE(main_test_rfh()->navigation_request());
 
+  speculative_rfh->SimulateCommitProcessed(navigation_id,
+                                           true /* was_successful */);
+  EXPECT_TRUE(speculative_rfh->navigation_request());
+
   speculative_rfh->SendNavigate(entry_id, true, kUrl2);
 
   RenderFrameHostImpl* final_rfh = main_test_rfh();
@@ -489,6 +492,8 @@
   EXPECT_EQ(1, GetLoaderForNavigationRequest(main_request)->redirect_count());
   EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
 
+  int64_t navigation_id = main_request->navigation_handle()->GetNavigationId();
+
   // Have the RenderFrameHost commit the navigation.
   scoped_refptr<network::ResourceResponse> response(
       new network::ResourceResponse);
@@ -497,9 +502,11 @@
   TestRenderFrameHost* final_speculative_rfh =
       GetSpeculativeRenderFrameHost(node);
   EXPECT_TRUE(final_speculative_rfh);
-  EXPECT_TRUE(final_speculative_rfh->navigation_request());
 
   // Commit the navigation.
+  final_speculative_rfh->SimulateCommitProcessed(navigation_id,
+                                                 true /* was_successful */);
+  EXPECT_TRUE(final_speculative_rfh->navigation_request());
   final_speculative_rfh->SendNavigate(entry_id, true, kUrl2);
   RenderFrameHostImpl* final_rfh = main_test_rfh();
   ASSERT_TRUE(final_rfh);
@@ -548,6 +555,7 @@
   int entry_id = RequestNavigation(node, kUrl2);
   main_test_rfh()->SendBeforeUnloadACK(true);
   NavigationRequest* request2 = node->navigation_request();
+  int64_t navigation_id = request2->navigation_handle()->GetNavigationId();
   ASSERT_TRUE(request2);
   EXPECT_EQ(kUrl2, request2->common_params().url);
   EXPECT_TRUE(request2->browser_initiated());
@@ -566,10 +574,11 @@
       new network::ResourceResponse);
   GetLoaderForNavigationRequest(request2)->CallOnResponseStarted(response,
                                                                  nullptr);
+  // Commit the navigation.
+  speculative_rfh->SimulateCommitProcessed(navigation_id,
+                                           true /* was_successful */);
   EXPECT_TRUE(speculative_rfh->navigation_request());
   EXPECT_FALSE(main_test_rfh()->navigation_request());
-
-  // Commit the navigation.
   speculative_rfh->SendNavigate(entry_id, true, kUrl2);
 
   // Confirm that the commit corresponds to the new request.
@@ -633,14 +642,6 @@
     EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
   }
 
-  // Have the RenderFrameHost commit the navigation.
-  navigation->ReadyToCommit();
-  if (AreAllSitesIsolatedForTesting()) {
-    EXPECT_TRUE(GetSpeculativeRenderFrameHost(node)->navigation_request());
-  } else {
-    EXPECT_TRUE(main_test_rfh()->navigation_request());
-  }
-
   // Commit the navigation.
   navigation->Commit();
 
@@ -700,14 +701,6 @@
     EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
   }
 
-  // Have the RenderFrameHost commit the navigation.
-  non_user_initiated_navigation->ReadyToCommit();
-  if (AreAllSitesIsolatedForTesting()) {
-    EXPECT_TRUE(GetSpeculativeRenderFrameHost(node)->navigation_request());
-  } else {
-    EXPECT_TRUE(main_test_rfh()->navigation_request());
-  }
-
   // Commit the navigation.
   non_user_initiated_navigation->Commit();
   EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
@@ -747,6 +740,7 @@
 
   // Now receive the beforeUnload ACK from the still ongoing navigation.
   main_test_rfh()->SendBeforeUnloadACK(true);
+  int64_t navigation_id = request1->navigation_handle()->GetNavigationId();
   TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node);
   ASSERT_TRUE(speculative_rfh);
 
@@ -755,6 +749,8 @@
       new network::ResourceResponse);
   GetLoaderForNavigationRequest(request2)->CallOnResponseStarted(response,
                                                                  nullptr);
+  speculative_rfh->SimulateCommitProcessed(navigation_id,
+                                           true /* was_successful */);
   EXPECT_TRUE(speculative_rfh->navigation_request());
   EXPECT_FALSE(main_test_rfh()->navigation_request());
 
@@ -818,14 +814,6 @@
   // Confirm that the first loader got destroyed.
   EXPECT_FALSE(loader1);
 
-  // Have the RenderFrameHost commit the navigation.
-  navigation2->ReadyToCommit();
-  if (AreAllSitesIsolatedForTesting()) {
-    EXPECT_TRUE(GetSpeculativeRenderFrameHost(node)->navigation_request());
-  } else {
-    EXPECT_TRUE(main_test_rfh()->navigation_request());
-  }
-
   // Commit the navigation.
   navigation2->Commit();
   EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
@@ -893,6 +881,8 @@
   EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl),
             speculative_rfh->GetSiteInstance()->GetSiteURL());
   int32_t site_instance_id = speculative_rfh->GetSiteInstance()->GetId();
+  int64_t navigation_id =
+      node->navigation_request()->navigation_handle()->GetNavigationId();
 
   // Ask Navigator to commit the navigation by simulating a call to
   // OnResponseStarted.
@@ -901,10 +891,12 @@
   GetLoaderForNavigationRequest(node->navigation_request())
       ->CallOnResponseStarted(response, nullptr);
   EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
-  EXPECT_TRUE(speculative_rfh->navigation_request());
   EXPECT_EQ(site_instance_id, speculative_rfh->GetSiteInstance()->GetId());
 
   // Invoke DidCommitProvisionalLoad.
+  speculative_rfh->SimulateCommitProcessed(navigation_id,
+                                           true /* was_successful */);
+  EXPECT_TRUE(speculative_rfh->navigation_request());
   speculative_rfh->SendNavigate(entry_id, true, kUrl);
   EXPECT_EQ(site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
   EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
@@ -940,6 +932,7 @@
 
   // It then redirects to yet another site.
   NavigationRequest* main_request = node->navigation_request();
+  int64_t navigation_id = main_request->navigation_handle()->GetNavigationId();
   ASSERT_TRUE(main_request);
   const GURL kUrlRedirect("https://www.google.com/");
   GetLoaderForNavigationRequest(main_request)
@@ -962,7 +955,6 @@
       ->CallOnResponseStarted(response, nullptr);
   speculative_rfh = GetSpeculativeRenderFrameHost(node);
   ASSERT_TRUE(speculative_rfh);
-  EXPECT_TRUE(speculative_rfh->navigation_request());
   EXPECT_EQ(init_site_instance_id, main_test_rfh()->GetSiteInstance()->GetId());
   EXPECT_TRUE(rfh_deleted_observer.deleted());
 
@@ -976,6 +968,9 @@
   EXPECT_NE(site_instance_id, redirect_site_instance_id);
 
   // Invoke DidCommitProvisionalLoad.
+  speculative_rfh->SimulateCommitProcessed(navigation_id,
+                                           true /* was_successful */);
+  EXPECT_TRUE(speculative_rfh->navigation_request());
   speculative_rfh->SendNavigate(entry_id, true, kUrlRedirect);
 
   // Check that the speculative RenderFrameHost was swapped in.
@@ -1309,4 +1304,31 @@
   ASSERT_FALSE(subframe_feature_policy->GetOriginForTest().unique());
 }
 
+TEST_F(NavigatorTestWithBrowserSideNavigation, TwoNavigationsRacingCommit) {
+  const GURL kUrl1("http://www.chromium.org/");
+  const GURL kUrl2("http://www.chromium.org/Home");
+
+  EXPECT_EQ(0u, contents()->GetMainFrame()->navigation_requests_.size());
+
+  // Have the first navigation reach ReadyToCommit.
+  auto first_navigation =
+      NavigationSimulator::CreateBrowserInitiated(kUrl1, contents());
+  first_navigation->ReadyToCommit();
+  EXPECT_EQ(1u, contents()->GetMainFrame()->navigation_requests_.size());
+
+  // A second navigation starts and reaches ReadyToCommit.
+  auto second_navigation =
+      NavigationSimulator::CreateBrowserInitiated(kUrl1, contents());
+  second_navigation->ReadyToCommit();
+  EXPECT_EQ(2u, contents()->GetMainFrame()->navigation_requests_.size());
+
+  // The first navigation commits.
+  first_navigation->Commit();
+  EXPECT_EQ(1u, contents()->GetMainFrame()->navigation_requests_.size());
+
+  // The second navigation commits.
+  second_navigation->Commit();
+  EXPECT_EQ(0u, contents()->GetMainFrame()->navigation_requests_.size());
+}
+
 }  // namespace content
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 412fc31..3aabf43 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -737,6 +737,14 @@
   return *overlay_routing_token_;
 }
 
+void RenderFrameHostImpl::DidCommitProvisionalLoadForTesting(
+    std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,
+    service_manager::mojom::InterfaceProviderRequest
+        interface_provider_request) {
+  DidCommitProvisionalLoad(std::move(params),
+                           std::move(interface_provider_request));
+}
+
 SiteInstanceImpl* RenderFrameHostImpl::GetSiteInstance() {
   return site_instance_.get();
 }
@@ -1817,6 +1825,7 @@
 void RenderFrameHostImpl::ResetNavigationRequests() {
   navigation_request_.reset();
   same_document_navigation_request_.reset();
+  navigation_requests_.clear();
 }
 
 void RenderFrameHostImpl::SetNavigationRequest(
@@ -1827,7 +1836,8 @@
     same_document_navigation_request_ = std::move(navigation_request);
     return;
   }
-  navigation_request_ = std::move(navigation_request);
+  navigation_requests_[navigation_request->navigation_handle()
+                           ->GetNavigationId()] = std::move(navigation_request);
 }
 
 void RenderFrameHostImpl::SwapOut(
@@ -3465,7 +3475,7 @@
       false /* started_from_context_menu */, false /* has_user_gesture */,
       std::vector<ContentSecurityPolicy>() /* initiator_csp */,
       CSPSource() /* initiator_self_source */);
-  CommitNavigation(nullptr, network::mojom::URLLoaderClientEndpointsPtr(),
+  CommitNavigation(0, nullptr, network::mojom::URLLoaderClientEndpointsPtr(),
                    common_params, RequestNavigationParams(), false,
                    base::nullopt, base::nullopt /* subresource_overrides */,
                    base::UnguessableToken::Create() /* not traced */);
@@ -3624,6 +3634,7 @@
 }
 
 void RenderFrameHostImpl::CommitNavigation(
+    int64_t navigation_id,
     network::ResourceResponse* response,
     network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
     const CommonNavigationParams& common_params,
@@ -3687,9 +3698,13 @@
       if (base::ContainsValue(schemes, scheme)) {
         network::mojom::URLLoaderFactoryPtr factory_for_webui =
             CreateWebUIURLLoaderBinding(this, scheme);
-        if (enabled_bindings_ & kWebUIBindingsPolicyMask) {
-          // If the renderer has webui bindings, then don't give it access to
-          // network loader for security reasons.
+        // If the renderer has webui bindings, then don't give it access to
+        // network loader for security reasons.
+        // http://crbug.com/829412: make an exception for a small whitelist
+        // of WebUIs that need to be fixed to not make network requests in JS.
+        if ((enabled_bindings_ & kWebUIBindingsPolicyMask) &&
+            !GetContentClient()->browser()->IsWebUIAllowedToMakeNetworkRequests(
+                url::Origin::Create(common_params.url.GetOrigin()))) {
           default_factory_info = factory_for_webui.PassInterface();
         } else {
           // This is a webui scheme that doesn't have webui bindings. Give it
@@ -3811,6 +3826,11 @@
                          CloneSubresourceFactories()));
     }
 
+    auto find_request = navigation_requests_.find(navigation_id);
+    NavigationRequest* request = find_request != navigation_requests_.end()
+                                     ? find_request->second.get()
+                                     : nullptr;
+
     if (IsPerNavigationMojoInterfaceEnabled() && navigation_request_ &&
         navigation_request_->GetCommitNavigationClient()) {
       navigation_request_->GetCommitNavigationClient()->CommitNavigation(
@@ -3824,13 +3844,11 @@
           std::move(url_loader_client_endpoints), CloneSubresourceFactories(),
           std::move(subresource_overrides), std::move(controller),
           std::move(prefetch_loader_factory), devtools_navigation_token,
-          navigation_request_
-              ? base::BindOnce(
-                    &RenderFrameHostImpl::OnCrossDocumentCommitProcessed,
-                    base::Unretained(this),
-                    navigation_request_->navigation_handle()->GetNavigationId())
-              : content::mojom::FrameNavigationControl::
-                    CommitNavigationCallback());
+          request ? base::BindOnce(
+                        &RenderFrameHostImpl::OnCrossDocumentCommitProcessed,
+                        base::Unretained(this), navigation_id)
+                  : content::mojom::FrameNavigationControl::
+                        CommitNavigationCallback());
     }
 
     // |remote_object| is an associated interface ptr, so calls can't be made on
@@ -3854,6 +3872,7 @@
 }
 
 void RenderFrameHostImpl::FailedNavigation(
+    int64_t navigation_id,
     const CommonNavigationParams& common_params,
     const RequestNavigationParams& request_params,
     bool has_stale_copy_in_cache,
@@ -3882,25 +3901,27 @@
   }
   SaveSubresourceFactories(std::move(subresource_loader_factories));
 
-  if (IsPerNavigationMojoInterfaceEnabled() && navigation_request_ &&
-      navigation_request_->GetCommitNavigationClient()) {
-    navigation_request_->GetCommitNavigationClient()->CommitFailedNavigation(
+  auto find_request = navigation_requests_.find(navigation_id);
+  NavigationRequest* request = find_request != navigation_requests_.end()
+                                   ? find_request->second.get()
+                                   : nullptr;
+  if (IsPerNavigationMojoInterfaceEnabled() && request &&
+      request->GetCommitNavigationClient()) {
+    request->GetCommitNavigationClient()->CommitFailedNavigation(
         common_params, request_params, has_stale_copy_in_cache, error_code,
         error_page_content, CloneSubresourceFactories());
   } else {
     GetNavigationControl()->CommitFailedNavigation(
         common_params, request_params, has_stale_copy_in_cache, error_code,
         error_page_content, CloneSubresourceFactories(),
-        base::BindOnce(
-            &RenderFrameHostImpl::OnCrossDocumentCommitProcessed,
-            base::Unretained(this),
-            navigation_request_->navigation_handle()->GetNavigationId()));
+        base::BindOnce(&RenderFrameHostImpl::OnCrossDocumentCommitProcessed,
+                       base::Unretained(this), navigation_id));
   }
 
   // An error page is expected to commit, hence why is_loading_ is set to true.
   is_loading_ = true;
-  DCHECK(GetNavigationHandle() &&
-         GetNavigationHandle()->GetNetErrorCode() != net::OK);
+  DCHECK(request && request->navigation_handle() &&
+         request->navigation_handle()->GetNetErrorCode() != net::OK);
 }
 
 void RenderFrameHostImpl::HandleRendererDebugURL(const GURL& url) {
@@ -4397,6 +4418,15 @@
       CloneSubresourceFactories());
 }
 
+std::set<int> RenderFrameHostImpl::GetNavigationEntryIdsPendingCommit() {
+  std::set<int> result;
+  if (navigation_request_)
+    result.insert(navigation_request_->nav_entry_id());
+  for (auto const& requests : navigation_requests_)
+    result.insert(requests.second->nav_entry_id());
+  return result;
+}
+
 void RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryAndObserve(
     network::mojom::URLLoaderFactoryRequest default_factory_request) {
   network::mojom::URLLoaderFactoryParamsPtr params =
@@ -5158,21 +5188,19 @@
 void RenderFrameHostImpl::OnCrossDocumentCommitProcessed(
     int64_t navigation_id,
     blink::mojom::CommitResult result) {
-  // If the NavigationRequest was deleted, another navigation commit started to
-  // be processed. Let the latest commit go through and stop doing anything.
-  if (!navigation_request_ ||
-      navigation_request_->navigation_handle()->GetNavigationId() !=
-          navigation_id) {
-    return;
-  }
   DCHECK_NE(blink::mojom::CommitResult::RestartCrossDocument, result);
-
-  // Note: if the commit was successful, navigation_request_ is reset in
-  // DidCommitProvisionalLoad.
-  if (result == blink::mojom::CommitResult::Ok)
-    return;
-
-  navigation_request_.reset();
+  if (result == blink::mojom::CommitResult::Ok) {
+    // The navigation will soon be committed. Move it out of the map to the
+    // NavigationRequest that is about to commit.
+    auto find_request = navigation_requests_.find(navigation_id);
+    if (find_request != navigation_requests_.end()) {
+      navigation_request_ = std::move(find_request->second);
+    } else {
+      NOTREACHED();
+    }
+  }
+  // Remove the requests from the list of NavigationRequests waiting to commit.
+  navigation_requests_.erase(navigation_id);
 }
 
 void RenderFrameHostImpl::SaveSubresourceFactories(
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index c0797ac..354acca 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -568,7 +568,11 @@
   // |subresource_loader_params| is used in network service land to pass
   // the parameters to create a custom subresource loader in the renderer
   // process, e.g. by AppCache etc.
+  // TODO(clamy): Pass the NavigationRequest directly to this function when
+  // interstitials have been refactored to no longer call CommitNavigation
+  // without a NavigationRequest.
   void CommitNavigation(
+      int64_t navigation_id,
       network::ResourceResponse* response,
       network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
       const CommonNavigationParams& common_params,
@@ -581,7 +585,8 @@
 
   // Indicates that a navigation failed and that this RenderFrame should display
   // an error page.
-  void FailedNavigation(const CommonNavigationParams& common_params,
+  void FailedNavigation(int64_t navigation_id,
+                        const CommonNavigationParams& common_params,
                         const RequestNavigationParams& request_params,
                         bool has_stale_copy_in_cache,
                         int error_code,
@@ -748,6 +753,15 @@
     received_post_message_from_non_descendant_ = true;
   }
 
+  // Returns the list of NavigationEntry ids corresponding to NavigationRequests
+  // waiting to commit in this RenderFrameHost.
+  std::set<int> GetNavigationEntryIdsPendingCommit();
+
+  void DidCommitProvisionalLoadForTesting(
+      std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,
+      service_manager::mojom::InterfaceProviderRequest
+          interface_provider_request);
+
  protected:
   friend class RenderFrameHostFactory;
 
@@ -771,6 +785,8 @@
   friend class TestRenderFrameHost;
   friend class TestRenderViewHost;
 
+  FRIEND_TEST_ALL_PREFIXES(NavigatorTestWithBrowserSideNavigation,
+                           TwoNavigationsRacingCommit);
   FRIEND_TEST_ALL_PREFIXES(RenderFrameHostManagerTest,
                            CreateRenderViewAfterProcessKillAndClosedProxy);
   FRIEND_TEST_ALL_PREFIXES(RenderFrameHostManagerTest, DontSelectInvalidFiles);
@@ -1373,10 +1389,18 @@
   std::unique_ptr<resource_coordinator::FrameResourceCoordinator>
       frame_resource_coordinator_;
 
-  // Holds a NavigationRequest while waiting for the navigation it is tracking
-  // to commit. This NavigationRequest is for a cross-document navigation.
+  // Holds a NavigationRequest when it's about to commit, ie. after
+  // OnCrossDocumentCommitProcessed has returned a positive answer for this
+  // NavigationRequest but before receiving DidCommitProvisionalLoad. This
+  // NavigationRequest is for a cross-document navigation.
   std::unique_ptr<NavigationRequest> navigation_request_;
 
+  // Holds the cross-document NavigationRequests that are waiting to commit,
+  // indexed by IDs. These are navigations that have passed ReadyToCommit stage
+  // and are waiting for the renderer to send back a matching
+  // OnCrossDocumentCommitProcessed.
+  std::map<int64_t, std::unique_ptr<NavigationRequest>> navigation_requests_;
+
   // Holds a same-document NavigationRequest while waiting for the navigation it
   // is tracking to commit.
   std::unique_ptr<NavigationRequest> same_document_navigation_request_;
diff --git a/content/browser/frame_host/render_frame_host_impl_browsertest.cc b/content/browser/frame_host/render_frame_host_impl_browsertest.cc
index 90f311d3..5b37999c 100644
--- a/content/browser/frame_host/render_frame_host_impl_browsertest.cc
+++ b/content/browser/frame_host/render_frame_host_impl_browsertest.cc
@@ -861,7 +861,7 @@
   }
 
  protected:
-  void WillDispatchDidCommitProvisionalLoad(
+  bool WillDispatchDidCommitProvisionalLoad(
       RenderFrameHost* render_frame_host,
       ::FrameHostMsg_DidCommitProvisionalLoad_Params* params,
       service_manager::mojom::InterfaceProviderRequest*
@@ -869,6 +869,7 @@
     url_of_last_commit_ = params->url;
     original_request_of_last_commit_ = std::move(*interface_provider_request);
     *interface_provider_request = std::move(next_fake_request_);
+    return true;
   }
 
  private:
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc
index 301b0d07..65725e89 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -526,11 +526,16 @@
       // navigation was started from BeginNavigation. If the navigation was
       // started through the NavigationController, the NavigationController has
       // already updated its state properly, and doesn't need to be notified.
-      if (speculative_render_frame_host_->GetNavigationHandle() &&
-          request.from_begin_navigation()) {
-        frame_tree_node_->navigator()->DiscardPendingEntryIfNeeded(
-            speculative_render_frame_host_->GetNavigationHandle()
-                ->pending_nav_entry_id());
+      // Note: We query all NavigationEntry IDs fom the RenderFrameHost, however
+      // at most one call to DiscardPendingEntryIfNeeded will succeed. Since we
+      // don't know which of the entries is the pending one, we have to try them
+      // all.
+      // TODO(clamy): Clean this up.
+      if (request.from_begin_navigation()) {
+        std::set<int> ids = speculative_render_frame_host_
+                                ->GetNavigationEntryIdsPendingCommit();
+        for (int id : ids)
+          frame_tree_node_->navigator()->DiscardPendingEntryIfNeeded(id);
       }
       DiscardUnusedFrame(UnsetSpeculativeRenderFrameHost());
     }
@@ -564,12 +569,16 @@
       // was started through the NavigationController, the NavigationController
       // has already updated its state properly, and doesn't need to be
       // notified.
-      if (speculative_render_frame_host_ &&
-          speculative_render_frame_host_->GetNavigationHandle() &&
-          request.from_begin_navigation()) {
-        frame_tree_node_->navigator()->DiscardPendingEntryIfNeeded(
-            speculative_render_frame_host_->GetNavigationHandle()
-                ->pending_nav_entry_id());
+      // Note: We query all NavigationEntry IDs fom the RenderFrameHost, however
+      // at most one call to DiscardPendingEntryIfNeeded will succeed. Since we
+      // don't know which of the entries is the pending one, we have to try them
+      // all.
+      // TODO(clamy): Clean this up.
+      if (request.from_begin_navigation() && speculative_render_frame_host_) {
+        std::set<int> ids = speculative_render_frame_host_
+                                ->GetNavigationEntryIdsPendingCommit();
+        for (int id : ids)
+          frame_tree_node_->navigator()->DiscardPendingEntryIfNeeded(id);
       }
 
       // If a previous speculative RenderFrameHost didn't exist or if its
diff --git a/content/browser/frame_host/render_frame_host_manager_unittest.cc b/content/browser/frame_host/render_frame_host_manager_unittest.cc
index e39e270b..b4fb251d 100644
--- a/content/browser/frame_host/render_frame_host_manager_unittest.cc
+++ b/content/browser/frame_host/render_frame_host_manager_unittest.cc
@@ -837,11 +837,18 @@
       kViewSourceUrl, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
   int entry_id = controller().GetPendingEntry()->GetUniqueID();
 
+  NavigationRequest* request =
+      main_test_rfh()->frame_tree_node()->navigation_request();
+  CHECK(request);
+
   // Simulate response from RenderFrame for DispatchBeforeUnload.
   contents()->GetMainFrame()->PrepareForCommit();
   ASSERT_TRUE(contents()->GetPendingMainFrame())
       << "Expected new pending RenderFrameHost to be created.";
   RenderFrameHost* last_rfh = contents()->GetPendingMainFrame();
+  contents()->GetPendingMainFrame()->SimulateCommitProcessed(
+      request->navigation_handle()->GetNavigationId(),
+      true /* was_successful */);
   contents()->GetPendingMainFrame()->SendNavigate(entry_id, true, kUrl);
 
   EXPECT_EQ(1, controller().GetLastCommittedEntryIndex());
@@ -860,6 +867,8 @@
   // Navigate, again.
   controller().LoadURL(
       kViewSourceUrl, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+  request = main_test_rfh()->frame_tree_node()->navigation_request();
+  CHECK(request);
   entry_id = controller().GetPendingEntry()->GetUniqueID();
   contents()->GetMainFrame()->PrepareForCommit();
 
@@ -868,6 +877,9 @@
   EXPECT_EQ(last_rfh, contents()->GetMainFrame());
 
   // The renderer sends a commit.
+  contents()->GetMainFrame()->SimulateCommitProcessed(
+      request->navigation_handle()->GetNavigationId(),
+      true /* was_successful */);
   contents()->GetMainFrame()->SendNavigateWithTransition(
       entry_id, false, kUrl, ui::PAGE_TRANSITION_TYPED);
   EXPECT_EQ(1, controller().GetLastCommittedEntryIndex());
diff --git a/content/browser/media/audio_log_factory.cc b/content/browser/media/audio_log_factory.cc
new file mode 100644
index 0000000..f7ec4fe
--- /dev/null
+++ b/content/browser/media/audio_log_factory.cc
@@ -0,0 +1,25 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/audio_log_factory.h"
+
+#include <utility>
+
+#include "content/browser/media/media_internals.h"
+
+namespace content {
+
+AudioLogFactory::AudioLogFactory() = default;
+AudioLogFactory::~AudioLogFactory() = default;
+
+void AudioLogFactory::CreateAudioLog(
+    media::mojom::AudioLogComponent component,
+    int32_t component_id,
+    media::mojom::AudioLogRequest audio_log_request) {
+  MediaInternals::GetInstance()->CreateMojoAudioLog(
+      static_cast<media::AudioLogFactory::AudioComponent>(component),
+      component_id, std::move(audio_log_request));
+}
+
+}  // namespace content
diff --git a/content/browser/media/audio_log_factory.h b/content/browser/media/audio_log_factory.h
new file mode 100644
index 0000000..513d5a48
--- /dev/null
+++ b/content/browser/media/audio_log_factory.h
@@ -0,0 +1,28 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEDIA_AUDIO_LOG_FACTORY_H_
+#define CONTENT_BROWSER_MEDIA_AUDIO_LOG_FACTORY_H_
+
+#include "media/mojo/interfaces/audio_logging.mojom.h"
+
+namespace content {
+
+class AudioLogFactory : public media::mojom::AudioLogFactory {
+ public:
+  AudioLogFactory();
+  ~AudioLogFactory() override;
+
+  // media::mojom::AudioLogFactory implementation.
+  void CreateAudioLog(media::mojom::AudioLogComponent component,
+                      int32_t component_id,
+                      media::mojom::AudioLogRequest audio_log_request) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AudioLogFactory);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_MEDIA_AUDIO_LOG_FACTORY_H_
diff --git a/content/browser/media/media_internals.cc b/content/browser/media/media_internals.cc
index e245a5f..801d67c 100644
--- a/content/browser/media/media_internals.cc
+++ b/content/browser/media/media_internals.cc
@@ -16,7 +16,6 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "build/build_config.h"
-#include "content/browser/media/mojo_audio_logging_adapter.h"
 #include "content/browser/renderer_host/media/media_stream_manager.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
@@ -118,7 +117,8 @@
 
 namespace content {
 
-class AudioLogImpl : public media::mojom::AudioLog {
+class MediaInternals::AudioLogImpl : public media::mojom::AudioLog,
+                                     public media::AudioLog {
  public:
   AudioLogImpl(int owner_id,
                media::AudioLogFactory::AudioComponent component,
@@ -164,12 +164,13 @@
   DISALLOW_COPY_AND_ASSIGN(AudioLogImpl);
 };
 
-AudioLogImpl::AudioLogImpl(int owner_id,
-                           media::AudioLogFactory::AudioComponent component,
-                           content::MediaInternals* media_internals,
-                           int component_id,
-                           int render_process_id,
-                           int render_frame_id)
+MediaInternals::AudioLogImpl::AudioLogImpl(
+    int owner_id,
+    media::AudioLogFactory::AudioComponent component,
+    content::MediaInternals* media_internals,
+    int component_id,
+    int render_process_id,
+    int render_frame_id)
     : owner_id_(owner_id),
       component_(component),
       media_internals_(media_internals),
@@ -177,10 +178,16 @@
       render_process_id_(render_process_id),
       render_frame_id_(render_frame_id) {}
 
-AudioLogImpl::~AudioLogImpl() {}
+MediaInternals::AudioLogImpl::~AudioLogImpl() {
+  // Ensure log is always closed. This covers the case of crashes in the audio
+  // service utility process, in which case the log may not be closed
+  // explicitly.
+  OnClosed();
+}
 
-void AudioLogImpl::OnCreated(const media::AudioParameters& params,
-                             const std::string& device_id) {
+void MediaInternals::AudioLogImpl::OnCreated(
+    const media::AudioParameters& params,
+    const std::string& device_id) {
   base::DictionaryValue dict;
   StoreComponentMetadata(&dict);
 
@@ -199,15 +206,15 @@
   SetWebContentsTitle();
 }
 
-void AudioLogImpl::OnStarted() {
+void MediaInternals::AudioLogImpl::OnStarted() {
   SendSingleStringUpdate(kAudioLogStatusKey, "started");
 }
 
-void AudioLogImpl::OnStopped() {
+void MediaInternals::AudioLogImpl::OnStopped() {
   SendSingleStringUpdate(kAudioLogStatusKey, "stopped");
 }
 
-void AudioLogImpl::OnClosed() {
+void MediaInternals::AudioLogImpl::OnClosed() {
   base::DictionaryValue dict;
   StoreComponentMetadata(&dict);
   dict.SetString(kAudioLogStatusKey, "closed");
@@ -216,11 +223,11 @@
                                    &dict);
 }
 
-void AudioLogImpl::OnError() {
+void MediaInternals::AudioLogImpl::OnError() {
   SendSingleStringUpdate("error_occurred", "true");
 }
 
-void AudioLogImpl::OnSetVolume(double volume) {
+void MediaInternals::AudioLogImpl::OnSetVolume(double volume) {
   base::DictionaryValue dict;
   StoreComponentMetadata(&dict);
   dict.SetDouble("volume", volume);
@@ -229,11 +236,11 @@
                                    &dict);
 }
 
-void AudioLogImpl::OnLogMessage(const std::string& message) {
+void MediaInternals::AudioLogImpl::OnLogMessage(const std::string& message) {
   MediaStreamManager::SendMessageToNativeLog(message);
 }
 
-void AudioLogImpl::SetWebContentsTitle() {
+void MediaInternals::AudioLogImpl::SetWebContentsTitle() {
   if (render_process_id_ < 0 || render_frame_id_ < 0)
     return;
   std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
@@ -242,12 +249,12 @@
                              render_process_id_, render_frame_id_);
 }
 
-std::string AudioLogImpl::FormatCacheKey() {
+std::string MediaInternals::AudioLogImpl::FormatCacheKey() {
   return base::StringPrintf("%d:%d:%d", owner_id_, component_, component_id_);
 }
 
 // static
-void AudioLogImpl::SendWebContentsTitleHelper(
+void MediaInternals::AudioLogImpl::SendWebContentsTitleHelper(
     const std::string& cache_key,
     std::unique_ptr<base::DictionaryValue> dict,
     int render_process_id,
@@ -275,8 +282,9 @@
       dict.get());
 }
 
-void AudioLogImpl::SendSingleStringUpdate(const std::string& key,
-                                          const std::string& value) {
+void MediaInternals::AudioLogImpl::SendSingleStringUpdate(
+    const std::string& key,
+    const std::string& value) {
   base::DictionaryValue dict;
   StoreComponentMetadata(&dict);
   dict.SetString(key, value);
@@ -285,7 +293,8 @@
                                    &dict);
 }
 
-void AudioLogImpl::StoreComponentMetadata(base::DictionaryValue* dict) {
+void MediaInternals::AudioLogImpl::StoreComponentMetadata(
+    base::DictionaryValue* dict) {
   dict->SetInteger("owner_id", owner_id_);
   dict->SetInteger("component_id", component_id_);
   dict->SetInteger("component_type", component_);
@@ -720,8 +729,7 @@
 std::unique_ptr<media::AudioLog> MediaInternals::CreateAudioLog(
     AudioComponent component,
     int component_id) {
-  return std::make_unique<MojoAudioLogAdapter>(
-      CreateMojoAudioLog(component, component_id));
+  return CreateAudioLogImpl(component, component_id, -1, MSG_ROUTING_NONE);
 }
 
 media::mojom::AudioLogPtr MediaInternals::CreateMojoAudioLog(
@@ -729,15 +737,36 @@
     int component_id,
     int render_process_id,
     int render_frame_id) {
-  base::AutoLock auto_lock(lock_);
   media::mojom::AudioLogPtr audio_log_ptr;
-  mojo::MakeStrongBinding(std::make_unique<AudioLogImpl>(
-                              owner_ids_[component]++, component, this,
-                              component_id, render_process_id, render_frame_id),
-                          mojo::MakeRequest(&audio_log_ptr));
+  CreateMojoAudioLog(component, component_id, mojo::MakeRequest(&audio_log_ptr),
+                     render_process_id, render_frame_id);
   return audio_log_ptr;
 }
 
+void MediaInternals::CreateMojoAudioLog(
+    media::AudioLogFactory::AudioComponent component,
+    int component_id,
+    media::mojom::AudioLogRequest request,
+    int render_process_id,
+    int render_frame_id) {
+  mojo::MakeStrongBinding(
+      CreateAudioLogImpl(component, component_id, render_process_id,
+                         render_frame_id),
+      std::move(request));
+}
+
+std::unique_ptr<MediaInternals::AudioLogImpl>
+MediaInternals::CreateAudioLogImpl(
+    media::AudioLogFactory::AudioComponent component,
+    int component_id,
+    int render_process_id,
+    int render_frame_id) {
+  base::AutoLock auto_lock(lock_);
+  return std::make_unique<AudioLogImpl>(owner_ids_[component]++, component,
+                                        this, component_id, render_process_id,
+                                        render_frame_id);
+}
+
 void MediaInternals::OnProcessTerminatedForTesting(int process_id) {
   uma_handler_->OnProcessTerminated(process_id);
 }
diff --git a/content/browser/media/media_internals.h b/content/browser/media/media_internals.h
index 25b1085d..494c251 100644
--- a/content/browser/media/media_internals.h
+++ b/content/browser/media/media_internals.h
@@ -92,14 +92,21 @@
       int render_process_id = -1,
       int render_frame_id = MSG_ROUTING_NONE);
 
+  // Strongly bounds |request| to a new media::mojom::AudioLog instance. Safe to
+  // call from any thread.
+  void CreateMojoAudioLog(AudioComponent component,
+                          int component_id,
+                          media::mojom::AudioLogRequest request,
+                          int render_process_id = -1,
+                          int render_frame_id = MSG_ROUTING_NONE);
+
   void OnProcessTerminatedForTesting(int process_id);
 
  private:
+  class AudioLogImpl;
   // Inner class to handle reporting pipelinestatus to UMA
   class MediaInternalsUMAHandler;
 
-  friend class AudioLogImpl;
-
   MediaInternals();
 
   // Sends |update| to each registered UpdateCallback.  Safe to call from any
@@ -123,6 +130,11 @@
                       const std::string& function,
                       const base::DictionaryValue* value);
 
+  std::unique_ptr<AudioLogImpl> CreateAudioLogImpl(AudioComponent component,
+                                                   int component_id,
+                                                   int render_process_id,
+                                                   int render_frame_id);
+
   // Must only be accessed on the UI thread.
   std::vector<UpdateCallback> update_callbacks_;
 
diff --git a/content/browser/media/mojo_audio_logging_adapter.cc b/content/browser/media/mojo_audio_logging_adapter.cc
deleted file mode 100644
index c3ee310..0000000
--- a/content/browser/media/mojo_audio_logging_adapter.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/media/mojo_audio_logging_adapter.h"
-
-#include <utility>
-
-#include "content/browser/media/media_internals.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-
-namespace content {
-
-MojoAudioLogAdapter::MojoAudioLogAdapter(media::mojom::AudioLogPtr audio_log)
-    : audio_log_(std::move(audio_log)) {}
-
-MojoAudioLogAdapter::~MojoAudioLogAdapter() = default;
-
-void MojoAudioLogAdapter::OnCreated(const media::AudioParameters& params,
-                                    const std::string& device_id) {
-  audio_log_->OnCreated(params, device_id);
-}
-
-void MojoAudioLogAdapter::OnStarted() {
-  audio_log_->OnStarted();
-}
-
-void MojoAudioLogAdapter::OnStopped() {
-  audio_log_->OnStopped();
-}
-
-void MojoAudioLogAdapter::OnClosed() {
-  audio_log_->OnClosed();
-}
-
-void MojoAudioLogAdapter::OnError() {
-  audio_log_->OnError();
-}
-
-void MojoAudioLogAdapter::OnSetVolume(double volume) {
-  audio_log_->OnSetVolume(volume);
-}
-
-void MojoAudioLogAdapter::OnLogMessage(const std::string& message) {
-  audio_log_->OnLogMessage(message);
-}
-
-}  // namespace content
diff --git a/content/browser/media/mojo_audio_logging_adapter.h b/content/browser/media/mojo_audio_logging_adapter.h
deleted file mode 100644
index 020d6244..0000000
--- a/content/browser/media/mojo_audio_logging_adapter.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_MEDIA_MOJO_AUDIO_LOGGING_ADAPTER_H_
-#define CONTENT_BROWSER_MEDIA_MOJO_AUDIO_LOGGING_ADAPTER_H_
-
-#include <map>
-#include <string>
-
-#include "base/macros.h"
-#include "base/sequence_checker.h"
-#include "content/common/content_export.h"
-#include "media/audio/audio_logging.h"
-#include "media/mojo/interfaces/audio_logging.mojom.h"
-
-namespace content {
-
-// This class wraps a media::mojom::AudioLogPtr into a media::AudioLog.
-// TODO(crbug.com/812557): Move this class to the audio service once the audio
-// service is in charge of creating and owning the AudioManager.
-class CONTENT_EXPORT MojoAudioLogAdapter : public media::AudioLog {
- public:
-  explicit MojoAudioLogAdapter(media::mojom::AudioLogPtr audio_log);
-  ~MojoAudioLogAdapter() override;
-
-  // media::AudioLog implementation.
-  void OnCreated(const media::AudioParameters& params,
-                 const std::string& device_id) override;
-  void OnStarted() override;
-  void OnStopped() override;
-  void OnClosed() override;
-  void OnError() override;
-  void OnSetVolume(double volume) override;
-  void OnLogMessage(const std::string& message) override;
-
- private:
-  media::mojom::AudioLogPtr audio_log_;
-
-  DISALLOW_COPY_AND_ASSIGN(MojoAudioLogAdapter);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_MEDIA_MOJO_AUDIO_LOGGING_ADAPTER_H_
diff --git a/content/browser/renderer_host/input/touch_action_browsertest.cc b/content/browser/renderer_host/input/touch_action_browsertest.cc
index f3b5a90..41c2c94 100644
--- a/content/browser/renderer_host/input/touch_action_browsertest.cc
+++ b/content/browser/renderer_host/input/touch_action_browsertest.cc
@@ -357,7 +357,9 @@
   DISALLOW_COPY_AND_ASSIGN(TouchActionBrowserTest);
 };
 
-#if defined(DEBUG)
+#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) ||       \
+    defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
+    defined(THREAD_SANITIZER)
 #define MAYBE_DefaultAuto DISABLED_DefaultAuto
 #else
 #define MAYBE_DefaultAuto DefaultAuto
@@ -379,7 +381,9 @@
 
 // Verify that touching a touch-action: none region disables scrolling and
 // enables all touch events to be sent.
-#if defined(DEBUG)
+#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) ||       \
+    defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
+    defined(THREAD_SANITIZER)
 #define MAYBE_TouchActionNone DISABLED_TouchActionNone
 #else
 #define MAYBE_TouchActionNone TouchActionNone
@@ -396,7 +400,9 @@
   EXPECT_EQ(0, ExecuteScriptAndExtractInt("eventCounts.touchcancel"));
 }
 
-#if defined(DEBUG)
+#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) ||       \
+    defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
+    defined(THREAD_SANITIZER)
 #define MAYBE_PanYMainThreadJanky DISABLED_PanYMainThreadJanky
 #else
 #define MAYBE_PanYMainThreadJanky PanYMainThreadJanky
@@ -408,7 +414,9 @@
                 gfx::Vector2d(0, 45), kShortJankTime);
 }
 
-#if defined(DEBUG)
+#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) ||       \
+    defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
+    defined(THREAD_SANITIZER)
 #define MAYBE_PanXMainThreadJanky DISABLED_PanXMainThreadJanky
 #else
 #define MAYBE_PanXMainThreadJanky PanXMainThreadJanky
@@ -449,7 +457,9 @@
   DoTwoFingerTouchScroll(false, gfx::Vector2d(20, 0));
 }
 
-#if defined(DEBUG)
+#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) ||       \
+    defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
+    defined(THREAD_SANITIZER)
 #define MAYBE_PanXYMainThreadJanky DISABLED_PanXYMainThreadJanky
 #else
 #define MAYBE_PanXYMainThreadJanky PanXYMainThreadJanky
@@ -461,7 +471,9 @@
                 gfx::Vector2d(45, 45), kShortJankTime);
 }
 
-#if defined(DEBUG)
+#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) ||       \
+    defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
+    defined(THREAD_SANITIZER)
 #define MAYBE_PanXYAtXAreaMainThreadJanky DISABLED_PanXYAtXAreaMainThreadJanky
 #else
 #define MAYBE_PanXYAtXAreaMainThreadJanky PanXYAtXAreaMainThreadJanky
@@ -474,7 +486,9 @@
                 gfx::Vector2d(45, 0), kShortJankTime);
 }
 
-#if defined(DEBUG)
+#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) ||       \
+    defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
+    defined(THREAD_SANITIZER)
 #define MAYBE_PanXYAtYAreaMainThreadJanky DISABLED_PanXYAtYAreaMainThreadJanky
 #else
 #define MAYBE_PanXYAtYAreaMainThreadJanky PanXYAtYAreaMainThreadJanky
@@ -487,7 +501,9 @@
                 gfx::Vector2d(0, 45), kShortJankTime);
 }
 
-#if defined(DEBUG)
+#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) ||       \
+    defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
+    defined(THREAD_SANITIZER)
 #define MAYBE_PanXYAtAutoYOverlapAreaMainThreadJanky \
   DISABLED_PanXYAtAutoYOverlapAreaMainThreadJanky
 #else
@@ -502,7 +518,9 @@
                 gfx::Vector2d(0, 45), kShortJankTime);
 }
 
-#if defined(DEBUG)
+#if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) ||       \
+    defined(MEMORY_SANITIZER) || defined(LEAK_SANITIZER) || \
+    defined(THREAD_SANITIZER)
 #define MAYBE_PanXYAtAutoXOverlapAreaMainThreadJanky \
   DISABLED_PanXYAtAutoXOverlapAreaMainThreadJanky
 #else
diff --git a/content/browser/renderer_host/render_widget_host_view_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_browsertest.cc
index 8018471..f454005 100644
--- a/content/browser/renderer_host/render_widget_host_view_browsertest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_browsertest.cc
@@ -152,13 +152,14 @@
 
  private:
   // DidCommitProvisionalLoadInterceptor:
-  void WillDispatchDidCommitProvisionalLoad(
+  bool WillDispatchDidCommitProvisionalLoad(
       RenderFrameHost* render_frame_host,
       ::FrameHostMsg_DidCommitProvisionalLoad_Params* params,
       service_manager::mojom::InterfaceProviderRequest*
           interface_provider_request) override {
     base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
     frame_observer_->WaitForAnyFrameSubmission();
+    return true;
   }
 
   // Not owned.
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
index 8b0f33aa..e3b04ed 100644
--- a/content/browser/security_exploit_browsertest.cc
+++ b/content/browser/security_exploit_browsertest.cc
@@ -591,14 +591,15 @@
   ~ScopedInterfaceProviderRequestReplacer() override = default;
 
  protected:
-  void WillDispatchDidCommitProvisionalLoad(
+  bool WillDispatchDidCommitProvisionalLoad(
       RenderFrameHost* render_frame_host,
       ::FrameHostMsg_DidCommitProvisionalLoad_Params* params,
       service_manager::mojom::InterfaceProviderRequest*
           interface_provider_request) override {
-    ASSERT_TRUE(interface_provider_request_override_.has_value());
+    CHECK(interface_provider_request_override_.has_value());
     *interface_provider_request =
         std::move(interface_provider_request_override_).value();
+    return true;
   }
 
  private:
diff --git a/content/browser/service_worker/README.md b/content/browser/service_worker/README.md
new file mode 100644
index 0000000..55d7fb79
--- /dev/null
+++ b/content/browser/service_worker/README.md
@@ -0,0 +1,44 @@
+# Service workers
+[content/browser/service_worker]: /content/browser/service_worker
+[content/renderer/service_worker]: /content/renderer/service_worker
+[content/renderer/service_worker]: /content/renderer/service_worker
+[content/common/service_worker]: /content/common/service_worker
+[third_party/blink/common/service_worker]: /third_party/blink/common/service_worker
+[third_party/blink/public/common/service_worker]: /third_party/blink/public/common/service_worker
+[third_party/blink/public/mojom/service_worker]: /third_party/blink/public/mojom/service_worker
+[third_party/blink/public/platform/modules/service_worker]: /third_party/blink/public/platform/modules/service_worker
+[third_party/blink/public/web/modules/service_worker]: /third_party/blink/public/web/modules/service_worker
+[third_party/blink/renderer/modules/service_worker]: /third_party/blink/renderer/modules/service_worker
+[Blink Public API]: /third_party/blink/public
+[Onion Soup]: https://docs.google.com/document/d/1K1nO8G9dO9kNSmtVz2gJ2GG9gQOTgm65sJlV3Fga4jE/edit?usp=sharing
+
+This is Chromium's implementation of [service
+workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API). See the
+[Service Worker specification](https://w3c.github.io/ServiceWorker/).
+
+## Directory structure
+
+- [content/browser/service_worker]: Browser process code, including stored
+  registration data, the inception of starting a service worker, and controlling
+  navigations. The browser process has host objects of most live renderer
+  entities that deal with service workers, and the bulk of work is performed by
+  these host objects.
+- [content/renderer/service_worker]: Renderer process code. This should move to
+  third_party/blink per [Onion Soup].
+- [content/common/service_worker]: Common process code.
+- [third_party/blink/common/service_worker]: Common process code. Contains the
+  implementation of third_party/blink/public/common/service_worker.
+- [third_party/blink/public/common/service_worker]: Header files for common
+  process code that can be used by both inside Blink and outside Blink.
+- [third_party/blink/public/mojom/service_worker]: Mojom files for common
+  process code that can be used by both Blink and content.
+- [third_party/blink/public/platform/modules/service_worker]: [Blink Public API]
+  header files. This should be removed per [Onion Soup].
+- [third_party/blink/public/web/modules/service_worker]: More [Blink Public API]
+  header files. This should be removed per [Onion Soup].
+- [third_party/blink/renderer/modules/service_worker]: Renderer process code in
+  Blink. This is the closest code to the web-exposed Service Worker API.
+
+## Other documentation
+
+- [Service Worker Security FAQ](/docs/security/service-worker-security-faq.md)
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.cc b/content/browser/service_worker/service_worker_dispatcher_host.cc
index 59e2abc..e358fd7 100644
--- a/content/browser/service_worker/service_worker_dispatcher_host.cc
+++ b/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -49,14 +49,14 @@
 }
 
 void ServiceWorkerDispatcherHost::OnProviderCreated(
-    ServiceWorkerProviderHostInfo info) {
+    mojom::ServiceWorkerProviderHostInfoPtr info) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   TRACE_EVENT0("ServiceWorker",
                "ServiceWorkerDispatcherHost::OnProviderCreated");
   ServiceWorkerContextCore* context = context_wrapper_->context();
   if (!context)
     return;
-  if (context->GetProviderHost(render_process_id_, info.provider_id)) {
+  if (context->GetProviderHost(render_process_id_, info->provider_id)) {
     bindings_.ReportBadMessage("SWDH_PROVIDER_CREATED_DUPLICATE_ID");
     return;
   }
@@ -64,8 +64,8 @@
   // Provider hosts for navigations are precreated on the browser process with a
   // browser-assigned id. The renderer process calls OnProviderCreated once it
   // creates the provider.
-  if (ServiceWorkerUtils::IsBrowserAssignedProviderId(info.provider_id)) {
-    if (info.type != blink::mojom::ServiceWorkerProviderType::kForWindow) {
+  if (ServiceWorkerUtils::IsBrowserAssignedProviderId(info->provider_id)) {
+    if (info->type != blink::mojom::ServiceWorkerProviderType::kForWindow) {
       bindings_.ReportBadMessage(
           "SWDH_PROVIDER_CREATED_ILLEGAL_TYPE_NOT_WINDOW");
       return;
@@ -74,7 +74,7 @@
     // Retrieve the provider host pre-created for the navigation.
     std::unique_ptr<ServiceWorkerProviderHost> provider_host =
         context->ReleaseProviderHost(ChildProcessHost::kInvalidUniqueID,
-                                     info.provider_id);
+                                     info->provider_id);
     // If no host is found, create one.
     // TODO(crbug.com/789111#c14): This is probably not right, see bug.
     if (!provider_host) {
@@ -93,7 +93,8 @@
   // Provider hosts for service workers don't call OnProviderCreated. They are
   // precreated and ServiceWorkerProviderHost::CompleteStartWorkerPreparation is
   // called during the startup sequence once a process is allocated.
-  if (info.type == blink::mojom::ServiceWorkerProviderType::kForServiceWorker) {
+  if (info->type ==
+      blink::mojom::ServiceWorkerProviderType::kForServiceWorker) {
     bindings_.ReportBadMessage(
         "SWDH_PROVIDER_CREATED_ILLEGAL_TYPE_SERVICE_WORKER");
     return;
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.h b/content/browser/service_worker/service_worker_dispatcher_host.h
index 4bddcd99..8faadf7 100644
--- a/content/browser/service_worker/service_worker_dispatcher_host.h
+++ b/content/browser/service_worker/service_worker_dispatcher_host.h
@@ -69,7 +69,7 @@
       CleanupOnRendererCrash);
 
   // mojom::ServiceWorkerDispatcherHost implementation
-  void OnProviderCreated(ServiceWorkerProviderHostInfo info) override;
+  void OnProviderCreated(mojom::ServiceWorkerProviderHostInfoPtr info) override;
 
   void RemoveAllProviderHostsForProcess();
 
diff --git a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
index 4c29bad8..5e4942d5 100644
--- a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
+++ b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
@@ -135,15 +135,15 @@
   }
 
   RemoteProviderInfo SendProviderCreated(
-      ServiceWorkerProviderHostInfo host_info) {
-    DCHECK(!host_info.host_request.is_pending());
-    DCHECK(!host_info.client_ptr_info.is_valid());
+      mojom::ServiceWorkerProviderHostInfoPtr host_info) {
+    DCHECK(!host_info->host_request.is_pending());
+    DCHECK(!host_info->client_ptr_info.is_valid());
 
     RemoteProviderInfo remote_info;
     mojom::ServiceWorkerContainerAssociatedPtrInfo client;
     remote_info.client_request = mojo::MakeRequest(&client);
-    host_info.host_request = mojo::MakeRequest(&remote_info.host_ptr);
-    host_info.client_ptr_info = std::move(client);
+    host_info->host_request = mojo::MakeRequest(&remote_info.host_ptr);
+    host_info->client_ptr_info = std::move(client);
 
     mojom::ServiceWorkerDispatcherHostAssociatedPtr ptr;
     dispatcher_host_->AddBinding(
@@ -177,9 +177,8 @@
             context()->AsWeakPtr(), true /* are_ancestors_secure */,
             base::RepeatingCallback<WebContents*(void)>());
     EXPECT_EQ(kProviderId, host->provider_id());
-    ServiceWorkerProviderHostInfo host_info(kProviderId, 1 /* route_id */,
-                                            host->provider_type(),
-                                            host->is_parent_frame_secure());
+    mojom::ServiceWorkerProviderHostInfoPtr host_info =
+        CreateProviderHostInfoForWindow(kProviderId, 1 /* route_id */);
     navigation_handle_core->DidPreCreateProviderHost(kProviderId);
     RemoteProviderInfo remote_provider =
         SendProviderCreated(std::move(host_info));
@@ -194,17 +193,12 @@
   {
     // Two with the same ID should be seen as a bad message.
     const int kProviderId = 99;
-    RemoteProviderInfo remote_provider_1 =
-        SendProviderCreated(ServiceWorkerProviderHostInfo(
-            kProviderId, 1 /* route_id */,
-            blink::mojom::ServiceWorkerProviderType::kForWindow,
-            true /* is_parent_frame_secure */));
+    RemoteProviderInfo remote_provider_1 = SendProviderCreated(
+        CreateProviderHostInfoForWindow(kProviderId, 1 /* route_id */));
+
     EXPECT_TRUE(bad_messages_.empty());
-    RemoteProviderInfo remote_provider_2 =
-        SendProviderCreated(ServiceWorkerProviderHostInfo(
-            kProviderId, 1 /* route_id */,
-            blink::mojom::ServiceWorkerProviderType::kForWindow,
-            true /* is_parent_frame_secure */));
+    RemoteProviderInfo remote_provider_2 = SendProviderCreated(
+        CreateProviderHostInfoForWindow(kProviderId, 1 /* route_id */));
     ASSERT_EQ(1u, bad_messages_.size());
     EXPECT_EQ("SWDH_PROVIDER_CREATED_DUPLICATE_ID", bad_messages_[0]);
   }
@@ -219,9 +213,8 @@
             context()->AsWeakPtr(), true /* are_ancestors_secure */,
             base::RepeatingCallback<WebContents*(void)>());
     EXPECT_EQ(kProviderId, host->provider_id());
-    ServiceWorkerProviderHostInfo host_info(kProviderId, 2 /* route_id */,
-                                            host->provider_type(),
-                                            host->is_parent_frame_secure());
+    mojom::ServiceWorkerProviderHostInfoPtr host_info =
+        CreateProviderHostInfoForWindow(kProviderId, 2 /* route_id */);
     navigation_handle_core->DidPreCreateProviderHost(kProviderId);
     RemoteProviderInfo remote_provider =
         SendProviderCreated(std::move(host_info));
@@ -241,10 +234,8 @@
   int process_id = helper_->mock_render_process_id();
 
   const int64_t kProviderId = 99;
-  ServiceWorkerProviderHostInfo host_info_1(
-      kProviderId, MSG_ROUTING_NONE,
-      blink::mojom::ServiceWorkerProviderType::kForWindow,
-      true /* is_parent_frame_secure */);
+  mojom::ServiceWorkerProviderHostInfoPtr host_info_1 =
+      CreateProviderHostInfoForWindow(kProviderId, MSG_ROUTING_NONE);
   RemoteProviderInfo remote_provider_1 =
       SendProviderCreated(std::move(host_info_1));
   ServiceWorkerProviderHost* provider_host = context()->GetProviderHost(
@@ -279,10 +270,8 @@
   // renderer process creates a provider with the same |kProviderId|. Since the
   // dispatcher host already cleaned up the old provider host, the new one won't
   // complain.
-  ServiceWorkerProviderHostInfo host_info_2(
-      kProviderId, MSG_ROUTING_NONE,
-      blink::mojom::ServiceWorkerProviderType::kForWindow,
-      true /* is_parent_frame_secure */);
+  mojom::ServiceWorkerProviderHostInfoPtr host_info_2 =
+      CreateProviderHostInfoForWindow(kProviderId, MSG_ROUTING_NONE);
   RemoteProviderInfo remote_provider_2 =
       SendProviderCreated(std::move(host_info_2));
   EXPECT_TRUE(bad_messages_.empty());
diff --git a/content/browser/service_worker/service_worker_navigation_loader.cc b/content/browser/service_worker/service_worker_navigation_loader.cc
index 7b828a4..dc933dc 100644
--- a/content/browser/service_worker/service_worker_navigation_loader.cc
+++ b/content/browser/service_worker/service_worker_navigation_loader.cc
@@ -4,6 +4,7 @@
 
 #include "content/browser/service_worker/service_worker_navigation_loader.h"
 
+#include <sstream>
 #include <utility>
 
 #include "base/optional.h"
@@ -22,6 +23,17 @@
 
 namespace {
 
+std::string ComposeFetchEventResultString(
+    ServiceWorkerFetchDispatcher::FetchEventResult result,
+    const ServiceWorkerResponse& response) {
+  if (result == ServiceWorkerFetchDispatcher::FetchEventResult::kShouldFallback)
+    return "Fallback to network";
+  std::stringstream stream;
+  stream << "Got response (status_code: " << response.status_code
+         << " status_text: '" << response.status_text << "')";
+  return stream.str();
+}
+
 bool BodyHasNoDataPipeGetters(const network::ResourceRequestBody* body) {
   if (!body)
     return true;
@@ -202,6 +214,11 @@
 void ServiceWorkerNavigationLoader::CommitResponseHeaders() {
   DCHECK_EQ(Status::kStarted, status_);
   DCHECK(url_loader_client_.is_bound());
+  TRACE_EVENT_WITH_FLOW2(
+      "ServiceWorker", "ServiceWorkerNavigationLoader::CommitResponseHeaders",
+      this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
+      "response_code", response_head_.headers->response_code(), "status_text",
+      response_head_.headers->GetStatusText());
   status_ = Status::kSentHeader;
   url_loader_client_->OnReceiveResponse(response_head_);
 }
@@ -269,10 +286,11 @@
   // Temporary CHECK for https://crbug.com/857005.
   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
-  TRACE_EVENT_WITH_FLOW1(
+  TRACE_EVENT_WITH_FLOW2(
       "ServiceWorker", "ServiceWorkerNavigationLoader::DidDispatchFetchEvent",
       this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "status",
-      blink::ServiceWorkerStatusToString(status));
+      blink::ServiceWorkerStatusToString(status), "result",
+      ComposeFetchEventResultString(fetch_result, response));
   ServiceWorkerMetrics::RecordFetchEventStatus(true /* is_main_resource */,
                                                status);
 
diff --git a/content/browser/service_worker/service_worker_object_host_unittest.cc b/content/browser/service_worker/service_worker_object_host_unittest.cc
index 23a8123..eec3157 100644
--- a/content/browser/service_worker/service_worker_object_host_unittest.cc
+++ b/content/browser/service_worker/service_worker_object_host_unittest.cc
@@ -334,10 +334,8 @@
       WebContentsTester::CreateTestWebContents(helper_->browser_context(),
                                                nullptr));
   RenderFrameHost* frame_host = web_contents->GetMainFrame();
-  ServiceWorkerProviderHostInfo provider_host_info(
-      kProviderId, frame_host->GetRoutingID(),
-      blink::mojom::ServiceWorkerProviderType::kForWindow,
-      true /* is_parent_frame_secure */);
+  mojom::ServiceWorkerProviderHostInfoPtr provider_host_info =
+      CreateProviderHostInfoForWindow(kProviderId, frame_host->GetRoutingID());
   std::unique_ptr<ServiceWorkerProviderHost> provider_host =
       ServiceWorkerProviderHost::Create(frame_host->GetProcess()->GetID(),
                                         std::move(provider_host_info),
@@ -391,10 +389,8 @@
       WebContentsTester::CreateTestWebContents(helper_->browser_context(),
                                                nullptr));
   RenderFrameHost* frame_host = web_contents->GetMainFrame();
-  ServiceWorkerProviderHostInfo provider_host_info(
-      kProviderId, frame_host->GetRoutingID(),
-      blink::mojom::ServiceWorkerProviderType::kForWindow,
-      true /* is_parent_frame_secure */);
+  mojom::ServiceWorkerProviderHostInfoPtr provider_host_info =
+      CreateProviderHostInfoForWindow(kProviderId, frame_host->GetRoutingID());
   std::unique_ptr<ServiceWorkerProviderHost> provider_host =
       ServiceWorkerProviderHost::Create(frame_host->GetProcess()->GetID(),
                                         std::move(provider_host_info),
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc
index 07780a5..941ccbd 100644
--- a/content/browser/service_worker/service_worker_provider_host.cc
+++ b/content/browser/service_worker/service_worker_provider_host.cc
@@ -156,10 +156,11 @@
   DCHECK(context);
   auto host = base::WrapUnique(new ServiceWorkerProviderHost(
       ChildProcessHost::kInvalidUniqueID,
-      ServiceWorkerProviderHostInfo(
+      mojom::ServiceWorkerProviderHostInfo::New(
           NextBrowserProvidedProviderId(), MSG_ROUTING_NONE,
           blink::mojom::ServiceWorkerProviderType::kForWindow,
-          are_ancestors_secure),
+          are_ancestors_secure, nullptr /* host_request */,
+          nullptr /* client_ptr_info */),
       context));
   host->web_contents_getter_ = web_contents_getter;
 
@@ -174,10 +175,11 @@
     base::WeakPtr<ServiceWorkerContextCore> context) {
   auto host = base::WrapUnique(new ServiceWorkerProviderHost(
       ChildProcessHost::kInvalidUniqueID,
-      ServiceWorkerProviderHostInfo(
+      mojom::ServiceWorkerProviderHostInfo::New(
           NextBrowserProvidedProviderId(), MSG_ROUTING_NONE,
           blink::mojom::ServiceWorkerProviderType::kForServiceWorker,
-          true /* is_parent_frame_secure */),
+          true /* is_parent_frame_secure */, nullptr /* host_request */,
+          nullptr /* client_ptr_info */),
       std::move(context)));
   return host;
 }
@@ -190,10 +192,11 @@
     mojom::ServiceWorkerProviderInfoForSharedWorkerPtr* out_provider_info) {
   auto host = base::WrapUnique(new ServiceWorkerProviderHost(
       ChildProcessHost::kInvalidUniqueID,
-      ServiceWorkerProviderHostInfo(
+      mojom::ServiceWorkerProviderHostInfo::New(
           NextBrowserProvidedProviderId(), MSG_ROUTING_NONE,
           blink::mojom::ServiceWorkerProviderType::kForSharedWorker,
-          true /* is_parent_frame_secure */),
+          true /* is_parent_frame_secure */, nullptr /* host_request */,
+          nullptr /* client_ptr_info */),
       context));
   host->render_process_id_ = process_id;
 
@@ -212,7 +215,7 @@
 // static
 std::unique_ptr<ServiceWorkerProviderHost> ServiceWorkerProviderHost::Create(
     int process_id,
-    ServiceWorkerProviderHostInfo info,
+    mojom::ServiceWorkerProviderHostInfoPtr info,
     base::WeakPtr<ServiceWorkerContextCore> context) {
   auto host = base::WrapUnique(
       new ServiceWorkerProviderHost(process_id, std::move(info), context));
@@ -222,7 +225,7 @@
 
 ServiceWorkerProviderHost::ServiceWorkerProviderHost(
     int render_process_id,
-    ServiceWorkerProviderHostInfo info,
+    mojom::ServiceWorkerProviderHostInfoPtr info,
     base::WeakPtr<ServiceWorkerContextCore> context)
     : client_uuid_(base::GenerateGUID()),
       create_time_(base::TimeTicks::Now()),
@@ -233,9 +236,9 @@
       allow_association_(true),
       binding_(this),
       interface_provider_binding_(this) {
-  DCHECK_NE(blink::mojom::ServiceWorkerProviderType::kUnknown, info_.type);
+  DCHECK_NE(blink::mojom::ServiceWorkerProviderType::kUnknown, info_->type);
 
-  if (info_.type ==
+  if (info_->type ==
       blink::mojom::ServiceWorkerProviderType::kForServiceWorker) {
     // Actual |render_process_id| will be set after choosing a process for the
     // controller, and |render_thread id| will be set when the service worker
@@ -249,13 +252,13 @@
   // |client_| and |binding_| will be bound on CompleteNavigationInitialized
   // (providers created for navigation) or on
   // CompleteStartWorkerPreparation (providers for service workers).
-  if (!info_.client_ptr_info.is_valid() && !info_.host_request.is_pending())
+  if (!info_->client_ptr_info.is_valid() && !info_->host_request.is_pending())
     return;
 
-  container_.Bind(std::move(info_.client_ptr_info));
-  binding_.Bind(std::move(info_.host_request));
+  container_.Bind(std::move(info_->client_ptr_info));
+  binding_.Bind(std::move(info_->host_request));
   binding_.set_connection_error_handler(base::BindOnce(
-      &RemoveProviderHost, context_, render_process_id, info_.provider_id));
+      &RemoveProviderHost, context_, render_process_id, info_->provider_id));
 }
 
 ServiceWorkerProviderHost::~ServiceWorkerProviderHost() {
@@ -269,7 +272,7 @@
     // Just log when hosts isn't empty. It'd be too noisy to record all provider
     // ctor/dtor otherwise.
     ServiceWorkerObjectHost::AddToDebugLog(
-        base::StringPrintf("ProvDtor:prov=%p,type=%d", this, info_.type));
+        base::StringPrintf("ProvDtor:prov=%p,type=%d", this, info_->type));
   }
 
   if (context_)
@@ -292,8 +295,8 @@
 }
 
 int ServiceWorkerProviderHost::frame_id() const {
-  if (info_.type == blink::mojom::ServiceWorkerProviderType::kForWindow)
-    return info_.route_id;
+  if (info_->type == blink::mojom::ServiceWorkerProviderType::kForWindow)
+    return info_->route_id;
   return MSG_ROUTING_NONE;
 }
 
@@ -437,12 +440,12 @@
 }
 
 bool ServiceWorkerProviderHost::IsProviderForServiceWorker() const {
-  return info_.type ==
+  return info_->type ==
          blink::mojom::ServiceWorkerProviderType::kForServiceWorker;
 }
 
 bool ServiceWorkerProviderHost::IsProviderForClient() const {
-  switch (info_.type) {
+  switch (info_->type) {
     case blink::mojom::ServiceWorkerProviderType::kForWindow:
     case blink::mojom::ServiceWorkerProviderType::kForSharedWorker:
       return true;
@@ -451,13 +454,13 @@
     case blink::mojom::ServiceWorkerProviderType::kUnknown:
       break;
   }
-  NOTREACHED() << info_.type;
+  NOTREACHED() << info_->type;
   return false;
 }
 
 blink::mojom::ServiceWorkerClientType ServiceWorkerProviderHost::client_type()
     const {
-  switch (info_.type) {
+  switch (info_->type) {
     case blink::mojom::ServiceWorkerProviderType::kForWindow:
       return blink::mojom::ServiceWorkerClientType::kWindow;
     case blink::mojom::ServiceWorkerProviderType::kForSharedWorker:
@@ -466,7 +469,7 @@
     case blink::mojom::ServiceWorkerProviderType::kUnknown:
       break;
   }
-  NOTREACHED() << info_.type;
+  NOTREACHED() << info_->type;
   return blink::mojom::ServiceWorkerClientType::kWindow;
 }
 
@@ -666,25 +669,25 @@
 
 void ServiceWorkerProviderHost::CompleteNavigationInitialized(
     int process_id,
-    ServiceWorkerProviderHostInfo info) {
+    mojom::ServiceWorkerProviderHostInfoPtr info) {
   DCHECK_EQ(ChildProcessHost::kInvalidUniqueID, render_process_id_);
-  DCHECK_EQ(blink::mojom::ServiceWorkerProviderType::kForWindow, info_.type);
+  DCHECK_EQ(blink::mojom::ServiceWorkerProviderType::kForWindow, info_->type);
   DCHECK_EQ(kDocumentMainThreadId, render_thread_id_);
 
   DCHECK_NE(ChildProcessHost::kInvalidUniqueID, process_id);
-  DCHECK_EQ(info_.provider_id, info.provider_id);
-  DCHECK_NE(MSG_ROUTING_NONE, info.route_id);
+  DCHECK_EQ(info_->provider_id, info->provider_id);
+  DCHECK_NE(MSG_ROUTING_NONE, info->route_id);
 
   is_execution_ready_ = true;
 
   // Connect with the mojom::ServiceWorkerContainer on the renderer.
   DCHECK(!container_.is_bound());
   DCHECK(!binding_.is_bound());
-  container_.Bind(std::move(info.client_ptr_info));
-  binding_.Bind(std::move(info.host_request));
+  container_.Bind(std::move(info->client_ptr_info));
+  binding_.Bind(std::move(info->host_request));
   binding_.set_connection_error_handler(
       base::BindOnce(&RemoveProviderHost, context_, process_id, provider_id()));
-  info_.route_id = info.route_id;
+  info_->route_id = info->route_id;
   render_process_id_ = process_id;
 
   // Now that there is a connection with the renderer-side provider, initialize
diff --git a/content/browser/service_worker/service_worker_provider_host.h b/content/browser/service_worker/service_worker_provider_host.h
index 8c4e9675..034b04d 100644
--- a/content/browser/service_worker/service_worker_provider_host.h
+++ b/content/browser/service_worker/service_worker_provider_host.h
@@ -23,7 +23,7 @@
 #include "content/browser/service_worker/service_worker_registration.h"
 #include "content/common/content_export.h"
 #include "content/common/service_worker/service_worker_container.mojom.h"
-#include "content/common/service_worker/service_worker_provider_host_info.h"
+#include "content/common/service_worker/service_worker_provider.mojom.h"
 #include "content/common/service_worker/service_worker_types.h"
 #include "content/public/common/request_context_type.h"
 #include "content/public/common/resource_type.h"
@@ -167,7 +167,7 @@
   // |process_id|.
   static std::unique_ptr<ServiceWorkerProviderHost> Create(
       int process_id,
-      ServiceWorkerProviderHostInfo info,
+      mojom::ServiceWorkerProviderHostInfoPtr info,
       base::WeakPtr<ServiceWorkerContextCore> context);
 
   ~ServiceWorkerProviderHost() override;
@@ -175,14 +175,14 @@
   const std::string& client_uuid() const { return client_uuid_; }
   base::TimeTicks create_time() const { return create_time_; }
   int process_id() const { return render_process_id_; }
-  int provider_id() const { return info_.provider_id; }
+  int provider_id() const { return info_->provider_id; }
   int frame_id() const;
-  int route_id() const { return info_.route_id; }
+  int route_id() const { return info_->route_id; }
   const WebContentsGetter& web_contents_getter() const {
     return web_contents_getter_;
   }
 
-  bool is_parent_frame_secure() const { return info_.is_parent_frame_secure; }
+  bool is_parent_frame_secure() const { return info_->is_parent_frame_secure; }
 
   // Returns whether this provider host is secure enough to have a service
   // worker controller.
@@ -246,7 +246,7 @@
   // CompleteStartWorkerPreparation() is called).
   ServiceWorkerVersion* running_hosted_version() const {
     DCHECK(!running_hosted_version_ ||
-           info_.type ==
+           info_->type ==
                blink::mojom::ServiceWorkerProviderType::kForServiceWorker);
     return running_hosted_version_.get();
   }
@@ -308,7 +308,7 @@
   const GURL& topmost_frame_url() const;
 
   blink::mojom::ServiceWorkerProviderType provider_type() const {
-    return info_.type;
+    return info_->type;
   }
   bool IsProviderForServiceWorker() const;
   bool IsProviderForClient() const;
@@ -386,8 +386,9 @@
 
   // For service worker clients. Completes initialization of
   // provider hosts used for navigation requests.
-  void CompleteNavigationInitialized(int process_id,
-                                     ServiceWorkerProviderHostInfo info);
+  void CompleteNavigationInitialized(
+      int process_id,
+      mojom::ServiceWorkerProviderHostInfoPtr info);
 
   // For service worker execution contexts. Completes initialization of this
   // provider host. It is called once a renderer process has been found to host
@@ -468,7 +469,7 @@
                            RegisterWithoutLiveSWRegistration);
 
   ServiceWorkerProviderHost(int process_id,
-                            ServiceWorkerProviderHostInfo info,
+                            mojom::ServiceWorkerProviderHostInfoPtr info,
                             base::WeakPtr<ServiceWorkerContextCore> context);
 
   // ServiceWorkerRegistration::Listener overrides.
@@ -578,7 +579,7 @@
   // Otherwise, |kDocumentMainThreadId|.
   int render_thread_id_;
 
-  ServiceWorkerProviderHostInfo info_;
+  mojom::ServiceWorkerProviderHostInfoPtr info_;
 
   // Only set when this object is pre-created for a navigation. It indicates the
   // tab where the navigation occurs.
diff --git a/content/browser/service_worker/service_worker_provider_host_unittest.cc b/content/browser/service_worker/service_worker_provider_host_unittest.cc
index 8a047165..72feced 100644
--- a/content/browser/service_worker/service_worker_provider_host_unittest.cc
+++ b/content/browser/service_worker/service_worker_provider_host_unittest.cc
@@ -172,7 +172,7 @@
   }
 
   void FinishNavigation(ServiceWorkerProviderHost* host,
-                        ServiceWorkerProviderHostInfo info) {
+                        mojom::ServiceWorkerProviderHostInfoPtr info) {
     // In production code, the loader/request handler does this.
     host->SetDocumentUrl(GURL("https://www.example.com/page"));
     host->SetTopmostFrameUrl(GURL("https://www.example.com/page"));
@@ -289,10 +289,8 @@
         ServiceWorkerProviderHost::PreCreateNavigationHost(
             helper_->context()->AsWeakPtr(), true,
             base::Callback<WebContents*(void)>());
-    ServiceWorkerProviderHostInfo info(
-        host->provider_id(), 1 /* route_id */,
-        blink::mojom::ServiceWorkerProviderType::kForWindow,
-        true /* is_parent_frame_secure */);
+    mojom::ServiceWorkerProviderHostInfoPtr info =
+        CreateProviderHostInfoForWindow(host->provider_id(), 1 /* route_id */);
     remote_endpoint->BindWithProviderHostInfo(&info);
 
     std::unique_ptr<ServiceWorkerProviderHost> owned_host =
@@ -442,10 +440,8 @@
       ServiceWorkerProviderHost::PreCreateNavigationHost(
           helper_->context()->AsWeakPtr(), true /* are_ancestors_secure */,
           base::Callback<WebContents*(void)>());
-  ServiceWorkerProviderHostInfo info(
-      host->provider_id(), 1 /* route_id */,
-      blink::mojom::ServiceWorkerProviderType::kForWindow,
-      true /* is_parent_frame_secure */);
+  mojom::ServiceWorkerProviderHostInfoPtr info =
+      CreateProviderHostInfoForWindow(host->provider_id(), 1 /* route_id */);
   remote_endpoints_.emplace_back();
   remote_endpoints_.back().BindWithProviderHostInfo(&info);
   auto container = std::make_unique<MockServiceWorkerContainer>(
@@ -479,10 +475,8 @@
       ServiceWorkerProviderHost::PreCreateNavigationHost(
           helper_->context()->AsWeakPtr(), true /* are_ancestors_secure */,
           base::Callback<WebContents*(void)>());
-  ServiceWorkerProviderHostInfo info(
-      host->provider_id(), 1 /* route_id */,
-      blink::mojom::ServiceWorkerProviderType::kForWindow,
-      true /* is_parent_frame_secure */);
+  mojom::ServiceWorkerProviderHostInfoPtr info =
+      CreateProviderHostInfoForWindow(host->provider_id(), 1 /* route_id */);
   remote_endpoints_.emplace_back();
   remote_endpoints_.back().BindWithProviderHostInfo(&info);
   auto container = std::make_unique<MockServiceWorkerContainer>(
@@ -856,10 +850,8 @@
         ServiceWorkerProviderHost::PreCreateNavigationHost(
             helper_->context()->AsWeakPtr(), true,
             base::RepeatingCallback<WebContents*(void)>());
-    ServiceWorkerProviderHostInfo info(
-        host->provider_id(), 1 /* route_id */,
-        blink::mojom::ServiceWorkerProviderType::kForWindow,
-        true /* is_parent_frame_secure */);
+    mojom::ServiceWorkerProviderHostInfoPtr info =
+        CreateProviderHostInfoForWindow(host->provider_id(), 1 /* route_id */);
     ServiceWorkerRemoteProviderEndpoint remote_endpoint;
     remote_endpoint.BindWithProviderHostInfo(&info);
     host->SetDocumentUrl(GURL("https://www.example.com/page"));
diff --git a/content/browser/service_worker/service_worker_test_utils.cc b/content/browser/service_worker/service_worker_test_utils.cc
index bad7bad..c3c0103 100644
--- a/content/browser/service_worker/service_worker_test_utils.cc
+++ b/content/browser/service_worker/service_worker_test_utils.cc
@@ -16,7 +16,6 @@
 #include "content/browser/service_worker/service_worker_provider_host.h"
 #include "content/browser/service_worker/service_worker_registration.h"
 #include "content/browser/service_worker/service_worker_storage.h"
-#include "content/common/service_worker/service_worker_provider.mojom.h"
 #include "content/public/common/child_process_host.h"
 #include "net/base/io_buffer.h"
 #include "net/base/test_completion_callback.h"
@@ -144,11 +143,12 @@
 ServiceWorkerRemoteProviderEndpoint::~ServiceWorkerRemoteProviderEndpoint() {}
 
 void ServiceWorkerRemoteProviderEndpoint::BindWithProviderHostInfo(
-    content::ServiceWorkerProviderHostInfo* info) {
+    mojom::ServiceWorkerProviderHostInfoPtr* info) {
   mojom::ServiceWorkerContainerAssociatedPtr client_ptr;
   client_request_ = mojo::MakeRequestAssociatedWithDedicatedPipe(&client_ptr);
-  info->client_ptr_info = client_ptr.PassInterface();
-  info->host_request = mojo::MakeRequestAssociatedWithDedicatedPipe(&host_ptr_);
+  (*info)->client_ptr_info = client_ptr.PassInterface();
+  (*info)->host_request =
+      mojo::MakeRequestAssociatedWithDedicatedPipe(&host_ptr_);
 }
 
 void ServiceWorkerRemoteProviderEndpoint::BindWithProviderInfo(
@@ -157,16 +157,25 @@
   host_ptr_.Bind(std::move(info->host_ptr_info));
 }
 
+mojom::ServiceWorkerProviderHostInfoPtr CreateProviderHostInfoForWindow(
+    int provider_id,
+    int route_id) {
+  return mojom::ServiceWorkerProviderHostInfo::New(
+      provider_id, route_id,
+      blink::mojom::ServiceWorkerProviderType::kForWindow,
+      true /* is_parent_frame_secure */, nullptr /* host_request */,
+      nullptr /* client_ptr_info */);
+}
+
 std::unique_ptr<ServiceWorkerProviderHost> CreateProviderHostForWindow(
     int process_id,
     int provider_id,
     bool is_parent_frame_secure,
     base::WeakPtr<ServiceWorkerContextCore> context,
     ServiceWorkerRemoteProviderEndpoint* output_endpoint) {
-  ServiceWorkerProviderHostInfo info(
-      provider_id, 1 /* route_id */,
-      blink::mojom::ServiceWorkerProviderType::kForWindow,
-      is_parent_frame_secure);
+  mojom::ServiceWorkerProviderHostInfoPtr info =
+      CreateProviderHostInfoForWindow(provider_id, 1 /* route_id */);
+  info->is_parent_frame_secure = is_parent_frame_secure;
   output_endpoint->BindWithProviderHostInfo(&info);
   return ServiceWorkerProviderHost::Create(process_id, std::move(info),
                                            std::move(context));
@@ -179,10 +188,6 @@
     ServiceWorkerVersion* hosted_version,
     base::WeakPtr<ServiceWorkerContextCore> context,
     ServiceWorkerRemoteProviderEndpoint* output_endpoint) {
-  ServiceWorkerProviderHostInfo info(
-      kInvalidServiceWorkerProviderId, MSG_ROUTING_NONE,
-      blink::mojom::ServiceWorkerProviderType::kForServiceWorker,
-      is_parent_frame_secure);
   std::unique_ptr<ServiceWorkerProviderHost> host =
       ServiceWorkerProviderHost::PreCreateForController(std::move(context));
   host->SetDocumentUrl(hosted_version->script_url());
diff --git a/content/browser/service_worker/service_worker_test_utils.h b/content/browser/service_worker/service_worker_test_utils.h
index 4bc50cf3..9c41ef1 100644
--- a/content/browser/service_worker/service_worker_test_utils.h
+++ b/content/browser/service_worker/service_worker_test_utils.h
@@ -30,7 +30,6 @@
 class ServiceWorkerProviderHost;
 class ServiceWorkerStorage;
 class ServiceWorkerVersion;
-struct ServiceWorkerProviderHostInfo;
 
 template <typename Arg>
 void ReceiveResult(BrowserThread::ID run_quit_thread,
@@ -68,7 +67,7 @@
       ServiceWorkerRemoteProviderEndpoint&& other);
   ~ServiceWorkerRemoteProviderEndpoint();
 
-  void BindWithProviderHostInfo(ServiceWorkerProviderHostInfo* info);
+  void BindWithProviderHostInfo(mojom::ServiceWorkerProviderHostInfoPtr* info);
   void BindWithProviderInfo(
       mojom::ServiceWorkerProviderInfoForStartWorkerPtr info);
 
@@ -91,6 +90,10 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRemoteProviderEndpoint);
 };
 
+mojom::ServiceWorkerProviderHostInfoPtr CreateProviderHostInfoForWindow(
+    int provider_id,
+    int route_id);
+
 std::unique_ptr<ServiceWorkerProviderHost> CreateProviderHostForWindow(
     int process_id,
     int provider_id,
diff --git a/content/browser/shared_worker/shared_worker_host.cc b/content/browser/shared_worker/shared_worker_host.cc
index 4cba76c8..eff04c7 100644
--- a/content/browser/shared_worker/shared_worker_host.cc
+++ b/content/browser/shared_worker/shared_worker_host.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/feature_list.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/unguessable_token.h"
 #include "content/browser/devtools/shared_worker_devtools_manager.h"
@@ -21,6 +22,7 @@
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/common/content_client.h"
+#include "services/network/public/cpp/features.h"
 #include "third_party/blink/public/common/message_port/message_port_channel.h"
 #include "third_party/blink/public/platform/web_feature.mojom.h"
 #include "third_party/blink/public/web/worker_content_settings_proxy.mojom.h"
@@ -154,22 +156,22 @@
       mojom::kNavigation_SharedWorkerSpec, process_id_,
       mojo::MakeRequest(&interface_provider)));
 
-  // NetworkService: Add the network factory to the bundle to pass to the
-  // renderer. The bundle is only provided (along with |script_loader_factory|)
-  // if NetworkService/S13nSW is enabled.
+  // Add the network factory to the bundle to pass to the renderer. The bundle
+  // is only provided (along with |script_loader_factory|) if
+  // NetworkService/S13nSW is enabled.
   DCHECK(!script_loader_factory || factory_bundle);
   if (factory_bundle) {
     network::mojom::URLLoaderFactoryPtrInfo network_factory_info;
-    CreateNetworkFactory(mojo::MakeRequest(&network_factory_info));
+    if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+      // NetworkService is on: Use the network service.
+      CreateNetworkFactory(mojo::MakeRequest(&network_factory_info));
+    } else {
+      // NetworkService is off: RenderProcessHost gives us a non-NetworkService
+      // network factory.
+      RenderProcessHost::FromID(process_id_)
+          ->CreateURLLoaderFactory(mojo::MakeRequest(&network_factory_info));
+    }
     DCHECK(!factory_bundle->default_factory_info());
-
-    // This is a NetworkService-backed factory, so it'd be better to send this
-    // only when NetworkService is enabled. But when S13nServiceWorker is
-    // enabled, we need to send the bundle and it crashes if it's sent over Mojo
-    // with no default factory. Furthermore, it is not easy to make a default
-    // URLLoaderFactoryImpl from the browser-side, since we need a
-    // ResourceRequestorInfo. So, just send the bundle and count on the renderer
-    // to clear the default factory upon arrival in that case.
     factory_bundle->default_factory_info() = std::move(network_factory_info);
 
     // TODO(falken): We might need to set the default factory to AppCache
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index 25aca98..3ec98f60 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -11007,7 +11007,7 @@
   void WaitForBothCommits() { outer_run_loop.Run(); }
 
  protected:
-  void WillDispatchDidCommitProvisionalLoad(
+  bool WillDispatchDidCommitProvisionalLoad(
       RenderFrameHost* render_frame_host,
       ::FrameHostMsg_DidCommitProvisionalLoad_Params* params,
       service_manager::mojom::InterfaceProviderRequest*
@@ -11026,6 +11026,7 @@
     } else if (nested_loop_quit_) {
       std::move(nested_loop_quit_).Run();
     }
+    return true;
   }
 
  private:
@@ -11922,7 +11923,7 @@
 
  private:
   // DidCommitProvisionalLoadInterceptor:
-  void WillDispatchDidCommitProvisionalLoad(
+  bool WillDispatchDidCommitProvisionalLoad(
       RenderFrameHost* render_frame_host,
       ::FrameHostMsg_DidCommitProvisionalLoad_Params* params,
       service_manager::mojom::InterfaceProviderRequest*
@@ -11933,6 +11934,7 @@
     rvh->ClosePage();
     if (run_loop_)
       run_loop_->Quit();
+    return true;
   }
 
   std::unique_ptr<base::RunLoop> run_loop_;
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc
index 8f0e469..26d7f5c0 100644
--- a/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -442,6 +442,10 @@
   load_params.is_renderer_initiated = false;
   controller().LoadURLWithParams(load_params);
 
+  NavigationRequest* request =
+      main_test_rfh()->frame_tree_node()->navigation_request();
+  CHECK(request);
+
   int entry_id = cont.GetPendingEntry()->GetUniqueID();
   // Did we get the expected message?
   EXPECT_TRUE(process()->sink().GetFirstMessageMatching(
@@ -455,6 +459,9 @@
       FrameHostMsg_DidStartProvisionalLoad(1, kRewrittenURL,
                                            std::vector<GURL>(),
                                            base::TimeTicks::Now()));
+  main_test_rfh()->SimulateCommitProcessed(
+      request->navigation_handle()->GetNavigationId(),
+      true /* was_successful */);
   main_test_rfh()->SendNavigateWithParams(&params,
                                           false /* was_within_same_document */);
 
@@ -473,24 +480,21 @@
   SiteInstance* instance1 = contents()->GetSiteInstance();
   EXPECT_EQ(nullptr, contents()->GetPendingMainFrame());
 
-  // Navigate to URL
+  // Navigate until ready to commit.
   const GURL url("http://www.google.com");
-  controller().LoadURL(
-      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  int entry_id = controller().GetPendingEntry()->GetUniqueID();
-  main_test_rfh()->PrepareForCommit();
+  auto navigation =
+      NavigationSimulator::CreateBrowserInitiated(url, contents());
+  navigation->ReadyToCommit();
   EXPECT_FALSE(contents()->CrossProcessNavigationPending());
   EXPECT_EQ(instance1, orig_rfh->GetSiteInstance());
   // Controller's pending entry will have a null site instance until we assign
-  // it in DidNavigate.
+  // it in Commit.
   EXPECT_EQ(
       nullptr,
       NavigationEntryImpl::FromNavigationEntry(controller().GetVisibleEntry())->
           site_instance());
 
-  // DidNavigate from the page
-  contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
-                              ui::PAGE_TRANSITION_TYPED);
+  navigation->Commit();
   EXPECT_FALSE(contents()->CrossProcessNavigationPending());
   EXPECT_EQ(orig_rfh, main_test_rfh());
   EXPECT_EQ(instance1, orig_rfh->GetSiteInstance());
@@ -550,10 +554,10 @@
 
   // Navigate to new site
   const GURL url2("http://www.yahoo.com");
-  controller().LoadURL(
-      url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+  auto new_site_navigation =
+      NavigationSimulator::CreateBrowserInitiated(url2, contents());
+  new_site_navigation->ReadyToCommit();
   int entry_id = controller().GetPendingEntry()->GetUniqueID();
-  orig_rfh->PrepareForCommit();
   EXPECT_TRUE(contents()->CrossProcessNavigationPending());
   EXPECT_EQ(url, contents()->GetLastCommittedURL());
   EXPECT_EQ(url2, contents()->GetVisibleURL());
@@ -588,9 +592,10 @@
   // Going back should switch SiteInstances again.  The first SiteInstance is
   // stored in the NavigationEntry, so it should be the same as at the start.
   // We should use the same RFH as before, swapping it back in.
-  controller().GoBack();
+  auto back_navigation =
+      NavigationSimulator::CreateHistoryNavigation(-1, contents());
+  back_navigation->ReadyToCommit();
   entry_id = controller().GetPendingEntry()->GetUniqueID();
-  main_test_rfh()->PrepareForCommit();
   TestRenderFrameHost* goback_rfh = contents()->GetPendingMainFrame();
   EXPECT_TRUE(contents()->CrossProcessNavigationPending());
 
@@ -624,13 +629,7 @@
 
   // Navigate to URL.  First URL should use first RenderViewHost.
   const GURL url("http://www.google.com");
-  controller().LoadURL(
-      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  int entry_id = controller().GetPendingEntry()->GetUniqueID();
-  main_test_rfh()->PrepareForCommit();
-  contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
-                              ui::PAGE_TRANSITION_TYPED);
-
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
   EXPECT_FALSE(contents()->CrossProcessNavigationPending());
   EXPECT_EQ(orig_rfh->GetRenderViewHost(), contents()->GetRenderViewHost());
 
@@ -639,21 +638,19 @@
   orig_rfh->GetProcess()->SimulateCrash();
   EXPECT_FALSE(orig_rfh->IsRenderFrameLive());
 
-  // Navigate to new site.  We should not go into PENDING.
+  // Start navigating to a new site. We should not go into PENDING.
   const GURL url2("http://www.yahoo.com");
-  controller().LoadURL(
-      url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  entry_id = controller().GetPendingEntry()->GetUniqueID();
-  main_test_rfh()->PrepareForCommit();
+  auto navigation_to_url2 =
+      NavigationSimulator::CreateBrowserInitiated(url2, contents());
+  navigation_to_url2->ReadyToCommit();
+
   TestRenderFrameHost* new_rfh = main_test_rfh();
   EXPECT_FALSE(contents()->CrossProcessNavigationPending());
   EXPECT_EQ(nullptr, contents()->GetPendingMainFrame());
   EXPECT_NE(orig_rfh, new_rfh);
   EXPECT_EQ(orig_rvh_delete_count, 1);
 
-  // DidNavigate from the new page
-  contents()->TestDidNavigate(new_rfh, entry_id, true, url2,
-                              ui::PAGE_TRANSITION_TYPED);
+  navigation_to_url2->Commit();
   SiteInstance* instance2 = contents()->GetSiteInstance();
 
   EXPECT_FALSE(contents()->CrossProcessNavigationPending());
@@ -670,37 +667,24 @@
 // both contentses to a new site will place both contentses in a single
 // SiteInstance.
 TEST_F(WebContentsImplTest, NavigateTwoTabsCrossSite) {
-  TestRenderFrameHost* orig_rfh = main_test_rfh();
   SiteInstance* instance1 = contents()->GetSiteInstance();
 
   // Navigate to URL.  First URL should use first RenderViewHost.
   const GURL url("http://www.google.com");
-  controller().LoadURL(
-      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  int entry_id = controller().GetPendingEntry()->GetUniqueID();
-  main_test_rfh()->PrepareForCommit();
-  contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
-                              ui::PAGE_TRANSITION_TYPED);
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
 
   // Open a new contents with the same SiteInstance, navigated to the same site.
   std::unique_ptr<TestWebContents> contents2(
       TestWebContents::Create(browser_context(), instance1));
-  contents2->GetController().LoadURL(url, Referrer(),
-                                     ui::PAGE_TRANSITION_TYPED,
-                                     std::string());
-  entry_id = contents2->GetController().GetPendingEntry()->GetUniqueID();
-  contents2->GetMainFrame()->PrepareForCommit();
-  // Need this page id to be 2 since the site instance is the same (which is the
-  // scope of page IDs) and we want to consider this a new page.
-  contents2->TestDidNavigate(contents2->GetMainFrame(), entry_id, true, url,
-                             ui::PAGE_TRANSITION_TYPED);
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents2.get(), url);
+  EXPECT_EQ(instance1, contents2->GetSiteInstance());
 
   // Navigate first contents to a new site.
   const GURL url2a("http://www.yahoo.com");
   controller().LoadURL(url2a, Referrer(), ui::PAGE_TRANSITION_LINK,
                        std::string());
-  entry_id = controller().GetPendingEntry()->GetUniqueID();
-  orig_rfh->PrepareForCommit();
+  int entry_id = controller().GetPendingEntry()->GetUniqueID();
+  contents()->GetMainFrame()->PrepareForCommit();
   TestRenderFrameHost* pending_rfh_a = contents()->GetPendingMainFrame();
   if (AreAllSitesIsolatedForTesting())
     EXPECT_TRUE(contents()->CrossProcessNavigationPending());
@@ -749,12 +733,7 @@
   browser_client.set_assign_site_for_url(false);
   // Navigate to an URL that will not assign a new SiteInstance.
   const GURL native_url("non-site-url://stuffandthings");
-  controller().LoadURL(
-      native_url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  int entry_id = controller().GetPendingEntry()->GetUniqueID();
-  main_test_rfh()->PrepareForCommit();
-  contents()->TestDidNavigate(orig_rfh, entry_id, true, native_url,
-                              ui::PAGE_TRANSITION_TYPED);
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), native_url);
 
   EXPECT_FALSE(contents()->CrossProcessNavigationPending());
   EXPECT_EQ(orig_rfh, main_test_rfh());
@@ -767,16 +746,14 @@
   browser_client.set_assign_site_for_url(true);
   // Navigate to new site (should keep same site instance).
   const GURL url("http://www.google.com");
-  controller().LoadURL(
-      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  entry_id = controller().GetPendingEntry()->GetUniqueID();
-  main_test_rfh()->PrepareForCommit();
+  auto navigation =
+      NavigationSimulator::CreateBrowserInitiated(url, contents());
+  navigation->ReadyToCommit();
   EXPECT_FALSE(contents()->CrossProcessNavigationPending());
   EXPECT_EQ(native_url, contents()->GetLastCommittedURL());
   EXPECT_EQ(url, contents()->GetVisibleURL());
   EXPECT_FALSE(contents()->GetPendingMainFrame());
-  contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
-                              ui::PAGE_TRANSITION_TYPED);
+  navigation->Commit();
 
   // Keep the number of active frames in orig_rfh's SiteInstance
   // non-zero so that orig_rfh doesn't get deleted when it gets
@@ -792,7 +769,7 @@
   const GURL url2("http://www.yahoo.com");
   controller().LoadURL(
       url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  entry_id = controller().GetPendingEntry()->GetUniqueID();
+  int entry_id = controller().GetPendingEntry()->GetUniqueID();
   orig_rfh->PrepareForCommit();
   EXPECT_TRUE(contents()->CrossProcessNavigationPending());
   EXPECT_EQ(url, contents()->GetLastCommittedURL());
@@ -862,12 +839,7 @@
   // Navigate to a regular site and verify that the SiteInstance was kept.
   browser_client.set_assign_site_for_url(true);
   const GURL url("http://www.google.com");
-  controller().LoadURL(
-      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  entry = controller().GetPendingEntry();
-  orig_rfh->PrepareForCommit();
-  contents()->TestDidNavigate(orig_rfh, entry->GetUniqueID(), true, url,
-                              ui::PAGE_TRANSITION_TYPED);
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
   EXPECT_EQ(orig_instance, contents()->GetSiteInstance());
 
   // Cleanup.
@@ -908,13 +880,7 @@
 
   // Navigate to another site and verify that a new SiteInstance was created.
   const GURL url("http://www.google.com");
-  controller().LoadURL(
-      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  entry = controller().GetPendingEntry();
-  orig_rfh->PrepareForCommit();
-  contents()->TestDidNavigate(contents()->GetPendingMainFrame(),
-                              entry->GetUniqueID(), true, url,
-                              ui::PAGE_TRANSITION_TYPED);
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
   EXPECT_NE(orig_instance, contents()->GetSiteInstance());
 
   // Cleanup.
@@ -924,22 +890,16 @@
 // Test that we can find an opener RVH even if it's pending.
 // http://crbug.com/176252.
 TEST_F(WebContentsImplTest, FindOpenerRVHWhenPending) {
-  TestRenderFrameHost* orig_rfh = main_test_rfh();
 
   // Navigate to a URL.
   const GURL url("http://www.google.com");
-  controller().LoadURL(
-      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  int entry_id = controller().GetPendingEntry()->GetUniqueID();
-  orig_rfh->PrepareForCommit();
-  contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
-                              ui::PAGE_TRANSITION_TYPED);
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
 
   // Start to navigate first tab to a new site, so that it has a pending RVH.
   const GURL url2("http://www.yahoo.com");
-  controller().LoadURL(
-      url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  orig_rfh->PrepareForCommit();
+  auto navigation =
+      NavigationSimulator::CreateBrowserInitiated(url2, contents());
+  navigation->ReadyToCommit();
   TestRenderFrameHost* pending_rfh = contents()->GetPendingMainFrame();
   SiteInstance* instance = pending_rfh->GetSiteInstance();
 
@@ -962,9 +922,7 @@
   EXPECT_EQ(proxy->GetRoutingID(), opener_frame_routing_id);
 
   // Ensure that committing the navigation removes the proxy.
-  entry_id = controller().GetPendingEntry()->GetUniqueID();
-  contents()->TestDidNavigate(pending_rfh, entry_id, true, url2,
-                              ui::PAGE_TRANSITION_TYPED);
+  navigation->Commit();
   EXPECT_FALSE(
       contents()->GetRenderManager()->GetRenderFrameProxyHost(instance));
 }
@@ -982,29 +940,20 @@
 
   // Navigate to URL.
   const GURL url("http://www.google.com");
-  controller().LoadURL(
-      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  int entry_id = controller().GetPendingEntry()->GetUniqueID();
-  main_test_rfh()->PrepareForCommit();
-  contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
-                              ui::PAGE_TRANSITION_TYPED);
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
 
   // Open a related contents to a second site.
   std::unique_ptr<TestWebContents> contents2(
       TestWebContents::Create(browser_context(), instance1));
   const GURL url2("http://www.yahoo.com");
-  contents2->GetController().LoadURL(url2, Referrer(),
-                                     ui::PAGE_TRANSITION_TYPED,
-                                     std::string());
-  entry_id = contents2->GetController().GetPendingEntry()->GetUniqueID();
-  contents2->GetMainFrame()->PrepareForCommit();
+  auto navigation =
+      NavigationSimulator::CreateBrowserInitiated(url2, contents2.get());
+  navigation->ReadyToCommit();
 
   // The first RVH in contents2 isn't live yet, so we shortcut the cross site
   // pending.
-  TestRenderFrameHost* rfh2 = contents2->GetMainFrame();
   EXPECT_FALSE(contents2->CrossProcessNavigationPending());
-  contents2->TestDidNavigate(rfh2, entry_id, true, url2,
-                             ui::PAGE_TRANSITION_TYPED);
+  navigation->Commit();
   SiteInstance* instance2 = contents2->GetSiteInstance();
   EXPECT_NE(instance1, instance2);
   EXPECT_FALSE(contents2->CrossProcessNavigationPending());
@@ -1019,13 +968,7 @@
   // Navigate to the new site.  Doesn't switch SiteInstancees, because we
   // compare against the current URL, not the SiteInstance's site.
   const GURL url3("http://mail.yahoo.com");
-  controller().LoadURL(
-      url3, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  entry_id = controller().GetPendingEntry()->GetUniqueID();
-  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
-  main_test_rfh()->PrepareForCommit();
-  contents()->TestDidNavigate(orig_rfh, entry_id, true, url3,
-                              ui::PAGE_TRANSITION_TYPED);
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url3);
   SiteInstance* instance4 = contents()->GetSiteInstance();
   EXPECT_EQ(instance1, instance4);
 }
@@ -1038,12 +981,7 @@
 
   // Navigate to URL.  First URL should use first RenderViewHost.
   const GURL url("http://www.google.com");
-  controller().LoadURL(
-      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  int entry_id = controller().GetPendingEntry()->GetUniqueID();
-  main_test_rfh()->PrepareForCommit();
-  contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
-                              ui::PAGE_TRANSITION_TYPED);
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
   EXPECT_FALSE(contents()->CrossProcessNavigationPending());
   EXPECT_EQ(orig_rfh, main_test_rfh());
 
@@ -1062,7 +1000,7 @@
   // Navigate again, but simulate an onbeforeunload approval.
   controller().LoadURL(
       url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  entry_id = controller().GetPendingEntry()->GetUniqueID();
+  int entry_id = controller().GetPendingEntry()->GetUniqueID();
   EXPECT_TRUE(orig_rfh->is_waiting_for_beforeunload_ack());
   now = base::TimeTicks::Now();
   orig_rfh->PrepareForCommit();
@@ -1091,12 +1029,7 @@
 
   // Navigate to URL.  First URL should use first RenderFrameHost.
   const GURL url("http://www.google.com");
-  controller().LoadURL(
-      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  int entry_id = controller().GetPendingEntry()->GetUniqueID();
-  main_test_rfh()->PrepareForCommit();
-  contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
-                              ui::PAGE_TRANSITION_TYPED);
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
   EXPECT_FALSE(contents()->CrossProcessNavigationPending());
   EXPECT_EQ(orig_rfh, main_test_rfh());
 
@@ -1214,18 +1147,12 @@
   // Start with a web ui page, which gets a new RVH with WebUI bindings.
   GURL url1(std::string(kChromeUIScheme) + "://" +
             std::string(kChromeUIGpuHost));
-  controller().LoadURL(url1, Referrer(), ui::PAGE_TRANSITION_TYPED,
-                       std::string());
-  int entry_id = controller().GetPendingEntry()->GetUniqueID();
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url1);
   TestRenderFrameHost* webui_rfh = main_test_rfh();
-  webui_rfh->PrepareForCommit();
-  contents()->TestDidNavigate(webui_rfh, entry_id, true, url1,
-                              ui::PAGE_TRANSITION_TYPED);
   NavigationEntry* entry1 = controller().GetLastCommittedEntry();
   SiteInstance* instance1 = contents()->GetSiteInstance();
 
   EXPECT_FALSE(contents()->CrossProcessNavigationPending());
-  EXPECT_EQ(webui_rfh, main_test_rfh());
   EXPECT_EQ(url1, entry1->GetURL());
   EXPECT_EQ(instance1,
             NavigationEntryImpl::FromNavigationEntry(entry1)->site_instance());
@@ -1233,24 +1160,12 @@
 
   // Navigate to new site.
   const GURL url2("http://www.google.com");
-  controller().LoadURL(url2, Referrer(), ui::PAGE_TRANSITION_TYPED,
-                       std::string());
-  entry_id = controller().GetPendingEntry()->GetUniqueID();
-  EXPECT_TRUE(contents()->CrossProcessNavigationPending());
-  TestRenderFrameHost* google_rfh = contents()->GetPendingMainFrame();
-
-  // Simulate beforeunload approval.
-  EXPECT_TRUE(webui_rfh->is_waiting_for_beforeunload_ack());
-  webui_rfh->PrepareForCommit();
-
-  // DidNavigate from the pending page.
-  contents()->TestDidNavigate(google_rfh, entry_id, true, url2,
-                              ui::PAGE_TRANSITION_TYPED);
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url2);
+  TestRenderFrameHost* google_rfh = main_test_rfh();
   NavigationEntry* entry2 = controller().GetLastCommittedEntry();
   SiteInstance* instance2 = contents()->GetSiteInstance();
 
   EXPECT_FALSE(contents()->CrossProcessNavigationPending());
-  EXPECT_EQ(google_rfh, main_test_rfh());
   EXPECT_NE(instance1, instance2);
   EXPECT_FALSE(contents()->GetPendingMainFrame());
   EXPECT_EQ(url2, entry2->GetURL());
@@ -1260,13 +1175,7 @@
 
   // Navigate to third page on same site.
   const GURL url3("http://news.google.com");
-  controller().LoadURL(url3, Referrer(), ui::PAGE_TRANSITION_TYPED,
-                       std::string());
-  entry_id = controller().GetPendingEntry()->GetUniqueID();
-  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
-  main_test_rfh()->PrepareForCommit();
-  contents()->TestDidNavigate(google_rfh, entry_id, true, url3,
-                              ui::PAGE_TRANSITION_TYPED);
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url3);
   NavigationEntry* entry3 = controller().GetLastCommittedEntry();
   SiteInstance* instance3 = contents()->GetSiteInstance();
 
@@ -1310,12 +1219,7 @@
 
   // Navigate to URL.  First URL should use the original RenderFrameHost.
   const GURL url("http://www.google.com");
-  controller().LoadURL(
-      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  int entry_id = controller().GetPendingEntry()->GetUniqueID();
-  main_test_rfh()->PrepareForCommit();
-  contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
-                              ui::PAGE_TRANSITION_TYPED);
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
   EXPECT_FALSE(contents()->CrossProcessNavigationPending());
   EXPECT_EQ(orig_rfh, main_test_rfh());
 
@@ -1343,7 +1247,7 @@
 void SetAsNonUserGesture(FrameHostMsg_DidCommitProvisionalLoad_Params* params) {
   params->gesture = NavigationGestureAuto;
 }
-}
+}  // namespace
 
 // Test that a cross-site navigation is not preempted if the previous
 // renderer sends a FrameNavigate message just before being told to stop.
@@ -1392,45 +1296,35 @@
 // Test that NavigationEntries have the correct page state after going
 // forward and back.  Prevents regression for bug 1116137.
 TEST_F(WebContentsImplTest, NavigationEntryContentState) {
-  TestRenderFrameHost* orig_rfh = main_test_rfh();
 
   // Navigate to URL.  There should be no committed entry yet.
   const GURL url("http://www.google.com");
-  controller().LoadURL(
-      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  int entry_id = controller().GetPendingEntry()->GetUniqueID();
+  auto navigation =
+      NavigationSimulator::CreateBrowserInitiated(url, contents());
+  navigation->ReadyToCommit();
   NavigationEntry* entry = controller().GetLastCommittedEntry();
   EXPECT_EQ(nullptr, entry);
 
-  // Committed entry should have page state after DidNavigate.
-  orig_rfh->PrepareForCommit();
-  contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
-                              ui::PAGE_TRANSITION_TYPED);
+  // Committed entry should have page state.
+  navigation->Commit();
   entry = controller().GetLastCommittedEntry();
   EXPECT_TRUE(entry->GetPageState().IsValid());
 
   // Navigate to same site.
   const GURL url2("http://images.google.com");
-  controller().LoadURL(
-      url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  entry_id = controller().GetPendingEntry()->GetUniqueID();
+  auto navigation2 =
+      NavigationSimulator::CreateBrowserInitiated(url2, contents());
+  navigation2->ReadyToCommit();
   entry = controller().GetLastCommittedEntry();
   EXPECT_TRUE(entry->GetPageState().IsValid());
 
-  // Committed entry should have page state after DidNavigate.
-  orig_rfh->PrepareForCommit();
-  contents()->TestDidNavigate(orig_rfh, entry_id, true, url2,
-                              ui::PAGE_TRANSITION_TYPED);
+  // Committed entry should have page state.
+  navigation2->Commit();
   entry = controller().GetLastCommittedEntry();
   EXPECT_TRUE(entry->GetPageState().IsValid());
 
   // Now go back.  Committed entry should still have page state.
-  controller().GoBack();
-  entry_id = controller().GetPendingEntry()->GetUniqueID();
-  orig_rfh->PrepareForCommit();
-  contents()->TestDidNavigate(
-      orig_rfh, entry_id, false, url,
-      controller().GetPendingEntry()->GetTransitionType());
+  NavigationSimulator::GoBack(contents());
   entry = controller().GetLastCommittedEntry();
   EXPECT_TRUE(entry->GetPageState().IsValid());
 }
@@ -1443,9 +1337,7 @@
 
   // Navigate to about:blank.
   const GURL url(url::kAboutBlankURL);
-  orig_rfh->SendRendererInitiatedNavigationRequest(url, false);
-  contents()->TestDidNavigate(orig_rfh, 0, true, url,
-                              ui::PAGE_TRANSITION_TYPED);
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
 
   // Should have a page state here.
   NavigationEntry* entry = controller().GetLastCommittedEntry();
@@ -1459,14 +1351,9 @@
 
   // Navigating to a normal page should not cause a process swap.
   const GURL new_url("http://www.google.com");
-  controller().LoadURL(new_url, Referrer(),
-                       ui::PAGE_TRANSITION_TYPED, std::string());
-  entry = controller().GetPendingEntry();
-  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), new_url);
+
   EXPECT_EQ(orig_rfh, main_test_rfh());
-  orig_rfh->PrepareForCommit();
-  contents()->TestDidNavigate(orig_rfh, entry->GetUniqueID(), true, new_url,
-                              ui::PAGE_TRANSITION_TYPED);
   NavigationEntryImpl* entry_impl2 = NavigationEntryImpl::FromNavigationEntry(
       controller().GetLastCommittedEntry());
   EXPECT_EQ(site_instance_id, entry_impl2->site_instance()->GetId());
@@ -1482,12 +1369,7 @@
 
   // Navigate to a site.
   const GURL url("http://www.google.com");
-  controller().LoadURL(
-      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  int entry_id = controller().GetPendingEntry()->GetUniqueID();
-  main_test_rfh()->PrepareForCommit();
-  contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
-                              ui::PAGE_TRANSITION_TYPED);
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
   EXPECT_EQ(orig_rfh, main_test_rfh());
 
   // Toggle fullscreen mode on (as if initiated via IPC from renderer).
@@ -1500,13 +1382,7 @@
 
   // Navigate to a new site.
   const GURL url2("http://www.yahoo.com");
-  controller().LoadURL(
-      url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  entry_id = controller().GetPendingEntry()->GetUniqueID();
-  main_test_rfh()->PrepareForCommit();
-  TestRenderFrameHost* const pending_rfh = contents()->GetPendingMainFrame();
-  contents()->TestDidNavigate(pending_rfh, entry_id, true, url2,
-                              ui::PAGE_TRANSITION_TYPED);
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url2);
 
   // Confirm fullscreen has exited.
   EXPECT_FALSE(contents()->IsFullscreenForCurrentTab());
@@ -1524,23 +1400,12 @@
 
   // Navigate to a site.
   const GURL url("http://www.google.com");
-  controller().LoadURL(
-      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  int entry_id = controller().GetPendingEntry()->GetUniqueID();
-  orig_rfh->PrepareForCommit();
-  contents()->TestDidNavigate(orig_rfh, entry_id, true, url,
-                              ui::PAGE_TRANSITION_TYPED);
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
   EXPECT_EQ(orig_rfh, main_test_rfh());
 
   // Now, navigate to another page on the same site.
   const GURL url2("http://www.google.com/search?q=kittens");
-  controller().LoadURL(
-      url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  entry_id = controller().GetPendingEntry()->GetUniqueID();
-  orig_rfh->PrepareForCommit();
-  EXPECT_FALSE(contents()->CrossProcessNavigationPending());
-  contents()->TestDidNavigate(orig_rfh, entry_id, true, url2,
-                              ui::PAGE_TRANSITION_TYPED);
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url2);
   EXPECT_EQ(orig_rfh, main_test_rfh());
 
   // Sanity-check: Confirm we're not starting out in fullscreen mode.
@@ -1556,16 +1421,9 @@
 
     // Navigate backward (or forward).
     if (i == 0)
-      controller().GoBack();
+      NavigationSimulator::GoBack(contents());
     else
-      controller().GoForward();
-    entry_id = controller().GetPendingEntry()->GetUniqueID();
-    orig_rfh->PrepareForCommit();
-    EXPECT_FALSE(contents()->CrossProcessNavigationPending());
-    EXPECT_EQ(orig_rfh, main_test_rfh());
-    contents()->TestDidNavigate(orig_rfh, entry_id, false, url,
-                                ui::PAGE_TRANSITION_FORWARD_BACK);
-    orig_rfh->SimulateNavigationStop();
+      NavigationSimulator::GoForward(contents());
 
     // Confirm fullscreen has exited.
     EXPECT_FALSE(contents()->IsFullscreenForCurrentTab());
@@ -1583,12 +1441,7 @@
 
   // Navigate to a site.
   const GURL url("http://www.google.com");
-  controller().LoadURL(
-      url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  int entry_id = controller().GetPendingEntry()->GetUniqueID();
-  main_test_rfh()->PrepareForCommit();
-  contents()->TestDidNavigate(main_test_rfh(), entry_id, true,
-                              url, ui::PAGE_TRANSITION_TYPED);
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url);
 
   // Toggle fullscreen mode on (as if initiated via IPC from renderer).
   EXPECT_FALSE(contents()->IsFullscreenForCurrentTab());
@@ -1619,7 +1472,7 @@
        ShowInterstitialFromBrowserWithNewNavigationDontProceed) {
   // Navigate to a page.
   GURL url1("http://www.google.com");
-  NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url1);
   EXPECT_EQ(1, controller().GetEntryCount());
 
   // Initiate a browser navigation that will trigger the interstitial.
@@ -1765,7 +1618,7 @@
        ShowInterstitialFromBrowserNewNavigationProceed) {
   // Navigate to a page.
   GURL url1("http://www.google.com");
-  NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url1);
   EXPECT_EQ(1, controller().GetEntryCount());
 
   // Initiate a browser navigation that will trigger the interstitial
@@ -1946,7 +1799,7 @@
 
   // While interstitial showing, navigate to a new URL.
   const GURL url2("http://www.yahoo.com");
-  NavigationSimulator::NavigateAndCommitFromDocument(url2, main_test_rfh());
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url2);
 
   EXPECT_EQ(TestInterstitialPage::CANCELED, state);
 
@@ -1958,7 +1811,7 @@
 TEST_F(WebContentsImplTest, ShowInterstitialThenGoBack) {
   // Navigate to a page so we have a navigation entry in the controller.
   GURL url1("http://www.google.com");
-  NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url1);
   EXPECT_EQ(1, controller().GetEntryCount());
 
   // Show interstitial.
@@ -1998,7 +1851,7 @@
 TEST_F(WebContentsImplTest, ShowInterstitialCrashRendererThenGoBack) {
   // Navigate to a page so we have a navigation entry in the controller.
   GURL url1("http://www.google.com");
-  NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url1);
   EXPECT_EQ(1, controller().GetEntryCount());
   NavigationEntry* entry = controller().GetLastCommittedEntry();
 
@@ -2040,7 +1893,7 @@
 TEST_F(WebContentsImplTest, ShowInterstitialCrashRendererThenNavigate) {
   // Navigate to a page so we have a navigation entry in the controller.
   GURL url1("http://www.google.com");
-  NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url1);
   EXPECT_EQ(1, controller().GetEntryCount());
 
   // Show interstitial.
@@ -2120,7 +1973,7 @@
 TEST_F(WebContentsImplTest, CreateInterstitialForClosingTab) {
   // Navigate to a page.
   GURL url1("http://www.google.com");
-  NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url1);
   EXPECT_EQ(1, controller().GetEntryCount());
 
   // Initiate a browser navigation that will trigger an interstitial.
@@ -2170,7 +2023,7 @@
 TEST_F(WebContentsImplTest, TabNavigationDoesntRaceInterstitial) {
   // Navigate to a page.
   GURL url1("http://www.google.com");
-  NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url1);
   EXPECT_EQ(1, controller().GetEntryCount());
 
   // Initiate a browser navigation that will trigger an interstitial.
@@ -2215,7 +2068,7 @@
 TEST_F(WebContentsImplTest, ShowInterstitialProceedMultipleCommands) {
   // Navigate to a page so we have a navigation entry in the controller.
   GURL url1("http://www.google.com");
-  NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url1);
   EXPECT_EQ(1, controller().GetEntryCount());
 
   // Show an interstitial.
@@ -2251,8 +2104,7 @@
 TEST_F(WebContentsImplTest, ShowInterstitialOnInterstitial) {
   // Navigate to a page so we have a navigation entry in the controller.
   GURL start_url("http://www.google.com");
-  NavigationSimulator::NavigateAndCommitFromDocument(start_url,
-                                                     main_test_rfh());
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), start_url);
   EXPECT_EQ(1, controller().GetEntryCount());
 
   // Show an interstitial.
@@ -2307,8 +2159,7 @@
 TEST_F(WebContentsImplTest, ShowInterstitialProceedShowInterstitial) {
   // Navigate to a page so we have a navigation entry in the controller.
   GURL start_url("http://www.google.com");
-  NavigationSimulator::NavigateAndCommitFromDocument(start_url,
-                                                     main_test_rfh());
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), start_url);
   EXPECT_EQ(1, controller().GetEntryCount());
 
   // Show an interstitial.
@@ -2529,13 +2380,7 @@
   const GURL kGURL(kUrl);
 
   // Start a navigation to a page
-  contents()->GetController().LoadURL(
-      kGURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
-  int entry_id = controller().GetPendingEntry()->GetUniqueID();
-  main_test_rfh()->PrepareForCommit();
-  // DidNavigate from the page
-  contents()->TestDidNavigate(main_test_rfh(), entry_id, true,
-                              kGURL, ui::PAGE_TRANSITION_TYPED);
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), kGURL);
 
   // Simulate showing an interstitial while the page is showing.
   TestInterstitialPage::InterstitialState state =
@@ -2562,7 +2407,7 @@
 TEST_F(WebContentsImplTest, CopyStateFromAndPruneSourceInterstitial) {
   // Navigate to a page.
   GURL url1("http://www.google.com");
-  NavigationSimulator::NavigateAndCommitFromDocument(url1, main_test_rfh());
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url1);
   EXPECT_EQ(1, controller().GetEntryCount());
 
   // Initiate a browser navigation that will trigger the interstitial
@@ -3727,19 +3572,20 @@
 }  // namespace
 
 TEST_F(WebContentsImplTest, ResetJavaScriptDialogOnUserNavigate) {
+  const GURL kUrl("http://www.google.com");
+  const GURL kUrl2("http://www.google.com/sub");
   TestJavaScriptDialogManager dialog_manager;
   contents()->SetJavaScriptDialogManagerForTesting(&dialog_manager);
 
   // A user-initiated navigation.
-  contents()->TestDidNavigate(main_test_rfh(), 0, true,
-                              GURL("about:whatever"),
-                              ui::PAGE_TRANSITION_TYPED);
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), kUrl);
   EXPECT_EQ(1u, dialog_manager.reset_count());
 
   // An automatic navigation.
-  main_test_rfh()->SendNavigateWithModificationCallback(
-      0, true, GURL(url::kAboutBlankURL), base::Bind(SetAsNonUserGesture));
-
+  auto navigation =
+      NavigationSimulator::CreateRendererInitiated(kUrl2, main_test_rfh());
+  navigation->SetHasUserGesture(false);
+  navigation->Commit();
   EXPECT_EQ(1u, dialog_manager.reset_count());
 
   contents()->SetJavaScriptDialogManagerForTesting(nullptr);
diff --git a/content/browser/webauth/webauth_browsertest.cc b/content/browser/webauth/webauth_browsertest.cc
index 91aa5f7..36fff588 100644
--- a/content/browser/webauth/webauth_browsertest.cc
+++ b/content/browser/webauth/webauth_browsertest.cc
@@ -163,13 +163,14 @@
   ~ClosureExecutorBeforeNavigationCommit() override = default;
 
  protected:
-  void WillDispatchDidCommitProvisionalLoad(
+  bool WillDispatchDidCommitProvisionalLoad(
       RenderFrameHost* render_frame_host,
       ::FrameHostMsg_DidCommitProvisionalLoad_Params* params,
       service_manager::mojom::InterfaceProviderRequest*
           interface_provider_request) override {
     if (closure_)
       std::move(closure_).Run();
+    return true;
   }
 
  private:
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index 5e78516..01b032b 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -261,8 +261,6 @@
     "service_worker/service_worker_loader_helpers.cc",
     "service_worker/service_worker_loader_helpers.h",
     "service_worker/service_worker_messages.h",
-    "service_worker/service_worker_provider_host_info.cc",
-    "service_worker/service_worker_provider_host_info.h",
     "service_worker/service_worker_types.cc",
     "service_worker/service_worker_types.h",
     "service_worker/service_worker_utils.cc",
diff --git a/content/common/service_worker/README.md b/content/common/service_worker/README.md
new file mode 100644
index 0000000..b31d887
--- /dev/null
+++ b/content/common/service_worker/README.md
@@ -0,0 +1,5 @@
+[content/browser/service_worker]: /content/browser/service_worker/README.md
+
+Common process code for service workers.
+
+See the main service worker documentation in [content/browser/service_worker].
diff --git a/content/common/service_worker/service_worker_provider.mojom b/content/common/service_worker/service_worker_provider.mojom
index 14b56e4..3befe08 100644
--- a/content/common/service_worker/service_worker_provider.mojom
+++ b/content/common/service_worker/service_worker_provider.mojom
@@ -51,16 +51,46 @@
   service_manager.mojom.InterfaceProvider interface_provider;
 };
 
-// Sent from the renderer to the browser process. Contains parameters that
-// describe a browser-side provider host.
-// See also comments in
-// content/common/service_worker/service_worker_provider_host_info.h.
+// Describes a browser-side provider host. See
+// content::ServiceWorkerProviderHost.
 struct ServiceWorkerProviderHostInfo {
+  // |provider_id| may be browser-assigned or renderer-assigned.
+  // Browser-assigned ids are unique among all providers. Renderer-assigned ids
+  // are unique among providers in a given renderer process. Most providers have
+  // browser-assigned ids. The exceptions are about:blank iframes, and shared
+  // workers (in the non-S13nServiceWorker case).
   int32 provider_id;
+
+  // When this provider is created for a document, |route_id| is the frame ID of
+  // it. Otherwise |route_id| is MSG_ROUTING_NONE.
   int32 route_id;
+
+  // This identifies whether this provider is for a service worker or for a
+  // service worker client (Documents and Shared Workers).
   blink.mojom.ServiceWorkerProviderType type;
+
+  // |is_parent_frame_secure| is false if the provider is created for a document
+  // whose parent frame is not secure from the point of view of the document;
+  // that is, blink::WebFrame::canHaveSecureChild() returns false. This doesn't
+  // mean the document is necessarily an insecure context, because the document
+  // may have a URL whose scheme is granted an exception that allows bypassing
+  // the ancestor secure context check. See the comment in
+  // blink::Document::isSecureContextImpl for more details. If the provider is
+  // not created for a document, or the document does not have a parent frame,
+  // is_parent_frame_secure| is true.
   bool is_parent_frame_secure;
+
+  // Mojo endpoint to send a message from the renderer to the browser. This
+  // will be associated with ServiceWorkerDisptacherHost. |host_request| should
+  // be valid when ServiceWorkerProviderHostInfo is passed to any Mojo method.
+  // After used to create the ServiceWorkerProviderHost, this will be invalid.
   associated ServiceWorkerContainerHost& host_request;
+
+  // Mojo endpoint to send a message from the browser to the renderer. This
+  // will be associated with ServiceWorkerDispatcherHost. |client_ptr_info|
+  // should be valid when ServiceWorkerProviderHostInfo is passed to any Mojo
+  // method.
+  // After used to create the ServiceWorkerProviderHost, this will be invalid.
   associated ServiceWorkerContainer client_ptr_info;
 };
 
diff --git a/content/common/service_worker/service_worker_provider.typemap b/content/common/service_worker/service_worker_provider.typemap
deleted file mode 100644
index 757d4a7..0000000
--- a/content/common/service_worker/service_worker_provider.typemap
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2017 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-mojom = "//content/common/service_worker/service_worker_provider.mojom"
-public_headers =
-    [ "//content/common/service_worker/service_worker_provider_host_info.h" ]
-traits_headers = [ "//content/common/service_worker/service_worker_provider_struct_traits.h" ]
-sources = [
-  "//content/common/service_worker/service_worker_provider_struct_traits.cc",
-]
-type_mappings = [ "content.mojom.ServiceWorkerProviderHostInfo=::content::ServiceWorkerProviderHostInfo[move_only]" ]
diff --git a/content/common/service_worker/service_worker_provider_host_info.cc b/content/common/service_worker/service_worker_provider_host_info.cc
deleted file mode 100644
index f387c1b5..0000000
--- a/content/common/service_worker/service_worker_provider_host_info.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/service_worker/service_worker_provider_host_info.h"
-
-#include "ipc/ipc_message.h"
-
-namespace content {
-
-namespace {
-
-void SetDefaultValues(ServiceWorkerProviderHostInfo* info) {
-  info->provider_id = kInvalidServiceWorkerProviderId;
-  info->route_id = MSG_ROUTING_NONE;
-  info->type = blink::mojom::ServiceWorkerProviderType::kUnknown;
-  info->is_parent_frame_secure = false;
-}
-
-}  // namespace
-
-ServiceWorkerProviderHostInfo::ServiceWorkerProviderHostInfo()
-    : provider_id(kInvalidServiceWorkerProviderId),
-      route_id(MSG_ROUTING_NONE),
-      type(blink::mojom::ServiceWorkerProviderType::kUnknown),
-      is_parent_frame_secure(false) {}
-
-ServiceWorkerProviderHostInfo::ServiceWorkerProviderHostInfo(
-    ServiceWorkerProviderHostInfo&& other)
-    : provider_id(other.provider_id),
-      route_id(other.route_id),
-      type(other.type),
-      is_parent_frame_secure(other.is_parent_frame_secure),
-      host_request(std::move(other.host_request)),
-      client_ptr_info(std::move(other.client_ptr_info)) {
-  SetDefaultValues(&other);
-}
-
-ServiceWorkerProviderHostInfo::ServiceWorkerProviderHostInfo(
-    ServiceWorkerProviderHostInfo&& other,
-    mojom::ServiceWorkerContainerHostAssociatedRequest host_request,
-    mojom::ServiceWorkerContainerAssociatedPtrInfo client_ptr_info)
-    : provider_id(other.provider_id),
-      route_id(other.route_id),
-      type(other.type),
-      is_parent_frame_secure(other.is_parent_frame_secure),
-      host_request(std::move(host_request)),
-      client_ptr_info(std::move(client_ptr_info)) {
-  DCHECK(!other.host_request.is_pending());
-  DCHECK(!other.client_ptr_info.is_valid());
-  SetDefaultValues(&other);
-}
-
-ServiceWorkerProviderHostInfo::ServiceWorkerProviderHostInfo(
-    int provider_id,
-    int route_id,
-    blink::mojom::ServiceWorkerProviderType type,
-    bool is_parent_frame_secure)
-    : provider_id(provider_id),
-      route_id(route_id),
-      type(type),
-      is_parent_frame_secure(is_parent_frame_secure) {}
-
-ServiceWorkerProviderHostInfo::~ServiceWorkerProviderHostInfo() {}
-
-ServiceWorkerProviderHostInfo& ServiceWorkerProviderHostInfo::operator=(
-    ServiceWorkerProviderHostInfo&& other) {
-  provider_id = other.provider_id;
-  route_id = other.route_id;
-  type = other.type;
-  is_parent_frame_secure = other.is_parent_frame_secure;
-
-  SetDefaultValues(&other);
-  return *this;
-}
-
-}  // namespace content
diff --git a/content/common/service_worker/service_worker_provider_host_info.h b/content/common/service_worker/service_worker_provider_host_info.h
deleted file mode 100644
index d7ebeb3..0000000
--- a/content/common/service_worker/service_worker_provider_host_info.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_HOST_INFO_H_
-#define CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_HOST_INFO_H_
-
-#include "content/common/service_worker/service_worker_container.mojom.h"
-#include "content/common/service_worker/service_worker_types.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_provider_type.mojom.h"
-
-namespace content {
-
-// ServiceWorkerProviderHostInfo contains params for creating a
-// ServiceWorkerProviderHost.
-// mojom::ServiceWorkerProviderHostInfo is mapped to this struct.
-struct CONTENT_EXPORT ServiceWorkerProviderHostInfo {
-  ServiceWorkerProviderHostInfo();
-  ServiceWorkerProviderHostInfo(ServiceWorkerProviderHostInfo&& other);
-  ServiceWorkerProviderHostInfo(
-      ServiceWorkerProviderHostInfo&& other,
-      mojom::ServiceWorkerContainerHostAssociatedRequest host_request,
-      mojom::ServiceWorkerContainerAssociatedPtrInfo client_ptr_info);
-  ServiceWorkerProviderHostInfo(int provider_id,
-                                int route_id,
-                                blink::mojom::ServiceWorkerProviderType type,
-                                bool is_parent_frame_secure);
-  ~ServiceWorkerProviderHostInfo();
-
-  ServiceWorkerProviderHostInfo& operator=(
-      ServiceWorkerProviderHostInfo&& other);
-
-  // This is unique within its child process except for PlzNavigate. When
-  // PlzNavigate is on, |provider_id| is managed on the browser process and it
-  // will be unique among all of providers.
-  int provider_id;
-
-  // When this provider is created for a document, |route_id| is the frame ID of
-  // it. Otherwise |route_id| is MSG_ROUTING_NONE.
-  int route_id;
-
-  // This identifies whether this provider is for a service worker or for a
-  // service worker client (Documents and Shared Workers).
-  blink::mojom::ServiceWorkerProviderType type;
-
-  // |is_parent_frame_secure| is false if the provider is created for a document
-  // whose parent frame is not secure from the point of view of the document;
-  // that is, blink::WebFrame::canHaveSecureChild() returns false. This doesn't
-  // mean the document is necessarily an insecure context, because the document
-  // may have a URL whose scheme is granted an exception that allows bypassing
-  // the ancestor secure context check. See the comment in
-  // blink::Document::isSecureContextImpl for more details. If the provider is
-  // not created for a document, or the document does not have a parent frame,
-  // is_parent_frame_secure| is true.
-  bool is_parent_frame_secure;
-
-  // Mojo endpoint to send a message from the renderer to the browser. This
-  // will be associated with ServiceWorkerDisptacherHost. |host_request| should
-  // be valid when ServiceWorkerProviderHostInfo is passed to any Mojo method.
-  // After used to create the ServiceWorkerProviderHost, this will be invalid.
-  mojom::ServiceWorkerContainerHostAssociatedRequest host_request;
-
-  // Mojo endpoint to send a message from the browser to the renderer. This
-  // will be associated with ServiceWorkerDispatcherHost. |client_ptr_info|
-  // should be valid when ServiceWorkerProviderHostInfo is passed to any Mojo
-  // method.
-  // After used to create the ServiceWorkerProviderHost, this will be invalid.
-  mojom::ServiceWorkerContainerAssociatedPtrInfo client_ptr_info;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProviderHostInfo);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_HOST_INFO_H_
diff --git a/content/common/service_worker/service_worker_provider_struct_traits.cc b/content/common/service_worker/service_worker_provider_struct_traits.cc
deleted file mode 100644
index 59833f8..0000000
--- a/content/common/service_worker/service_worker_provider_struct_traits.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/service_worker/service_worker_provider_struct_traits.h"
-
-namespace mojo {
-
-bool StructTraits<content::mojom::ServiceWorkerProviderHostInfoDataView,
-                  content::ServiceWorkerProviderHostInfo>::
-    Read(content::mojom::ServiceWorkerProviderHostInfoDataView in,
-         content::ServiceWorkerProviderHostInfo* out) {
-  if (!in.ReadType(&out->type))
-    return false;
-  out->provider_id = in.provider_id();
-  out->route_id = in.route_id();
-  out->is_parent_frame_secure = in.is_parent_frame_secure();
-  out->host_request = in.TakeHostRequest<
-      content::mojom::ServiceWorkerContainerHostAssociatedRequest>();
-  out->client_ptr_info = in.TakeClientPtrInfo<
-      content::mojom::ServiceWorkerContainerAssociatedPtrInfo>();
-  return true;
-}
-
-}  // namespace mojo
diff --git a/content/common/service_worker/service_worker_provider_struct_traits.h b/content/common/service_worker/service_worker_provider_struct_traits.h
deleted file mode 100644
index 2031620..0000000
--- a/content/common/service_worker/service_worker_provider_struct_traits.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_STRUCT_TRAITS_H_
-#define CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_STRUCT_TRAITS_H_
-
-#include "content/common/service_worker/service_worker_provider.mojom.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_provider_type.mojom.h"
-
-namespace mojo {
-
-template <>
-struct StructTraits<content::mojom::ServiceWorkerProviderHostInfoDataView,
-                    content::ServiceWorkerProviderHostInfo> {
-  static int32_t provider_id(
-      const content::ServiceWorkerProviderHostInfo& info) {
-    return info.provider_id;
-  }
-
-  static int32_t route_id(const content::ServiceWorkerProviderHostInfo& info) {
-    return info.route_id;
-  }
-
-  static blink::mojom::ServiceWorkerProviderType type(
-      const content::ServiceWorkerProviderHostInfo& info) {
-    return info.type;
-  }
-
-  static bool is_parent_frame_secure(
-      const content::ServiceWorkerProviderHostInfo& info) {
-    return info.is_parent_frame_secure;
-  }
-
-  static content::mojom::ServiceWorkerContainerHostAssociatedRequest&
-  host_request(content::ServiceWorkerProviderHostInfo& info) {
-    return info.host_request;
-  }
-
-  static content::mojom::ServiceWorkerContainerAssociatedPtrInfo&
-  client_ptr_info(content::ServiceWorkerProviderHostInfo& info) {
-    return info.client_ptr_info;
-  }
-
-  static bool Read(content::mojom::ServiceWorkerProviderHostInfoDataView in,
-                   content::ServiceWorkerProviderHostInfo* out);
-};
-
-}  // namespace mojo
-
-#endif  // CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_STRUCT_TRAITS_H_
diff --git a/content/common/typemaps.gni b/content/common/typemaps.gni
index f1da0657..85870f8 100644
--- a/content/common/typemaps.gni
+++ b/content/common/typemaps.gni
@@ -18,7 +18,6 @@
   "//content/common/service_worker/service_worker_event_dispatcher.typemap",
   "//content/common/service_worker/service_worker_fetch_request.typemap",
   "//content/common/service_worker/service_worker_fetch_response.typemap",
-  "//content/common/service_worker/service_worker_provider.typemap",
   "//content/common/url_loader_factory_bundle.typemap",
   "//content/common/web_preferences.typemap",
   "//content/common/media/media_session.typemap",
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index 93601ed..ac20bf65b 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -118,6 +118,11 @@
   return false;
 }
 
+bool ContentBrowserClient::IsWebUIAllowedToMakeNetworkRequests(
+    const url::Origin& origin) {
+  return false;
+}
+
 bool ContentBrowserClient::IsHandledURL(const GURL& url) {
   return false;
 }
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index 9ada955..32b99c73 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -306,6 +306,13 @@
   // chrome://) URLs are logged. Returns whether the URL was actually logged.
   virtual bool LogWebUIUrl(const GURL& web_ui_url) const;
 
+  // http://crbug.com/829412
+  // Renderers with WebUI bindings shouldn't make http(s) requests for security
+  // reasons (e.g. to avoid malicious responses being able to run code in
+  // priviliged renderers). Fix these webui's to make requests through C++
+  // code instead.
+  virtual bool IsWebUIAllowedToMakeNetworkRequests(const url::Origin& origin);
+
   // Returns whether a specified URL is handled by the embedder's internal
   // protocol handlers.
   virtual bool IsHandledURL(const GURL& url);
diff --git a/content/public/browser/network_connection_tracker.cc b/content/public/browser/network_connection_tracker.cc
index 1b1612e..41e7327 100644
--- a/content/public/browser/network_connection_tracker.cc
+++ b/content/public/browser/network_connection_tracker.cc
@@ -35,17 +35,30 @@
 
 }  // namespace
 
-NetworkConnectionTracker::NetworkConnectionTracker(
-    base::RepeatingCallback<network::mojom::NetworkService*()> callback)
-    : get_network_service_callback_(callback),
-      task_runner_(base::ThreadTaskRunnerHandle::Get()),
+NetworkConnectionTracker::NetworkConnectionTracker()
+    : task_runner_(base::ThreadTaskRunnerHandle::Get()),
       connection_type_(kConnectionTypeInvalid),
       network_change_observer_list_(
           new base::ObserverListThreadSafe<NetworkConnectionObserver>(
               base::ObserverListPolicy::EXISTING_ONLY)),
-      binding_(this) {
-  Initialize();
-  DCHECK(binding_.is_bound());
+      binding_(this) {}
+
+void NetworkConnectionTracker::Initialize(
+    network::mojom::NetworkService* network_service) {
+  DCHECK(!binding_.is_bound());
+  DCHECK(network_service);
+  // Get NetworkChangeManagerPtr.
+  network::mojom::NetworkChangeManagerPtr manager_ptr;
+  network::mojom::NetworkChangeManagerRequest request(
+      mojo::MakeRequest(&manager_ptr));
+  network_service->GetNetworkChangeManager(std::move(request));
+
+  // Request notification from NetworkChangeManagerPtr.
+  network::mojom::NetworkChangeManagerClientPtr client_ptr;
+  network::mojom::NetworkChangeManagerClientRequest client_request(
+      mojo::MakeRequest(&client_ptr));
+  binding_.Bind(std::move(client_request));
+  manager_ptr->RequestNotifications(std::move(client_ptr));
 }
 
 NetworkConnectionTracker::~NetworkConnectionTracker() {
@@ -112,13 +125,6 @@
   network_change_observer_list_->RemoveObserver(observer);
 }
 
-NetworkConnectionTracker::NetworkConnectionTracker()
-    : connection_type_(kConnectionTypeInvalid),
-      network_change_observer_list_(
-          new base::ObserverListThreadSafe<NetworkConnectionObserver>(
-              base::ObserverListPolicy::EXISTING_ONLY)),
-      binding_(this) {}
-
 void NetworkConnectionTracker::OnInitialConnectionType(
     network::mojom::ConnectionType type) {
   base::AutoLock lock(lock_);
@@ -138,40 +144,4 @@
       FROM_HERE, &NetworkConnectionObserver::OnConnectionChanged, type);
 }
 
-void NetworkConnectionTracker::Initialize() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(!binding_.is_bound());
-
-  network::mojom::NetworkService* network_service =
-      get_network_service_callback_.Run();
-
-  // Get NetworkChangeManagerPtr.
-  network::mojom::NetworkChangeManagerPtr manager_ptr;
-  network::mojom::NetworkChangeManagerRequest request(
-      mojo::MakeRequest(&manager_ptr));
-  network_service->GetNetworkChangeManager(std::move(request));
-
-  // Request notification from NetworkChangeManagerPtr.
-  network::mojom::NetworkChangeManagerClientPtr client_ptr;
-  network::mojom::NetworkChangeManagerClientRequest client_request(
-      mojo::MakeRequest(&client_ptr));
-  binding_.Bind(std::move(client_request));
-  manager_ptr->RequestNotifications(std::move(client_ptr));
-
-  // base::Unretained is safe as |binding_| is owned by |this|.
-  binding_.set_connection_error_handler(base::BindRepeating(
-      &NetworkConnectionTracker::HandleNetworkServicePipeBroken,
-      base::Unretained(this)));
-}
-
-void NetworkConnectionTracker::HandleNetworkServicePipeBroken() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  binding_.Close();
-  // Reset |connection_type_| to invalid, so future GetConnectionType() can be
-  // delayed after network service has restarted, and that there isn't an
-  // incorrectly cached state.
-  base::subtle::NoBarrier_Store(&connection_type_, kConnectionTypeInvalid);
-  Initialize();
-}
-
 }  // namespace content
diff --git a/content/public/browser/network_connection_tracker.h b/content/public/browser/network_connection_tracker.h
index 86746d52..0e40cba 100644
--- a/content/public/browser/network_connection_tracker.h
+++ b/content/public/browser/network_connection_tracker.h
@@ -13,7 +13,6 @@
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/observer_list_threadsafe.h"
-#include "base/sequence_checker.h"
 #include "base/synchronization/lock.h"
 #include "content/common/content_export.h"
 #include "mojo/public/cpp/bindings/binding.h"
@@ -47,14 +46,18 @@
     DISALLOW_COPY_AND_ASSIGN(NetworkConnectionObserver);
   };
 
-  // Constructs a NetworkConnectionTracker. |callback| should return the network
-  // service that is in use. NetworkConnectionTracker does not need to be
-  // destroyed before the network service.
-  explicit NetworkConnectionTracker(
-      base::RepeatingCallback<network::mojom::NetworkService*()> callback);
+  NetworkConnectionTracker();
 
   ~NetworkConnectionTracker() override;
 
+  // Starts listening for connection notifications from |network_service|.
+  // Observers may be added and GetConnectionType called, but no network
+  // information will be provided until this method is called. For unit tests,
+  // this class can be subclassed, and OnInitialConnectionType /
+  // OnNetworkChanged may be called directly, instead of providing a
+  // NetworkService.
+  void Initialize(network::mojom::NetworkService* network_service);
+
   // If connection type can be retrieved synchronously, returns true and |type|
   // will contain the current connection type; Otherwise, returns false and
   // does not modify |type|, in which case, |callback| will be called on the
@@ -82,9 +85,6 @@
   void RemoveNetworkConnectionObserver(NetworkConnectionObserver* observer);
 
  protected:
-  // Constructor used in testing to mock out network service.
-  NetworkConnectionTracker();
-
   // NetworkChangeManagerClient implementation. Protected for testing.
   void OnInitialConnectionType(network::mojom::ConnectionType type) override;
   void OnNetworkChanged(network::mojom::ConnectionType type) override;
@@ -92,24 +92,6 @@
  private:
   FRIEND_TEST_ALL_PREFIXES(NetworkGetConnectionTest,
                            GetConnectionTypeOnDifferentThread);
-
-  // Starts listening for connection change notifications from
-  // |network_service|. Observers may be added and GetConnectionType called, but
-  // no network information will be provided until this method is called. For
-  // unit tests, this class can be subclassed, and OnInitialConnectionType /
-  // OnNetworkChanged may be called directly, instead of providing a
-  // NetworkService.
-  void Initialize();
-
-  // Serves as a connection error handler, and is invoked when network service
-  // restarts.
-  void HandleNetworkServicePipeBroken();
-
-  // Callback to get the current network service raw mojo pointer. This is to
-  // ensure that |this| can survive crashes and restarts of network service.
-  const base::RepeatingCallback<network::mojom::NetworkService*()>
-      get_network_service_callback_;
-
   // The task runner that |this| lives on.
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
 
@@ -128,10 +110,6 @@
 
   mojo::Binding<network::mojom::NetworkChangeManagerClient> binding_;
 
-  // Only the initialization and re-initialization of |this| are required to
-  // be bound to the same sequence.
-  SEQUENCE_CHECKER(sequence_checker_);
-
   DISALLOW_COPY_AND_ASSIGN(NetworkConnectionTracker);
 };
 
diff --git a/content/public/browser/network_connection_tracker_unittest.cc b/content/public/browser/network_connection_tracker_unittest.cc
index 65689197f..cd86f1d 100644
--- a/content/public/browser/network_connection_tracker_unittest.cc
+++ b/content/public/browser/network_connection_tracker_unittest.cc
@@ -138,15 +138,12 @@
     network_service_ =
         network::NetworkService::Create(std::move(network_service_request),
                                         /*netlog=*/nullptr);
-    tracker_ = std::make_unique<NetworkConnectionTracker>(
-        base::BindRepeating(&NetworkConnectionTrackerTest::network_service,
-                            base::Unretained(this)));
+    tracker_ = std::make_unique<NetworkConnectionTracker>();
+    tracker_->Initialize(network_service_.get());
     observer_ = std::make_unique<TestNetworkConnectionObserver>(tracker_.get());
   }
 
-  network::mojom::NetworkService* network_service() {
-    return network_service_.get();
-  }
+  network::NetworkService* network_service() { return network_service_.get(); }
 
   NetworkConnectionTracker* network_connection_tracker() {
     return tracker_.get();
@@ -252,24 +249,13 @@
 // Tests that GetConnectionType returns false and doesn't modify its |type|
 // parameter when the connection type is unavailable.
 TEST_F(NetworkConnectionTrackerTest, GetConnectionTypeUnavailable) {
-  // Returns a dummy network service that has not been initialized.
-  network::mojom::NetworkServicePtr* network_service_ptr =
-      new network::mojom::NetworkServicePtr;
+  auto tracker = std::make_unique<NetworkConnectionTracker>();
 
-  network::mojom::NetworkServiceRequest request =
-      mojo::MakeRequest(network_service_ptr);
-  base::RepeatingCallback<network::mojom::NetworkService*()> callback =
-      base::BindRepeating(
-          [](network::mojom::NetworkService* service) { return service; },
-          base::Unretained(network_service_ptr->get()));
-
-  auto tracker = std::make_unique<NetworkConnectionTracker>(callback);
   auto type = network::mojom::ConnectionType::CONNECTION_3G;
   bool sync = tracker->GetConnectionType(&type, base::DoNothing());
 
   EXPECT_FALSE(sync);
   EXPECT_EQ(type, network::mojom::ConnectionType::CONNECTION_3G);
-  delete network_service_ptr;
 }
 
 // Tests GetConnectionType() on a different thread.
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
index 6de4b0b3..cac1283 100644
--- a/content/public/test/browser_test_utils.cc
+++ b/content/public/test/browser_test_utils.cc
@@ -572,7 +572,7 @@
   void WebContentsDestroyed() override { delete this; }
 
  protected:
-  void WillDispatchDidCommitProvisionalLoad(
+  bool WillDispatchDidCommitProvisionalLoad(
       RenderFrameHost* render_frame_host,
       ::FrameHostMsg_DidCommitProvisionalLoad_Params* params,
       service_manager::mojom::InterfaceProviderRequest*
@@ -581,6 +581,7 @@
       params->url = new_url_;
       params->origin = new_origin_;
     }
+    return true;
   }
 
  private:
diff --git a/content/public/test/navigation_simulator.cc b/content/public/test/navigation_simulator.cc
index 8e3c55c3..4c0b09d 100644
--- a/content/public/test/navigation_simulator.cc
+++ b/content/public/test/navigation_simulator.cc
@@ -501,6 +501,11 @@
   RenderFrameHostImpl* previous_rfh =
       render_frame_host_->frame_tree_node()->current_frame_host();
 
+  if (!same_document_) {
+    render_frame_host_->SimulateCommitProcessed(handle_->GetNavigationId(),
+                                                true /* was_successful */);
+  }
+
   FrameHostMsg_DidCommitProvisionalLoad_Params params;
   params.nav_entry_id = handle_->pending_nav_entry_id();
   params.url = navigation_url_;
@@ -558,7 +563,8 @@
 
   CHECK(render_frame_host_) << "NavigationSimulator::AbortCommit can only be "
                                "called for navigations that commit.";
-  render_frame_host_->AbortNavigationCommit();
+  render_frame_host_->SimulateCommitProcessed(handle_->GetNavigationId(),
+                                              false /* was_successful */);
 
   state_ = FINISHED;
   CHECK_EQ(1, num_did_finish_navigation_called_);
@@ -631,6 +637,9 @@
   RenderFrameHostImpl* previous_rfh =
       render_frame_host_->frame_tree_node()->current_frame_host();
 
+  render_frame_host_->SimulateCommitProcessed(handle_->GetNavigationId(),
+                                              true /* was_successful */);
+
   GURL error_url = GURL(kUnreachableWebDataURL);
   render_frame_host_->OnMessageReceived(FrameHostMsg_DidStartProvisionalLoad(
       render_frame_host_->GetRoutingID(), error_url, std::vector<GURL>(),
diff --git a/content/public/test/test_renderer_host.cc b/content/public/test/test_renderer_host.cc
index 942ff89..d6c4b4d4 100644
--- a/content/public/test/test_renderer_host.cc
+++ b/content/public/test/test_renderer_host.cc
@@ -11,7 +11,10 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "content/browser/compositor/test/test_image_transport_factory.h"
+#include "content/browser/frame_host/frame_tree_node.h"
 #include "content/browser/frame_host/navigation_entry_impl.h"
+#include "content/browser/frame_host/navigation_handle_impl.h"
+#include "content/browser/frame_host/navigation_request.h"
 #include "content/browser/renderer_host/render_view_host_factory.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/browser/site_instance_impl.h"
@@ -78,30 +81,33 @@
   // place to handle this simulation. Unfortunately, it is not trivial to make
   // that change, so for now we have this extra simulation for
   // non-TestWebContents.
-  RenderFrameHost* old_rfh = controller->GetWebContents()->GetMainFrame();
-  TestRenderFrameHost* old_rfh_tester =
-      static_cast<TestRenderFrameHost*>(old_rfh);
-  old_rfh_tester->PrepareForCommitIfNecessary();
+  TestRenderFrameHost* old_rfh = static_cast<TestRenderFrameHost*>(
+      controller->GetWebContents()->GetMainFrame());
+  NavigationRequest* request = old_rfh->frame_tree_node()->navigation_request();
+  old_rfh->PrepareForCommitIfNecessary();
 
   WebContentsImpl* web_contents =
       static_cast<WebContentsImpl*>(controller->GetWebContents());
-  RenderFrameHost* pending_rfh = web_contents->GetRenderManagerForTesting()
-                                     ->speculative_render_frame_host_.get();
+  TestRenderFrameHost* pending_rfh = static_cast<TestRenderFrameHost*>(
+      web_contents->GetRenderManagerForTesting()
+          ->speculative_render_frame_host_.get());
 
   // Commit on the pending_rfh, if one exists.
-  RenderFrameHost* test_rfh = pending_rfh ? pending_rfh : old_rfh;
-  RenderFrameHostTester* test_rfh_tester = For(test_rfh);
+  TestRenderFrameHost* test_rfh = pending_rfh ? pending_rfh : old_rfh;
+  if (request && !request->navigation_handle()->IsSameDocument()) {
+    test_rfh->SimulateCommitProcessed(
+        request->navigation_handle()->GetNavigationId(),
+        true /* was successful */);
+  }
 
   if (controller->GetPendingEntryIndex() >= 0) {
-    test_rfh_tester->SendNavigateWithTransition(
-        controller->GetPendingEntry()->GetUniqueID(),
-        false,
+    test_rfh->SendNavigateWithTransition(
+        controller->GetPendingEntry()->GetUniqueID(), false,
         controller->GetPendingEntry()->GetURL(),
         controller->GetPendingEntry()->GetTransitionType());
   } else {
-    test_rfh_tester->SendNavigateWithTransition(
-        controller->GetPendingEntry()->GetUniqueID(),
-        true,
+    test_rfh->SendNavigateWithTransition(
+        controller->GetPendingEntry()->GetUniqueID(), true,
         controller->GetPendingEntry()->GetURL(),
         controller->GetPendingEntry()->GetTransitionType());
   }
diff --git a/content/renderer/service_worker/service_worker_network_provider.cc b/content/renderer/service_worker/service_worker_network_provider.cc
index 9ca949a..61b529a 100644
--- a/content/renderer/service_worker/service_worker_network_provider.cc
+++ b/content/renderer/service_worker/service_worker_network_provider.cc
@@ -8,7 +8,7 @@
 #include "base/single_thread_task_runner.h"
 #include "content/common/navigation_params.h"
 #include "content/common/service_worker/service_worker_messages.h"
-#include "content/common/service_worker/service_worker_provider_host_info.h"
+#include "content/common/service_worker/service_worker_provider.mojom.h"
 #include "content/common/service_worker/service_worker_utils.h"
 #include "content/public/common/browser_side_navigation_policy.h"
 #include "content/public/common/origin_util.h"
@@ -277,14 +277,15 @@
          provider_type ==
              blink::mojom::ServiceWorkerProviderType::kForSharedWorker);
 
-  ServiceWorkerProviderHostInfo host_info(provider_id, route_id, provider_type,
-                                          is_parent_frame_secure);
+  auto host_info = mojom::ServiceWorkerProviderHostInfo::New(
+      provider_id, route_id, provider_type, is_parent_frame_secure,
+      nullptr /* host_request */, nullptr /* client_ptr_info */);
   mojom::ServiceWorkerContainerAssociatedRequest client_request =
-      mojo::MakeRequest(&host_info.client_ptr_info);
+      mojo::MakeRequest(&host_info->client_ptr_info);
   mojom::ServiceWorkerContainerHostAssociatedPtrInfo host_ptr_info;
-  host_info.host_request = mojo::MakeRequest(&host_ptr_info);
-  DCHECK(host_info.host_request.is_pending());
-  DCHECK(host_info.host_request.handle().is_valid());
+  host_info->host_request = mojo::MakeRequest(&host_ptr_info);
+  DCHECK(host_info->host_request.is_pending());
+  DCHECK(host_info->host_request.handle().is_valid());
 
   // current() may be null in tests.
   if (ChildThreadImpl::current()) {
diff --git a/content/renderer/shared_worker/embedded_shared_worker_stub.cc b/content/renderer/shared_worker/embedded_shared_worker_stub.cc
index fa7ceca..908d6a8 100644
--- a/content/renderer/shared_worker/embedded_shared_worker_stub.cc
+++ b/content/renderer/shared_worker/embedded_shared_worker_stub.cc
@@ -229,27 +229,18 @@
   }
 
   if (subresource_loaders) {
-    if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
-      // S13nServiceWorker enabled, NetworkService disabled:
-      // Clear the default factory from |subresource_loaders|, as it's the
-      // NetworkService factory.
-      subresource_loaders->default_factory_info() = nullptr;
-    }
-
     loader_factories_->Update(std::make_unique<ChildURLLoaderFactoryBundleInfo>(
                                   std::move(subresource_loaders)),
                               base::nullopt /* subresource_overrides */);
   }
 
   // It is important to understand the default factory of |loader_factories_|.
-  // Since |loader_factories_| was made from
-  // CreateDefaultURLLoaderFactoryBundle, which does not set a default factory,
-  // and |subresource_loaders|, whose default factory is the restartable
-  // NetworkService (as SharedWorkerHost sets it that way), the default factory
-  // either does not exist (when NetworkService is disabled) or is a
-  // NetworkService-backed factory with auto-reconnect. Therefore, we don't need
-  // to call CloneWithoutDefault() to bypass features like AppCache, unlike the
-  // bundle created for a frame.
+  // |loader_factories_| was made from CreateDefaultURLLoaderFactoryBundle,
+  // which does not set a default factory, and |subresource_loaders|, whose
+  // default factory is the direct network factory (as SharedWorkerHost sets it
+  // that way). Therefore, the default factory either does not exist or is the
+  // direct network factory. So we don't need to call CloneWithoutDefault() to
+  // bypass features like AppCache, unlike the bundle created for a frame.
 
   impl_->StartWorkerContext(
       url_, blink::WebString::FromUTF8(name_),
diff --git a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc
index 0cefd42..a781d9a 100644
--- a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc
+++ b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc
@@ -1360,14 +1360,6 @@
       device, identifier, BluetoothUUID(uuid), true /* is_primary */,
       false /* is_local */);
 
-  ON_CALL(*service, GetCharacteristics())
-      .WillByDefault(Invoke(service.get(),
-                            &MockBluetoothGattService::GetMockCharacteristics));
-
-  ON_CALL(*service, GetCharacteristic(_))
-      .WillByDefault(Invoke(service.get(),
-                            &MockBluetoothGattService::GetMockCharacteristic));
-
   return service;
 }
 
diff --git a/content/test/data/accessibility/event/description-change-indirect-expected-win.txt b/content/test/data/accessibility/event/description-change-indirect-expected-win.txt
index 8f0f6b73..86d03d6 100644
--- a/content/test/data/accessibility/event/description-change-indirect-expected-win.txt
+++ b/content/test/data/accessibility/event/description-change-indirect-expected-win.txt
@@ -3,5 +3,5 @@
 EVENT_OBJECT_NAMECHANGE on <h1#title> role=H1 name="oranges" level=1
 EVENT_OBJECT_REORDER on <h1#title> role=H1 name="oranges" level=1
 EVENT_OBJECT_SHOW on role=ROLE_SYSTEM_STATICTEXT name="oranges"
-IA2_EVENT_TEXT_INSERTED on <h1#title> role=H1 name="oranges" level=1 new_text={'orang' start=0 end=5}
-IA2_EVENT_TEXT_REMOVED on <h1#title> role=H1 name="oranges" level=1 old_text={'appl' start=0 end=4}
+IA2_EVENT_TEXT_INSERTED on <h1#title> role=H1 name="oranges" level=1 new_text={'oranges' start=0 end=7}
+IA2_EVENT_TEXT_REMOVED on <h1#title> role=H1 name="oranges" level=1 old_text={'apples' start=0 end=6}
diff --git a/content/test/data/accessibility/event/name-change-indirect-expected-win.txt b/content/test/data/accessibility/event/name-change-indirect-expected-win.txt
index 9004d20b..a5d175d 100644
--- a/content/test/data/accessibility/event/name-change-indirect-expected-win.txt
+++ b/content/test/data/accessibility/event/name-change-indirect-expected-win.txt
@@ -3,5 +3,5 @@
 EVENT_OBJECT_NAMECHANGE on <h1#title> role=H1 name="oranges" level=1
 EVENT_OBJECT_REORDER on <h1#title> role=H1 name="oranges" level=1
 EVENT_OBJECT_SHOW on role=ROLE_SYSTEM_STATICTEXT name="oranges"
-IA2_EVENT_TEXT_INSERTED on <h1#title> role=H1 name="oranges" level=1 new_text={'orang' start=0 end=5}
-IA2_EVENT_TEXT_REMOVED on <h1#title> role=H1 name="oranges" level=1 old_text={'appl' start=0 end=4}
+IA2_EVENT_TEXT_INSERTED on <h1#title> role=H1 name="oranges" level=1 new_text={'oranges' start=0 end=7}
+IA2_EVENT_TEXT_REMOVED on <h1#title> role=H1 name="oranges" level=1 old_text={'apples' start=0 end=6}
diff --git a/content/test/data/accessibility/event/text-changed-expected-win.txt b/content/test/data/accessibility/event/text-changed-expected-win.txt
index a590526..7ffeb922 100644
--- a/content/test/data/accessibility/event/text-changed-expected-win.txt
+++ b/content/test/data/accessibility/event/text-changed-expected-win.txt
@@ -3,6 +3,8 @@
 EVENT_OBJECT_NAMECHANGE on role=ROLE_SYSTEM_STATICTEXT name="Text modified"
 EVENT_OBJECT_SHOW on role=ROLE_SYSTEM_STATICTEXT name="Modified Para"
 IA2_EVENT_TEXT_INSERTED on <div> role=DIV name="div" new_text={'Text modified' start=0 end=13}
-IA2_EVENT_TEXT_INSERTED on <h2#h> role=H2 name="Heading" level=2 new_text={'Modified ' start=0 end=9}
-IA2_EVENT_TEXT_INSERTED on <p#p> role=P new_text={'Modified ' start=0 end=9}
+IA2_EVENT_TEXT_INSERTED on <h2#h> role=H2 name="Heading" level=2 new_text={'Modified Heading' start=0 end=16}
+IA2_EVENT_TEXT_INSERTED on <p#p> role=P new_text={'Modified Para' start=0 end=13}
 IA2_EVENT_TEXT_REMOVED on <div> role=DIV name="div" old_text={'Div' start=0 end=3}
+IA2_EVENT_TEXT_REMOVED on <h2#h> role=H2 name="Heading" level=2 old_text={'Heading' start=0 end=7}
+IA2_EVENT_TEXT_REMOVED on <p#p> role=P old_text={'Para' start=0 end=4}
\ No newline at end of file
diff --git a/content/test/data/infinite_load_1.html b/content/test/data/infinite_load_1.html
new file mode 100644
index 0000000..c95a104c
--- /dev/null
+++ b/content/test/data/infinite_load_1.html
@@ -0,0 +1 @@
+<img src="/hung">
diff --git a/content/test/data/infinite_load_2.html b/content/test/data/infinite_load_2.html
new file mode 100644
index 0000000..c95a104c
--- /dev/null
+++ b/content/test/data/infinite_load_2.html
@@ -0,0 +1 @@
+<img src="/hung">
diff --git a/content/test/did_commit_provisional_load_interceptor.cc b/content/test/did_commit_provisional_load_interceptor.cc
index e78a959..2afa7844 100644
--- a/content/test/did_commit_provisional_load_interceptor.cc
+++ b/content/test/did_commit_provisional_load_interceptor.cc
@@ -40,10 +40,11 @@
       std::unique_ptr<::FrameHostMsg_DidCommitProvisionalLoad_Params> params,
       ::service_manager::mojom::InterfaceProviderRequest
           interface_provider_request) override {
-    interceptor_->WillDispatchDidCommitProvisionalLoad(
-        rfhi_, params.get(), &interface_provider_request);
-    GetForwardingInterface()->DidCommitProvisionalLoad(
-        std::move(params), std::move(interface_provider_request));
+    if (interceptor_->WillDispatchDidCommitProvisionalLoad(
+            rfhi_, params.get(), &interface_provider_request)) {
+      GetForwardingInterface()->DidCommitProvisionalLoad(
+          std::move(params), std::move(interface_provider_request));
+    }
   }
 
  private:
diff --git a/content/test/did_commit_provisional_load_interceptor.h b/content/test/did_commit_provisional_load_interceptor.h
index 26270f5..bac23311 100644
--- a/content/test/did_commit_provisional_load_interceptor.h
+++ b/content/test/did_commit_provisional_load_interceptor.h
@@ -29,7 +29,9 @@
 
   // Called just before DidCommitProvisionalLoad with |params| and
   // |interface_provider_request| would be dispatched to |render_frame_host|.
-  virtual void WillDispatchDidCommitProvisionalLoad(
+  // Return false to cancel the dispatching of this message to
+  // |render_frame_host|.
+  virtual bool WillDispatchDidCommitProvisionalLoad(
       RenderFrameHost* render_frame_host,
       ::FrameHostMsg_DidCommitProvisionalLoad_Params* params,
       service_manager::mojom::InterfaceProviderRequest*
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc
index 3a43fe2..98a99a7 100644
--- a/content/test/test_render_frame_host.cc
+++ b/content/test/test_render_frame_host.cc
@@ -513,14 +513,6 @@
 void TestRenderFrameHost::PrepareForCommitInternal(
     const GURL& redirect_url,
     const net::HostPortPair& socket_address) {
-  if (!IsBrowserSideNavigationEnabled()) {
-    // Non PlzNavigate
-    if (is_waiting_for_beforeunload_ack())
-      SendBeforeUnloadACK(true);
-    return;
-  }
-
-  // PlzNavigate
   NavigationRequest* request = frame_tree_node_->navigation_request();
   CHECK(request);
   bool have_to_make_network_request =
@@ -571,12 +563,11 @@
   }
 }
 
-void TestRenderFrameHost::AbortNavigationCommit() {
-  if (navigation_request_) {
-    RenderFrameHostImpl::OnCrossDocumentCommitProcessed(
-        navigation_request_->navigation_handle()->GetNavigationId(),
-        blink::mojom::CommitResult::Aborted);
-  }
+void TestRenderFrameHost::SimulateCommitProcessed(int64_t navigation_id,
+                                                  bool was_successful) {
+  RenderFrameHostImpl::OnCrossDocumentCommitProcessed(
+      navigation_id, was_successful ? blink::mojom::CommitResult::Ok
+                                    : blink::mojom::CommitResult::Aborted);
 }
 
 WebBluetoothServiceImpl*
diff --git a/content/test/test_render_frame_host.h b/content/test/test_render_frame_host.h
index f03d812..be49874 100644
--- a/content/test/test_render_frame_host.h
+++ b/content/test/test_render_frame_host.h
@@ -172,9 +172,9 @@
   // interaction with the IO thread up until the response is ready to commit.
   void PrepareForCommitIfNecessary();
 
-  // Used to simulate the abort of a navigation waiting to be committed in this
-  // RenderFrameHost.
-  void AbortNavigationCommit();
+  // Used to simulate the commit of a navigation having been processed in the
+  // renderer.
+  void SimulateCommitProcessed(int64_t navigation_id, bool was_successful);
 
   // Send a message with the sandbox flags and feature policy
   void SendFramePolicy(blink::WebSandboxFlags sandbox_flags,
diff --git a/content/test/test_web_contents.cc b/content/test/test_web_contents.cc
index 54d6437..1960f17 100644
--- a/content/test/test_web_contents.cc
+++ b/content/test/test_web_contents.cc
@@ -302,6 +302,7 @@
   DCHECK(entry);
 
   TestRenderFrameHost* old_rfh = GetMainFrame();
+  NavigationRequest* request = old_rfh->frame_tree_node()->navigation_request();
 
   // PlzNavigate: the pending RenderFrameHost is not created before the
   // navigation commit, so it is necessary to simulate the IO thread response
@@ -319,11 +320,14 @@
   TestRenderFrameHost* rfh = GetPendingMainFrame();
   if (!rfh)
     rfh = old_rfh;
-  const bool browser_side_navigation = IsBrowserSideNavigationEnabled();
-  CHECK(!browser_side_navigation || rfh->is_loading() ||
-        IsRendererDebugURL(entry->GetURL()));
-  CHECK(!browser_side_navigation ||
-        !rfh->frame_tree_node()->navigation_request());
+  CHECK(rfh->is_loading() || IsRendererDebugURL(entry->GetURL()));
+  CHECK(!rfh->frame_tree_node()->navigation_request());
+
+  if (request && !request->navigation_handle()->IsSameDocument()) {
+    rfh->SimulateCommitProcessed(
+        request->navigation_handle()->GetNavigationId(),
+        true /* was successful */);
+  }
 
   rfh->SendNavigateWithTransition(entry->GetUniqueID(),
                                   GetController().GetPendingEntryIndex() == -1,
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic.h b/device/bluetooth/bluetooth_remote_gatt_characteristic.h
index 88ff19ff..1a30eec 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic.h
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic.h
@@ -7,6 +7,7 @@
 
 #include <stdint.h>
 
+#include <memory>
 #include <set>
 #include <string>
 #include <vector>
@@ -26,7 +27,6 @@
 
 class BluetoothGattNotifySession;
 class BluetoothRemoteGattDescriptor;
-class BluetoothRemoteGattService;
 
 // BluetoothRemoteGattCharacteristic represents a remote GATT characteristic.
 // This class is used to represent GATT characteristics that belong to a service
@@ -50,6 +50,8 @@
   typedef base::Callback<void(std::unique_ptr<BluetoothGattNotifySession>)>
       NotifySessionCallback;
 
+  ~BluetoothRemoteGattCharacteristic() override;
+
   // Returns the value of the characteristic. For remote characteristics, this
   // is the most recently cached value. For local characteristics, this is the
   // most recently updated value or the value retrieved from the delegate.
@@ -168,7 +170,6 @@
 
  protected:
   BluetoothRemoteGattCharacteristic();
-  ~BluetoothRemoteGattCharacteristic() override;
 
   // Writes to the Client Characteristic Configuration descriptor to enable
   // notifications/indications. This method is meant to be called from
diff --git a/device/bluetooth/bluetooth_remote_gatt_service.cc b/device/bluetooth/bluetooth_remote_gatt_service.cc
index 1df683b..1441f58 100644
--- a/device/bluetooth/bluetooth_remote_gatt_service.cc
+++ b/device/bluetooth/bluetooth_remote_gatt_service.cc
@@ -4,6 +4,8 @@
 
 #include "device/bluetooth/bluetooth_remote_gatt_service.h"
 
+#include <utility>
+
 #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h"
 #include "device/bluetooth/bluetooth_uuid.h"
 
@@ -14,16 +16,30 @@
 BluetoothRemoteGattService::~BluetoothRemoteGattService() = default;
 
 std::vector<BluetoothRemoteGattCharacteristic*>
+BluetoothRemoteGattService::GetCharacteristics() const {
+  std::vector<BluetoothRemoteGattCharacteristic*> characteristics;
+  characteristics.reserve(characteristics_.size());
+  for (const auto& characteristic : characteristics_)
+    characteristics.push_back(characteristic.second.get());
+  return characteristics;
+}
+
+BluetoothRemoteGattCharacteristic*
+BluetoothRemoteGattService::GetCharacteristic(
+    const std::string& identifier) const {
+  auto iter = characteristics_.find(identifier);
+  return iter != characteristics_.end() ? iter->second.get() : nullptr;
+}
+
+std::vector<BluetoothRemoteGattCharacteristic*>
 BluetoothRemoteGattService::GetCharacteristicsByUUID(
-    const BluetoothUUID& characteristic_uuid) {
+    const BluetoothUUID& characteristic_uuid) const {
   std::vector<BluetoothRemoteGattCharacteristic*> result;
-  std::vector<BluetoothRemoteGattCharacteristic*> characteristics =
-      GetCharacteristics();
-  for (auto* characteristic : characteristics) {
-    if (characteristic->GetUUID() == characteristic_uuid) {
-      result.push_back(characteristic);
-    }
+  for (const auto& characteristic : characteristics_) {
+    if (characteristic.second->GetUUID() == characteristic_uuid)
+      result.push_back(characteristic.second.get());
   }
+
   return result;
 }
 
@@ -35,4 +51,16 @@
   discovery_complete_ = complete;
 }
 
+bool BluetoothRemoteGattService::AddCharacteristic(
+    std::unique_ptr<BluetoothRemoteGattCharacteristic> characteristic) {
+  if (!characteristic)
+    return false;
+
+  const auto& characteristic_raw = *characteristic;
+  return characteristics_
+      .try_emplace(characteristic_raw.GetIdentifier(),
+                   std::move(characteristic))
+      .second;
+}
+
 }  // namespace device
diff --git a/device/bluetooth/bluetooth_remote_gatt_service.h b/device/bluetooth/bluetooth_remote_gatt_service.h
index d21fe2f..97c00b1 100644
--- a/device/bluetooth/bluetooth_remote_gatt_service.h
+++ b/device/bluetooth/bluetooth_remote_gatt_service.h
@@ -5,9 +5,11 @@
 #ifndef DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_SERVICE_H_
 #define DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_SERVICE_H_
 
+#include <memory>
 #include <string>
 #include <vector>
 
+#include "base/containers/flat_map.h"
 #include "base/macros.h"
 #include "device/bluetooth/bluetooth_export.h"
 #include "device/bluetooth/bluetooth_gatt_service.h"
@@ -40,7 +42,7 @@
 
   // List of characteristics that belong to this service.
   virtual std::vector<BluetoothRemoteGattCharacteristic*> GetCharacteristics()
-      const = 0;
+      const;
 
   // List of GATT services that are included by this service.
   virtual std::vector<BluetoothRemoteGattService*> GetIncludedServices()
@@ -49,7 +51,12 @@
   // Returns the GATT characteristic with identifier |identifier| if it belongs
   // to this GATT service.
   virtual BluetoothRemoteGattCharacteristic* GetCharacteristic(
-      const std::string& identifier) const = 0;
+      const std::string& identifier) const;
+
+  // List of characteristics that belong to this service and have a UUID equal
+  // to |characteristic_uuid|.
+  virtual std::vector<BluetoothRemoteGattCharacteristic*>
+  GetCharacteristicsByUUID(const BluetoothUUID& characteristic_uuid) const;
 
   // Returns true if all the characteristics have been discovered.
   virtual bool IsDiscoveryComplete() const;
@@ -57,12 +64,18 @@
   // Sets characteristic discovery as complete or incomplete.
   virtual void SetDiscoveryComplete(bool complete);
 
-  std::vector<BluetoothRemoteGattCharacteristic*> GetCharacteristicsByUUID(
-      const BluetoothUUID& characteristic_uuid);
-
  protected:
+  using CharacteristicMap =
+      base::flat_map<std::string,
+                     std::unique_ptr<BluetoothRemoteGattCharacteristic>>;
+
   BluetoothRemoteGattService();
 
+  bool AddCharacteristic(
+      std::unique_ptr<BluetoothRemoteGattCharacteristic> characteristic);
+
+  CharacteristicMap characteristics_;
+
  private:
   // Is true if all the characteristics have been discovered.
   bool discovery_complete_ = false;
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_android.cc b/device/bluetooth/bluetooth_remote_gatt_service_android.cc
index 80258f41..a8e3957d 100644
--- a/device/bluetooth/bluetooth_remote_gatt_service_android.cc
+++ b/device/bluetooth/bluetooth_remote_gatt_service_android.cc
@@ -128,10 +128,7 @@
 std::vector<device::BluetoothRemoteGattCharacteristic*>
 BluetoothRemoteGattServiceAndroid::GetCharacteristics() const {
   EnsureCharacteristicsCreated();
-  std::vector<device::BluetoothRemoteGattCharacteristic*> characteristics;
-  for (const auto& map_iter : characteristics_)
-    characteristics.push_back(map_iter.second.get());
-  return characteristics;
+  return BluetoothRemoteGattService::GetCharacteristics();
 }
 
 std::vector<device::BluetoothRemoteGattService*>
@@ -144,10 +141,15 @@
 BluetoothRemoteGattServiceAndroid::GetCharacteristic(
     const std::string& identifier) const {
   EnsureCharacteristicsCreated();
-  const auto& iter = characteristics_.find(identifier);
-  if (iter == characteristics_.end())
-    return nullptr;
-  return iter->second.get();
+  return BluetoothRemoteGattService::GetCharacteristic(identifier);
+}
+
+std::vector<BluetoothRemoteGattCharacteristic*>
+BluetoothRemoteGattServiceAndroid::GetCharacteristicsByUUID(
+    const BluetoothUUID& characteristic_uuid) const {
+  EnsureCharacteristicsCreated();
+  return BluetoothRemoteGattService::GetCharacteristicsByUUID(
+      characteristic_uuid);
 }
 
 bool BluetoothRemoteGattServiceAndroid::IsDiscoveryComplete() const {
@@ -175,11 +177,9 @@
       base::android::ConvertJavaStringToUTF8(env, instance_id);
 
   DCHECK(!base::ContainsKey(characteristics_, instance_id_string));
-
-  characteristics_[instance_id_string] =
-      BluetoothRemoteGattCharacteristicAndroid::Create(
-          adapter_, this, instance_id_string,
-          bluetooth_gatt_characteristic_wrapper, chrome_bluetooth_device);
+  AddCharacteristic(BluetoothRemoteGattCharacteristicAndroid::Create(
+      adapter_, this, instance_id_string, bluetooth_gatt_characteristic_wrapper,
+      chrome_bluetooth_device));
 }
 
 BluetoothRemoteGattServiceAndroid::BluetoothRemoteGattServiceAndroid(
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_android.h b/device/bluetooth/bluetooth_remote_gatt_service_android.h
index be602a8d..5f76758 100644
--- a/device/bluetooth/bluetooth_remote_gatt_service_android.h
+++ b/device/bluetooth/bluetooth_remote_gatt_service_android.h
@@ -8,7 +8,6 @@
 #include <map>
 #include <memory>
 #include <string>
-#include <unordered_map>
 #include <vector>
 
 #include "base/android/jni_android.h"
@@ -21,7 +20,6 @@
 
 class BluetoothAdapterAndroid;
 class BluetoothDeviceAndroid;
-class BluetoothRemoteGattCharacteristicAndroid;
 
 // BluetoothRemoteGattServiceAndroid along with its owned Java class
 // org.chromium.device.bluetooth.ChromeBluetoothRemoteGattService implement
@@ -70,6 +68,8 @@
       const override;
   device::BluetoothRemoteGattCharacteristic* GetCharacteristic(
       const std::string& identifier) const override;
+  std::vector<BluetoothRemoteGattCharacteristic*> GetCharacteristicsByUUID(
+      const BluetoothUUID& characteristic_uuid) const override;
   bool IsDiscoveryComplete() const override;
   void SetDiscoveryComplete(bool complete) override;
 
@@ -107,11 +107,6 @@
   // Adapter unique instance ID.
   std::string instance_id_;
 
-  // Map of characteristics, keyed by characteristic identifier.
-  std::unordered_map<std::string,
-                     std::unique_ptr<BluetoothRemoteGattCharacteristicAndroid>>
-      characteristics_;
-
   DISALLOW_COPY_AND_ASSIGN(BluetoothRemoteGattServiceAndroid);
 };
 
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_mac.h b/device/bluetooth/bluetooth_remote_gatt_service_mac.h
index e2d6cd2..20bfd73 100644
--- a/device/bluetooth/bluetooth_remote_gatt_service_mac.h
+++ b/device/bluetooth/bluetooth_remote_gatt_service_mac.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include <unordered_map>
+#include <string>
 #include <vector>
 
 #include "base/mac/scoped_nsobject.h"
@@ -40,11 +40,7 @@
   BluetoothUUID GetUUID() const override;
   bool IsPrimary() const override;
   BluetoothDevice* GetDevice() const override;
-  std::vector<BluetoothRemoteGattCharacteristic*> GetCharacteristics()
-      const override;
   std::vector<BluetoothRemoteGattService*> GetIncludedServices() const override;
-  BluetoothRemoteGattCharacteristic* GetCharacteristic(
-      const std::string& identifier) const override;
 
  private:
   friend class BluetoothLowEnergyDeviceMac;
@@ -80,10 +76,6 @@
   BluetoothLowEnergyDeviceMac* bluetooth_device_mac_;
   // A service from CBPeripheral.services.
   base::scoped_nsobject<CBService> service_;
-  // Map of characteristics, keyed by characteristic identifier.
-  std::unordered_map<std::string,
-                     std::unique_ptr<BluetoothRemoteGattCharacteristicMac>>
-      gatt_characteristic_macs_;
   bool is_primary_;
   // Service identifier.
   std::string identifier_;
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_mac.mm b/device/bluetooth/bluetooth_remote_gatt_service_mac.mm
index 58c4ecca..a9db0c0 100644
--- a/device/bluetooth/bluetooth_remote_gatt_service_mac.mm
+++ b/device/bluetooth/bluetooth_remote_gatt_service_mac.mm
@@ -49,34 +49,12 @@
   return bluetooth_device_mac_;
 }
 
-std::vector<BluetoothRemoteGattCharacteristic*>
-BluetoothRemoteGattServiceMac::GetCharacteristics() const {
-  std::vector<BluetoothRemoteGattCharacteristic*> gatt_characteristics;
-  for (const auto& iter : gatt_characteristic_macs_) {
-    BluetoothRemoteGattCharacteristic* gatt_characteristic =
-        static_cast<BluetoothRemoteGattCharacteristic*>(iter.second.get());
-    gatt_characteristics.push_back(gatt_characteristic);
-  }
-  return gatt_characteristics;
-}
-
 std::vector<BluetoothRemoteGattService*>
 BluetoothRemoteGattServiceMac::GetIncludedServices() const {
   NOTIMPLEMENTED();
   return std::vector<BluetoothRemoteGattService*>();
 }
 
-BluetoothRemoteGattCharacteristic*
-BluetoothRemoteGattServiceMac::GetCharacteristic(
-    const std::string& identifier) const {
-  auto searched_pair = gatt_characteristic_macs_.find(identifier);
-  if (searched_pair == gatt_characteristic_macs_.end()) {
-    return nullptr;
-  }
-  return static_cast<BluetoothRemoteGattCharacteristic*>(
-      searched_pair->second.get());
-}
-
 void BluetoothRemoteGattServiceMac::DiscoverCharacteristics() {
   VLOG(1) << *this << ": DiscoverCharacteristics.";
   SetDiscoveryComplete(false);
@@ -96,7 +74,7 @@
   VLOG(1) << *this << ": DidDiscoverCharacteristics.";
   --discovery_pending_count_;
   std::unordered_set<std::string> characteristic_identifier_to_remove;
-  for (const auto& iter : gatt_characteristic_macs_) {
+  for (const auto& iter : characteristics_) {
     characteristic_identifier_to_remove.insert(iter.first);
   }
 
@@ -114,10 +92,8 @@
     }
     gatt_characteristic_mac =
         new BluetoothRemoteGattCharacteristicMac(this, cb_characteristic);
-    const std::string& identifier = gatt_characteristic_mac->GetIdentifier();
-    auto result_iter = gatt_characteristic_macs_.insert(
-        {identifier, base::WrapUnique(gatt_characteristic_mac)});
-    DCHECK(result_iter.second);
+    bool result = AddCharacteristic(base::WrapUnique(gatt_characteristic_mac));
+    DCHECK(result);
     VLOG(1) << *gatt_characteristic_mac << ": New characteristic, properties "
             << gatt_characteristic_mac->GetProperties();
     if (discovery_pending_count_ == 0) {
@@ -127,12 +103,12 @@
   }
 
   for (const std::string& identifier : characteristic_identifier_to_remove) {
-    auto pair_to_remove = gatt_characteristic_macs_.find(identifier);
-    std::unique_ptr<BluetoothRemoteGattCharacteristicMac>
-        characteristic_to_remove;
-    pair_to_remove->second.swap(characteristic_to_remove);
-    VLOG(1) << *characteristic_to_remove << ": Removed characteristic.";
-    gatt_characteristic_macs_.erase(pair_to_remove);
+    auto pair_to_remove = characteristics_.find(identifier);
+    auto characteristic_to_remove = std::move(pair_to_remove->second);
+    VLOG(1) << static_cast<BluetoothRemoteGattCharacteristicMac&>(
+                   *characteristic_to_remove)
+            << ": Removed characteristic.";
+    characteristics_.erase(pair_to_remove);
     GetMacAdapter()->NotifyGattCharacteristicRemoved(
         characteristic_to_remove.get());
   }
@@ -160,13 +136,12 @@
   // Notify when all characteristics have been fully discovered.
   SetDiscoveryComplete(
       discovery_pending_count_ == 0 &&
-      std::find_if_not(
-          gatt_characteristic_macs_.begin(), gatt_characteristic_macs_.end(),
-          [](const std::pair<
-              const std::string,
-              std::unique_ptr<BluetoothRemoteGattCharacteristicMac>>& pair) {
-            return pair.second->IsDiscoveryComplete();
-          }) == gatt_characteristic_macs_.end());
+      std::all_of(characteristics_.begin(), characteristics_.end(),
+                  [](const auto& pair) {
+                    return static_cast<BluetoothRemoteGattCharacteristicMac*>(
+                               pair.second.get())
+                        ->IsDiscoveryComplete();
+                  }));
   if (IsDiscoveryComplete()) {
     VLOG(1) << *this << ": Discovery complete.";
     GetMacAdapter()->NotifyGattServiceChanged(this);
@@ -188,19 +163,14 @@
 BluetoothRemoteGattCharacteristicMac*
 BluetoothRemoteGattServiceMac::GetBluetoothRemoteGattCharacteristicMac(
     CBCharacteristic* cb_characteristic) const {
-  auto found = std::find_if(
-      gatt_characteristic_macs_.begin(), gatt_characteristic_macs_.end(),
-      [cb_characteristic](
-          const std::pair<
-              const std::string,
-              std::unique_ptr<BluetoothRemoteGattCharacteristicMac>>& pair) {
-        return pair.second->GetCBCharacteristic() == cb_characteristic;
-      });
-  if (found == gatt_characteristic_macs_.end()) {
-    return nullptr;
-  } else {
-    return found->second.get();
+  for (const auto& pair : characteristics_) {
+    auto* characteristic_mac =
+        static_cast<BluetoothRemoteGattCharacteristicMac*>(pair.second.get());
+    if (characteristic_mac->GetCBCharacteristic() == cb_characteristic)
+      return characteristic_mac;
   }
+
+  return nullptr;
 }
 
 BluetoothRemoteGattDescriptorMac*
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_win.cc b/device/bluetooth/bluetooth_remote_gatt_service_win.cc
index 7278bf54..24ab750 100644
--- a/device/bluetooth/bluetooth_remote_gatt_service_win.cc
+++ b/device/bluetooth/bluetooth_remote_gatt_service_win.cc
@@ -9,6 +9,7 @@
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
+#include "base/stl_util.h"
 #include "device/bluetooth/bluetooth_adapter_win.h"
 #include "device/bluetooth/bluetooth_device_win.h"
 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_win.h"
@@ -73,14 +74,6 @@
   return device_;
 }
 
-std::vector<BluetoothRemoteGattCharacteristic*>
-BluetoothRemoteGattServiceWin::GetCharacteristics() const {
-  std::vector<BluetoothRemoteGattCharacteristic*> has_characteristics;
-  for (const auto& c : included_characteristics_)
-    has_characteristics.push_back(c.second.get());
-  return has_characteristics;
-}
-
 std::vector<BluetoothRemoteGattService*>
 BluetoothRemoteGattServiceWin::GetIncludedServices() const {
   NOTIMPLEMENTED();
@@ -88,25 +81,14 @@
   return std::vector<BluetoothRemoteGattService*>();
 }
 
-BluetoothRemoteGattCharacteristic*
-BluetoothRemoteGattServiceWin::GetCharacteristic(
-    const std::string& identifier) const {
-  GattCharacteristicsMap::const_iterator it =
-      included_characteristics_.find(identifier);
-  if (it != included_characteristics_.end())
-    return it->second.get();
-  return nullptr;
-}
-
 void BluetoothRemoteGattServiceWin::GattCharacteristicDiscoveryComplete(
     BluetoothRemoteGattCharacteristicWin* characteristic) {
   DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
-  DCHECK(included_characteristics_.find(characteristic->GetIdentifier()) !=
-         included_characteristics_.end());
+  DCHECK(base::ContainsKey(characteristics_, characteristic->GetIdentifier()));
 
   discovery_completed_included_characteristics_.insert(
       characteristic->GetIdentifier());
-  SetDiscoveryComplete(included_characteristics_.size() ==
+  SetDiscoveryComplete(characteristics_.size() ==
                        discovery_completed_included_characteristics_.size());
   adapter_->NotifyGattCharacteristicAdded(characteristic);
   NotifyGattServiceDiscoveryCompleteIfNecessary();
@@ -132,7 +114,7 @@
     return;
 
   UpdateIncludedCharacteristics(characteristics.get(), num);
-  SetDiscoveryComplete(included_characteristics_.size() ==
+  SetDiscoveryComplete(characteristics_.size() ==
                        discovery_completed_included_characteristics_.size());
 
   // In case there are new included characterisitics that haven't been
@@ -152,7 +134,7 @@
     PBTH_LE_GATT_CHARACTERISTIC characteristics,
     uint16_t num) {
   if (num == 0) {
-    if (included_characteristics_.size() > 0) {
+    if (!characteristics_.empty()) {
       ClearIncludedCharacteristics();
       adapter_->NotifyGattServiceChanged(this);
     }
@@ -161,20 +143,26 @@
 
   // First, remove characteristics that no longer exist.
   std::vector<std::string> to_be_removed;
-  for (const auto& c : included_characteristics_) {
-    if (!DoesCharacteristicExist(characteristics, num, c.second.get()))
+  for (const auto& c : characteristics_) {
+    if (!DoesCharacteristicExist(
+            characteristics, num,
+            static_cast<BluetoothRemoteGattCharacteristicWin*>(
+                c.second.get()))) {
       to_be_removed.push_back(c.second->GetIdentifier());
+    }
   }
   for (const auto& id : to_be_removed) {
     RemoveIncludedCharacteristic(id);
   }
 
   // Update previously known characteristics.
-  for (auto& c : included_characteristics_)
-    c.second->Update();
+  for (auto& c : characteristics_) {
+    static_cast<BluetoothRemoteGattCharacteristicWin*>(c.second.get())
+        ->Update();
+  }
 
   // Return if no new characteristics have been added.
-  if (included_characteristics_.size() == num)
+  if (characteristics_.size() == num)
     return;
 
   // Add new characteristics.
@@ -183,11 +171,8 @@
                                     characteristics[i].AttributeHandle)) {
       PBTH_LE_GATT_CHARACTERISTIC info = new BTH_LE_GATT_CHARACTERISTIC();
       *info = characteristics[i];
-      auto characteristic_object =
-          std::make_unique<BluetoothRemoteGattCharacteristicWin>(
-              this, info, ui_task_runner_);
-      included_characteristics_.emplace(characteristic_object->GetIdentifier(),
-                                        std::move(characteristic_object));
+      AddCharacteristic(std::make_unique<BluetoothRemoteGattCharacteristicWin>(
+          this, info, ui_task_runner_));
     }
   }
 }
@@ -205,9 +190,11 @@
     uint16_t attribute_handle) {
   BluetoothUUID bt_uuid =
       BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid(uuid);
-  for (const auto& c : included_characteristics_) {
+  for (const auto& c : characteristics_) {
     if (bt_uuid == c.second->GetUUID() &&
-        attribute_handle == c.second->GetAttributeHandle()) {
+        attribute_handle ==
+            static_cast<BluetoothRemoteGattCharacteristicWin*>(c.second.get())
+                ->GetAttributeHandle()) {
       return true;
     }
   }
@@ -234,17 +221,24 @@
 void BluetoothRemoteGattServiceWin::RemoveIncludedCharacteristic(
     std::string identifier) {
   discovery_completed_included_characteristics_.erase(identifier);
-  included_characteristics_[identifier].reset();
-  included_characteristics_.erase(identifier);
+
+  // Explicitly moving the to be deleted characteristic into a local variable,
+  // so that we can erase the entry from |characteristics_| before calling the
+  // characteristic's destructor. This will ensure that any call to
+  // GetCharacteristics() won't contain an entry corresponding to |identifier|.
+  // Note: `characteristics_.erase(identifier);` would not guarantee this.
+  DCHECK(base::ContainsKey(characteristics_, identifier));
+  auto iter = characteristics_.find(identifier);
+  auto pair = std::move(*iter);
+  characteristics_.erase(iter);
 }
 
 void BluetoothRemoteGattServiceWin::ClearIncludedCharacteristics() {
   discovery_completed_included_characteristics_.clear();
-  // Explicitly reset to null to ensure that calling GetCharacteristic() on the
-  // removed characteristic in GattDescriptorRemoved() returns null.
-  for (auto& entry : included_characteristics_)
-    entry.second.reset();
-  included_characteristics_.clear();
+  // Explicitly reset to null to ensure that calling GetCharacteristics() in
+  // GattCharacteristicRemoved() will return an empty collection.
+  // Note: `characteristics_.clear();` would not guarantee this.
+  std::exchange(characteristics_, {});
 }
 
 }  // namespace device.
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_win.h b/device/bluetooth/bluetooth_remote_gatt_service_win.h
index e44b077f..9ef078b 100644
--- a/device/bluetooth/bluetooth_remote_gatt_service_win.h
+++ b/device/bluetooth/bluetooth_remote_gatt_service_win.h
@@ -8,7 +8,6 @@
 #include <memory>
 #include <set>
 #include <string>
-#include <unordered_map>
 #include <vector>
 
 #include "base/files/file.h"
@@ -44,11 +43,7 @@
   BluetoothUUID GetUUID() const override;
   bool IsPrimary() const override;
   BluetoothDevice* GetDevice() const override;
-  std::vector<BluetoothRemoteGattCharacteristic*> GetCharacteristics()
-      const override;
   std::vector<BluetoothRemoteGattService*> GetIncludedServices() const override;
-  BluetoothRemoteGattCharacteristic* GetCharacteristic(
-      const std::string& identifier) const override;
 
   // Notify |characteristic| discovery complete, |characteristic| is the
   // included characteritic of this service.
@@ -102,14 +97,6 @@
   // dependent operations.
   scoped_refptr<BluetoothTaskManagerWin> task_manager_;
 
-  // The key of GattCharacteristicsMap is the identifier of
-  // BluetoothRemoteGattCharacteristicWin instance.
-  typedef std::unordered_map<
-      std::string,
-      std::unique_ptr<BluetoothRemoteGattCharacteristicWin>>
-      GattCharacteristicsMap;
-  GattCharacteristicsMap included_characteristics_;
-
   // The element of the set is the identifier of
   // BluetoothRemoteGattCharacteristicWin instance.
   std::set<std::string> discovery_completed_included_characteristics_;
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_winrt.cc b/device/bluetooth/bluetooth_remote_gatt_service_winrt.cc
index 0b6a6da..b2de385 100644
--- a/device/bluetooth/bluetooth_remote_gatt_service_winrt.cc
+++ b/device/bluetooth/bluetooth_remote_gatt_service_winrt.cc
@@ -70,25 +70,12 @@
   return device_;
 }
 
-std::vector<BluetoothRemoteGattCharacteristic*>
-BluetoothRemoteGattServiceWinrt::GetCharacteristics() const {
-  NOTIMPLEMENTED();
-  return {};
-}
-
 std::vector<BluetoothRemoteGattService*>
 BluetoothRemoteGattServiceWinrt::GetIncludedServices() const {
   NOTIMPLEMENTED();
   return {};
 }
 
-BluetoothRemoteGattCharacteristic*
-BluetoothRemoteGattServiceWinrt::GetCharacteristic(
-    const std::string& identifier) const {
-  NOTIMPLEMENTED();
-  return nullptr;
-}
-
 BluetoothRemoteGattServiceWinrt::BluetoothRemoteGattServiceWinrt(
     BluetoothDevice* device,
     Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::
diff --git a/device/bluetooth/bluetooth_remote_gatt_service_winrt.h b/device/bluetooth/bluetooth_remote_gatt_service_winrt.h
index 7a45a33..c04a73af 100644
--- a/device/bluetooth/bluetooth_remote_gatt_service_winrt.h
+++ b/device/bluetooth/bluetooth_remote_gatt_service_winrt.h
@@ -20,7 +20,6 @@
 namespace device {
 
 class BluetoothDevice;
-class BluetoothRemoteGattCharacteristic;
 
 class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattServiceWinrt
     : public BluetoothRemoteGattService {
@@ -37,11 +36,7 @@
   BluetoothUUID GetUUID() const override;
   bool IsPrimary() const override;
   BluetoothDevice* GetDevice() const override;
-  std::vector<BluetoothRemoteGattCharacteristic*> GetCharacteristics()
-      const override;
   std::vector<BluetoothRemoteGattService*> GetIncludedServices() const override;
-  BluetoothRemoteGattCharacteristic* GetCharacteristic(
-      const std::string& identifier) const override;
 
  private:
   BluetoothRemoteGattServiceWinrt(
diff --git a/device/bluetooth/bluez/bluetooth_remote_gatt_service_bluez.cc b/device/bluetooth/bluez/bluetooth_remote_gatt_service_bluez.cc
index 158e0ad..fbc94a2e 100644
--- a/device/bluetooth/bluez/bluetooth_remote_gatt_service_bluez.cc
+++ b/device/bluetooth/bluez/bluetooth_remote_gatt_service_bluez.cc
@@ -87,27 +87,12 @@
   return device_;
 }
 
-std::vector<device::BluetoothRemoteGattCharacteristic*>
-BluetoothRemoteGattServiceBlueZ::GetCharacteristics() const {
-  std::vector<device::BluetoothRemoteGattCharacteristic*> characteristics;
-  for (const auto& characteristic : characteristics_)
-    characteristics.push_back(characteristic.second.get());
-  return characteristics;
-}
-
 std::vector<device::BluetoothRemoteGattService*>
 BluetoothRemoteGattServiceBlueZ::GetIncludedServices() const {
   // TODO(armansito): Return the actual included services here.
   return std::vector<device::BluetoothRemoteGattService*>();
 }
 
-device::BluetoothRemoteGattCharacteristic*
-BluetoothRemoteGattServiceBlueZ::GetCharacteristic(
-    const std::string& identifier) const {
-  auto iter = characteristics_.find(dbus::ObjectPath(identifier));
-  return iter != characteristics_.end() ? iter->second.get() : nullptr;
-}
-
 void BluetoothRemoteGattServiceBlueZ::NotifyServiceChanged() {
   // Don't send service changed unless we know that all characteristics have
   // already been discovered. This is to prevent spammy events before sending
@@ -164,7 +149,7 @@
 
 void BluetoothRemoteGattServiceBlueZ::GattCharacteristicAdded(
     const dbus::ObjectPath& object_path) {
-  if (characteristics_.find(object_path) != characteristics_.end()) {
+  if (characteristics_.find(object_path.value()) != characteristics_.end()) {
     VLOG(1) << "Remote GATT characteristic already exists: "
             << object_path.value();
     return;
@@ -186,7 +171,7 @@
   // NOTE: Can't use std::make_unique due to private constructor.
   BluetoothRemoteGattCharacteristicBlueZ* characteristic =
       new BluetoothRemoteGattCharacteristicBlueZ(this, object_path);
-  characteristics_.emplace(object_path, base::WrapUnique(characteristic));
+  AddCharacteristic(base::WrapUnique(characteristic));
   DCHECK(characteristic->GetIdentifier() == object_path.value());
   DCHECK(characteristic->GetUUID().IsValid());
 
@@ -196,7 +181,7 @@
 
 void BluetoothRemoteGattServiceBlueZ::GattCharacteristicRemoved(
     const dbus::ObjectPath& object_path) {
-  CharacteristicMap::iterator iter = characteristics_.find(object_path);
+  CharacteristicMap::iterator iter = characteristics_.find(object_path.value());
   if (iter == characteristics_.end()) {
     VLOG(2) << "Unknown GATT characteristic removed: " << object_path.value();
     return;
@@ -206,7 +191,9 @@
           << GetIdentifier() << ", UUID: " << GetUUID().canonical_value();
 
   auto characteristic = std::move(iter->second);
-  DCHECK(characteristic->object_path() == object_path);
+  DCHECK(
+      static_cast<BluetoothRemoteGattCharacteristicBlueZ*>(characteristic.get())
+          ->object_path() == object_path);
   characteristics_.erase(iter);
 
   DCHECK(GetAdapter());
@@ -216,8 +203,11 @@
 void BluetoothRemoteGattServiceBlueZ::GattCharacteristicPropertyChanged(
     const dbus::ObjectPath& object_path,
     const std::string& property_name) {
-  CharacteristicMap::iterator iter = characteristics_.find(object_path);
-  if (iter == characteristics_.end()) {
+  auto* characteristic_bluez =
+      static_cast<BluetoothRemoteGattCharacteristicBlueZ*>(
+          GetCharacteristic(object_path.value()));
+
+  if (!characteristic_bluez) {
     VLOG(3) << "Properties of unknown characteristic changed";
     return;
   }
@@ -238,12 +228,14 @@
   if (property_name == properties->flags.name()) {
     NotifyServiceChanged();
   } else if (property_name == properties->value.name()) {
-    DCHECK_GE(iter->second->num_of_characteristic_value_read_in_progress_, 0);
-    if (iter->second->num_of_characteristic_value_read_in_progress_ > 0) {
-      --iter->second->num_of_characteristic_value_read_in_progress_;
+    DCHECK_GE(
+        characteristic_bluez->num_of_characteristic_value_read_in_progress_, 0);
+    if (characteristic_bluez->num_of_characteristic_value_read_in_progress_ >
+        0) {
+      --characteristic_bluez->num_of_characteristic_value_read_in_progress_;
     } else {
       GetAdapter()->NotifyGattCharacteristicValueChanged(
-          iter->second.get(), properties->value.value());
+          characteristic_bluez, properties->value.value());
     }
   }
 }
diff --git a/device/bluetooth/bluez/bluetooth_remote_gatt_service_bluez.h b/device/bluetooth/bluez/bluetooth_remote_gatt_service_bluez.h
index 116f2db7..b192ead 100644
--- a/device/bluetooth/bluez/bluetooth_remote_gatt_service_bluez.h
+++ b/device/bluetooth/bluez/bluetooth_remote_gatt_service_bluez.h
@@ -7,7 +7,6 @@
 
 #include <stdint.h>
 
-#include <map>
 #include <memory>
 #include <string>
 #include <vector>
@@ -24,7 +23,6 @@
 namespace device {
 
 class BluetoothDevice;
-class BluetoothRemoteGattCharacteristic;
 
 }  // namespace device
 
@@ -49,12 +47,8 @@
   device::BluetoothUUID GetUUID() const override;
   device::BluetoothDevice* GetDevice() const override;
   bool IsPrimary() const override;
-  std::vector<device::BluetoothRemoteGattCharacteristic*> GetCharacteristics()
-      const override;
   std::vector<device::BluetoothRemoteGattService*> GetIncludedServices()
       const override;
-  device::BluetoothRemoteGattCharacteristic* GetCharacteristic(
-      const std::string& identifier) const override;
 
   // Notifies its observers that the GATT service has changed. This is mainly
   // used by BluetoothRemoteGattCharacteristicBlueZ instances to notify
@@ -102,16 +96,6 @@
   // here since |device_| owns this instance.
   BluetoothDeviceBlueZ* device_;
 
-  using CharacteristicMap =
-      std::map<dbus::ObjectPath,
-               std::unique_ptr<BluetoothRemoteGattCharacteristicBlueZ>>;
-
-  // Mapping from GATT characteristic object paths to characteristic objects.
-  // owned by this service. Since the BlueZ implementation uses object
-  // paths as unique identifiers, we also use this mapping to return
-  // characteristics by identifier.
-  CharacteristicMap characteristics_;
-
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
   base::WeakPtrFactory<BluetoothRemoteGattServiceBlueZ> weak_ptr_factory_;
diff --git a/device/bluetooth/cast/bluetooth_remote_gatt_service_cast.cc b/device/bluetooth/cast/bluetooth_remote_gatt_service_cast.cc
index 96f43d9e..73d22da 100644
--- a/device/bluetooth/cast/bluetooth_remote_gatt_service_cast.cc
+++ b/device/bluetooth/cast/bluetooth_remote_gatt_service_cast.cc
@@ -23,10 +23,9 @@
   std::vector<scoped_refptr<chromecast::bluetooth::RemoteCharacteristic>>
       characteristics = remote_service_->GetCharacteristics();
   characteristics_.reserve(characteristics.size());
-  for (auto& characteristic : characteristics) {
-    characteristics_.push_back(
-        std::make_unique<BluetoothRemoteGattCharacteristicCast>(
-            this, characteristic));
+  for (const auto& characteristic : characteristics) {
+    AddCharacteristic(std::make_unique<BluetoothRemoteGattCharacteristicCast>(
+        this, characteristic));
   }
   SetDiscoveryComplete(true);
 }
@@ -43,35 +42,16 @@
 
 bool BluetoothRemoteGattServiceCast::IsPrimary() const {
   return remote_service_->primary();
-};
+}
 
 BluetoothDevice* BluetoothRemoteGattServiceCast::GetDevice() const {
   return device_;
 }
 
-std::vector<BluetoothRemoteGattCharacteristic*>
-BluetoothRemoteGattServiceCast::GetCharacteristics() const {
-  std::vector<BluetoothRemoteGattCharacteristic*> results;
-  results.reserve(characteristics_.size());
-  for (auto& characteristic : characteristics_)
-    results.push_back(characteristic.get());
-  return results;
-}
-
 std::vector<BluetoothRemoteGattService*>
 BluetoothRemoteGattServiceCast::GetIncludedServices() const {
   NOTIMPLEMENTED();
   return std::vector<BluetoothRemoteGattService*>();
 }
 
-BluetoothRemoteGattCharacteristic*
-BluetoothRemoteGattServiceCast::GetCharacteristic(
-    const std::string& identifier) const {
-  for (auto& characteristic : characteristics_) {
-    if (characteristic->GetIdentifier() == identifier)
-      return characteristic.get();
-  }
-  return nullptr;
-}
-
 }  // namespace device
diff --git a/device/bluetooth/cast/bluetooth_remote_gatt_service_cast.h b/device/bluetooth/cast/bluetooth_remote_gatt_service_cast.h
index 223a5ef..8280cac 100644
--- a/device/bluetooth/cast/bluetooth_remote_gatt_service_cast.h
+++ b/device/bluetooth/cast/bluetooth_remote_gatt_service_cast.h
@@ -23,7 +23,6 @@
 namespace device {
 
 class BluetoothDeviceCast;
-class BluetoothRemoteGattCharacteristicCast;
 
 class BluetoothRemoteGattServiceCast : public BluetoothRemoteGattService {
  public:
@@ -39,19 +38,12 @@
 
   // BluetoothRemoteGattService implementation:
   BluetoothDevice* GetDevice() const override;
-  std::vector<BluetoothRemoteGattCharacteristic*> GetCharacteristics()
-      const override;
   std::vector<BluetoothRemoteGattService*> GetIncludedServices() const override;
-  BluetoothRemoteGattCharacteristic* GetCharacteristic(
-      const std::string& identifier) const override;
 
  private:
   BluetoothDeviceCast* const device_;
   scoped_refptr<chromecast::bluetooth::RemoteService> remote_service_;
 
-  std::vector<std::unique_ptr<BluetoothRemoteGattCharacteristicCast>>
-      characteristics_;
-
   DISALLOW_COPY_AND_ASSIGN(BluetoothRemoteGattServiceCast);
 };
 
diff --git a/device/bluetooth/device_unittest.cc b/device/bluetooth/device_unittest.cc
index 29596f1..2c5f4ec 100644
--- a/device/bluetooth/device_unittest.cc
+++ b/device/bluetooth/device_unittest.cc
@@ -107,16 +107,6 @@
 
     service2->AddMockCharacteristic(std::move(characteristic3));
 
-    EXPECT_CALL(*service1, GetCharacteristics())
-        .WillRepeatedly(
-            Invoke(service1.get(),
-                   &device::MockBluetoothGattService::GetMockCharacteristics));
-
-    EXPECT_CALL(*service2, GetCharacteristics())
-        .WillRepeatedly(
-            Invoke(service2.get(),
-                   &device::MockBluetoothGattService::GetMockCharacteristics));
-
     device_.AddMockService(std::move(service1));
     device_.AddMockService(std::move(service2));
 
diff --git a/device/bluetooth/test/fake_remote_gatt_service.cc b/device/bluetooth/test/fake_remote_gatt_service.cc
index bf6b41d..9ec5c67 100644
--- a/device/bluetooth/test/fake_remote_gatt_service.cc
+++ b/device/bluetooth/test/fake_remote_gatt_service.cc
@@ -26,28 +26,29 @@
     : service_id_(service_id),
       service_uuid_(service_uuid),
       is_primary_(is_primary),
-      device_(device),
-      last_characteristic_id_(0) {}
+      device_(device) {}
 
 FakeRemoteGattService::~FakeRemoteGattService() = default;
 
 bool FakeRemoteGattService::AllResponsesConsumed() {
   return std::all_of(
-      fake_characteristics_.begin(), fake_characteristics_.end(),
-      [](const auto& e) { return e.second->AllResponsesConsumed(); });
+      characteristics_.begin(), characteristics_.end(), [](const auto& e) {
+        return static_cast<FakeRemoteGattCharacteristic*>(e.second.get())
+            ->AllResponsesConsumed();
+      });
 }
 
 std::string FakeRemoteGattService::AddFakeCharacteristic(
     const device::BluetoothUUID& characteristic_uuid,
     mojom::CharacteristicPropertiesPtr properties) {
-  FakeCharacteristicMap::iterator it;
+  CharacteristicMap::iterator it;
   bool inserted;
 
   // Attribute instance Ids need to be unique.
   std::string new_characteristic_id = base::StringPrintf(
       "%s_%zu", GetIdentifier().c_str(), ++last_characteristic_id_);
 
-  std::tie(it, inserted) = fake_characteristics_.emplace(
+  std::tie(it, inserted) = characteristics_.emplace(
       new_characteristic_id, std::make_unique<FakeRemoteGattCharacteristic>(
                                  new_characteristic_id, characteristic_uuid,
                                  std::move(properties), this));
@@ -58,14 +59,7 @@
 
 bool FakeRemoteGattService::RemoveFakeCharacteristic(
     const std::string& identifier) {
-  GetCharacteristic(identifier);
-  const auto& it = fake_characteristics_.find(identifier);
-  if (it == fake_characteristics_.end()) {
-    return false;
-  }
-
-  fake_characteristics_.erase(it);
-  return true;
+  return characteristics_.erase(identifier) != 0u;
 }
 
 std::string FakeRemoteGattService::GetIdentifier() const {
@@ -84,27 +78,10 @@
   return device_;
 }
 
-std::vector<device::BluetoothRemoteGattCharacteristic*>
-FakeRemoteGattService::GetCharacteristics() const {
-  std::vector<device::BluetoothRemoteGattCharacteristic*> characteristics;
-  for (const auto& it : fake_characteristics_)
-    characteristics.push_back(it.second.get());
-  return characteristics;
-}
-
 std::vector<device::BluetoothRemoteGattService*>
 FakeRemoteGattService::GetIncludedServices() const {
   NOTREACHED();
   return std::vector<device::BluetoothRemoteGattService*>();
 }
 
-device::BluetoothRemoteGattCharacteristic*
-FakeRemoteGattService::GetCharacteristic(const std::string& identifier) const {
-  const auto& it = fake_characteristics_.find(identifier);
-  if (it == fake_characteristics_.end())
-    return nullptr;
-
-  return it->second.get();
-}
-
 }  // namespace bluetooth
diff --git a/device/bluetooth/test/fake_remote_gatt_service.h b/device/bluetooth/test/fake_remote_gatt_service.h
index 0076391..97ad98e 100644
--- a/device/bluetooth/test/fake_remote_gatt_service.h
+++ b/device/bluetooth/test/fake_remote_gatt_service.h
@@ -17,7 +17,6 @@
 namespace device {
 class BluetoothDevice;
 class BluetoothRemoteGattService;
-class BluetoothRemoteGattCharacteristic;
 }  // namespace device
 
 namespace bluetooth {
@@ -53,12 +52,8 @@
 
   // device::BluetoothRemoteGattService overrides:
   device::BluetoothDevice* GetDevice() const override;
-  std::vector<device::BluetoothRemoteGattCharacteristic*> GetCharacteristics()
-      const override;
   std::vector<device::BluetoothRemoteGattService*> GetIncludedServices()
       const override;
-  device::BluetoothRemoteGattCharacteristic* GetCharacteristic(
-      const std::string& identifier) const override;
 
  private:
   const std::string service_id_;
@@ -66,11 +61,7 @@
   const bool is_primary_;
   device::BluetoothDevice* device_;
 
-  size_t last_characteristic_id_;
-
-  using FakeCharacteristicMap =
-      std::map<std::string, std::unique_ptr<FakeRemoteGattCharacteristic>>;
-  FakeCharacteristicMap fake_characteristics_;
+  size_t last_characteristic_id_ = 0;
 };
 
 }  // namespace bluetooth
diff --git a/device/bluetooth/test/mock_bluetooth_gatt_service.cc b/device/bluetooth/test/mock_bluetooth_gatt_service.cc
index 8cdd2fe..5c5c8387 100644
--- a/device/bluetooth/test/mock_bluetooth_gatt_service.cc
+++ b/device/bluetooth/test/mock_bluetooth_gatt_service.cc
@@ -10,6 +10,7 @@
 #include "device/bluetooth/test/mock_bluetooth_device.h"
 
 using testing::Return;
+using testing::Invoke;
 using testing::_;
 
 namespace device {
@@ -25,39 +26,22 @@
   ON_CALL(*this, IsLocal()).WillByDefault(Return(is_local));
   ON_CALL(*this, IsPrimary()).WillByDefault(Return(is_primary));
   ON_CALL(*this, GetDevice()).WillByDefault(Return(device));
-  ON_CALL(*this, GetCharacteristics())
-      .WillByDefault(Return(std::vector<BluetoothRemoteGattCharacteristic*>()));
+  ON_CALL(*this, GetCharacteristics()).WillByDefault(Invoke([this] {
+    return BluetoothRemoteGattService::GetCharacteristics();
+  }));
   ON_CALL(*this, GetIncludedServices())
       .WillByDefault(Return(std::vector<BluetoothRemoteGattService*>()));
   ON_CALL(*this, GetCharacteristic(_))
-      .WillByDefault(
-          Return(static_cast<BluetoothRemoteGattCharacteristic*>(NULL)));
+      .WillByDefault(Invoke([this](const std::string& id) {
+        return BluetoothRemoteGattService::GetCharacteristic(id);
+      }));
 }
 
 MockBluetoothGattService::~MockBluetoothGattService() = default;
 
 void MockBluetoothGattService::AddMockCharacteristic(
     std::unique_ptr<MockBluetoothGattCharacteristic> mock_characteristic) {
-  mock_characteristics_.push_back(std::move(mock_characteristic));
-}
-
-std::vector<BluetoothRemoteGattCharacteristic*>
-MockBluetoothGattService::GetMockCharacteristics() const {
-  std::vector<BluetoothRemoteGattCharacteristic*> characteristics;
-  for (const auto& characteristic : mock_characteristics_)
-    characteristics.push_back(characteristic.get());
-
-  return characteristics;
-}
-
-BluetoothRemoteGattCharacteristic*
-MockBluetoothGattService::GetMockCharacteristic(
-    const std::string& identifier) const {
-  for (const auto& characteristic : mock_characteristics_)
-    if (characteristic->GetIdentifier() == identifier)
-      return characteristic.get();
-
-  return nullptr;
+  AddCharacteristic(std::move(mock_characteristic));
 }
 
 }  // namespace device
diff --git a/device/bluetooth/test/mock_bluetooth_gatt_service.h b/device/bluetooth/test/mock_bluetooth_gatt_service.h
index dd841ff..c84ba88 100644
--- a/device/bluetooth/test/mock_bluetooth_gatt_service.h
+++ b/device/bluetooth/test/mock_bluetooth_gatt_service.h
@@ -40,32 +40,14 @@
                      std::vector<BluetoothRemoteGattService*>());
   MOCK_CONST_METHOD1(GetCharacteristic,
                      BluetoothRemoteGattCharacteristic*(const std::string&));
-  MOCK_METHOD1(AddCharacteristic, bool(BluetoothRemoteGattCharacteristic*));
   MOCK_METHOD1(AddIncludedService, bool(BluetoothRemoteGattService*));
   MOCK_METHOD2(Register, void(const base::Closure&, const ErrorCallback&));
   MOCK_METHOD2(Unregister, void(const base::Closure&, const ErrorCallback&));
 
-  // BluetoothRemoteGattService manages the lifetime of its
-  // BluetoothGATTCharacteristics.
-  // This method takes ownership of the MockBluetoothGATTCharacteristics. This
-  // is only for convenience as far as testing is concerned, and it's possible
-  // to write test cases without using these functions.
-  // Example:
-  // ON_CALL(*mock_service, GetCharacteristics))
-  //   .WillByDefault(Invoke(
-  //     *mock_service,
-  //      &MockBluetoothGattService::GetMockCharacteristics));
   void AddMockCharacteristic(
       std::unique_ptr<MockBluetoothGattCharacteristic> mock_characteristic);
-  std::vector<BluetoothRemoteGattCharacteristic*> GetMockCharacteristics()
-      const;
-  BluetoothRemoteGattCharacteristic* GetMockCharacteristic(
-      const std::string& identifier) const;
 
  private:
-  std::vector<std::unique_ptr<MockBluetoothGattCharacteristic>>
-      mock_characteristics_;
-
   DISALLOW_COPY_AND_ASSIGN(MockBluetoothGattService);
 };
 
diff --git a/device/fido/fido_ble_connection_unittest.cc b/device/fido/fido_ble_connection_unittest.cc
index d7cf1a24..4e767f5 100644
--- a/device/fido/fido_ble_connection_unittest.cc
+++ b/device/fido/fido_ble_connection_unittest.cc
@@ -274,13 +274,6 @@
     u2f_service_ = u2f_service.get();
     u2f_device_->AddMockService(std::move(u2f_service));
 
-    ON_CALL(*u2f_service_, GetCharacteristics())
-        .WillByDefault(Invoke(
-            u2f_service_, &MockBluetoothGattService::GetMockCharacteristics));
-
-    ON_CALL(*u2f_service_, GetCharacteristic(_))
-        .WillByDefault(Invoke(
-            u2f_service_, &MockBluetoothGattService::GetMockCharacteristic));
     AddU2fCharacteristics();
   }
 
diff --git a/extensions/browser/api/web_request/web_request_permissions.cc b/extensions/browser/api/web_request/web_request_permissions.cc
index d9ca827..5ad2cb0 100644
--- a/extensions/browser/api/web_request/web_request_permissions.cc
+++ b/extensions/browser/api/web_request/web_request_permissions.cc
@@ -15,6 +15,7 @@
 #include "extensions/browser/api/web_request/web_request_api_constants.h"
 #include "extensions/browser/api/web_request/web_request_info.h"
 #include "extensions/browser/extension_navigation_ui_data.h"
+#include "extensions/browser/extensions_browser_client.h"
 #include "extensions/browser/info_map.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/extension.h"
@@ -90,23 +91,6 @@
   return access;
 }
 
-bool IsWebUIAllowedToMakeNetworkRequests(const url::Origin& origin) {
-  // Whitelist to work around exceptional cases. This is only used to elide a
-  // DCHECK.
-  //
-  // If you are adding a new host to this list, please file a corresponding bug
-  // to track its removal. See https://crbug.com/829412 for the metabug.
-  return
-      // https://crbug.com/829414
-      origin.host() == "print" ||
-      // https://crbug.com/831812
-      origin.host() == "sync-confirmation" ||
-      // https://crbug.com/831813
-      origin.host() == "inspect" ||
-      // https://crbug.com/859345
-      origin.host() == "downloads";
-}
-
 PermissionsData::PageAccess CanExtensionAccessURLInternal(
     const extensions::InfoMap* extension_info_map,
     const std::string& extension_id,
@@ -210,7 +194,8 @@
     // treat the requests as sensitive to ensure that the Web Request API
     // doesn't see them.
     DCHECK(request.initiator.has_value());
-    DCHECK(IsWebUIAllowedToMakeNetworkRequests(*request.initiator))
+    DCHECK(extensions::ExtensionsBrowserClient::Get()
+               ->IsWebUIAllowedToMakeNetworkRequests(*request.initiator))
         << "Unsupported network request from "
         << request.initiator->GetURL().spec() << " for " << url.spec();
     return true;
diff --git a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
index f69ed0b..5d4baf9 100644
--- a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
+++ b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
@@ -202,7 +202,7 @@
       status.error_code);
 
   // Deletes |this|.
-  factory_->RemoveRequest(network_service_request_id_);
+  factory_->RemoveRequest(network_service_request_id_, request_id_);
 }
 
 void WebRequestProxyingURLLoaderFactory::InProgressRequest::HandleAuthRequest(
@@ -506,7 +506,7 @@
       true /* started */, status.error_code);
 
   // Deletes |this|.
-  factory_->RemoveRequest(network_service_request_id_);
+  factory_->RemoveRequest(network_service_request_id_, request_id_);
 }
 
 WebRequestProxyingURLLoaderFactory::WebRequestProxyingURLLoaderFactory(
@@ -572,6 +572,12 @@
     const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
+  // The request ID doesn't really matter in the Network Service path. It just
+  // needs to be unique per-BrowserContext so extensions can make sense of it.
+  // Note that |network_service_request_id_| by contrast is not necessarily
+  // unique, so we don't use it for identity here.
+  const uint64_t web_request_id = request_id_generator_->Generate();
+
   if (request_id) {
     // Only requests with a non-zero request ID can have their proxy associated
     // with said ID. This is necessary to support correlation against any auth
@@ -579,14 +585,9 @@
     // do not support dispatching |WebRequest.onAuthRequired| events.
     proxies_->AssociateProxyWithRequestId(
         this, content::GlobalRequestID(render_process_id_, request_id));
+    network_request_id_to_web_request_id_.emplace(request_id, web_request_id);
   }
 
-  // The request ID doesn't really matter in the Network Service path. It just
-  // needs to be unique per-BrowserContext so extensions can make sense of it.
-  // Note that |network_service_request_id_| by contrast is not necessarily
-  // unique, so we don't use it for identity here.
-  const uint64_t web_request_id = request_id_generator_->Generate();
-
   // The WebRequest API treats browser-originated non-navigation requests with a
   // few additional restrictions, so we deduce and propagate that information
   // here.
@@ -599,7 +600,6 @@
           this, web_request_id, request_id, routing_id, options,
           is_non_navigation_browser_request, request, traffic_annotation,
           std::move(loader_request), std::move(client)));
-  network_request_id_to_web_request_id_.emplace(request_id, web_request_id);
   result.first->second->Restart();
 }
 
@@ -650,13 +650,10 @@
 }
 
 void WebRequestProxyingURLLoaderFactory::RemoveRequest(
-    int32_t network_service_request_id) {
-  auto it =
-      network_request_id_to_web_request_id_.find(network_service_request_id);
-  DCHECK(it != network_request_id_to_web_request_id_.end());
-  uint64_t web_request_id = it->second;
-  network_request_id_to_web_request_id_.erase(it);
-  requests_.erase(web_request_id);
+    int32_t network_service_request_id,
+    uint64_t request_id) {
+  network_request_id_to_web_request_id_.erase(network_service_request_id);
+  requests_.erase(request_id);
 }
 
 }  // namespace extensions
diff --git a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h
index 7ccbf1a..19632669 100644
--- a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h
+++ b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h
@@ -197,7 +197,7 @@
  private:
   void OnTargetFactoryError();
   void OnProxyBindingError();
-  void RemoveRequest(int32_t network_service_request_id);
+  void RemoveRequest(int32_t network_service_request_id, uint64_t request_id);
 
   void* const browser_context_;
   content::ResourceContext* const resource_context_;
diff --git a/extensions/browser/extensions_browser_client.cc b/extensions/browser/extensions_browser_client.cc
index 557f5c7..882897c 100644
--- a/extensions/browser/extensions_browser_client.cc
+++ b/extensions/browser/extensions_browser_client.cc
@@ -66,6 +66,11 @@
   return false;
 }
 
+bool ExtensionsBrowserClient::IsWebUIAllowedToMakeNetworkRequests(
+    const url::Origin& origin) {
+  return false;
+}
+
 ExtensionsBrowserClient* ExtensionsBrowserClient::Get() {
   return g_extension_browser_client;
 }
diff --git a/extensions/browser/extensions_browser_client.h b/extensions/browser/extensions_browser_client.h
index 0a0003d..bb45a8ac 100644
--- a/extensions/browser/extensions_browser_client.h
+++ b/extensions/browser/extensions_browser_client.h
@@ -327,6 +327,13 @@
   virtual bool IsExtensionEnabled(const std::string& extension_id,
                                   content::BrowserContext* context) const;
 
+  // http://crbug.com/829412
+  // Renderers with WebUI bindings shouldn't make http(s) requests for security
+  // reasons (e.g. to avoid malicious responses being able to run code in
+  // priviliged renderers). Fix these webui's to make requests through C++
+  // code instead.
+  virtual bool IsWebUIAllowedToMakeNetworkRequests(const url::Origin& origin);
+
   // Returns the single instance of |this|.
   static ExtensionsBrowserClient* Get();
 
diff --git a/infra/config/global/luci-milo-dev.cfg b/infra/config/global/luci-milo-dev.cfg
index 21510c9..dfce76f 100644
--- a/infra/config/global/luci-milo-dev.cfg
+++ b/infra/config/global/luci-milo-dev.cfg
@@ -1103,7 +1103,7 @@
     short_name: "N5"
   }
   builders: {
-    name: "buildbot/chromium.perf/Android Nexus5X Perf"
+    name: "buildbot/chromium.perf/android-nexus5x-perf"
     category: "perf|android"
     short_name: "N5X"
   }
@@ -1128,7 +1128,7 @@
     short_name: "dpi"
   }
   builders: {
-    name: "buildbot/chromium.perf/Win 10 Perf"
+    name: "buildbot/chromium.perf/win-10-perf"
     category: "perf|win|10"
     short_name: ""
   }
diff --git a/infra/config/global/luci-milo.cfg b/infra/config/global/luci-milo.cfg
index ddd7f4f..05954f7e 100644
--- a/infra/config/global/luci-milo.cfg
+++ b/infra/config/global/luci-milo.cfg
@@ -1239,8 +1239,8 @@
     short_name: "N5"
   }
   builders {
-    name: "buildbot/chromium.perf/Android Nexus5X Perf"
-    name: "buildbucket/luci.chromium.ci/Android Nexus5X Perf"
+    name: "buildbot/chromium.perf/android-nexus5x-perf"
+    name: "buildbucket/luci.chromium.ci/android-nexus5x-perf"
     category: "perf|android"
     short_name: "N5X"
   }
@@ -1269,8 +1269,8 @@
     short_name: "dpi"
   }
   builders {
-    name: "buildbot/chromium.perf/Win 10 Perf"
-    name: "buildbucket/luci.chromium.ci/Win 10 Perf"
+    name: "buildbot/chromium.perf/win-10-perf"
+    name: "buildbucket/luci.chromium.ci/win-10-perf"
     category: "perf|win|10"
   }
   builders {
diff --git a/ios/chrome/browser/consent_auditor/consent_auditor_factory.cc b/ios/chrome/browser/consent_auditor/consent_auditor_factory.cc
index 3a5cdcf..ff64ee1 100644
--- a/ios/chrome/browser/consent_auditor/consent_auditor_factory.cc
+++ b/ios/chrome/browser/consent_auditor/consent_auditor_factory.cc
@@ -9,7 +9,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/memory/singleton.h"
 #include "components/browser_sync/profile_sync_service.h"
-#include "components/consent_auditor/consent_auditor.h"
+#include "components/consent_auditor/consent_auditor_impl.h"
 #include "components/consent_auditor/consent_sync_bridge.h"
 #include "components/consent_auditor/consent_sync_bridge_impl.h"
 #include "components/keyed_service/ios/browser_state_dependency_manager.h"
@@ -76,7 +76,7 @@
         IOSUserEventServiceFactory::GetForBrowserState(ios_browser_state);
   }
 
-  return std::make_unique<consent_auditor::ConsentAuditor>(
+  return std::make_unique<consent_auditor::ConsentAuditorImpl>(
       ios_browser_state->GetPrefs(), std::move(consent_sync_bridge),
       user_event_service,
       // The browser version and locale do not change runtime, so we can pass
@@ -91,5 +91,5 @@
 
 void ConsentAuditorFactory::RegisterBrowserStatePrefs(
     user_prefs::PrefRegistrySyncable* registry) {
-  consent_auditor::ConsentAuditor::RegisterProfilePrefs(registry);
+  consent_auditor::ConsentAuditorImpl::RegisterProfilePrefs(registry);
 }
diff --git a/ios/chrome/browser/passwords/password_generation_utils.mm b/ios/chrome/browser/passwords/password_generation_utils.mm
index dec6d212..4234a7d 100644
--- a/ios/chrome/browser/passwords/password_generation_utils.mm
+++ b/ios/chrome/browser/passwords/password_generation_utils.mm
@@ -4,9 +4,6 @@
 
 #include "ios/chrome/browser/passwords/password_generation_utils.h"
 
-#include "base/i18n/rtl.h"
-#include "ios/chrome/browser/ui/ui_util.h"
-
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
@@ -15,8 +12,6 @@
 
 namespace {
 
-const CGFloat kPadding = IsIPadIdiom() ? 16 : 8;
-
 // The actual implementation of |RunPipeline| that begins with the first block
 // in |blocks|.
 void RunSearchPipeline(NSArray* blocks,
diff --git a/ios/chrome/browser/ui/authentication/chrome_signin_view_controller_unittest.mm b/ios/chrome/browser/ui/authentication/chrome_signin_view_controller_unittest.mm
index ab220e9f..e9af4908 100644
--- a/ios/chrome/browser/ui/authentication/chrome_signin_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/authentication/chrome_signin_view_controller_unittest.mm
@@ -83,12 +83,7 @@
 
 static std::unique_ptr<KeyedService> CreateFakeConsentAuditor(
     web::BrowserState* context) {
-  ios::ChromeBrowserState* ios_context =
-      ios::ChromeBrowserState::FromBrowserState(context);
-  syncer::UserEventService* const user_event_service =
-      IOSUserEventServiceFactory::GetForBrowserState(ios_context);
-  return std::make_unique<consent_auditor::FakeConsentAuditor>(
-      ios_context->GetPrefs(), user_event_service);
+  return std::make_unique<consent_auditor::FakeConsentAuditor>();
 }
 
 // These tests verify that Chrome correctly records user's consent to Chrome
diff --git a/ios/chrome/browser/ui/find_bar/BUILD.gn b/ios/chrome/browser/ui/find_bar/BUILD.gn
index 99bc96f7..e47301c 100644
--- a/ios/chrome/browser/ui/find_bar/BUILD.gn
+++ b/ios/chrome/browser/ui/find_bar/BUILD.gn
@@ -41,6 +41,7 @@
     "//ios/chrome/browser/find_in_page",
     "//ios/chrome/browser/ui",
     "//ios/chrome/browser/ui/commands",
+    "//ios/chrome/browser/ui/toolbar/buttons",
     "//ios/third_party/material_components_ios",
     "//ui/base",
     "//ui/gfx",
diff --git a/ios/chrome/browser/ui/find_bar/find_bar_controller_ios.mm b/ios/chrome/browser/ui/find_bar/find_bar_controller_ios.mm
index 4a48180..1bf4bc3 100644
--- a/ios/chrome/browser/ui/find_bar/find_bar_controller_ios.mm
+++ b/ios/chrome/browser/ui/find_bar/find_bar_controller_ios.mm
@@ -15,8 +15,11 @@
 #import "ios/chrome/browser/ui/UIView+SizeClassSupport.h"
 #import "ios/chrome/browser/ui/commands/browser_commands.h"
 #import "ios/chrome/browser/ui/find_bar/find_bar_ui_element.h"
+#import "ios/chrome/browser/ui/find_bar/find_bar_view.h"
 #import "ios/chrome/browser/ui/find_bar/legacy_find_bar_view.h"
+#import "ios/chrome/browser/ui/toolbar/buttons/toolbar_constants.h"
 #include "ios/chrome/browser/ui/ui_util.h"
+#import "ios/chrome/browser/ui/uikit_ui_util.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 #include "ui/base/resource/resource_bundle.h"
 
@@ -126,11 +129,30 @@
   } else {
     findBarBackground =
         [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 56)];
-    findBarBackground.backgroundColor = [UIColor whiteColor];
+    if (self.isIncognito) {
+      findBarBackground.backgroundColor =
+          [UIColor colorWithWhite:115 / 255.0 alpha:1];
+    } else {
+      findBarBackground.backgroundColor = [UIColor whiteColor];
+    }
   }
 
-  self.findBarView = [[LegacyFindBarView alloc]
-      initWithDarkAppearance:self.isIncognito && !IsIPadIdiom()];
+  if (IsUIRefreshPhase1Enabled()) {
+    FindBarView* findBarView =
+        [[FindBarView alloc] initWithDarkAppearance:self.isIncognito];
+    self.findBarView = findBarView;
+    if (self.isIncognito) {
+      findBarBackground.backgroundColor =
+          UIColorFromRGB(kIncognitoToolbarBackgroundColor);
+    } else {
+      findBarBackground.backgroundColor =
+          UIColorFromRGB(kToolbarBackgroundColor);
+    }
+  } else {
+    self.findBarView = [[LegacyFindBarView alloc]
+        initWithDarkAppearance:self.isIncognito && !IsIPadIdiom()];
+  }
+
   [findBarBackground addSubview:self.findBarView];
   self.findBarView.translatesAutoresizingMaskIntoConstraints = NO;
   NSMutableArray* constraints = [[NSMutableArray alloc] init];
@@ -199,10 +221,6 @@
   CGRect frame = self.view.frame;
   frame.size.height = [self findBarHeight];
   self.view.frame = frame;
-
-  if (self.isIncognito) {
-    [self.view setBackgroundColor:[UIColor colorWithWhite:115 / 255.0 alpha:1]];
-  }
 }
 
 - (void)setUpIPad {
diff --git a/ios/chrome/browser/ui/find_bar/find_bar_ui_element.h b/ios/chrome/browser/ui/find_bar/find_bar_ui_element.h
index 560df9b..aab832f 100644
--- a/ios/chrome/browser/ui/find_bar/find_bar_ui_element.h
+++ b/ios/chrome/browser/ui/find_bar/find_bar_ui_element.h
@@ -17,13 +17,13 @@
 - (void)updateResultsLabelWithText:(NSString*)text;
 
 // The textfield with search term.
-@property(nonatomic, weak) UITextField* inputField;
+@property(nonatomic, strong) UITextField* inputField;
 // Button to go to previous search result.
-@property(nonatomic, weak) UIButton* previousButton;
+@property(nonatomic, strong) UIButton* previousButton;
 // Button to go to next search result.
-@property(nonatomic, weak) UIButton* nextButton;
+@property(nonatomic, strong) UIButton* nextButton;
 // Button to dismiss Find in Page.
-@property(nonatomic, weak) UIButton* closeButton;
+@property(nonatomic, strong) UIButton* closeButton;
 
 @end
 
diff --git a/ios/chrome/browser/ui/find_bar/find_bar_view.h b/ios/chrome/browser/ui/find_bar/find_bar_view.h
index 08448ea..dae76f2 100644
--- a/ios/chrome/browser/ui/find_bar/find_bar_view.h
+++ b/ios/chrome/browser/ui/find_bar/find_bar_view.h
@@ -14,6 +14,14 @@
 // in format of "1 of 13", and next/previous/close buttons.
 @interface FindBarView : UIView<FindBarUIElement>
 
+// Designated initializer. |darkAppearance| makes the background to dark color
+// and changes font colors to lighter colors.
+- (instancetype)initWithDarkAppearance:(BOOL)darkAppearance
+    NS_DESIGNATED_INITIALIZER;
+
+- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
+- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_FIND_BAR_FIND_BAR_VIEW_H_
diff --git a/ios/chrome/browser/ui/find_bar/find_bar_view.mm b/ios/chrome/browser/ui/find_bar/find_bar_view.mm
index 01c3988..496e736 100644
--- a/ios/chrome/browser/ui/find_bar/find_bar_view.mm
+++ b/ios/chrome/browser/ui/find_bar/find_bar_view.mm
@@ -4,19 +4,278 @@
 
 #import "ios/chrome/browser/ui/find_bar/find_bar_view.h"
 
+#include "components/strings/grit/components_strings.h"
+#import "ios/chrome/browser/ui/find_bar/find_bar_constants.h"
+#import "ios/chrome/browser/ui/find_bar/find_bar_touch_forwarding_view.h"
+#import "ios/chrome/browser/ui/toolbar/buttons/toolbar_constants.h"
+#import "ios/chrome/browser/ui/uikit_ui_util.h"
+#import "ios/chrome/common/ui_util/constraints_ui_util.h"
+#include "ios/chrome/grit/ios_strings.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
+namespace {
+// Horizontal padding betwee all elements (except the previous/next buttons).
+const CGFloat kPadding = 8;
+const CGFloat kInputFieldCornerRadius = 10;
+const CGFloat kFontSize = 15;
+const CGFloat kButtonFontSize = 17;
+const CGFloat kInputFieldHeight = 38;
+const CGFloat kButtonLength = 44;
+const CGFloat kInputFieldTextAlpha = 0.7;
+const CGFloat kPlaceholderAlpha = 0.3;
+const CGFloat kPlaceholderAlphaIncognito = 0.5;
+const CGFloat kResultsCountLabelAdditionalAlpha = 0.2;
+const CGFloat kBlueTintColor = 0x1A73E8;
+}  // namespace
+
+@interface FindBarView ()
+
+// The overlay that shows number of results in format "1 of 13".
+@property(nonatomic, strong) UILabel* resultsCountLabel;
+
+@property(nonatomic, assign) BOOL darkMode;
+
+@end
+
 @implementation FindBarView
 
 @synthesize inputField = _inputField;
 @synthesize previousButton = _previousButton;
 @synthesize nextButton = _nextButton;
 @synthesize closeButton = _closeButton;
+@synthesize resultsCountLabel = _resultsCountLabel;
+@synthesize darkMode = _darkMode;
+
+#pragma mark - Public
+
+- (instancetype)initWithDarkAppearance:(BOOL)darkAppearance {
+  self = [super initWithFrame:CGRectZero];
+  if (self) {
+    _darkMode = darkAppearance;
+  }
+  return self;
+}
 
 - (void)updateResultsLabelWithText:(NSString*)text {
-  // TODO(crbug.com/805504): Implement this.
+  self.resultsCountLabel.hidden = (text.length == 0);
+  self.resultsCountLabel.text = text;
+}
+
+- (void)didMoveToSuperview {
+  [super didMoveToSuperview];
+
+  if (self.inputField.superview)
+    return;
+
+  [self setupSubviews];
+  [self setupConstraints];
+}
+
+#pragma mark - Private
+
+// Creates, adds and configures the subviews.
+- (void)setupSubviews {
+  [self addLabel:self.resultsCountLabel asRightViewOfTextField:self.inputField];
+  [self addSubview:self.inputField];
+  [self addSubview:self.previousButton];
+  [self addSubview:self.nextButton];
+  [self addSubview:self.closeButton];
+
+  [self setupColors];
+}
+
+// Sets the constraints for the subviews up.
+// The subviews layout is the following:
+// |-[inputField]-[previousButton][nextButton]-[closeButton]-|
+- (void)setupConstraints {
+  id<LayoutGuideProvider> safeArea = SafeAreaLayoutGuideForView(self);
+
+  [NSLayoutConstraint activateConstraints:@[
+    // Input Field.
+    [self.inputField.centerYAnchor constraintEqualToAnchor:self.centerYAnchor],
+    [self.inputField.heightAnchor constraintEqualToConstant:kInputFieldHeight],
+    [self.inputField.leadingAnchor
+        constraintEqualToAnchor:safeArea.leadingAnchor
+                       constant:kPadding],
+
+    [self.inputField.trailingAnchor
+        constraintEqualToAnchor:self.previousButton.leadingAnchor
+                       constant:-kPadding],
+
+    // Previous Button.
+    [self.previousButton.centerYAnchor
+        constraintEqualToAnchor:self.centerYAnchor],
+    [self.previousButton.widthAnchor constraintEqualToConstant:kButtonLength],
+    [self.previousButton.heightAnchor constraintEqualToConstant:kButtonLength],
+
+    [self.previousButton.trailingAnchor
+        constraintEqualToAnchor:self.nextButton.leadingAnchor],
+
+    // Next Button.
+    [self.nextButton.centerYAnchor constraintEqualToAnchor:self.centerYAnchor],
+    [self.nextButton.widthAnchor constraintEqualToConstant:kButtonLength],
+    [self.nextButton.heightAnchor constraintEqualToConstant:kButtonLength],
+
+    [self.nextButton.trailingAnchor
+        constraintEqualToAnchor:self.closeButton.leadingAnchor
+                       constant:-kPadding],
+
+    // Close Button.
+    [self.closeButton.centerYAnchor constraintEqualToAnchor:self.centerYAnchor],
+    [self.closeButton.heightAnchor constraintEqualToConstant:kButtonLength],
+    // Use button intrinsic width.
+    [self.closeButton.trailingAnchor
+        constraintEqualToAnchor:safeArea.trailingAnchor
+                       constant:-kPadding],
+  ]];
+}
+
+// Sets the colors for the different subviews, based on the |darkMode|.
+- (void)setupColors {
+  UIColor* inputFieldBackground =
+      self.darkMode
+          ? [UIColor
+                colorWithWhite:1
+                         alpha:kAdaptiveLocationBarBackgroundAlphaIncognito]
+          : [UIColor colorWithWhite:0
+                              alpha:kAdaptiveLocationBarBackgroundAlpha];
+  UIColor* inputFieldPlaceHolderTextColor =
+      self.darkMode
+          ? [UIColor colorWithWhite:1 alpha:kPlaceholderAlphaIncognito]
+          : [UIColor colorWithWhite:0 alpha:kPlaceholderAlpha];
+  UIColor* inputFieldTextColor =
+      self.darkMode ? [UIColor whiteColor]
+                    : [UIColor colorWithWhite:0 alpha:kInputFieldTextAlpha];
+  UIColor* resultsCountLabelTextColor =
+      self.darkMode
+          ? [UIColor colorWithWhite:1
+                              alpha:kPlaceholderAlphaIncognito +
+                                    kResultsCountLabelAdditionalAlpha]
+          : [UIColor colorWithWhite:0
+                              alpha:kPlaceholderAlpha +
+                                    kResultsCountLabelAdditionalAlpha];
+  UIColor* buttonTintColor =
+      self.darkMode ? [UIColor whiteColor] : UIColorFromRGB(kBlueTintColor);
+
+  self.inputField.backgroundColor = inputFieldBackground;
+  NSString* placeholder = [self.inputField placeholder];
+  NSDictionary* attributes =
+      @{NSForegroundColorAttributeName : inputFieldPlaceHolderTextColor};
+  [self.inputField setAttributedPlaceholder:[[NSAttributedString alloc]
+                                                initWithString:placeholder
+                                                    attributes:attributes]];
+  self.inputField.textColor = inputFieldTextColor;
+  self.inputField.tintColor = buttonTintColor;
+
+  // Results count.
+  self.resultsCountLabel.textColor = resultsCountLabelTextColor;
+
+  // Buttons.
+  self.previousButton.tintColor = buttonTintColor;
+  self.nextButton.tintColor = buttonTintColor;
+  self.closeButton.tintColor = buttonTintColor;
+}
+
+#pragma mark - Configuration
+
+// Adds |rightLabel| as right view of the |textField|.
+- (void)addLabel:(UILabel*)rightLabel
+    asRightViewOfTextField:(UITextField*)textField {
+  UIView* rightView = [[UIView alloc] init];
+  rightView.userInteractionEnabled = NO;
+  rightView.translatesAutoresizingMaskIntoConstraints = NO;
+  [rightView addSubview:rightLabel];
+  AddSameConstraintsToSidesWithInsets(
+      rightLabel, rightView,
+      LayoutSides::kTop | LayoutSides::kBottom | LayoutSides::kLeading |
+          LayoutSides::kTrailing,
+      ChromeDirectionalEdgeInsetsMake(0, 0, 0, kPadding));
+  textField.rightView = rightView;
+  textField.rightViewMode = UITextFieldViewModeAlways;
+}
+
+#pragma mark - Property accessors
+
+// Creates and returns the input text field.
+- (UITextField*)inputField {
+  if (!_inputField) {
+    _inputField = [[UITextField alloc] init];
+    UIView* leftPadding =
+        [[UIView alloc] initWithFrame:CGRectMake(0, 0, kPadding, 0)];
+    leftPadding.userInteractionEnabled = NO;
+    _inputField.leftView = leftPadding;
+    _inputField.leftViewMode = UITextFieldViewModeAlways;
+
+    _inputField.layer.cornerRadius = kInputFieldCornerRadius;
+    _inputField.translatesAutoresizingMaskIntoConstraints = NO;
+    _inputField.placeholder =
+        l10n_util::GetNSString(IDS_IOS_PLACEHOLDER_FIND_IN_PAGE);
+    _inputField.font = [UIFont systemFontOfSize:kFontSize];
+    _inputField.accessibilityIdentifier = kFindInPageInputFieldId;
+  }
+  return _inputField;
+}
+
+// Creates and returns the results count label.
+- (UILabel*)resultsCountLabel {
+  if (!_resultsCountLabel) {
+    _resultsCountLabel = [[UILabel alloc] init];
+    _resultsCountLabel.translatesAutoresizingMaskIntoConstraints = NO;
+    _resultsCountLabel.font = [UIFont systemFontOfSize:kFontSize];
+  }
+
+  return _resultsCountLabel;
+}
+
+// Creates and returns the previous button.
+- (UIButton*)previousButton {
+  if (!_previousButton) {
+    _previousButton = [UIButton buttonWithType:UIButtonTypeSystem];
+    [_previousButton
+        setImage:[[UIImage imageNamed:@"find_prev"]
+                     imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]
+        forState:UIControlStateNormal];
+    _previousButton.translatesAutoresizingMaskIntoConstraints = NO;
+    SetA11yLabelAndUiAutomationName(_previousButton,
+                                    IDS_FIND_IN_PAGE_PREVIOUS_TOOLTIP,
+                                    kFindInPagePreviousButtonId);
+  }
+
+  return _previousButton;
+}
+
+// Creates and returns the next button.
+- (UIButton*)nextButton {
+  if (!_nextButton) {
+    _nextButton = [UIButton buttonWithType:UIButtonTypeSystem];
+    [_nextButton
+        setImage:[[UIImage imageNamed:@"find_next"]
+                     imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]
+        forState:UIControlStateNormal];
+    _nextButton.translatesAutoresizingMaskIntoConstraints = NO;
+    SetA11yLabelAndUiAutomationName(_nextButton, IDS_FIND_IN_PAGE_NEXT_TOOLTIP,
+                                    kFindInPageNextButtonId);
+  }
+
+  return _nextButton;
+}
+
+// Creates and returns the closes button.
+- (UIButton*)closeButton {
+  if (!_closeButton) {
+    _closeButton = [UIButton buttonWithType:UIButtonTypeSystem];
+    [_closeButton setTitle:l10n_util::GetNSString(IDS_DONE)
+                  forState:UIControlStateNormal];
+    _closeButton.translatesAutoresizingMaskIntoConstraints = NO;
+    _closeButton.accessibilityIdentifier = kFindInPageCloseButtonId;
+    _closeButton.titleLabel.font = [UIFont systemFontOfSize:kButtonFontSize];
+  }
+
+  return _closeButton;
 }
 
 @end
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm b/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm
index 2059098..8419a95 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm
+++ b/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm
@@ -19,7 +19,7 @@
 namespace {
 
 // Length of the trailing button side.
-const CGFloat kButtonSize = 28;
+const CGFloat kButtonSize = 24;
 
 // Space between the location icon and the location label.
 const CGFloat kLocationImageToLabelSpacing = 2.0;
@@ -202,8 +202,6 @@
 
     // Setup and activate the show button constraints.
     _showButtonConstraints = @[
-      // TODO(crbug.com/821804) Replace the temporary size when the icon is
-      // available.
       [_trailingButton.widthAnchor constraintEqualToConstant:kButtonSize],
       [_trailingButton.heightAnchor constraintEqualToConstant:kButtonSize],
       [self.trailingButton.trailingAnchor
@@ -295,9 +293,7 @@
 - (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection {
   [super traitCollectionDidChange:previousTraitCollection];
   self.locationLabel.font =
-      [UIFont systemFontOfSize:IsRegularXRegularSizeClass()
-                                   ? kLocationBarRegularRegularFontSize
-                                   : kLocationBarFontSize];
+      [UIFont systemFontOfSize:kLocationBarSteadyFontSize];
 }
 
 #pragma mark - UIAccessibilityContainer
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/location_bar_dangerous.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/location_bar_dangerous.png
index eb34d75d..059130a2 100644
--- a/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/location_bar_dangerous.png
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/location_bar_dangerous.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/location_bar_dangerous@2x.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/location_bar_dangerous@2x.png
index c811e280..02b5d1bb 100644
--- a/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/location_bar_dangerous@2x.png
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/location_bar_dangerous@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/location_bar_dangerous@3x.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/location_bar_dangerous@3x.png
index 32162e26..c06be342 100644
--- a/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/location_bar_dangerous@3x.png
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/location_bar_dangerous@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/location_bar_insecure.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/location_bar_insecure.png
index 15eceac..11be682 100644
--- a/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/location_bar_insecure.png
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/location_bar_insecure.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/location_bar_insecure@2x.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/location_bar_insecure@2x.png
index afbff5b..c21ea9ab0 100644
--- a/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/location_bar_insecure@2x.png
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/location_bar_insecure@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/location_bar_insecure@3x.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/location_bar_insecure@3x.png
index ae826e6..aa387183 100644
--- a/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/location_bar_insecure@3x.png
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/location_bar_insecure@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_offline.imageset/location_bar_offline.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_offline.imageset/location_bar_offline.png
index 0b56a87..8518a81f 100644
--- a/ios/chrome/browser/ui/location_bar/resources/location_bar_offline.imageset/location_bar_offline.png
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_offline.imageset/location_bar_offline.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_offline.imageset/location_bar_offline@2x.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_offline.imageset/location_bar_offline@2x.png
index b8830683..dcc0c26c 100644
--- a/ios/chrome/browser/ui/location_bar/resources/location_bar_offline.imageset/location_bar_offline@2x.png
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_offline.imageset/location_bar_offline@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_offline.imageset/location_bar_offline@3x.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_offline.imageset/location_bar_offline@3x.png
index b1fca28..cb908a8 100644
--- a/ios/chrome/browser/ui/location_bar/resources/location_bar_offline.imageset/location_bar_offline@3x.png
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_offline.imageset/location_bar_offline@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure.png
index 2d70b5d..0cc7718 100644
--- a/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure.png
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure@2x.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure@2x.png
index d0f9899..d1053cb93 100644
--- a/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure@2x.png
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure@3x.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure@3x.png
index d869872..2267e325 100644
--- a/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure@3x.png
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_share.imageset/location_bar_share.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_share.imageset/location_bar_share.png
index 06bb1c1..c50dc13 100644
--- a/ios/chrome/browser/ui/location_bar/resources/location_bar_share.imageset/location_bar_share.png
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_share.imageset/location_bar_share.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_share.imageset/location_bar_share@2x.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_share.imageset/location_bar_share@2x.png
index 3b9f752..30f8985 100644
--- a/ios/chrome/browser/ui/location_bar/resources/location_bar_share.imageset/location_bar_share@2x.png
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_share.imageset/location_bar_share@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_share.imageset/location_bar_share@3x.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_share.imageset/location_bar_share@3x.png
index 80affe49..bde8f31 100644
--- a/ios/chrome/browser/ui/location_bar/resources/location_bar_share.imageset/location_bar_share@3x.png
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_share.imageset/location_bar_share@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_voice.imageset/location_bar_voice.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_voice.imageset/location_bar_voice.png
index 1f550d81..0fd3174 100644
--- a/ios/chrome/browser/ui/location_bar/resources/location_bar_voice.imageset/location_bar_voice.png
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_voice.imageset/location_bar_voice.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_voice.imageset/location_bar_voice@2x.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_voice.imageset/location_bar_voice@2x.png
index 74f7eed..cd593e9f 100644
--- a/ios/chrome/browser/ui/location_bar/resources/location_bar_voice.imageset/location_bar_voice@2x.png
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_voice.imageset/location_bar_voice@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_voice.imageset/location_bar_voice@3x.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_voice.imageset/location_bar_voice@3x.png
index 529c250..d05be27 100644
--- a/ios/chrome/browser/ui/location_bar/resources/location_bar_voice.imageset/location_bar_voice@3x.png
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_voice.imageset/location_bar_voice@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm b/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm
index ad680c7..2b4172e 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm
+++ b/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm
@@ -445,7 +445,7 @@
     return self.normalFont;
   }
 
-  return IsRegularXRegularSizeClass() ? self.largerFont : self.normalFont;
+  return IsCompactWidth() ? self.normalFont : self.largerFont;
 }
 
 #pragma mark - Private methods
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm b/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm
index 8ce2705..4d85fe2 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm
+++ b/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm
@@ -96,6 +96,23 @@
 
 #pragma mark - private
 
+- (void)updateLeadingImageVisibility {
+  [self.view setLeadingImageHidden:!IsRegularXRegularSizeClass(self)];
+}
+
+// Tint color for the textfield placeholder and the clear button.
+- (UIColor*)placeholderAndClearButtonColor {
+  return self.incognito ? [UIColor colorWithWhite:1 alpha:0.5]
+                        : [UIColor colorWithWhite:0 alpha:0.3];
+}
+
+#pragma mark clear button
+
+// Omnibox uses a custom clear button. It has a custom tint and image, but
+// otherwise it should act exactly like a system button. To achieve this, a
+// custom button is used as the |rightView|. Textfield's setRightViewMode: is
+// used to make the button invisible when the textfield is empty; the visibility
+// is updated on textfield text changes and clear button presses.
 - (void)setupClearButton {
   // Do not use the system clear button. Use a custom "right view" instead.
   // Note that |rightView| is an incorrect name, it's really a trailing view.
@@ -113,6 +130,12 @@
   clearButton.tintColor = [self placeholderAndClearButtonColor];
   SetA11yLabelAndUiAutomationName(clearButton, IDS_IOS_ACCNAME_CLEAR_TEXT,
                                   @"Clear Text");
+
+  // Observe text changes to show the clear button when there is text and hide
+  // it when the textfield is empty.
+  [self.textField addTarget:self
+                     action:@selector(textFieldDidChange:)
+           forControlEvents:UIControlEventEditingChanged];
 }
 
 - (UIImage*)clearButtonIcon {
@@ -128,17 +151,22 @@
       [self.textField.delegate textFieldShouldClear:self.textField];
   if (shouldClear) {
     [self.textField setText:@""];
+    // Calling setText: does not trigger UIControlEventEditingChanged, so update
+    // the clear button visibility manually.
+    [self updateClearButtonVisibility];
   }
 }
 
-- (void)updateLeadingImageVisibility {
-  [self.view setLeadingImageHidden:!IsRegularXRegularSizeClass(self)];
+// Called on textField's UIControlEventEditingChanged.
+- (void)textFieldDidChange:(UITextField*)textField {
+  [self updateClearButtonVisibility];
 }
 
-// Tint color for the textfield placeholder and the clear button.
-- (UIColor*)placeholderAndClearButtonColor {
-  return self.incognito ? [UIColor colorWithWhite:1 alpha:0.5]
-                        : [UIColor colorWithWhite:0 alpha:0.3];
+// Hides the clear button if the textfield is empty; shows it otherwise.
+- (void)updateClearButtonVisibility {
+  BOOL hasText = self.textField.text.length > 0;
+  [self.textField setRightViewMode:hasText ? UITextFieldViewModeAlways
+                                           : UITextFieldViewModeNever];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_mediator.mm b/ios/chrome/browser/ui/reading_list/reading_list_mediator.mm
index 4b255b7..6fcff42 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_mediator.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_mediator.mm
@@ -13,6 +13,7 @@
 #include "components/reading_list/core/reading_list_model.h"
 #import "components/reading_list/ios/reading_list_model_bridge_observer.h"
 #include "components/url_formatter/url_formatter.h"
+#include "ios/chrome/browser/experimental_flags.h"
 #import "ios/chrome/browser/ui/favicon/favicon_attributes_provider.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_data_sink.h"
@@ -21,6 +22,7 @@
 #import "ios/chrome/browser/ui/reading_list/reading_list_list_item_util.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_table_view_item.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_utils.h"
+#import "ios/chrome/browser/ui/uikit_ui_util.h"
 #import "ios/chrome/common/favicon/favicon_view.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -32,6 +34,10 @@
 bool EntrySorter(const ReadingListEntry* rhs, const ReadingListEntry* lhs) {
   return rhs->UpdateTime() > lhs->UpdateTime();
 }
+// Light gray color that matches the favicon background image color to eliminate
+// setting a non-opaque background color.
+const CGFloat kFallbackIconDefaultBackgroundColor = 0xf1f3f4;
+
 }  // namespace
 
 @interface ReadingListMediator ()<ReadingListModelBridgeObserver> {
@@ -164,7 +170,17 @@
         if (!strongSelf || !strongItem) {
           return;
         }
-
+        if (attributes.monogramString &&
+            experimental_flags::IsCollectionsUIRebootEnabled()) {
+          UIColor* textColor = [UIColor colorWithWhite:0 alpha:0.33];
+          UIColor* backgroundColor =
+              UIColorFromRGB(kFallbackIconDefaultBackgroundColor);
+          attributes = [FaviconAttributes
+              attributesWithMonogram:attributes.monogramString
+                           textColor:textColor
+                     backgroundColor:backgroundColor
+              defaultBackgroundColor:NO];
+        }
         strongItem.attributes = attributes;
 
         [strongSelf.dataSink itemHasChangedAfterDelay:strongItem];
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn
index b776880..3eebe327 100644
--- a/ios/chrome/browser/ui/settings/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -98,9 +98,19 @@
   deps = [
     "resources:app_icon_placeholder",
     "resources:encryption_error",
+    "resources:settings_about_chrome",
     "resources:settings_accounts_add_account",
+    "resources:settings_article_suggestions",
+    "resources:settings_autofill_forms",
+    "resources:settings_bandwidth",
+    "resources:settings_content_settings",
+    "resources:settings_debug",
     "resources:settings_error",
+    "resources:settings_passwords",
+    "resources:settings_privacy",
+    "resources:settings_search_engine",
     "resources:settings_sync",
+    "resources:settings_voice_search",
     "//base",
     "//base:i18n",
     "//components/autofill/core/browser",
diff --git a/ios/chrome/browser/ui/settings/cells/settings_switch_item.mm b/ios/chrome/browser/ui/settings/cells/settings_switch_item.mm
index f1f3ff1c..12a1d53b 100644
--- a/ios/chrome/browser/ui/settings/cells/settings_switch_item.mm
+++ b/ios/chrome/browser/ui/settings/cells/settings_switch_item.mm
@@ -179,6 +179,7 @@
     return;
   }
 
+  self.iconImageView.image = image;
   self.iconImageView.hidden = hidden;
   if (hidden) {
     self.iconVisibleConstraint.active = NO;
diff --git a/ios/chrome/browser/ui/settings/resources/BUILD.gn b/ios/chrome/browser/ui/settings/resources/BUILD.gn
index 3dd4220..610c042 100644
--- a/ios/chrome/browser/ui/settings/resources/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/resources/BUILD.gn
@@ -48,3 +48,93 @@
     "settings_sync.imageset/settings_sync@3x.png",
   ]
 }
+
+imageset("settings_about_chrome") {
+  sources = [
+    "settings_about_chrome.imageset/Contents.json",
+    "settings_about_chrome.imageset/settings_about_chrome.png",
+    "settings_about_chrome.imageset/settings_about_chrome@2x.png",
+    "settings_about_chrome.imageset/settings_about_chrome@3x.png",
+  ]
+}
+
+imageset("settings_article_suggestions") {
+  sources = [
+    "settings_article_suggestions.imageset/Contents.json",
+    "settings_article_suggestions.imageset/settings_article_suggestions.png",
+    "settings_article_suggestions.imageset/settings_article_suggestions@2x.png",
+    "settings_article_suggestions.imageset/settings_article_suggestions@3x.png",
+  ]
+}
+
+imageset("settings_autofill_forms") {
+  sources = [
+    "settings_autofill_forms.imageset/Contents.json",
+    "settings_autofill_forms.imageset/settings_autofill_forms.png",
+    "settings_autofill_forms.imageset/settings_autofill_forms@2x.png",
+    "settings_autofill_forms.imageset/settings_autofill_forms@3x.png",
+  ]
+}
+
+imageset("settings_bandwidth") {
+  sources = [
+    "settings_bandwidth.imageset/Contents.json",
+    "settings_bandwidth.imageset/settings_bandwidth.png",
+    "settings_bandwidth.imageset/settings_bandwidth@2x.png",
+    "settings_bandwidth.imageset/settings_bandwidth@3x.png",
+  ]
+}
+
+imageset("settings_content_settings") {
+  sources = [
+    "settings_content_settings.imageset/Contents.json",
+    "settings_content_settings.imageset/settings_content_settings.png",
+    "settings_content_settings.imageset/settings_content_settings@2x.png",
+    "settings_content_settings.imageset/settings_content_settings@3x.png",
+  ]
+}
+
+imageset("settings_debug") {
+  sources = [
+    "settings_debug.imageset/Contents.json",
+    "settings_debug.imageset/settings_debug.png",
+    "settings_debug.imageset/settings_debug@2x.png",
+    "settings_debug.imageset/settings_debug@3x.png",
+  ]
+}
+
+imageset("settings_passwords") {
+  sources = [
+    "settings_passwords.imageset/Contents.json",
+    "settings_passwords.imageset/settings_passwords.png",
+    "settings_passwords.imageset/settings_passwords@2x.png",
+    "settings_passwords.imageset/settings_passwords@3x.png",
+  ]
+}
+
+imageset("settings_privacy") {
+  sources = [
+    "settings_privacy.imageset/Contents.json",
+    "settings_privacy.imageset/settings_privacy.png",
+    "settings_privacy.imageset/settings_privacy@2x.png",
+    "settings_privacy.imageset/settings_privacy@3x.png",
+  ]
+}
+
+imageset("settings_search_engine") {
+  sources = [
+    "settings_search_engine.imageset/Contents.json",
+    "settings_search_engine.imageset/settings_search_engine.png",
+    "settings_search_engine.imageset/settings_search_engine@2x.png",
+    "settings_search_engine.imageset/settings_search_engine@3x.png",
+  ]
+}
+
+imageset("settings_voice_search") {
+  sources = [
+    "settings_voice_search.imageset/Contents.json",
+    "settings_voice_search.imageset/settings_voice_search.png",
+    "settings_voice_search.imageset/settings_voice_search@2x.png",
+    "settings_voice_search.imageset/settings_voice_search@3x.png",
+  ]
+}
diff --git a/ios/chrome/browser/ui/settings/resources/settings_about_chrome.imageset/Contents.json b/ios/chrome/browser/ui/settings/resources/settings_about_chrome.imageset/Contents.json
new file mode 100644
index 0000000..81e77e9
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_about_chrome.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+    "images": [
+        {
+            "idiom": "universal",
+            "scale": "1x",
+            "filename": "settings_about_chrome.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "2x",
+            "filename": "settings_about_chrome@2x.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "3x",
+            "filename": "settings_about_chrome@3x.png"
+        }
+    ],
+    "info": {
+        "version": 1,
+        "author": "xcode"
+    }
+}
diff --git a/ios/chrome/browser/ui/settings/resources/settings_about_chrome.imageset/settings_about_chrome.png b/ios/chrome/browser/ui/settings/resources/settings_about_chrome.imageset/settings_about_chrome.png
new file mode 100644
index 0000000..6b99ab5
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_about_chrome.imageset/settings_about_chrome.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_about_chrome.imageset/settings_about_chrome@2x.png b/ios/chrome/browser/ui/settings/resources/settings_about_chrome.imageset/settings_about_chrome@2x.png
new file mode 100644
index 0000000..0b952e01
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_about_chrome.imageset/settings_about_chrome@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_about_chrome.imageset/settings_about_chrome@3x.png b/ios/chrome/browser/ui/settings/resources/settings_about_chrome.imageset/settings_about_chrome@3x.png
new file mode 100644
index 0000000..092a30a
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_about_chrome.imageset/settings_about_chrome@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_article_suggestions.imageset/Contents.json b/ios/chrome/browser/ui/settings/resources/settings_article_suggestions.imageset/Contents.json
new file mode 100644
index 0000000..d7bff0e
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_article_suggestions.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+    "images": [
+        {
+            "idiom": "universal",
+            "scale": "1x",
+            "filename": "settings_article_suggestions.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "2x",
+            "filename": "settings_article_suggestions@2x.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "3x",
+            "filename": "settings_article_suggestions@3x.png"
+        }
+    ],
+    "info": {
+        "version": 1,
+        "author": "xcode"
+    }
+}
diff --git a/ios/chrome/browser/ui/settings/resources/settings_article_suggestions.imageset/settings_article_suggestions.png b/ios/chrome/browser/ui/settings/resources/settings_article_suggestions.imageset/settings_article_suggestions.png
new file mode 100644
index 0000000..cbcd093
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_article_suggestions.imageset/settings_article_suggestions.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_article_suggestions.imageset/settings_article_suggestions@2x.png b/ios/chrome/browser/ui/settings/resources/settings_article_suggestions.imageset/settings_article_suggestions@2x.png
new file mode 100644
index 0000000..b9415596
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_article_suggestions.imageset/settings_article_suggestions@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_article_suggestions.imageset/settings_article_suggestions@3x.png b/ios/chrome/browser/ui/settings/resources/settings_article_suggestions.imageset/settings_article_suggestions@3x.png
new file mode 100644
index 0000000..1a57e5b
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_article_suggestions.imageset/settings_article_suggestions@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/Contents.json b/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/Contents.json
new file mode 100644
index 0000000..248316be
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+    "images": [
+        {
+            "idiom": "universal",
+            "scale": "1x",
+            "filename": "settings_autofill_forms.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "2x",
+            "filename": "settings_autofill_forms@2x.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "3x",
+            "filename": "settings_autofill_forms@3x.png"
+        }
+    ],
+    "info": {
+        "version": 1,
+        "author": "xcode"
+    }
+}
diff --git a/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/settings_autofill_forms.png b/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/settings_autofill_forms.png
new file mode 100644
index 0000000..5b5fb84
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/settings_autofill_forms.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/settings_autofill_forms@2x.png b/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/settings_autofill_forms@2x.png
new file mode 100644
index 0000000..3f62534
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/settings_autofill_forms@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/settings_autofill_forms@3x.png b/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/settings_autofill_forms@3x.png
new file mode 100644
index 0000000..d65d49d
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_autofill_forms.imageset/settings_autofill_forms@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_bandwidth.imageset/Contents.json b/ios/chrome/browser/ui/settings/resources/settings_bandwidth.imageset/Contents.json
new file mode 100644
index 0000000..c68fe0e
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_bandwidth.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+    "images": [
+        {
+            "idiom": "universal",
+            "scale": "1x",
+            "filename": "settings_bandwidth.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "2x",
+            "filename": "settings_bandwidth@2x.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "3x",
+            "filename": "settings_bandwidth@3x.png"
+        }
+    ],
+    "info": {
+        "version": 1,
+        "author": "xcode"
+    }
+}
diff --git a/ios/chrome/browser/ui/settings/resources/settings_bandwidth.imageset/settings_bandwidth.png b/ios/chrome/browser/ui/settings/resources/settings_bandwidth.imageset/settings_bandwidth.png
new file mode 100644
index 0000000..ddd844a
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_bandwidth.imageset/settings_bandwidth.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_bandwidth.imageset/settings_bandwidth@2x.png b/ios/chrome/browser/ui/settings/resources/settings_bandwidth.imageset/settings_bandwidth@2x.png
new file mode 100644
index 0000000..822c82b
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_bandwidth.imageset/settings_bandwidth@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_bandwidth.imageset/settings_bandwidth@3x.png b/ios/chrome/browser/ui/settings/resources/settings_bandwidth.imageset/settings_bandwidth@3x.png
new file mode 100644
index 0000000..899463c
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_bandwidth.imageset/settings_bandwidth@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_content_settings.imageset/Contents.json b/ios/chrome/browser/ui/settings/resources/settings_content_settings.imageset/Contents.json
new file mode 100644
index 0000000..005cd93
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_content_settings.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+    "images": [
+        {
+            "idiom": "universal",
+            "scale": "1x",
+            "filename": "settings_content_settings.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "2x",
+            "filename": "settings_content_settings@2x.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "3x",
+            "filename": "settings_content_settings@3x.png"
+        }
+    ],
+    "info": {
+        "version": 1,
+        "author": "xcode"
+    }
+}
diff --git a/ios/chrome/browser/ui/settings/resources/settings_content_settings.imageset/settings_content_settings.png b/ios/chrome/browser/ui/settings/resources/settings_content_settings.imageset/settings_content_settings.png
new file mode 100644
index 0000000..316f8f071
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_content_settings.imageset/settings_content_settings.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_content_settings.imageset/settings_content_settings@2x.png b/ios/chrome/browser/ui/settings/resources/settings_content_settings.imageset/settings_content_settings@2x.png
new file mode 100644
index 0000000..52ac1b2
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_content_settings.imageset/settings_content_settings@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_content_settings.imageset/settings_content_settings@3x.png b/ios/chrome/browser/ui/settings/resources/settings_content_settings.imageset/settings_content_settings@3x.png
new file mode 100644
index 0000000..2c2187b5
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_content_settings.imageset/settings_content_settings@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_debug.imageset/Contents.json b/ios/chrome/browser/ui/settings/resources/settings_debug.imageset/Contents.json
new file mode 100644
index 0000000..a9e0100
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_debug.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+    "images": [
+        {
+            "idiom": "universal",
+            "scale": "1x",
+            "filename": "settings_debug.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "2x",
+            "filename": "settings_debug@2x.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "3x",
+            "filename": "settings_debug@3x.png"
+        }
+    ],
+    "info": {
+        "version": 1,
+        "author": "xcode"
+    }
+}
diff --git a/ios/chrome/browser/ui/settings/resources/settings_debug.imageset/settings_debug.png b/ios/chrome/browser/ui/settings/resources/settings_debug.imageset/settings_debug.png
new file mode 100644
index 0000000..be0d5eb
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_debug.imageset/settings_debug.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_debug.imageset/settings_debug@2x.png b/ios/chrome/browser/ui/settings/resources/settings_debug.imageset/settings_debug@2x.png
new file mode 100644
index 0000000..7cfcb578
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_debug.imageset/settings_debug@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_debug.imageset/settings_debug@3x.png b/ios/chrome/browser/ui/settings/resources/settings_debug.imageset/settings_debug@3x.png
new file mode 100644
index 0000000..452bfc2
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_debug.imageset/settings_debug@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_passwords.imageset/Contents.json b/ios/chrome/browser/ui/settings/resources/settings_passwords.imageset/Contents.json
new file mode 100644
index 0000000..0d0207e
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_passwords.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+    "images": [
+        {
+            "idiom": "universal",
+            "scale": "1x",
+            "filename": "settings_passwords.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "2x",
+            "filename": "settings_passwords@2x.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "3x",
+            "filename": "settings_passwords@3x.png"
+        }
+    ],
+    "info": {
+        "version": 1,
+        "author": "xcode"
+    }
+}
diff --git a/ios/chrome/browser/ui/settings/resources/settings_passwords.imageset/settings_passwords.png b/ios/chrome/browser/ui/settings/resources/settings_passwords.imageset/settings_passwords.png
new file mode 100644
index 0000000..6b1dbdd
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_passwords.imageset/settings_passwords.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_passwords.imageset/settings_passwords@2x.png b/ios/chrome/browser/ui/settings/resources/settings_passwords.imageset/settings_passwords@2x.png
new file mode 100644
index 0000000..6da324e
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_passwords.imageset/settings_passwords@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_passwords.imageset/settings_passwords@3x.png b/ios/chrome/browser/ui/settings/resources/settings_passwords.imageset/settings_passwords@3x.png
new file mode 100644
index 0000000..95b55230
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_passwords.imageset/settings_passwords@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_privacy.imageset/Contents.json b/ios/chrome/browser/ui/settings/resources/settings_privacy.imageset/Contents.json
new file mode 100644
index 0000000..10182c8
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_privacy.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+    "images": [
+        {
+            "idiom": "universal",
+            "scale": "1x",
+            "filename": "settings_privacy.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "2x",
+            "filename": "settings_privacy@2x.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "3x",
+            "filename": "settings_privacy@3x.png"
+        }
+    ],
+    "info": {
+        "version": 1,
+        "author": "xcode"
+    }
+}
diff --git a/ios/chrome/browser/ui/settings/resources/settings_privacy.imageset/settings_privacy.png b/ios/chrome/browser/ui/settings/resources/settings_privacy.imageset/settings_privacy.png
new file mode 100644
index 0000000..85809b3
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_privacy.imageset/settings_privacy.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_privacy.imageset/settings_privacy@2x.png b/ios/chrome/browser/ui/settings/resources/settings_privacy.imageset/settings_privacy@2x.png
new file mode 100644
index 0000000..ec470728
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_privacy.imageset/settings_privacy@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_privacy.imageset/settings_privacy@3x.png b/ios/chrome/browser/ui/settings/resources/settings_privacy.imageset/settings_privacy@3x.png
new file mode 100644
index 0000000..a49c3b8
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_privacy.imageset/settings_privacy@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_search_engine.imageset/Contents.json b/ios/chrome/browser/ui/settings/resources/settings_search_engine.imageset/Contents.json
new file mode 100644
index 0000000..6bfc37a
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_search_engine.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+    "images": [
+        {
+            "idiom": "universal",
+            "scale": "1x",
+            "filename": "settings_search_engine.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "2x",
+            "filename": "settings_search_engine@2x.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "3x",
+            "filename": "settings_search_engine@3x.png"
+        }
+    ],
+    "info": {
+        "version": 1,
+        "author": "xcode"
+    }
+}
diff --git a/ios/chrome/browser/ui/settings/resources/settings_search_engine.imageset/settings_search_engine.png b/ios/chrome/browser/ui/settings/resources/settings_search_engine.imageset/settings_search_engine.png
new file mode 100644
index 0000000..3e3480e
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_search_engine.imageset/settings_search_engine.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_search_engine.imageset/settings_search_engine@2x.png b/ios/chrome/browser/ui/settings/resources/settings_search_engine.imageset/settings_search_engine@2x.png
new file mode 100644
index 0000000..82a66f8
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_search_engine.imageset/settings_search_engine@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_search_engine.imageset/settings_search_engine@3x.png b/ios/chrome/browser/ui/settings/resources/settings_search_engine.imageset/settings_search_engine@3x.png
new file mode 100644
index 0000000..9b46956
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_search_engine.imageset/settings_search_engine@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_voice_search.imageset/Contents.json b/ios/chrome/browser/ui/settings/resources/settings_voice_search.imageset/Contents.json
new file mode 100644
index 0000000..9152ed26
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_voice_search.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+    "images": [
+        {
+            "idiom": "universal",
+            "scale": "1x",
+            "filename": "settings_voice_search.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "2x",
+            "filename": "settings_voice_search@2x.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "3x",
+            "filename": "settings_voice_search@3x.png"
+        }
+    ],
+    "info": {
+        "version": 1,
+        "author": "xcode"
+    }
+}
diff --git a/ios/chrome/browser/ui/settings/resources/settings_voice_search.imageset/settings_voice_search.png b/ios/chrome/browser/ui/settings/resources/settings_voice_search.imageset/settings_voice_search.png
new file mode 100644
index 0000000..746bd73
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_voice_search.imageset/settings_voice_search.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_voice_search.imageset/settings_voice_search@2x.png b/ios/chrome/browser/ui/settings/resources/settings_voice_search.imageset/settings_voice_search@2x.png
new file mode 100644
index 0000000..bdf6931
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_voice_search.imageset/settings_voice_search@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_voice_search.imageset/settings_voice_search@3x.png b/ios/chrome/browser/ui/settings/resources/settings_voice_search.imageset/settings_voice_search@3x.png
new file mode 100644
index 0000000..54b7245
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/resources/settings_voice_search.imageset/settings_voice_search@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm b/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm
index f7fdd971..b24e5e7 100644
--- a/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm
@@ -376,12 +376,15 @@
 
   // Basics section
   [model addSectionWithIdentifier:SectionIdentifierBasics];
-  SettingsTextItem* basicsHeader =
-      [[SettingsTextItem alloc] initWithType:ItemTypeHeader];
-  basicsHeader.text = l10n_util::GetNSString(IDS_IOS_OPTIONS_GENERAL_TAB_LABEL);
-  basicsHeader.textColor = [[MDCPalette greyPalette] tint500];
-  [model setHeader:basicsHeader
-      forSectionWithIdentifier:SectionIdentifierBasics];
+  if (!experimental_flags::IsSettingsUIRebootEnabled()) {
+    SettingsTextItem* basicsHeader =
+        [[SettingsTextItem alloc] initWithType:ItemTypeHeader];
+    basicsHeader.text =
+        l10n_util::GetNSString(IDS_IOS_OPTIONS_GENERAL_TAB_LABEL);
+    basicsHeader.textColor = [[MDCPalette greyPalette] tint500];
+    [model setHeader:basicsHeader
+        forSectionWithIdentifier:SectionIdentifierBasics];
+  }
   [model addItem:[self searchEngineDetailItem]
       toSectionWithIdentifier:SectionIdentifierBasics];
   [model addItem:[self savePasswordsDetailItem]
@@ -391,13 +394,15 @@
 
   // Advanced Section
   [model addSectionWithIdentifier:SectionIdentifierAdvanced];
-  SettingsTextItem* advancedHeader =
-      [[SettingsTextItem alloc] initWithType:ItemTypeHeader];
-  advancedHeader.text =
-      l10n_util::GetNSString(IDS_IOS_OPTIONS_ADVANCED_TAB_LABEL);
-  advancedHeader.textColor = [[MDCPalette greyPalette] tint500];
-  [model setHeader:advancedHeader
-      forSectionWithIdentifier:SectionIdentifierAdvanced];
+  if (!experimental_flags::IsSettingsUIRebootEnabled()) {
+    SettingsTextItem* advancedHeader =
+        [[SettingsTextItem alloc] initWithType:ItemTypeHeader];
+    advancedHeader.text =
+        l10n_util::GetNSString(IDS_IOS_OPTIONS_ADVANCED_TAB_LABEL);
+    advancedHeader.textColor = [[MDCPalette greyPalette] tint500];
+    [model setHeader:advancedHeader
+        forSectionWithIdentifier:SectionIdentifierAdvanced];
+  }
   [model addItem:[self voiceSearchDetailItem]
       toSectionWithIdentifier:SectionIdentifierAdvanced];
   [model addItem:[self privacyDetailItem]
@@ -418,12 +423,14 @@
   // Debug Section
   if ([self hasDebugSection]) {
     [model addSectionWithIdentifier:SectionIdentifierDebug];
-    SettingsTextItem* debugHeader =
-        [[SettingsTextItem alloc] initWithType:ItemTypeHeader];
-    debugHeader.text = @"Debug";
-    debugHeader.textColor = [[MDCPalette greyPalette] tint500];
-    [model setHeader:debugHeader
-        forSectionWithIdentifier:SectionIdentifierDebug];
+    if (!experimental_flags::IsSettingsUIRebootEnabled()) {
+      SettingsTextItem* debugHeader =
+          [[SettingsTextItem alloc] initWithType:ItemTypeHeader];
+      debugHeader.text = @"Debug";
+      debugHeader.textColor = [[MDCPalette greyPalette] tint500];
+      [model setHeader:debugHeader
+          forSectionWithIdentifier:SectionIdentifierDebug];
+    }
   }
 
   if (experimental_flags::IsMemoryDebuggingEnabled()) {
@@ -474,10 +481,13 @@
 }
 
 - (CollectionViewItem*)googleServicesCellItem {
+  // TODO(crbug.com/805214): This branded icon image needs to come from
+  // BrandedImageProvider.
   return [self detailItemWithType:ItemGoogleServices
                              text:l10n_util::GetNSString(
                                       IDS_IOS_GOOGLE_SERVICES_SETTINGS_TITLE)
-                       detailText:nil];
+                       detailText:nil
+                    iconImageName:nil];
 }
 
 - (CollectionViewItem*)accountCellItem {
@@ -500,7 +510,8 @@
       [self detailItemWithType:ItemTypeSearchEngine
                           text:l10n_util::GetNSString(
                                    IDS_IOS_SEARCH_ENGINE_SETTING_TITLE)
-                    detailText:defaultSearchEngineName];
+                    detailText:defaultSearchEngineName
+                 iconImageName:@"settings_search_engine"];
   _defaultSearchEngineItem.accessibilityIdentifier =
       kSettingsSearchEngineCellId;
   return _defaultSearchEngineItem;
@@ -510,7 +521,8 @@
   _savePasswordsDetailItem =
       [self detailItemWithType:ItemTypeSavedPasswords
                           text:l10n_util::GetNSString(IDS_IOS_PASSWORDS)
-                    detailText:nil];
+                    detailText:nil
+                 iconImageName:@"settings_passwords"];
 
   return _savePasswordsDetailItem;
 }
@@ -524,7 +536,8 @@
   _autoFillDetailItem =
       [self detailItemWithType:ItemTypeAutofill
                           text:l10n_util::GetNSString(IDS_IOS_AUTOFILL)
-                    detailText:autofillDetail];
+                    detailText:autofillDetail
+                 iconImageName:@"settings_autofill_forms"];
 
   return _autoFillDetailItem;
 }
@@ -541,7 +554,8 @@
       [self detailItemWithType:ItemTypeVoiceSearch
                           text:l10n_util::GetNSString(
                                    IDS_IOS_VOICE_SEARCH_SETTING_TITLE)
-                    detailText:languageName];
+                    detailText:languageName
+                 iconImageName:@"settings_voice_search"];
   _voiceSearchDetailItem.accessibilityIdentifier = kSettingsVoiceSearchCellId;
   return _voiceSearchDetailItem;
 }
@@ -551,33 +565,38 @@
       [self detailItemWithType:ItemTypePrivacy
                           text:l10n_util::GetNSString(
                                    IDS_OPTIONS_ADVANCED_SECTION_TITLE_PRIVACY)
-                    detailText:nil];
+                    detailText:nil
+                 iconImageName:@"settings_privacy"];
 }
 
 - (CollectionViewItem*)contentSettingsDetailItem {
   return [self
       detailItemWithType:ItemTypeContentSettings
                     text:l10n_util::GetNSString(IDS_IOS_CONTENT_SETTINGS_TITLE)
-              detailText:nil];
+              detailText:nil
+           iconImageName:@"settings_content_settings"];
 }
 
 - (CollectionViewItem*)bandwidthManagementDetailItem {
   return [self detailItemWithType:ItemTypeBandwidth
                              text:l10n_util::GetNSString(
                                       IDS_IOS_BANDWIDTH_MANAGEMENT_SETTINGS)
-                       detailText:nil];
+                       detailText:nil
+                    iconImageName:@"settings_bandwidth"];
 }
 
 - (CollectionViewItem*)aboutChromeDetailItem {
   return [self detailItemWithType:ItemTypeAboutChrome
                              text:l10n_util::GetNSString(IDS_IOS_PRODUCT_NAME)
-                       detailText:nil];
+                       detailText:nil
+                    iconImageName:@"settings_about_chrome"];
 }
 
 - (SettingsSwitchItem*)showMemoryDebugSwitchItem {
   SettingsSwitchItem* showMemoryDebugSwitchItem =
       [self switchItemWithType:ItemTypeMemoryDebugging
                          title:@"Show memory debug tools"
+                 iconImageName:@"settings_debug"
                withDefaultsKey:nil];
   showMemoryDebugSwitchItem.on = [_showMemoryDebugToolsEnabled value];
 
@@ -589,6 +608,7 @@
       [self switchItemWithType:ItemTypeArticlesForYou
                          title:l10n_util::GetNSString(
                                    IDS_IOS_CONTENT_SUGGESTIONS_SETTING_TITLE)
+                 iconImageName:@"settings_article_suggestions"
                withDefaultsKey:nil];
   articlesForYouSwitchItem.on = [_articlesEnabled value];
 
@@ -599,25 +619,29 @@
 - (SettingsSwitchItem*)viewSourceSwitchItem {
   return [self switchItemWithType:ItemTypeViewSource
                             title:@"View source menu"
+                    iconImageName:@"settings_debug"
                   withDefaultsKey:kDevViewSourceKey];
 }
 
 - (SettingsSwitchItem*)logJavascriptConsoleSwitchItem {
   return [self switchItemWithType:ItemTypeLogJavascript
                             title:@"Log JS"
+                    iconImageName:@"settings_debug"
                   withDefaultsKey:kLogJavascriptKey];
 }
 
 - (SettingsDetailItem*)collectionViewCatalogDetailItem {
   return [self detailItemWithType:ItemTypeCollectionCellCatalog
                              text:@"Collection Cell Catalog"
-                       detailText:nil];
+                       detailText:nil
+                    iconImageName:@"settings_debug"];
 }
 
 - (SettingsDetailItem*)tableViewCatalogDetailItem {
   return [self detailItemWithType:ItemTypeTableCellCatalog
                              text:@"TableView Cell Catalog"
-                       detailText:nil];
+                       detailText:nil
+                    iconImageName:@"settings_debug"];
 }
 #endif  // CHROMIUM_BUILD && !defined(NDEBUG)
 
@@ -636,12 +660,14 @@
 
 - (SettingsDetailItem*)detailItemWithType:(NSInteger)type
                                      text:(NSString*)text
-                               detailText:(NSString*)detailText {
+                               detailText:(NSString*)detailText
+                            iconImageName:(NSString*)iconImageName {
   SettingsDetailItem* detailItem =
       [[SettingsDetailItem alloc] initWithType:type];
   detailItem.text = text;
   detailItem.detailText = detailText;
   detailItem.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator;
+  detailItem.iconImageName = iconImageName;
   detailItem.accessibilityTraits |= UIAccessibilityTraitButton;
 
   return detailItem;
@@ -649,10 +675,12 @@
 
 - (SettingsSwitchItem*)switchItemWithType:(NSInteger)type
                                     title:(NSString*)title
+                            iconImageName:(NSString*)iconImageName
                           withDefaultsKey:(NSString*)key {
   SettingsSwitchItem* switchItem =
       [[SettingsSwitchItem alloc] initWithType:type];
   switchItem.text = title;
+  switchItem.iconImageName = iconImageName;
   if (key) {
     NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
     switchItem.on = [defaults boolForKey:key];
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
index 4d8f00e5a..5e283b5 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -134,8 +134,13 @@
 - (void)viewWillAppear:(BOOL)animated {
   [self.topToolbar.pageControl setSelectedPage:self.currentPage animated:YES];
   [self configureViewControllerForCurrentSizeClassesAndPage];
+  // The toolbars should be hidden (alpha 0.0) before the tab appears, so that
+  // they can be animated in. They can't be set to 0.0 here, because if
+  // |animated| is YES, this method is being called inside the animation block.
   if (animated && self.transitionCoordinator) {
     [self animateToolbarsForAppearance];
+  } else {
+    [self showToolbars];
   }
   [super viewWillAppear:animated];
 }
@@ -143,8 +148,12 @@
 - (void)viewWillDisappear:(BOOL)animated {
   self.undoCloseAllAvailable = NO;
   [self.regularTabsDelegate discardSavedClosedItems];
+  // When the view disappears, the toolbar alpha should be set to 0; either as
+  // part of the animation, or directly with -hideToolbars.
   if (animated && self.transitionCoordinator) {
     [self animateToolbarsForDisappearance];
+  } else {
+    [self hideToolbars];
   }
   [super viewWillDisappear:animated];
 }
@@ -279,7 +288,7 @@
 
 - (UIView*)proxyPositionForTransitionContext:
     (id<UIViewControllerContextTransitioning>)context {
-  return self.scrollView;
+  return self.floatingButton;
 }
 
 #pragma mark - Public
@@ -561,7 +570,9 @@
   TabGridNewTabButton* button = [TabGridNewTabButton
       buttonWithSizeClass:TabGridNewTabButtonSizeClassLarge];
   button.translatesAutoresizingMaskIntoConstraints = NO;
-  [self.view addSubview:button];
+  // Position the floating button over the scroll view, so transition animations
+  // can be above the button but below the toolbars.
+  [self.view insertSubview:button aboveSubview:self.scrollView];
   self.floatingButton = button;
   CGFloat verticalInset = kTabGridFloatingButtonVerticalInsetSmall;
   if (self.traitCollection.verticalSizeClass ==
@@ -676,27 +687,36 @@
       kTabGridCloseAllButtonIdentifier;
 }
 
+// Shows (by setting the alpha to 1.0) the two toolbar views. Suitable for use
+// in animations.
+- (void)showToolbars {
+  self.topToolbar.alpha = 1.0;
+  self.bottomToolbar.alpha = 1.0;
+}
+
+// Hides (by setting the alpha to 0.0) the two toolbar views. Suitable for use
+// in animations.
+- (void)hideToolbars {
+  self.topToolbar.alpha = 0.0;
+  self.bottomToolbar.alpha = 0.0;
+}
+
 // Translates the toolbar views offscreen and then animates them back in using
 // the transition coordinator. Transitions are preferred here since they don't
 // interact with the layout system at all.
 - (void)animateToolbarsForAppearance {
   DCHECK(self.transitionCoordinator);
-  // Set toolbar alphas to 0 prior to animation.
-  self.topToolbar.alpha = 0;
-  self.bottomToolbar.alpha = 0;
   // Unless reduce motion is enabled, hide the scroll view during the
   // animation.
   if (!UIAccessibilityIsReduceMotionEnabled()) {
     self.scrollView.hidden = YES;
   }
-
   // Fade the toolbars in for the last 60% of the transition.
   auto keyframe = ^{
     [UIView addKeyframeWithRelativeStartTime:0.4
                             relativeDuration:0.6
                                   animations:^{
-                                    self.topToolbar.alpha = 1.0;
-                                    self.bottomToolbar.alpha = 1.0;
+                                    [self showToolbars];
                                   }];
   };
   // Animation block that does the keyframe animation.
@@ -712,8 +732,7 @@
   // complete) as part of the completion.
   auto cleanup = ^(id<UIViewControllerTransitionCoordinatorContext> context) {
     self.scrollView.hidden = NO;
-    self.topToolbar.alpha = 1.0;
-    self.bottomToolbar.alpha = 1.0;
+    [self showToolbars];
   };
 
   // Animate the toolbar alphas alongside the current transition.
@@ -724,14 +743,17 @@
 // Translates the toolbar views offscreen using the transition coordinator.
 - (void)animateToolbarsForDisappearance {
   DCHECK(self.transitionCoordinator);
-
+  // Unless reduce motion is enabled, hide the scroll view during the
+  // animation.
+  if (!UIAccessibilityIsReduceMotionEnabled()) {
+    self.scrollView.hidden = YES;
+  }
   // Fade the toolbars out in the first 66% of the transition.
   auto keyframe = ^{
     [UIView addKeyframeWithRelativeStartTime:0
                             relativeDuration:0.66
                                   animations:^{
-                                    self.topToolbar.alpha = 0.0;
-                                    self.bottomToolbar.alpha = 0.0;
+                                    [self hideToolbars];
                                   }];
   };
 
@@ -746,11 +768,8 @@
 
   // Hide the scroll view (and thus the tab grids) until the transition
   // completes. Restore the toolbar opacity when the transition completes.
-  self.scrollView.hidden = YES;
   auto cleanup = ^(id<UIViewControllerTransitionCoordinatorContext> context) {
     self.scrollView.hidden = NO;
-    self.topToolbar.alpha = 1.0;
-    self.bottomToolbar.alpha = 1.0;
   };
 
   // Animate the toolbar alphas alongside the current transition.
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_animation.mm b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_animation.mm
index ee535bf2..271eeb2 100644
--- a/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_animation.mm
+++ b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_animation.mm
@@ -109,8 +109,8 @@
   // fractions of the overall animation duration.
   CGFloat partialDuration = 0.6;
   CGFloat briefDuration = partialDuration * 0.5;
-  CGFloat shortDelay = 0.12;
-  CGFloat longDelay = 0.4;
+  CGFloat delay = 0.4;
+  CGFloat shortDelay = 0.2;
 
   // If there's only one cell, the animation has two parts.
   //   (A) Zooming the active cell into position.
@@ -129,8 +129,8 @@
   //  {0%}------------------[A]----------{60%}
   //                 {40%}--[B]---------------{70%}
   //  {0%}---[C]---{30%}
-  //  {0%}------------------[D]--------------------{100%}
-  //     {12%}--------------[E]-------------- {72%}
+  //           {20%}--[D]-------------------------{100%}
+  //           {20%}--[E]----------------------{80%}
   //
   // All animations are timed ease-in (so more motion happens later), except
   // for C which is relatively small in space and short in duration; it has
@@ -154,7 +154,7 @@
   // B: Fade in the active cell's auxillary view
   UIView* auxillaryView = self.layout.activeItem.auxillaryView;
   auto fadeInAuxillaryKeyframeAnimation =
-      [self keyframeAnimationWithRelativeStart:longDelay
+      [self keyframeAnimationWithRelativeStart:delay
                               relativeDuration:briefDuration
                                     animations:^{
                                       auxillaryView.alpha = 1.0;
@@ -195,10 +195,15 @@
       item.cell.transform = CGAffineTransformIdentity;
     }
   };
+
+  auto scaleUpCellsKeyframeAnimation =
+      [self keyframeAnimationWithRelativeStart:shortDelay
+                              relativeDuration:1 - shortDelay
+                                    animations:scaleUpCellsAnimation];
   UIViewPropertyAnimator* scaleUpCells = [[UIViewPropertyAnimator alloc]
       initWithDuration:self.duration
-                 curve:UIViewAnimationCurveEaseOut
-            animations:scaleUpCellsAnimation];
+                 curve:UIViewAnimationCurveEaseIn
+            animations:scaleUpCellsKeyframeAnimation];
   [self.animations addAnimator:scaleUpCells];
 
   // E: Fade in inactive cells.
@@ -210,12 +215,12 @@
     }
   };
   auto fadeInCellsKeyframeAnimation =
-      [self keyframeAnimationWithRelativeStart:shortDelay
+      [self keyframeAnimationWithRelativeStart:delay
                               relativeDuration:partialDuration
                                     animations:fadeInCellsAnimation];
   UIViewPropertyAnimator* fadeInCells = [[UIViewPropertyAnimator alloc]
       initWithDuration:self.duration
-                 curve:UIViewAnimationCurveEaseOut
+                 curve:UIViewAnimationCurveEaseIn
             animations:fadeInCellsKeyframeAnimation];
   [self.animations addAnimator:fadeInCells];
 }
diff --git a/ios/chrome/browser/ui/toolbar/buttons/toolbar_constants.h b/ios/chrome/browser/ui/toolbar/buttons/toolbar_constants.h
index 722c670..6ab2a2c 100644
--- a/ios/chrome/browser/ui/toolbar/buttons/toolbar_constants.h
+++ b/ios/chrome/browser/ui/toolbar/buttons/toolbar_constants.h
@@ -143,5 +143,6 @@
 // Font sizes used in omnibox and location bar.
 extern const CGFloat kLocationBarFontSize;
 extern const CGFloat kLocationBarRegularRegularFontSize;
+extern const CGFloat kLocationBarSteadyFontSize;
 
 #endif  // IOS_CHROME_BROWSER_UI_TOOLBAR_BUTTONS_TOOLBAR_CONSTANTS_H_
diff --git a/ios/chrome/browser/ui/toolbar/buttons/toolbar_constants.mm b/ios/chrome/browser/ui/toolbar/buttons/toolbar_constants.mm
index 4fbc3518..14cdf8f 100644
--- a/ios/chrome/browser/ui/toolbar/buttons/toolbar_constants.mm
+++ b/ios/chrome/browser/ui/toolbar/buttons/toolbar_constants.mm
@@ -98,3 +98,4 @@
 const CGFloat kLocationBarTintBlue = 0x1A73E8;
 const CGFloat kLocationBarFontSize = 15.0f;
 const CGFloat kLocationBarRegularRegularFontSize = 17.0f;
+const CGFloat kLocationBarSteadyFontSize = 17.0f;
diff --git a/ios/web_view/test/web_view_restorable_state_inttest.mm b/ios/web_view/test/web_view_restorable_state_inttest.mm
index 2515775..c4a8400 100644
--- a/ios/web_view/test/web_view_restorable_state_inttest.mm
+++ b/ios/web_view/test/web_view_restorable_state_inttest.mm
@@ -35,7 +35,6 @@
   // Create second web view and restore its state from the first web view.
   CWVWebView* restored_web_view = test::CreateWebView();
   test::CopyWebViewState(web_view_, restored_web_view);
-  ASSERT_TRUE(test::WaitForWebViewLoadCompletionOrTimeout(restored_web_view));
 
   // Verify that the state has been restored correctly.
   EXPECT_NSEQ(@"about:blank",
diff --git a/media/capture/video/chromeos/mojo/camera_metadata_tags.mojom b/media/capture/video/chromeos/mojo/camera_metadata_tags.mojom
index d4543e7b..4fcfad8d 100644
--- a/media/capture/video/chromeos/mojo/camera_metadata_tags.mojom
+++ b/media/capture/video/chromeos/mojo/camera_metadata_tags.mojom
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -55,7 +55,9 @@
     ANDROID_SYNC                   = 0x17,
     ANDROID_REPROCESS              = 0x18,
     ANDROID_DEPTH                  = 0x19,
-    ANDROID_SECTION_COUNT          = 0x1A,
+    ANDROID_LOGICAL_MULTI_CAMERA   = 0x1A,
+    ANDROID_DISTORTION_CORRECTION  = 0x1B,
+    ANDROID_SECTION_COUNT          = 0x1C,
 
     VENDOR_SECTION                 = 0x8000
 };
@@ -92,6 +94,10 @@
     ANDROID_SYNC_START             = 0x170000,
     ANDROID_REPROCESS_START        = 0x180000,
     ANDROID_DEPTH_START            = 0x190000,
+    ANDROID_LOGICAL_MULTI_CAMERA_START
+                                   = 0x1A0000,
+    ANDROID_DISTORTION_CORRECTION_START
+                                   = 0x1B0000,
 
     // Mojom maps enum to int32_t in C++. This causes problem on the VENDOR_SECTION_START
     // below as 0x80000000 would generate -Wc++11-narrowing warnings while compiling the
@@ -155,6 +161,7 @@
     ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE,
     ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST,
     ANDROID_CONTROL_ENABLE_ZSL,
+    ANDROID_CONTROL_AF_SCENE_CHANGE,
     ANDROID_CONTROL_END,
     ANDROID_DEMOSAIC_MODE =                            0x20000, // ANDROID_DEMOSAIC_START,
     ANDROID_DEMOSAIC_END,
@@ -198,6 +205,8 @@
     ANDROID_LENS_STATE,
     ANDROID_LENS_INTRINSIC_CALIBRATION,
     ANDROID_LENS_RADIAL_DISTORTION,
+    ANDROID_LENS_POSE_REFERENCE,
+    ANDROID_LENS_DISTORTION,
     ANDROID_LENS_END,
     ANDROID_LENS_INFO_AVAILABLE_APERTURES =            0x90000, // ANDROID_LENS_INFO_START,
     ANDROID_LENS_INFO_AVAILABLE_FILTER_DENSITIES,
@@ -234,6 +243,8 @@
     ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS,
     ANDROID_REQUEST_AVAILABLE_RESULT_KEYS,
     ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
+    ANDROID_REQUEST_AVAILABLE_SESSION_KEYS,
+    ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS,
     ANDROID_REQUEST_END,
     ANDROID_SCALER_CROP_REGION =                       0xD0000, // ANDROID_SCALER_START,
     ANDROID_SCALER_AVAILABLE_FORMATS,
@@ -315,6 +326,10 @@
     ANDROID_STATISTICS_SCENE_FLICKER,
     ANDROID_STATISTICS_HOT_PIXEL_MAP,
     ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
+    ANDROID_STATISTICS_OIS_DATA_MODE,
+    ANDROID_STATISTICS_OIS_TIMESTAMPS,
+    ANDROID_STATISTICS_OIS_X_SHIFTS,
+    ANDROID_STATISTICS_OIS_Y_SHIFTS,
     ANDROID_STATISTICS_END,
     ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES =
                                                        0x120000, // ANDROID_STATISTICS_INFO_START,
@@ -325,6 +340,7 @@
     ANDROID_STATISTICS_INFO_SHARPNESS_MAP_SIZE,
     ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
     ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
+    ANDROID_STATISTICS_INFO_AVAILABLE_OIS_DATA_MODES,
     ANDROID_STATISTICS_INFO_END,
     ANDROID_TONEMAP_CURVE_BLUE =                       0x130000, // ANDROID_TONEMAP_START,
     ANDROID_TONEMAP_CURVE_GREEN,
@@ -339,6 +355,7 @@
     ANDROID_LED_AVAILABLE_LEDS,
     ANDROID_LED_END,
     ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL =            0x150000, // ANDROID_INFO_START,
+    ANDROID_INFO_VERSION,
     ANDROID_INFO_END,
     ANDROID_BLACK_LEVEL_LOCK =                         0x160000, // ANDROID_BLACK_LEVEL_START,
     ANDROID_BLACK_LEVEL_END,
@@ -354,6 +371,12 @@
     ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS,
     ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE,
     ANDROID_DEPTH_END,
+    ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS =        0x1A0000, // ANDROID_LOGICAL_MULTI_CAMERA_START,
+    ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE,
+    ANDROID_LOGICAL_MULTI_CAMERA_END,
+    ANDROID_DISTORTION_CORRECTION_MODE =               0x1B0000, // ANDROID_DISTORTION_CORRECTION_START,
+    ANDROID_DISTORTION_CORRECTION_AVAILABLE_MODES,
+    ANDROID_DISTORTION_CORRECTION_END,
 };
 
 /**
@@ -395,6 +418,7 @@
     ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH,
     ANDROID_CONTROL_AE_MODE_ON_ALWAYS_FLASH,
     ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE,
+    ANDROID_CONTROL_AE_MODE_ON_EXTERNAL_FLASH,
 };
 
 // ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER
@@ -449,6 +473,7 @@
     ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT,
     ANDROID_CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG,
     ANDROID_CONTROL_CAPTURE_INTENT_MANUAL,
+    ANDROID_CONTROL_CAPTURE_INTENT_MOTION_TRACKING,
 };
 
 // ANDROID_CONTROL_EFFECT_MODE
@@ -551,6 +576,12 @@
     ANDROID_CONTROL_ENABLE_ZSL_TRUE,
 };
 
+// ANDROID_CONTROL_AF_SCENE_CHANGE
+enum AndroidControlAfSceneChange {
+    ANDROID_CONTROL_AF_SCENE_CHANGE_NOT_DETECTED,
+    ANDROID_CONTROL_AF_SCENE_CHANGE_DETECTED,
+};
+
 // ANDROID_DEMOSAIC_MODE
 enum AndroidDemosaicMode {
     ANDROID_DEMOSAIC_MODE_FAST,
@@ -613,6 +644,12 @@
     ANDROID_LENS_STATE_MOVING,
 };
 
+// ANDROID_LENS_POSE_REFERENCE
+enum AndroidLensPoseReference {
+    ANDROID_LENS_POSE_REFERENCE_PRIMARY_CAMERA,
+    ANDROID_LENS_POSE_REFERENCE_GYROSCOPE,
+};
+
 // ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION
 enum AndroidLensInfoFocusDistanceCalibration {
     ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED,
@@ -659,6 +696,9 @@
     ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING,
     ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT,
     ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME,
 };
 
 // ANDROID_SCALER_AVAILABLE_FORMATS
@@ -783,6 +823,12 @@
     ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_ON,
 };
 
+// ANDROID_STATISTICS_OIS_DATA_MODE
+enum AndroidStatisticsOisDataMode {
+    ANDROID_STATISTICS_OIS_DATA_MODE_OFF,
+    ANDROID_STATISTICS_OIS_DATA_MODE_ON,
+};
+
 // ANDROID_TONEMAP_MODE
 enum AndroidTonemapMode {
     ANDROID_TONEMAP_MODE_CONTRAST_CURVE,
@@ -815,6 +861,7 @@
     ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
     ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY,
     ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_3,
+    ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL,
 };
 
 // ANDROID_BLACK_LEVEL_LOCK
@@ -846,3 +893,16 @@
     ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE_FALSE,
     ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE_TRUE,
 };
+
+// ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE
+enum AndroidLogicalMultiCameraSensorSyncType {
+    ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_APPROXIMATE,
+    ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_CALIBRATED,
+};
+
+// ANDROID_DISTORTION_CORRECTION_MODE
+enum AndroidDistortionCorrectionMode {
+    ANDROID_DISTORTION_CORRECTION_MODE_OFF,
+    ANDROID_DISTORTION_CORRECTION_MODE_FAST,
+    ANDROID_DISTORTION_CORRECTION_MODE_HIGH_QUALITY,
+};
diff --git a/media/gpu/test/rendering_helper.cc b/media/gpu/test/rendering_helper.cc
index a9f9ec5..7f4e135 100644
--- a/media/gpu/test/rendering_helper.cc
+++ b/media/gpu/test/rendering_helper.cc
@@ -365,6 +365,16 @@
   glScissor(area.x(), area.y(), area.width(), area.height());
 }
 
+void RenderingHelper::ConsumeVideoFrame(
+    size_t window_id,
+    scoped_refptr<VideoFrameTexture> video_frame) {
+  if (render_as_thumbnails_) {
+    RenderThumbnail(video_frame->texture_target(), video_frame->texture_id());
+  } else {
+    QueueVideoFrame(window_id, std::move(video_frame));
+  }
+}
+
 void RenderingHelper::RenderThumbnail(uint32_t texture_target,
                                       uint32_t texture_id) {
   CHECK(task_runner_->BelongsToCurrentThread());
diff --git a/media/gpu/test/rendering_helper.h b/media/gpu/test/rendering_helper.h
index f1624efe..02ca8589 100644
--- a/media/gpu/test/rendering_helper.h
+++ b/media/gpu/test/rendering_helper.h
@@ -102,13 +102,10 @@
                      const gfx::Size& size,
                      base::WaitableEvent* done);
 
-  // Render thumbnail in the |texture_id| to the FBO buffer using target
-  // |texture_target|.
-  void RenderThumbnail(uint32_t texture_target, uint32_t texture_id);
-
-  // Queues the |video_frame| for rendering.
-  void QueueVideoFrame(size_t window_id,
-                       scoped_refptr<VideoFrameTexture> video_frame);
+  // If |render_as_thumbnails_| is true, renders |video_frame| as thumbnail.
+  // Otherwise, queues |video_frame| to |pending_frames|.
+  void ConsumeVideoFrame(size_t window_id,
+                         scoped_refptr<VideoFrameTexture> video_frame);
 
   // Flushes the pending frames. Notify the rendering_helper there won't be
   // more video frames.
@@ -148,6 +145,14 @@
     ~RenderedVideo();
   };
 
+  // Render thumbnail in the |texture_id| to the FBO buffer using target
+  // |texture_target|.
+  void RenderThumbnail(uint32_t texture_target, uint32_t texture_id);
+
+  // Queues the |video_frame| for rendering.
+  void QueueVideoFrame(size_t window_id,
+                       scoped_refptr<VideoFrameTexture> video_frame);
+
   void Clear();
   void RenderContent();
   void DropOneFrameForAllVideos();
diff --git a/media/gpu/video_decode_accelerator_unittest.cc b/media/gpu/video_decode_accelerator_unittest.cc
index 3738db6..1bf42525 100644
--- a/media/gpu/video_decode_accelerator_unittest.cc
+++ b/media/gpu/video_decode_accelerator_unittest.cc
@@ -258,8 +258,6 @@
   // will start delaying the call to ReusePictureBuffer() for kReuseDelay.
   // |decode_calls_per_second| is the number of VDA::Decode calls per second.
   // If |decode_calls_per_second| > 0, |num_in_flight_decodes| must be 1.
-  // |render_as_thumbnails| indicates if the decoded picture will be rendered
-  // as thumbnails at the end of tests.
   // |num_frames| is the number of frames that must be verified to be decoded
   // during the test.
   struct Config {
@@ -277,7 +275,6 @@
     bool fake_decoder = false;
     size_t delay_reuse_after_frame_num = std::numeric_limits<size_t>::max();
     size_t decode_calls_per_second = 0;
-    bool render_as_thumbnails = false;
     size_t num_frames = 0;
   };
 
@@ -603,13 +600,8 @@
       base::Bind(&GLRenderingVDAClient::ReturnPicture, AsWeakPtr(),
                  picture.picture_buffer_id()));
   ASSERT_TRUE(pending_textures_.insert(*texture_it).second);
-
-  if (config_.render_as_thumbnails) {
-    rendering_helper_->RenderThumbnail(video_frame->texture_target(),
-                                       video_frame->texture_id());
-  } else {
-    rendering_helper_->QueueVideoFrame(config_.window_id, video_frame);
-  }
+  rendering_helper_->ConsumeVideoFrame(config_.window_id,
+                                       std::move(video_frame));
 }
 
 void GLRenderingVDAClient::ReturnPicture(int32_t picture_buffer_id) {
@@ -1182,7 +1174,6 @@
     config.profile = video_file->profile;
     config.fake_decoder = g_fake_decoder;
     config.delay_reuse_after_frame_num = delay_reuse_after_frame_num;
-    config.render_as_thumbnails = render_as_thumbnails;
     config.num_frames = video_file->num_frames;
 
     clients_[index] = std::make_unique<GLRenderingVDAClient>(
diff --git a/media/mojo/interfaces/audio_logging.mojom b/media/mojo/interfaces/audio_logging.mojom
index 36027ed..d8484274 100644
--- a/media/mojo/interfaces/audio_logging.mojom
+++ b/media/mojo/interfaces/audio_logging.mojom
@@ -36,3 +36,21 @@
   // Called when an audio component wants to forward a log message.
   OnLogMessage(string message);
 };
+
+enum AudioLogComponent {
+  kInputController,
+  kOutputController,
+  kOutputStream,
+};
+
+// This interface is implemented by the browser process to allow clients to
+// create AudioLog instances for tracking the behavior of an audio component.
+// The only client for this interface is the audio service.
+interface AudioLogFactory {
+  // Creates an AudioLog object for tracking the behavior for one instance of
+  // the given |component|.  Each instance of an "owning" class must create its
+  // own AudioLog. The created AudioLog object is bound to |audio_log_request|.
+  CreateAudioLog(AudioLogComponent component,
+                 int32 component_id,
+                 AudioLog& audio_log_request);
+};
diff --git a/services/content/BUILD.gn b/services/content/BUILD.gn
index ad48a188..bd57f62a 100644
--- a/services/content/BUILD.gn
+++ b/services/content/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//services/content/public/features.gni")
 import("//services/service_manager/public/service_manifest.gni")
 
 source_set("impl") {
@@ -26,7 +27,9 @@
 
   public_deps = [
     "//base",
+    "//services/content/public/cpp:buildflags",
     "//services/service_manager/public/cpp",
+    "//ui/gfx",
   ]
 
   deps = [
@@ -34,6 +37,14 @@
     "//services/content/public/cpp",
     "//services/content/public/mojom",
   ]
+
+  if (enable_aura_content_view_embedding) {
+    deps += [
+      "//ui/aura",
+      "//ui/views",
+      "//ui/views/mus/remote_view:remote_view_provider",
+    ]
+  }
 }
 
 source_set("tests") {
diff --git a/services/content/DEPS b/services/content/DEPS
new file mode 100644
index 0000000..e327b36
--- /dev/null
+++ b/services/content/DEPS
@@ -0,0 +1,5 @@
+include_rules = [
+  "+ui/aura",
+  "+ui/gfx",
+  "+ui/views",
+]
diff --git a/services/content/public/cpp/BUILD.gn b/services/content/public/cpp/BUILD.gn
index 8dbbdab..5a031ff 100644
--- a/services/content/public/cpp/BUILD.gn
+++ b/services/content/public/cpp/BUILD.gn
@@ -2,6 +2,15 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//services/content/public/features.gni")
+
+buildflag_header("buildflags") {
+  header = "buildflags.h"
+  flags = [
+    "ENABLE_AURA_CONTENT_VIEW_EMBEDDING=$enable_aura_content_view_embedding",
+  ]
+}
+
 component("cpp") {
   output_name = "content_service_cpp"
 
@@ -16,8 +25,18 @@
   defines = [ "IS_CONTENT_SERVICE_CPP_IMPL" ]
 
   public_deps = [
+    ":buildflags",
     "//base",
     "//services/content/public/mojom",
     "//url",
   ]
+
+  deps = []
+  if (enable_aura_content_view_embedding) {
+    deps += [
+      "//services/ui/public/interfaces",
+      "//ui/views",
+      "//ui/views/mus/remote_view:remote_view_host",
+    ]
+  }
 }
diff --git a/services/content/public/cpp/DEPS b/services/content/public/cpp/DEPS
new file mode 100644
index 0000000..e1df7c3
--- /dev/null
+++ b/services/content/public/cpp/DEPS
@@ -0,0 +1,5 @@
+include_rules = [
+  "+services/ui/public",
+  "+ui/aura",
+  "+ui/views",
+]
diff --git a/services/content/public/cpp/view.cc b/services/content/public/cpp/view.cc
index b02fbe48..15574a2 100644
--- a/services/content/public/cpp/view.cc
+++ b/services/content/public/cpp/view.cc
@@ -4,6 +4,15 @@
 
 #include "services/content/public/cpp/view.h"
 
+#include "services/content/public/cpp/buildflags.h"
+
+#if BUILDFLAG(ENABLE_AURA_CONTENT_VIEW_EMBEDDING)
+#include "services/ui/public/interfaces/window_tree_constants.mojom.h"  // nogncheck
+#include "ui/views/layout/fill_layout.h"                // nogncheck
+#include "ui/views/mus/remote_view/remote_view_host.h"  // nogncheck
+#include "ui/views/view.h"                              // nogncheck
+#endif
+
 namespace content {
 
 View::View(mojom::ViewFactory* factory) : client_binding_(this) {
@@ -15,6 +24,24 @@
 
 View::~View() = default;
 
+views::View* View::CreateUI() {
+  view_->PrepareToEmbed(
+      base::BindOnce(&View::OnEmbedTokenReceived, base::Unretained(this)));
+#if BUILDFLAG(ENABLE_AURA_CONTENT_VIEW_EMBEDDING)
+  DCHECK(!ui_view_);
+  ui_view_ = std::make_unique<views::View>();
+  ui_view_->set_owned_by_client();
+  ui_view_->SetLayoutManager(std::make_unique<views::FillLayout>());
+
+  DCHECK(!remote_view_host_);
+  remote_view_host_ = new views::RemoteViewHost;
+  ui_view_->AddChildView(remote_view_host_);
+  return ui_view_.get();
+#else
+  return nullptr;
+#endif
+}
+
 void View::Navigate(const GURL& url) {
   view_->Navigate(url);
 }
@@ -24,4 +51,12 @@
     did_stop_loading_callback_.Run();
 }
 
+void View::OnEmbedTokenReceived(const base::UnguessableToken& token) {
+#if BUILDFLAG(ENABLE_AURA_CONTENT_VIEW_EMBEDDING)
+  const uint32_t kEmbedFlags = ui::mojom::kEmbedFlagEmbedderInterceptsEvents |
+                               ui::mojom::kEmbedFlagEmbedderControlsVisibility;
+  remote_view_host_->EmbedUsingToken(token, kEmbedFlags, base::DoNothing());
+#endif  // defined(USE_AURA)
+}
+
 }  // namespace content
diff --git a/services/content/public/cpp/view.h b/services/content/public/cpp/view.h
index 6c2fdb2..9a62f2b 100644
--- a/services/content/public/cpp/view.h
+++ b/services/content/public/cpp/view.h
@@ -11,21 +11,36 @@
 #include "base/component_export.h"
 #include "base/macros.h"
 #include "mojo/public/cpp/bindings/binding.h"
+#include "services/content/public/cpp/buildflags.h"
 #include "services/content/public/mojom/view.mojom.h"
 #include "services/content/public/mojom/view_factory.mojom.h"
 
+namespace views {
+class RemoteViewHost;
+class View;
+}  // namespace views
+
 namespace content {
 
 // A View is a navigable, top-level view of web content which applications can
 // embed within their own UI.
 //
-// TODO(https://crbug.com/855092): Actually support UI embedding.
+// A View does not need to be used only for displaying visually renderable web
+// contents, so by default it has no graphical presence. Call |CreateUI()| to
+// get a usable Views widget which displays the navigated web contents and which
+// can be attached to an existing window tree.
 class COMPONENT_EXPORT(CONTENT_SERVICE_CPP) View : public mojom::ViewClient {
  public:
   // Constructs a new View using |factory|.
   explicit View(mojom::ViewFactory* factory);
   ~View() override;
 
+  // Initialize's this View for use within a window tree. Returns the
+  // corresponding |views::View|, which the caller may parent to some other
+  // widget. This widget will display the web content navigated by the Content
+  // Service on this View's behalf.
+  views::View* CreateUI();
+
   // Begins an attempt to asynchronously navigate this View to |url|.
   void Navigate(const GURL& url);
 
@@ -38,9 +53,18 @@
   // mojom::ViewClient:
   void DidStopLoading() override;
 
+  void OnEmbedTokenReceived(const base::UnguessableToken& token);
+
   mojom::ViewPtr view_;
   mojo::Binding<mojom::ViewClient> client_binding_;
 
+#if BUILDFLAG(ENABLE_AURA_CONTENT_VIEW_EMBEDDING)
+  // This View's node in the client's window tree. Non-existent by default, but
+  // may be initialized by calling InitializeUI.
+  std::unique_ptr<views::View> ui_view_;
+  views::RemoteViewHost* remote_view_host_ = nullptr;
+#endif
+
   base::RepeatingClosure did_stop_loading_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(View);
diff --git a/services/content/public/features.gni b/services/content/public/features.gni
new file mode 100644
index 0000000..eab14ee
--- /dev/null
+++ b/services/content/public/features.gni
@@ -0,0 +1,13 @@
+# Copyright 2018 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/buildflag_header.gni")
+import("//build/config/chromecast_build.gni")
+import("//build/config/ui.gni")
+
+declare_args() {
+  # Determines whether or not Aura-based view embedding should be supported by
+  # the Content Service.
+  enable_aura_content_view_embedding = use_aura && !is_fuchsia && !is_chromecast
+}
diff --git a/services/content/public/mojom/BUILD.gn b/services/content/public/mojom/BUILD.gn
index d40c878..bbcac09 100644
--- a/services/content/public/mojom/BUILD.gn
+++ b/services/content/public/mojom/BUILD.gn
@@ -18,6 +18,7 @@
   ]
 
   public_deps = [
+    "//mojo/public/mojom/base",
     "//url/mojom:url_mojom_gurl",
   ]
 
diff --git a/services/content/public/mojom/view.mojom b/services/content/public/mojom/view.mojom
index 59bce68..b19b720e 100644
--- a/services/content/public/mojom/view.mojom
+++ b/services/content/public/mojom/view.mojom
@@ -4,11 +4,17 @@
 
 module content.mojom;
 
+import "mojo/public/mojom/base/unguessable_token.mojom";
 import "url/mojom/url.mojom";
 
 // The primary interface driving a navigable content view embedded by an
 // application which wants to display web contents.
 interface View {
+  // Prepares the visible content frame associated with this View to be embedded
+  // within another Mus window tree. The response's |token| can be passed to the
+  // desired embedder once received.
+  PrepareToEmbed() => (mojo_base.mojom.UnguessableToken token);
+
   // Initiates a navigation to |url|.
   Navigate(url.mojom.Url url);
 };
diff --git a/services/content/service_unittest.cc b/services/content/service_unittest.cc
index 78889ed..928ee1f 100644
--- a/services/content/service_unittest.cc
+++ b/services/content/service_unittest.cc
@@ -53,6 +53,8 @@
       navigation_callback_.Run();
   }
 
+  gfx::NativeView GetNativeView() override { return nullptr; }
+
  private:
   GURL last_navigated_url_;
   base::RepeatingClosure navigation_callback_;
diff --git a/services/content/simple_browser/BUILD.gn b/services/content/simple_browser/BUILD.gn
new file mode 100644
index 0000000..791c21d3
--- /dev/null
+++ b/services/content/simple_browser/BUILD.gn
@@ -0,0 +1,47 @@
+# Copyright 2018 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("//services/service_manager/public/service_manifest.gni")
+
+component("simple_browser") {
+  public = [
+    "simple_browser_service.h",
+  ]
+
+  sources = [
+    "simple_browser_service.cc",
+    "window.cc",
+    "window.h",
+  ]
+
+  defines = [ "IS_SIMPLE_BROWSER_IMPL" ]
+
+  public_deps = [
+    "//base",
+    "//mojo/public/cpp/bindings",
+    "//mojo/public/cpp/system",
+    "//services/content/simple_browser/public/mojom",
+    "//services/service_manager/public/cpp",
+  ]
+
+  deps = [
+    "//services/content/public/cpp",
+    "//services/content/public/mojom",
+    "//ui/aura",
+    "//ui/views",
+    "//ui/views/mus",
+  ]
+
+  if (is_linux) {
+    public_deps += [
+      "//components/services/font/public/cpp",
+      "//components/services/font/public/interfaces",
+    ]
+  }
+}
+
+service_manifest("manifest") {
+  name = "simple_browser"
+  source = "manifest.json"
+}
diff --git a/services/content/simple_browser/DEPS b/services/content/simple_browser/DEPS
new file mode 100644
index 0000000..10525a0b
--- /dev/null
+++ b/services/content/simple_browser/DEPS
@@ -0,0 +1,6 @@
+include_rules = [
+  "+components/services/font/public",
+  "+third_party/skia/include",
+  "+ui/aura",
+  "+ui/views",
+]
diff --git a/services/content/simple_browser/OWNERS b/services/content/simple_browser/OWNERS
new file mode 100644
index 0000000..59dfd4b3
--- /dev/null
+++ b/services/content/simple_browser/OWNERS
@@ -0,0 +1,2 @@
+per-file manifest.json=set noparent
+per-file manifest.json=file://ipc/SECURITY_OWNERS
diff --git a/services/content/simple_browser/README.md b/services/content/simple_browser/README.md
new file mode 100644
index 0000000..de9d7b55
--- /dev/null
+++ b/services/content/simple_browser/README.md
@@ -0,0 +1,9 @@
+This directory contains an implementation of a simple, sandboxed, Content
+Service client application which serves as a tool for manual developer testing
+of the Content Service, a straightforward example browser application consuming
+the Content Service, and potentially as a target for driving automated
+Content Service integration tests.
+
+To play around with simple_browser today, build Chrome with
+`target_os = "chromeos"` and run with `--enable-features=Mash` and
+`--launch-simple-browser`.
diff --git a/services/content/simple_browser/manifest.json b/services/content/simple_browser/manifest.json
new file mode 100644
index 0000000..5d8332a
--- /dev/null
+++ b/services/content/simple_browser/manifest.json
@@ -0,0 +1,18 @@
+{
+  "name": "simple_browser",
+  "display_name": "Simple Browser",
+  "sandbox_type": "utility",
+  "interface_provider_specs": {
+    "service_manager:connector": {
+      "provides": {
+        // Dummy capability so someone can start/connect.
+        "app": []
+      },
+      "requires": {
+        "content": [ "view" ],
+        "font_service": [ "font_service" ],
+        "ui": [ "app" ]
+      }
+    }
+  }
+}
diff --git a/services/content/simple_browser/public/mojom/BUILD.gn b/services/content/simple_browser/public/mojom/BUILD.gn
new file mode 100644
index 0000000..97d6cd4
--- /dev/null
+++ b/services/content/simple_browser/public/mojom/BUILD.gn
@@ -0,0 +1,11 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+mojom("mojom") {
+  sources = [
+    "constants.mojom",
+  ]
+}
diff --git a/services/content/simple_browser/public/mojom/OWNERS b/services/content/simple_browser/public/mojom/OWNERS
new file mode 100644
index 0000000..08850f4
--- /dev/null
+++ b/services/content/simple_browser/public/mojom/OWNERS
@@ -0,0 +1,2 @@
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/services/content/simple_browser/public/mojom/constants.mojom b/services/content/simple_browser/public/mojom/constants.mojom
new file mode 100644
index 0000000..fb751d7
--- /dev/null
+++ b/services/content/simple_browser/public/mojom/constants.mojom
@@ -0,0 +1,7 @@
+// Copyright 2018 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.
+
+module simple_browser.mojom;
+
+const string kServiceName = "simple_browser";
diff --git a/services/content/simple_browser/simple_browser_service.cc b/services/content/simple_browser/simple_browser_service.cc
new file mode 100644
index 0000000..d2f6b9f
--- /dev/null
+++ b/services/content/simple_browser/simple_browser_service.cc
@@ -0,0 +1,39 @@
+// Copyright 2018 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/content/simple_browser/simple_browser_service.h"
+
+#include "build/build_config.h"
+#include "services/content/simple_browser/window.h"
+#include "services/service_manager/public/cpp/service_context.h"
+#include "ui/views/mus/aura_init.h"
+
+#if defined(OS_LINUX)
+#include "third_party/skia/include/ports/SkFontConfigInterface.h"
+#endif
+
+namespace simple_browser {
+
+SimpleBrowserService::SimpleBrowserService() = default;
+
+SimpleBrowserService::~SimpleBrowserService() = default;
+
+void SimpleBrowserService::OnStart() {
+#if defined(OS_LINUX)
+  font_loader_ = sk_make_sp<font_service::FontLoader>(context()->connector());
+  SkFontConfigInterface::SetGlobal(font_loader_);
+#endif
+
+  views::AuraInit::InitParams params;
+  params.connector = context()->connector();
+  params.identity = context()->identity();
+  params.mode = views::AuraInit::Mode::AURA_MUS2;
+  params.register_path_provider = false;
+  aura_init_ = views::AuraInit::Create(params);
+  CHECK(aura_init_);
+
+  window_ = std::make_unique<Window>(context()->connector());
+}
+
+}  // namespace simple_browser
diff --git a/services/content/simple_browser/simple_browser_service.h b/services/content/simple_browser/simple_browser_service.h
new file mode 100644
index 0000000..921082d6
--- /dev/null
+++ b/services/content/simple_browser/simple_browser_service.h
@@ -0,0 +1,50 @@
+// Copyright 2018 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_CONTENT_SIMPLE_BROWSER_SIMPLE_BROWSER_SERVICE_H_
+#define SERVICES_CONTENT_SIMPLE_BROWSER_SIMPLE_BROWSER_SERVICE_H_
+
+#include <map>
+#include <memory>
+
+#include "base/component_export.h"
+#include "base/macros.h"
+#include "build/build_config.h"
+#include "services/service_manager/public/cpp/service.h"
+
+#if defined(OS_LINUX)
+#include "components/services/font/public/cpp/font_loader.h"
+#endif
+
+namespace views {
+class AuraInit;
+}
+
+namespace simple_browser {
+
+class Window;
+
+class COMPONENT_EXPORT(SIMPLE_BROWSER) SimpleBrowserService
+    : public service_manager::Service {
+ public:
+  SimpleBrowserService();
+  ~SimpleBrowserService() override;
+
+ private:
+  // service_manager::Service:
+  void OnStart() override;
+
+#if defined(OS_LINUX)
+  sk_sp<font_service::FontLoader> font_loader_;
+#endif
+
+  std::unique_ptr<views::AuraInit> aura_init_;
+  std::unique_ptr<Window> window_;
+
+  DISALLOW_COPY_AND_ASSIGN(SimpleBrowserService);
+};
+
+}  // namespace simple_browser
+
+#endif  // SERVICES_CONTENT_SIMPLE_BROWSER_SIMPLE_BROWSER_SERVICE_H_
diff --git a/services/content/simple_browser/window.cc b/services/content/simple_browser/window.cc
new file mode 100644
index 0000000..4dc31d9d
--- /dev/null
+++ b/services/content/simple_browser/window.cc
@@ -0,0 +1,103 @@
+// Copyright 2018 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/content/simple_browser/window.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/strings/utf_string_conversions.h"
+#include "services/content/public/cpp/view.h"
+#include "services/content/public/mojom/constants.mojom.h"
+#include "services/content/public/mojom/view_factory.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/views/background.h"
+#include "ui/views/border.h"
+#include "ui/views/controls/textfield/textfield.h"
+#include "ui/views/controls/textfield/textfield_controller.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_delegate.h"
+
+namespace simple_browser {
+
+namespace {
+
+class SimpleBrowserUI : public views::WidgetDelegateView,
+                        public views::TextfieldController {
+ public:
+  explicit SimpleBrowserUI(service_manager::Connector* connector)
+      : connector_(connector), location_bar_(new views::Textfield) {
+    SetBackground(views::CreateStandardPanelBackground());
+    location_bar_->set_controller(this);
+    AddChildView(location_bar_);
+
+    connector_->BindInterface(content::mojom::kServiceName,
+                              MakeRequest(&view_factory_));
+    view_ = std::make_unique<content::View>(view_factory_.get());
+    content_area_ = view_->CreateUI();
+    content_area_->SetBorder(views::CreateSolidBorder(2, SK_ColorGREEN));
+    AddChildView(content_area_);
+  }
+
+  ~SimpleBrowserUI() override = default;
+
+ private:
+  // views::WidgetDelegate:
+  base::string16 GetWindowTitle() const override {
+    return base::ASCIIToUTF16("Simple Browser");
+  }
+
+  // views::View:
+  void Layout() override {
+    gfx::Rect location_bar_bounds{GetLocalBounds().width(), 20};
+    location_bar_bounds.Inset(5, 0);
+    location_bar_->SetBoundsRect(location_bar_bounds);
+
+    gfx::Rect content_area_bounds = GetLocalBounds();
+    content_area_bounds.Inset(5, 25, 5, 5);
+    content_area_->SetBoundsRect(content_area_bounds);
+  }
+
+  gfx::Size CalculatePreferredSize() const override {
+    return gfx::Size(640, 480);
+  }
+
+  // views::TextFieldController:
+  bool HandleKeyEvent(views::Textfield* sender,
+                      const ui::KeyEvent& key_event) override {
+    if (key_event.type() != ui::ET_KEY_PRESSED)
+      return false;
+
+    if (key_event.key_code() == ui::VKEY_RETURN)
+      view_->Navigate(GURL(base::UTF16ToUTF8(location_bar_->text())));
+
+    return false;
+  }
+
+  service_manager::Connector* const connector_;
+
+  content::mojom::ViewFactoryPtr view_factory_;
+  std::unique_ptr<content::View> view_;
+
+  views::Textfield* location_bar_;
+  views::View* content_area_;
+
+  DISALLOW_COPY_AND_ASSIGN(SimpleBrowserUI);
+};
+
+}  // namespace
+
+Window::Window(service_manager::Connector* connector) {
+  window_widget_ = views::Widget::CreateWindowWithContextAndBounds(
+      new SimpleBrowserUI(connector), nullptr, gfx::Rect(10, 640, 0, 0));
+  window_widget_->GetNativeWindow()->GetHost()->window()->SetName(
+      "SimpleBrowser");
+  window_widget_->Show();
+}
+
+Window::~Window() = default;
+
+}  // namespace simple_browser
diff --git a/services/content/simple_browser/window.h b/services/content/simple_browser/window.h
new file mode 100644
index 0000000..d597806
--- /dev/null
+++ b/services/content/simple_browser/window.h
@@ -0,0 +1,33 @@
+// Copyright 2018 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_CONTENT_SIMPLE_BROWSER_WINDOW_H_
+#define SERVICES_CONTENT_SIMPLE_BROWSER_WINDOW_H_
+
+#include "base/macros.h"
+
+namespace service_manager {
+class Connector;
+}
+
+namespace views {
+class Widget;
+}
+
+namespace simple_browser {
+
+class Window {
+ public:
+  explicit Window(service_manager::Connector* connector);
+  ~Window();
+
+ private:
+  views::Widget* window_widget_;
+
+  DISALLOW_COPY_AND_ASSIGN(Window);
+};
+
+}  // namespace simple_browser
+
+#endif  // SERVICES_CONTENT_SIMPLE_BROWSER_WINDOW_H_
diff --git a/services/content/view_delegate.h b/services/content/view_delegate.h
index f2cfc359..5c3364b 100644
--- a/services/content/view_delegate.h
+++ b/services/content/view_delegate.h
@@ -5,6 +5,8 @@
 #ifndef SERVICES_CONTENT_VIEW_DELEGATE_H_
 #define SERVICES_CONTENT_VIEW_DELEGATE_H_
 
+#include "ui/gfx/native_widget_types.h"
+
 class GURL;
 
 namespace content {
@@ -23,6 +25,10 @@
  public:
   virtual ~ViewDelegate() {}
 
+  // Returns a NativeView that can be embedded into a client application's
+  // window tree to display the web contents navigated by the delegate's View.
+  virtual gfx::NativeView GetNativeView() = 0;
+
   // Navigates the content object to a new URL.
   virtual void Navigate(const GURL& url) = 0;
 };
diff --git a/services/content/view_impl.cc b/services/content/view_impl.cc
index 54ccae9..208616a 100644
--- a/services/content/view_impl.cc
+++ b/services/content/view_impl.cc
@@ -5,10 +5,16 @@
 #include "services/content/view_impl.h"
 
 #include "base/bind.h"
+#include "services/content/public/cpp/buildflags.h"
 #include "services/content/service.h"
 #include "services/content/service_delegate.h"
 #include "services/content/view_delegate.h"
 
+#if BUILDFLAG(ENABLE_AURA_CONTENT_VIEW_EMBEDDING)
+#include "ui/aura/window.h"                                 // nogncheck
+#include "ui/views/mus/remote_view/remote_view_provider.h"  // nogncheck
+#endif
+
 namespace content {
 
 ViewImpl::ViewImpl(Service* service,
@@ -18,13 +24,36 @@
     : service_(service),
       binding_(this, std::move(request)),
       client_(std::move(client)),
-      delegate_(service_->delegate()->CreateViewDelegate(client_.get())) {
+      delegate_(service_->delegate()->CreateViewDelegate(client_.get())),
+      native_content_view_(delegate_->GetNativeView()) {
   binding_.set_connection_error_handler(base::BindRepeating(
       &Service::RemoveView, base::Unretained(service_), this));
+
+#if BUILDFLAG(ENABLE_AURA_CONTENT_VIEW_EMBEDDING)
+  if (native_content_view_) {
+    DCHECK(!remote_view_provider_);
+    remote_view_provider_ =
+        std::make_unique<views::RemoteViewProvider>(native_content_view_);
+  }
+#endif
 }
 
 ViewImpl::~ViewImpl() = default;
 
+void ViewImpl::PrepareToEmbed(PrepareToEmbedCallback callback) {
+#if BUILDFLAG(ENABLE_AURA_CONTENT_VIEW_EMBEDDING)
+  if (remote_view_provider_) {
+    remote_view_provider_->GetEmbedToken(
+        base::BindOnce(&ViewImpl::OnEmbedTokenReceived, base::Unretained(this),
+                       std::move(callback)));
+    return;
+  }
+#endif
+
+  DLOG(ERROR) << "View embedding not yet supported on this platform.";
+  std::move(callback).Run(base::UnguessableToken::Create());
+}
+
 void ViewImpl::Navigate(const GURL& url) {
   // Ignore non-HTTP/HTTPS requests for now.
   if (!url.SchemeIsHTTPOrHTTPS())
@@ -33,4 +62,13 @@
   delegate_->Navigate(url);
 }
 
+void ViewImpl::OnEmbedTokenReceived(PrepareToEmbedCallback callback,
+                                    const base::UnguessableToken& token) {
+#if BUILDFLAG(ENABLE_AURA_CONTENT_VIEW_EMBEDDING)
+  if (native_content_view_)
+    native_content_view_->Show();
+#endif
+  std::move(callback).Run(token);
+}
+
 }  // namespace content
diff --git a/services/content/view_impl.h b/services/content/view_impl.h
index 96a78394..dfac642 100644
--- a/services/content/view_impl.h
+++ b/services/content/view_impl.h
@@ -6,9 +6,16 @@
 #define SERVICES_CONTENT_VIEW_IMPL_H_
 
 #include "base/macros.h"
+#include "base/unguessable_token.h"
 #include "mojo/public/cpp/bindings/binding.h"
+#include "services/content/public/cpp/buildflags.h"
 #include "services/content/public/mojom/view.mojom.h"
 #include "services/content/public/mojom/view_factory.mojom.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace views {
+class RemoteViewProvider;
+}
 
 namespace content {
 
@@ -24,15 +31,23 @@
   ~ViewImpl() override;
 
  private:
-  // mojom::ContentView:
+  // mojom::View:
+  void PrepareToEmbed(PrepareToEmbedCallback callback) override;
   void Navigate(const GURL& url) override;
 
+  void OnEmbedTokenReceived(PrepareToEmbedCallback callback,
+                            const base::UnguessableToken& token);
+
   Service* const service_;
 
   mojo::Binding<mojom::View> binding_;
   mojom::ViewClientPtr client_;
-
   std::unique_ptr<ViewDelegate> delegate_;
+  gfx::NativeView native_content_view_;
+
+#if BUILDFLAG(ENABLE_AURA_CONTENT_VIEW_EMBEDDING)
+  std::unique_ptr<views::RemoteViewProvider> remote_view_provider_;
+#endif
 
   DISALLOW_COPY_AND_ASSIGN(ViewImpl);
 };
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index 92cafc3..a57d9323 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -165,7 +165,7 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 1200,
+          "hard_timeout": 600,
           "output_links": [
             {
               "link": [
@@ -175,8 +175,7 @@
               ],
               "name": "shard #${SHARD_INDEX} logcats"
             }
-          ],
-          "shards": 2
+          ]
         },
         "test": "cronet_test_instrumentation_apk"
       },
@@ -474,7 +473,7 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 1200,
+          "hard_timeout": 600,
           "output_links": [
             {
               "link": [
@@ -484,8 +483,7 @@
               ],
               "name": "shard #${SHARD_INDEX} logcats"
             }
-          ],
-          "shards": 2
+          ]
         },
         "test": "cronet_test_instrumentation_apk"
       },
@@ -1244,7 +1242,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1200,
+          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -1255,7 +1253,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 8
+          "shards": 20
         },
         "test": "chrome_public_test_apk"
       },
@@ -1421,7 +1419,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 960,
+          "hard_timeout": 900,
           "output_links": [
             {
               "link": [
@@ -1431,7 +1429,8 @@
               ],
               "name": "shard #${SHARD_INDEX} logcats"
             }
-          ]
+          ],
+          "shards": 2
         },
         "test": "components_unittests"
       },
@@ -1466,7 +1465,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1200,
+          "hard_timeout": 1500,
           "output_links": [
             {
               "link": [
@@ -1477,7 +1476,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 6
+          "shards": 9
         },
         "test": "content_browsertests"
       },
@@ -1508,7 +1507,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1200,
+          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -1519,7 +1518,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 4
+          "shards": 3
         },
         "test": "content_shell_test_apk"
       },
@@ -1554,7 +1553,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1200,
+          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -1565,7 +1564,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 2
+          "shards": 3
         },
         "test": "content_unittests"
       },
@@ -1960,7 +1959,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 960,
+          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -2996,7 +2995,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1200,
+          "hard_timeout": 900,
           "output_links": [
             {
               "link": [
@@ -3007,7 +3006,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 2
+          "shards": 5
         },
         "test": "unit_tests"
       },
@@ -3263,7 +3262,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1500,
+          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -3274,7 +3273,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 6
+          "shards": 7
         },
         "test": "webview_instrumentation_test_apk"
       },
@@ -3506,10 +3505,6 @@
         "test": "gpu_unittests"
       },
       {
-        "args": [
-          "--shard-timeout",
-          "600"
-        ],
         "swarming": {
           "can_use_on_swarming_builders": false
         },
@@ -3874,10 +3869,6 @@
         "test": "gpu_unittests"
       },
       {
-        "args": [
-          "--shard-timeout",
-          "600"
-        ],
         "swarming": {
           "can_use_on_swarming_builders": false
         },
@@ -4385,7 +4376,9 @@
               "device_type": "coho",
               "os": "Android"
             }
-          ]
+          ],
+          "hard_timeout": 1500,
+          "shards": 20
         },
         "test": "chrome_public_test_apk"
       },
@@ -4431,7 +4424,8 @@
               "device_type": "coho",
               "os": "Android"
             }
-          ]
+          ],
+          "hard_timeout": 960
         },
         "test": "chrome_sync_shell_test_apk"
       },
@@ -4481,7 +4475,9 @@
               "device_type": "coho",
               "os": "Android"
             }
-          ]
+          ],
+          "hard_timeout": 900,
+          "shards": 2
         },
         "test": "components_unittests"
       },
@@ -4506,7 +4502,9 @@
               "device_type": "coho",
               "os": "Android"
             }
-          ]
+          ],
+          "hard_timeout": 1500,
+          "shards": 9
         },
         "test": "content_browsertests"
       },
@@ -4531,7 +4529,9 @@
               "device_type": "coho",
               "os": "Android"
             }
-          ]
+          ],
+          "hard_timeout": 960,
+          "shards": 3
         },
         "test": "content_shell_test_apk"
       },
@@ -4557,6 +4557,7 @@
               "os": "Android"
             }
           ],
+          "hard_timeout": 960,
           "shards": 3
         },
         "test": "content_unittests"
@@ -5367,6 +5368,7 @@
               "os": "Android"
             }
           ],
+          "hard_timeout": 900,
           "shards": 5
         },
         "test": "unit_tests"
@@ -5672,8 +5674,7 @@
               "device_type": "gce_x86",
               "os": "Android"
             }
-          ],
-          "hard_timeout": 120
+          ]
         },
         "test": "blink_heap_unittests"
       },
@@ -5896,7 +5897,8 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 1200
+          "hard_timeout": 1500,
+          "shards": 20
         },
         "test": "chrome_public_test_apk"
       },
@@ -5943,7 +5945,7 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 600
+          "hard_timeout": 960
         },
         "test": "chrome_sync_shell_test_apk"
       },
@@ -5993,7 +5995,9 @@
               "device_type": "gce_x86",
               "os": "Android"
             }
-          ]
+          ],
+          "hard_timeout": 900,
+          "shards": 2
         },
         "test": "components_unittests"
       },
@@ -6019,7 +6023,8 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 960
+          "hard_timeout": 1500,
+          "shards": 9
         },
         "test": "content_browsertests"
       },
@@ -6041,7 +6046,8 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 1920
+          "hard_timeout": 960,
+          "shards": 3
         },
         "test": "content_shell_test_apk"
       },
@@ -6067,6 +6073,7 @@
               "os": "Android"
             }
           ],
+          "hard_timeout": 960,
           "shards": 3
         },
         "test": "content_unittests"
@@ -6877,6 +6884,7 @@
               "os": "Android"
             }
           ],
+          "hard_timeout": 900,
           "shards": 5
         },
         "test": "unit_tests"
@@ -7024,7 +7032,6 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 960,
           "shards": 7
         },
         "test": "webview_instrumentation_test_apk"
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index 28e1d8a5..eb22a817 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -725,7 +725,6 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 180,
           "output_links": [
             {
               "link": [
@@ -2640,7 +2639,6 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 180,
           "output_links": [
             {
               "link": [
@@ -3221,7 +3219,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 300,
           "output_links": [
             {
               "link": [
@@ -3486,7 +3483,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 60,
           "output_links": [
             {
               "link": [
@@ -3575,7 +3571,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -3709,7 +3704,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 2400,
+          "hard_timeout": 1500,
           "output_links": [
             {
               "link": [
@@ -3755,7 +3750,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1200,
+          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -3800,7 +3795,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 600,
           "output_links": [
             {
               "link": [
@@ -3845,7 +3839,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1500,
+          "hard_timeout": 900,
           "output_links": [
             {
               "link": [
@@ -3891,7 +3885,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1800,
+          "hard_timeout": 1500,
           "output_links": [
             {
               "link": [
@@ -3902,7 +3896,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 6
+          "shards": 9
         },
         "test": "content_browsertests"
       },
@@ -3937,7 +3931,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1800,
+          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -3948,7 +3942,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 2
+          "shards": 3
         },
         "test": "content_shell_test_apk"
       },
@@ -3983,7 +3977,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1200,
+          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -4073,7 +4067,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -4162,7 +4155,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 60,
           "output_links": [
             {
               "link": [
@@ -4340,7 +4332,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -4519,7 +4510,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 60,
           "output_links": [
             {
               "link": [
@@ -4608,7 +4598,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 60,
           "output_links": [
             {
               "link": [
@@ -5010,7 +4999,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 60,
           "output_links": [
             {
               "link": [
@@ -5188,7 +5176,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 60,
           "output_links": [
             {
               "link": [
@@ -5233,7 +5220,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -5278,7 +5264,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -5323,7 +5308,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -5368,7 +5352,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -5413,7 +5396,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1200,
+          "hard_timeout": 900,
           "output_links": [
             {
               "link": [
@@ -5424,7 +5407,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 2
+          "shards": 5
         },
         "test": "unit_tests"
       },
@@ -5503,7 +5486,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 300,
           "output_links": [
             {
               "link": [
@@ -5548,7 +5530,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 300,
           "output_links": [
             {
               "link": [
@@ -6314,7 +6295,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1800,
+          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -6362,7 +6343,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1920,
+          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -6497,7 +6478,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 960,
+          "hard_timeout": 900,
           "output_links": [
             {
               "link": [
@@ -6543,7 +6524,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1800,
+          "hard_timeout": 1500,
           "output_links": [
             {
               "link": [
@@ -6554,7 +6535,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 6
+          "shards": 9
         },
         "test": "content_browsertests"
       },
@@ -6600,7 +6581,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 2
+          "shards": 3
         },
         "test": "content_shell_test_apk"
       },
@@ -7041,7 +7022,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 960,
+          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -8077,7 +8058,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 960,
+          "hard_timeout": 900,
           "output_links": [
             {
               "link": [
@@ -8088,7 +8069,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 2
+          "shards": 5
         },
         "test": "unit_tests"
       },
@@ -8359,7 +8340,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 6
+          "shards": 7
         },
         "test": "webview_instrumentation_test_apk"
       },
@@ -8443,7 +8424,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 900,
+          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -8533,7 +8514,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 600,
+          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -8803,7 +8784,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 60,
+          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -9028,7 +9009,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1800,
+          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -9074,7 +9055,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1200,
+          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -9119,7 +9100,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 600,
+          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -9164,7 +9145,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1200,
+          "hard_timeout": 900,
           "output_links": [
             {
               "link": [
@@ -9210,7 +9191,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1800,
+          "hard_timeout": 1500,
           "output_links": [
             {
               "link": [
@@ -9221,7 +9202,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 6
+          "shards": 9
         },
         "test": "content_browsertests"
       },
@@ -9256,7 +9237,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1200,
+          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -9267,7 +9248,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 2
+          "shards": 3
         },
         "test": "content_shell_test_apk"
       },
@@ -9302,7 +9283,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1200,
+          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -9483,7 +9464,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 60,
+          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -9843,7 +9824,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 60,
+          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -10023,7 +10004,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 300,
+          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -10339,7 +10320,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 60,
+          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -10519,7 +10500,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 60,
+          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -10564,7 +10545,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 300,
+          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -10744,7 +10725,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1200,
+          "hard_timeout": 900,
           "output_links": [
             {
               "link": [
@@ -10755,7 +10736,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 2
+          "shards": 5
         },
         "test": "unit_tests"
       },
@@ -10835,7 +10816,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 300,
+          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -10880,7 +10861,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 300,
+          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -11015,7 +10996,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1800,
+          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -11026,7 +11007,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 6
+          "shards": 7
         },
         "test": "webview_instrumentation_test_apk"
       },
@@ -11682,7 +11663,7 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 1200,
+          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -11861,7 +11842,7 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 960,
+          "hard_timeout": 900,
           "output_links": [
             {
               "link": [
@@ -11906,7 +11887,7 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 1200,
+          "hard_timeout": 1500,
           "output_links": [
             {
               "link": [
@@ -11917,7 +11898,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 6
+          "shards": 9
         },
         "test": "content_browsertests"
       },
@@ -12393,7 +12374,7 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 960,
+          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -13406,7 +13387,7 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 960,
+          "hard_timeout": 900,
           "output_links": [
             {
               "link": [
@@ -13417,7 +13398,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 2
+          "shards": 5
         },
         "test": "unit_tests"
       },
@@ -13671,7 +13652,7 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 1200,
+          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -13682,7 +13663,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 8
+          "shards": 7
         },
         "test": "webview_instrumentation_test_apk"
       },
@@ -13765,7 +13746,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 900,
           "output_links": [
             {
               "link": [
@@ -13854,7 +13834,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 600,
           "output_links": [
             {
               "link": [
@@ -14119,7 +14098,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 60,
           "output_links": [
             {
               "link": [
@@ -14208,7 +14186,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -14342,7 +14319,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1800,
+          "hard_timeout": 1500,
           "output_links": [
             {
               "link": [
@@ -14388,7 +14365,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1200,
+          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -14433,7 +14410,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 600,
           "output_links": [
             {
               "link": [
@@ -14478,7 +14454,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1500,
+          "hard_timeout": 900,
           "output_links": [
             {
               "link": [
@@ -14524,7 +14500,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1800,
+          "hard_timeout": 1500,
           "output_links": [
             {
               "link": [
@@ -14535,7 +14511,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 6
+          "shards": 9
         },
         "test": "content_browsertests"
       },
@@ -14570,7 +14546,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1500,
+          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -14581,7 +14557,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 2
+          "shards": 3
         },
         "test": "content_shell_test_apk"
       },
@@ -14616,7 +14592,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1500,
+          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -14706,7 +14682,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -14795,7 +14770,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -14973,7 +14947,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -15152,7 +15125,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -15329,7 +15301,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 300,
           "output_links": [
             {
               "link": [
@@ -15643,7 +15614,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 60,
           "output_links": [
             {
               "link": [
@@ -15821,7 +15791,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -15866,7 +15835,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 300,
           "output_links": [
             {
               "link": [
@@ -15911,7 +15879,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -15956,7 +15923,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -16001,7 +15967,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 120,
           "output_links": [
             {
               "link": [
@@ -16046,7 +16011,7 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1200,
+          "hard_timeout": 900,
           "output_links": [
             {
               "link": [
@@ -16057,7 +16022,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 2
+          "shards": 5
         },
         "test": "unit_tests"
       },
@@ -16136,7 +16101,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 300,
           "output_links": [
             {
               "link": [
@@ -16181,7 +16145,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 300,
           "output_links": [
             {
               "link": [
@@ -16314,7 +16277,6 @@
             }
           ],
           "expiration": 10800,
-          "hard_timeout": 1800,
           "output_links": [
             {
               "link": [
@@ -16325,7 +16287,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 6
+          "shards": 7
         },
         "test": "webview_instrumentation_test_apk"
       },
@@ -16754,7 +16716,6 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 180,
           "output_links": [
             {
               "link": [
@@ -17191,7 +17152,6 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 1920,
           "output_links": [
             {
               "link": [
@@ -18672,7 +18632,6 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 180,
           "output_links": [
             {
               "link": [
@@ -19313,7 +19272,6 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -19400,7 +19358,6 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -19838,7 +19795,6 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 1200,
           "output_links": [
             {
               "link": [
@@ -19926,7 +19882,6 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -19970,7 +19925,7 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 960,
+          "hard_timeout": 900,
           "output_links": [
             {
               "link": [
@@ -20015,7 +19970,7 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 1200,
+          "hard_timeout": 1500,
           "output_links": [
             {
               "link": [
@@ -20026,7 +19981,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 6
+          "shards": 9
         },
         "test": "content_browsertests"
       },
@@ -20193,7 +20148,6 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -21493,7 +21447,7 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 960,
+          "hard_timeout": 900,
           "output_links": [
             {
               "link": [
@@ -21504,7 +21458,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 2
+          "shards": 5
         },
         "test": "unit_tests"
       },
@@ -21581,7 +21535,6 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -21625,7 +21578,6 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -21755,7 +21707,6 @@
               "os": "Android"
             }
           ],
-          "hard_timeout": 1200,
           "output_links": [
             {
               "link": [
@@ -21766,7 +21717,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 8
+          "shards": 7
         },
         "test": "webview_instrumentation_test_apk"
       },
@@ -21860,7 +21811,7 @@
               "temp_band": "<30"
             }
           ],
-          "hard_timeout": 1500,
+          "hard_timeout": 960,
           "shards": 15
         }
       }
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index bc49286..66d9765 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -526,6 +526,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -593,6 +599,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -1132,6 +1144,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -1199,6 +1217,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json
index 5c3c50e..7506ca7 100644
--- a/testing/buildbot/chromium.clang.json
+++ b/testing/buildbot/chromium.clang.json
@@ -1973,6 +1973,17 @@
             }
           ]
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Windows-10-15063"
+            }
+          ]
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -2134,6 +2145,17 @@
             }
           ]
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Windows-10-15063"
+            }
+          ]
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -3102,6 +3124,17 @@
             }
           ]
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Windows-10-15063"
+            }
+          ]
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -3263,6 +3296,17 @@
             }
           ]
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Windows-10-15063"
+            }
+          ]
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -4219,6 +4263,17 @@
             }
           ]
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Windows-10-15063"
+            }
+          ]
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -4380,6 +4435,17 @@
             }
           ]
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Windows-10-15063"
+            }
+          ]
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -5118,6 +5184,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -5213,6 +5285,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -5769,6 +5847,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -5864,6 +5948,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -6420,6 +6510,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -6515,6 +6611,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -7071,6 +7173,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -7166,6 +7274,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -10715,6 +10829,7 @@
               "os": "Android"
             }
           ],
+          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -10891,6 +11006,7 @@
               "os": "Android"
             }
           ],
+          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -10900,7 +11016,8 @@
               ],
               "name": "shard #${SHARD_INDEX} logcats"
             }
-          ]
+          ],
+          "shards": 3
         },
         "test": "content_shell_test_apk"
       },
@@ -11800,6 +11917,7 @@
               "os": "Android"
             }
           ],
+          "hard_timeout": 300,
           "output_links": [
             {
               "link": [
@@ -16137,8 +16255,7 @@
       },
       {
         "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 5
+          "can_use_on_swarming_builders": true
         },
         "test": "base_unittests"
       },
@@ -16325,6 +16442,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -16392,6 +16515,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -16888,6 +17017,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -16955,6 +17090,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -17453,6 +17594,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -17548,6 +17695,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -18104,6 +18257,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -18199,6 +18358,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -18755,6 +18920,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -18850,6 +19021,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -19406,6 +19583,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -19501,6 +19684,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -20057,6 +20246,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -20152,6 +20347,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -20708,6 +20909,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -20803,6 +21010,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -21359,6 +21572,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -21454,6 +21673,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -22010,6 +22235,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -22105,6 +22336,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -22661,6 +22898,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -22756,6 +22999,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -23312,6 +23561,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -23407,6 +23662,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -24867,6 +25128,17 @@
             }
           ]
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Windows-10"
+            }
+          ]
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -25028,6 +25300,17 @@
             }
           ]
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Windows-10"
+            }
+          ]
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 5ef4341d..19a79829 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -532,6 +532,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -599,6 +605,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -1783,7 +1795,8 @@
               "device_type": "bullhead",
               "os": "Android"
             }
-          ]
+          ],
+          "hard_timeout": 960
         },
         "test": "content_unittests"
       },
@@ -2352,6 +2365,12 @@
         "swarming": {
           "can_use_on_swarming_builders": false
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -2440,6 +2459,12 @@
         "swarming": {
           "can_use_on_swarming_builders": false
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -5046,6 +5071,15 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "args": [
+          "--enable-features=ViewsBrowserWindows"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -5146,6 +5180,15 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "args": [
+          "--enable-features=ViewsBrowserWindows"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index 4485702..0efd5c4 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -215,6 +215,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -282,6 +288,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -797,6 +809,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -864,6 +882,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -1578,6 +1602,18 @@
             }
           ]
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:0a2e",
+              "os": "Mac-10.12.6"
+            }
+          ]
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -1711,6 +1747,18 @@
             }
           ]
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:0a2e",
+              "os": "Mac-10.12.6"
+            }
+          ]
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -2468,6 +2516,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -2535,6 +2589,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -3045,6 +3105,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -3112,6 +3178,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index eebf213..ceb651c 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -636,6 +636,7 @@
               "os": "Android"
             }
           ],
+          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -812,6 +813,7 @@
               "os": "Android"
             }
           ],
+          "hard_timeout": 960,
           "output_links": [
             {
               "link": [
@@ -821,7 +823,8 @@
               ],
               "name": "shard #${SHARD_INDEX} logcats"
             }
-          ]
+          ],
+          "shards": 3
         },
         "test": "content_shell_test_apk"
       },
@@ -1721,6 +1724,7 @@
               "os": "Android"
             }
           ],
+          "hard_timeout": 300,
           "output_links": [
             {
               "link": [
@@ -4485,6 +4489,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -4546,6 +4556,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -5085,6 +5101,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -5146,6 +5168,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -6822,6 +6850,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -6889,6 +6923,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index 3bf50b2..801ce8ae 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -230,272 +230,6 @@
       }
     ]
   },
-  "Android Nexus5X Perf": {
-    "isolated_scripts": [
-      {
-        "args": [
-          "--non-telemetry=true",
-          "--migrated-test=true",
-          "--shard-timeout=300"
-        ],
-        "isolate_name": "angle_perftests",
-        "merge": {
-          "args": [
-            "--service-account-file",
-            "/creds/service_accounts/service-account-chromium-perf-histograms.json"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "angle_perftests",
-        "override_compile_targets": [
-          "angle_perftests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_flavor": "google",
-              "device_type": "bullhead",
-              "os": "Android",
-              "pool": "chrome.tests.perf"
-            }
-          ],
-          "expiration": 21600,
-          "hard_timeout": 25200,
-          "ignore_task_failure": false,
-          "io_timeout": 1800,
-          "shards": 1,
-          "upload_test_results": true
-        },
-        "trigger_script": {
-          "args": [
-            "--multiple-dimension-script-verbose",
-            "True"
-          ],
-          "script": "//testing/trigger_scripts/perf_device_trigger.py"
-        }
-      },
-      {
-        "args": [
-          "--non-telemetry=true",
-          "--migrated-test=true"
-        ],
-        "isolate_name": "components_perftests",
-        "merge": {
-          "args": [
-            "--service-account-file",
-            "/creds/service_accounts/service-account-chromium-perf-histograms.json"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "components_perftests",
-        "override_compile_targets": [
-          "components_perftests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_flavor": "google",
-              "device_type": "bullhead",
-              "os": "Android",
-              "pool": "chrome.tests.perf"
-            }
-          ],
-          "expiration": 21600,
-          "hard_timeout": 25200,
-          "ignore_task_failure": false,
-          "io_timeout": 1800,
-          "shards": 1,
-          "upload_test_results": true
-        },
-        "trigger_script": {
-          "args": [
-            "--multiple-dimension-script-verbose",
-            "True"
-          ],
-          "script": "//testing/trigger_scripts/perf_device_trigger.py"
-        }
-      },
-      {
-        "args": [
-          "--non-telemetry=true",
-          "--migrated-test=true"
-        ],
-        "isolate_name": "gpu_perftests",
-        "merge": {
-          "args": [
-            "--service-account-file",
-            "/creds/service_accounts/service-account-chromium-perf-histograms.json"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "gpu_perftests",
-        "override_compile_targets": [
-          "gpu_perftests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_flavor": "google",
-              "device_type": "bullhead",
-              "os": "Android",
-              "pool": "chrome.tests.perf"
-            }
-          ],
-          "expiration": 21600,
-          "hard_timeout": 25200,
-          "ignore_task_failure": false,
-          "io_timeout": 1800,
-          "shards": 1,
-          "upload_test_results": true
-        },
-        "trigger_script": {
-          "args": [
-            "--multiple-dimension-script-verbose",
-            "True"
-          ],
-          "script": "//testing/trigger_scripts/perf_device_trigger.py"
-        }
-      },
-      {
-        "args": [
-          "--non-telemetry=true",
-          "--migrated-test=true"
-        ],
-        "isolate_name": "media_perftests",
-        "merge": {
-          "args": [
-            "--service-account-file",
-            "/creds/service_accounts/service-account-chromium-perf-histograms.json"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "media_perftests",
-        "override_compile_targets": [
-          "media_perftests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_flavor": "google",
-              "device_type": "bullhead",
-              "os": "Android",
-              "pool": "chrome.tests.perf"
-            }
-          ],
-          "expiration": 21600,
-          "hard_timeout": 25200,
-          "ignore_task_failure": false,
-          "io_timeout": 1800,
-          "shards": 1,
-          "upload_test_results": true
-        },
-        "trigger_script": {
-          "args": [
-            "--multiple-dimension-script-verbose",
-            "True"
-          ],
-          "script": "//testing/trigger_scripts/perf_device_trigger.py"
-        }
-      },
-      {
-        "args": [
-          "-v",
-          "--browser=android-chromium",
-          "--upload-results",
-          "--run-ref-build",
-          "--test-shard-map-filename=android_nexus5x_16_shard_map.json"
-        ],
-        "isolate_name": "performance_test_suite",
-        "merge": {
-          "args": [
-            "--service-account-file",
-            "/creds/service_accounts/service-account-chromium-perf-histograms.json"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "performance_test_suite",
-        "override_compile_targets": [
-          "performance_test_suite"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_flavor": "google",
-              "device_type": "bullhead",
-              "os": "Android",
-              "pool": "chrome.tests.perf"
-            }
-          ],
-          "expiration": 21600,
-          "hard_timeout": 25200,
-          "ignore_task_failure": false,
-          "io_timeout": 1800,
-          "shards": 16,
-          "upload_test_results": true
-        },
-        "trigger_script": {
-          "args": [
-            "--multiple-dimension-script-verbose",
-            "True"
-          ],
-          "script": "//testing/trigger_scripts/perf_device_trigger.py"
-        }
-      },
-      {
-        "args": [
-          "--non-telemetry=true",
-          "--migrated-test=true"
-        ],
-        "isolate_name": "tracing_perftests",
-        "merge": {
-          "args": [
-            "--service-account-file",
-            "/creds/service_accounts/service-account-chromium-perf-histograms.json"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "tracing_perftests",
-        "override_compile_targets": [
-          "tracing_perftests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_flavor": "google",
-              "device_type": "bullhead",
-              "os": "Android",
-              "pool": "chrome.tests.perf"
-            }
-          ],
-          "expiration": 21600,
-          "hard_timeout": 25200,
-          "ignore_task_failure": false,
-          "io_timeout": 1800,
-          "shards": 1,
-          "upload_test_results": true
-        },
-        "trigger_script": {
-          "args": [
-            "--multiple-dimension-script-verbose",
-            "True"
-          ],
-          "script": "//testing/trigger_scripts/perf_device_trigger.py"
-        }
-      }
-    ]
-  },
   "Android Nexus5X WebView Perf": {
     "isolated_scripts": [
       {
@@ -753,177 +487,6 @@
       }
     ]
   },
-  "Win 10 Perf": {
-    "isolated_scripts": [
-      {
-        "args": [
-          "--non-telemetry=true",
-          "--migrated-test=true"
-        ],
-        "isolate_name": "components_perftests",
-        "merge": {
-          "args": [
-            "--service-account-file",
-            "C:\\creds\\service_accounts\\service-account-chromium-perf-histograms.json"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "components_perftests",
-        "override_compile_targets": [
-          "components_perftests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:5912",
-              "os": "Windows-10",
-              "pool": "chrome.tests.perf"
-            }
-          ],
-          "expiration": 21600,
-          "hard_timeout": 25200,
-          "ignore_task_failure": false,
-          "io_timeout": 1800,
-          "shards": 1,
-          "upload_test_results": true
-        },
-        "trigger_script": {
-          "args": [
-            "--multiple-dimension-script-verbose",
-            "True"
-          ],
-          "script": "//testing/trigger_scripts/perf_device_trigger.py"
-        }
-      },
-      {
-        "args": [
-          "--non-telemetry=true",
-          "--migrated-test=true"
-        ],
-        "isolate_name": "media_perftests",
-        "merge": {
-          "args": [
-            "--service-account-file",
-            "C:\\creds\\service_accounts\\service-account-chromium-perf-histograms.json"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "media_perftests",
-        "override_compile_targets": [
-          "media_perftests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:5912",
-              "os": "Windows-10",
-              "pool": "chrome.tests.perf"
-            }
-          ],
-          "expiration": 21600,
-          "hard_timeout": 25200,
-          "ignore_task_failure": false,
-          "io_timeout": 1800,
-          "shards": 1,
-          "upload_test_results": true
-        },
-        "trigger_script": {
-          "args": [
-            "--multiple-dimension-script-verbose",
-            "True"
-          ],
-          "script": "//testing/trigger_scripts/perf_device_trigger.py"
-        }
-      },
-      {
-        "args": [
-          "-v",
-          "--browser=release_x64",
-          "--upload-results",
-          "--run-ref-build",
-          "--test-shard-map-filename=win10_shard_map.json"
-        ],
-        "isolate_name": "performance_test_suite",
-        "merge": {
-          "args": [
-            "--service-account-file",
-            "C:\\creds\\service_accounts\\service-account-chromium-perf-histograms.json"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "performance_test_suite",
-        "override_compile_targets": [
-          "performance_test_suite"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:5912",
-              "os": "Windows-10",
-              "pool": "chrome.tests.perf"
-            }
-          ],
-          "expiration": 21600,
-          "hard_timeout": 25200,
-          "ignore_task_failure": false,
-          "io_timeout": 1800,
-          "shards": 5,
-          "upload_test_results": true
-        },
-        "trigger_script": {
-          "args": [
-            "--multiple-dimension-script-verbose",
-            "True"
-          ],
-          "script": "//testing/trigger_scripts/perf_device_trigger.py"
-        }
-      },
-      {
-        "args": [
-          "--non-telemetry=true",
-          "--migrated-test=true"
-        ],
-        "isolate_name": "views_perftests",
-        "merge": {
-          "args": [
-            "--service-account-file",
-            "C:\\creds\\service_accounts\\service-account-chromium-perf-histograms.json"
-          ],
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "views_perftests",
-        "override_compile_targets": [
-          "views_perftests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:5912",
-              "os": "Windows-10",
-              "pool": "chrome.tests.perf"
-            }
-          ],
-          "expiration": 21600,
-          "hard_timeout": 25200,
-          "ignore_task_failure": false,
-          "io_timeout": 1800,
-          "shards": 1,
-          "upload_test_results": true
-        },
-        "trigger_script": {
-          "args": [
-            "--multiple-dimension-script-verbose",
-            "True"
-          ],
-          "script": "//testing/trigger_scripts/perf_device_trigger.py"
-        }
-      }
-    ]
-  },
   "Win 7 Nvidia GPU Perf": {
     "isolated_scripts": [
       {
@@ -1362,6 +925,272 @@
       "chromedriver"
     ]
   },
+  "android-nexus5x-perf": {
+    "isolated_scripts": [
+      {
+        "args": [
+          "--non-telemetry=true",
+          "--migrated-test=true",
+          "--shard-timeout=300"
+        ],
+        "isolate_name": "angle_perftests",
+        "merge": {
+          "args": [
+            "--service-account-file",
+            "/creds/service_accounts/service-account-chromium-perf-histograms.json"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "angle_perftests",
+        "override_compile_targets": [
+          "angle_perftests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_os_flavor": "google",
+              "device_type": "bullhead",
+              "os": "Android",
+              "pool": "chrome.tests.perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 25200,
+          "ignore_task_failure": false,
+          "io_timeout": 1800,
+          "shards": 1,
+          "upload_test_results": true
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      },
+      {
+        "args": [
+          "--non-telemetry=true",
+          "--migrated-test=true"
+        ],
+        "isolate_name": "components_perftests",
+        "merge": {
+          "args": [
+            "--service-account-file",
+            "/creds/service_accounts/service-account-chromium-perf-histograms.json"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "components_perftests",
+        "override_compile_targets": [
+          "components_perftests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_os_flavor": "google",
+              "device_type": "bullhead",
+              "os": "Android",
+              "pool": "chrome.tests.perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 25200,
+          "ignore_task_failure": false,
+          "io_timeout": 1800,
+          "shards": 1,
+          "upload_test_results": true
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      },
+      {
+        "args": [
+          "--non-telemetry=true",
+          "--migrated-test=true"
+        ],
+        "isolate_name": "gpu_perftests",
+        "merge": {
+          "args": [
+            "--service-account-file",
+            "/creds/service_accounts/service-account-chromium-perf-histograms.json"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "gpu_perftests",
+        "override_compile_targets": [
+          "gpu_perftests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_os_flavor": "google",
+              "device_type": "bullhead",
+              "os": "Android",
+              "pool": "chrome.tests.perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 25200,
+          "ignore_task_failure": false,
+          "io_timeout": 1800,
+          "shards": 1,
+          "upload_test_results": true
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      },
+      {
+        "args": [
+          "--non-telemetry=true",
+          "--migrated-test=true"
+        ],
+        "isolate_name": "media_perftests",
+        "merge": {
+          "args": [
+            "--service-account-file",
+            "/creds/service_accounts/service-account-chromium-perf-histograms.json"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "media_perftests",
+        "override_compile_targets": [
+          "media_perftests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_os_flavor": "google",
+              "device_type": "bullhead",
+              "os": "Android",
+              "pool": "chrome.tests.perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 25200,
+          "ignore_task_failure": false,
+          "io_timeout": 1800,
+          "shards": 1,
+          "upload_test_results": true
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      },
+      {
+        "args": [
+          "-v",
+          "--browser=android-chromium",
+          "--upload-results",
+          "--run-ref-build",
+          "--test-shard-map-filename=android_nexus5x_16_shard_map.json"
+        ],
+        "isolate_name": "performance_test_suite",
+        "merge": {
+          "args": [
+            "--service-account-file",
+            "/creds/service_accounts/service-account-chromium-perf-histograms.json"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "performance_test_suite",
+        "override_compile_targets": [
+          "performance_test_suite"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_os_flavor": "google",
+              "device_type": "bullhead",
+              "os": "Android",
+              "pool": "chrome.tests.perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 25200,
+          "ignore_task_failure": false,
+          "io_timeout": 1800,
+          "shards": 16,
+          "upload_test_results": true
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      },
+      {
+        "args": [
+          "--non-telemetry=true",
+          "--migrated-test=true"
+        ],
+        "isolate_name": "tracing_perftests",
+        "merge": {
+          "args": [
+            "--service-account-file",
+            "/creds/service_accounts/service-account-chromium-perf-histograms.json"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "tracing_perftests",
+        "override_compile_targets": [
+          "tracing_perftests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_os_flavor": "google",
+              "device_type": "bullhead",
+              "os": "Android",
+              "pool": "chrome.tests.perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 25200,
+          "ignore_task_failure": false,
+          "io_timeout": 1800,
+          "shards": 1,
+          "upload_test_results": true
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      }
+    ]
+  },
   "linux-perf": {
     "isolated_scripts": [
       {
@@ -1874,5 +1703,176 @@
         }
       }
     ]
+  },
+  "win-10-perf": {
+    "isolated_scripts": [
+      {
+        "args": [
+          "--non-telemetry=true",
+          "--migrated-test=true"
+        ],
+        "isolate_name": "components_perftests",
+        "merge": {
+          "args": [
+            "--service-account-file",
+            "C:\\creds\\service_accounts\\service-account-chromium-perf-histograms.json"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "components_perftests",
+        "override_compile_targets": [
+          "components_perftests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912",
+              "os": "Windows-10",
+              "pool": "chrome.tests.perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 25200,
+          "ignore_task_failure": false,
+          "io_timeout": 1800,
+          "shards": 1,
+          "upload_test_results": true
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      },
+      {
+        "args": [
+          "--non-telemetry=true",
+          "--migrated-test=true"
+        ],
+        "isolate_name": "media_perftests",
+        "merge": {
+          "args": [
+            "--service-account-file",
+            "C:\\creds\\service_accounts\\service-account-chromium-perf-histograms.json"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "media_perftests",
+        "override_compile_targets": [
+          "media_perftests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912",
+              "os": "Windows-10",
+              "pool": "chrome.tests.perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 25200,
+          "ignore_task_failure": false,
+          "io_timeout": 1800,
+          "shards": 1,
+          "upload_test_results": true
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      },
+      {
+        "args": [
+          "-v",
+          "--browser=release_x64",
+          "--upload-results",
+          "--run-ref-build",
+          "--test-shard-map-filename=win10_shard_map.json"
+        ],
+        "isolate_name": "performance_test_suite",
+        "merge": {
+          "args": [
+            "--service-account-file",
+            "C:\\creds\\service_accounts\\service-account-chromium-perf-histograms.json"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "performance_test_suite",
+        "override_compile_targets": [
+          "performance_test_suite"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912",
+              "os": "Windows-10",
+              "pool": "chrome.tests.perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 25200,
+          "ignore_task_failure": false,
+          "io_timeout": 1800,
+          "shards": 5,
+          "upload_test_results": true
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      },
+      {
+        "args": [
+          "--non-telemetry=true",
+          "--migrated-test=true"
+        ],
+        "isolate_name": "views_perftests",
+        "merge": {
+          "args": [
+            "--service-account-file",
+            "C:\\creds\\service_accounts\\service-account-chromium-perf-histograms.json"
+          ],
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "views_perftests",
+        "override_compile_targets": [
+          "views_perftests"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912",
+              "os": "Windows-10",
+              "pool": "chrome.tests.perf"
+            }
+          ],
+          "expiration": 21600,
+          "hard_timeout": 25200,
+          "ignore_task_failure": false,
+          "io_timeout": 1800,
+          "shards": 1,
+          "upload_test_results": true
+        },
+        "trigger_script": {
+          "args": [
+            "--multiple-dimension-script-verbose",
+            "True"
+          ],
+          "script": "//testing/trigger_scripts/perf_device_trigger.py"
+        }
+      }
+    ]
   }
 }
diff --git a/testing/buildbot/chromium.swarm.json b/testing/buildbot/chromium.swarm.json
index 87ec7f68..b2e0d7a 100644
--- a/testing/buildbot/chromium.swarm.json
+++ b/testing/buildbot/chromium.swarm.json
@@ -542,7 +542,7 @@
               "name": "shard #${SHARD_INDEX} logcats"
             }
           ],
-          "shards": 4
+          "shards": 3
         },
         "test": "content_unittests"
       },
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json
index 21fcb12..c800548 100644
--- a/testing/buildbot/chromium.win.json
+++ b/testing/buildbot/chromium.win.json
@@ -303,6 +303,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -398,6 +404,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -1015,6 +1027,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -1110,6 +1128,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -1588,6 +1612,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -1685,6 +1715,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -2290,6 +2326,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -2374,6 +2416,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
@@ -3015,6 +3063,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "filesystem_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "gcm_unit_tests"
       },
       {
@@ -3110,6 +3164,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "leveldb_service_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "libjingle_xmpp_unittests"
       },
       {
diff --git a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
index 7e11f2b..6c71af6 100644
--- a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
+++ b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
@@ -272,8 +272,6 @@
 -ExtensionWebRequestApiTest.WebRequestTestOSDD
 # Note WebRequestUnloadImmediately is disabled on Linux
 -ExtensionWebRequestApiTest.WebRequestUnloadImmediately
-# http://crbug.com/853118 Flaky with serivicified network stack.
--LocalNTPInterceptionWebRequestAPITest.OneGoogleBarRequestsHidden
 
 # WebRequest implementation needs to handle extension
 # installation/uninstallation events.
diff --git a/testing/buildbot/filters/viz.android.content_browsertests.filter b/testing/buildbot/filters/viz.android.content_browsertests.filter
index 3216603f..982fafd7 100644
--- a/testing/buildbot/filters/viz.android.content_browsertests.filter
+++ b/testing/buildbot/filters/viz.android.content_browsertests.filter
@@ -19,7 +19,6 @@
 # InputEventAckWaiter never receives the event: https://crbug.com/848348
 -SitePerProcessHitTestBrowserTest.CrossProcessMouseEnterAndLeaveTest*
 -SitePerProcessHitTestBrowserTest.CrossProcessMouseCapture*
--SitePerProcessHitTestBrowserTest.TouchpadPinchOverOOPIF*
 
 # /2 Variant does not handle overlapping surfaces: https://crbug.com/846798
--SitePerProcessHitTestBrowserTest.HitTestStaleDataDeletedView*
+-SitePerProcessHitTestBrowserTest.HitTestStaleDataDeletedView*
\ No newline at end of file
diff --git a/testing/buildbot/filters/viz.content_browsertests.filter b/testing/buildbot/filters/viz.content_browsertests.filter
index 1bc69ef..7749b7e 100644
--- a/testing/buildbot/filters/viz.content_browsertests.filter
+++ b/testing/buildbot/filters/viz.content_browsertests.filter
@@ -9,7 +9,6 @@
 # InputEventAckWaiter never receives the event: https://crbug.com/848348
 -SitePerProcessHitTestBrowserTest.CrossProcessMouseEnterAndLeaveTest*
 -SitePerProcessHitTestBrowserTest.CrossProcessMouseCapture*
--SitePerProcessHitTestBrowserTest.TouchpadPinchOverOOPIF*
 
 ### Mac
 # BrowserSideFlingBrowserTest timing out https://crbug.com/842325
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 7ce28629..35831be 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -25,18 +25,6 @@
       # chromium.android.fyi
       'x64 Device Tester',
     ],
-    'modifications': {
-      'Lollipop Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 900,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 900,
-        },
-      },
-    },
   },
   'angle_end2end_tests': {
     'remove_from': [
@@ -71,66 +59,11 @@
       },
     },
   },
-  'base_unittests': {
-    'modifications': {
-      # chromium.android
-      'android-marshmallow-arm64-rel': {
-        'swarming': {
-          'hard_timeout': 960,
-        },
-      },
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 300,
-        },
-      },
-      'Lollipop Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 600,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 600,
-        },
-      },
-      # chromium.clang
-      'ToTMac': {
-        'swarming': {
-          'shards': 5,
-        },
-      },
-    },
-  },
   'blink_heap_unittests': {
     'remove_from': [
       # chromium.memory
       'Linux TSan Tests',  # https://crbug.com/831674
     ],
-    'modifications': {
-      # chromium.android
-      'android-kitkat-arm-rel': {
-        'swarming': {
-          'hard_timeout': 180,
-        },
-      },
-      'android-marshmallow-arm64-rel': {
-        'swarming': {
-          'hard_timeout': 960,
-        },
-      },
-      'KitKat Phone Tester (dbg)': {
-        'swarming': {
-          'hard_timeout': 180,
-        },
-      },
-      # chromium.android.fyi
-      'x86 Cloud Tester': {
-        'swarming': {
-          'hard_timeout': 120,
-        },
-      },
-    },
   },
   'blink_platform_unittests': {
     'modifications': {
@@ -142,25 +75,6 @@
       },
     },
   },
-  'breakpad_unittests': {
-    'modifications': {
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 60,
-        },
-      },
-      'Lollipop Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 60,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 60,
-        },
-      },
-    },
-  },
   'browser_tests': {
     'remove_from': [
       # chromium.clang
@@ -306,20 +220,6 @@
       },
     },
   },
-  'capture_unittests': {
-    'modifications': {
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 120,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 120,
-        },
-      },
-    },
-  },
   'cast_shell_browsertests': {
     'modifications': {
       'Cast Audio Linux': {
@@ -390,64 +290,17 @@
           'shards': 20,
         },
       },
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 2400,
-        },
-      },
-      'Lollipop Phone Tester': {
-        'swarming': {
-          'hard_timeout': 1800,
-        },
-      },
-      'Lollipop Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 1800,
-        },
-      },
       'Marshmallow 64 bit Tester': {
         # TODO(crbug.com/731759): Enable this once we're confident that it
         # passes.
         'experiment_percentage': 100,
         'swarming': {
-          'hard_timeout': 1200,
           'shards': 14,
         },
       },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 1800,
-        },
-      },
       'Oreo Phone Tester': {
         'experiment_percentage': 100,
       },
-      # chromium.android.fyi
-      'Nougat Phone Tester': {
-        'swarming': {
-          'hard_timeout': 1200,
-          'shards': 8,
-        },
-      },
-      'x64 Device Tester': {
-        'swarming': {
-          'hard_timeout': 0,
-          'shards': 1,
-        },
-      },
-      'x86 Cloud Tester': {
-        'swarming': {
-          'hard_timeout': 1200,
-          'shards': 1,
-        },
-      },
-      # chromium.clang
-      'ToTAndroid x64': {
-        'swarming': {
-          'shards': 1,
-          'hard_timeout': 0,
-        },
-      },
       # chromium.swarm
       'Android N5X Swarm': {
         # TODO(crbug.com/731759): Enable this once we're confident that it
@@ -469,27 +322,18 @@
           '--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_cardboard_skipdon_setupcomplete.json',
           '--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk',
         ],
-        'swarming': {
-          'hard_timeout': 1920,
-        },
       },
       'android-marshmallow-arm64-rel': {
         'args': [
           '--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_cardboard_skipdon_setupcomplete.json',
           '--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk',
         ],
-        'swarming': {
-          'hard_timeout': 1200,
-        },
       },
       'Lollipop Phone Tester': {
         'args': [
           '--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_cardboard_skipdon_setupcomplete.json',
           '--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk',
         ],
-        'swarming': {
-          'hard_timeout': 1920,
-        },
       },
       'Marshmallow 64 bit Tester': {
         'args': [
@@ -524,49 +368,6 @@
           'shards': 2,
         },
       },
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 1200,
-        },
-      },
-      'Lollipop Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 1200,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 1200,
-        },
-      },
-      # chromium.android.fyi
-      'x64 Device Tester': {
-        'swarming': {
-          'hard_timeout': 0,
-        },
-      },
-      'x86 Cloud Tester': {
-        'swarming': {
-          'hard_timeout': 600,
-        },
-      },
-      # chromium.clang
-      'ToTAndroid x64': {
-        'swarming': {
-          'hard_timeout': 0,
-        },
-      },
-      'ToTAndroidCFI': {
-        'swarming': {
-          'hard_timeout': 0,
-        },
-      },
-      # chromium.memory
-      'Android CFI': {
-        'swarming': {
-          'hard_timeout': 0,
-        },
-      },
     },
   },
   'chromevox_tests': {
@@ -587,81 +388,9 @@
       'Win7 Tests (dbg)(1)',
       'Win10 Tests x64 (dbg)',
     ],
-    'modifications': {
-      'android-marshmallow-arm64-rel': {
-        'swarming': {
-          'hard_timeout': 960,
-        },
-      },
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 600,
-        },
-      },
-      'Lollipop Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 600,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 600,
-        },
-      },
-    },
   },
   'components_unittests': {
     'modifications': {
-      # chromium.android
-      'android-marshmallow-arm64-rel': {
-        'swarming': {
-          'hard_timeout': 960,
-        },
-      },
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 1500,
-        },
-      },
-      'Lollipop Phone Tester': {
-        'swarming': {
-          'hard_timeout': 960,
-        },
-      },
-      'Lollipop Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 1200,
-        },
-      },
-      'Marshmallow 64 bit Tester': {
-        'swarming': {
-          'hard_timeout': 960,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 1500,
-        },
-      },
-      # chromium.android.fyi
-      'Nougat Phone Tester': {
-        'swarming': {
-          'hard_timeout': 960,
-          'shards': 1,
-        },
-      },
-      'x64 Device Tester': {
-        'swarming': {
-          'hard_timeout': 0,
-          'shards': 1,
-        },
-      },
-      'x86 Cloud Tester': {
-        'swarming': {
-          'hard_timeout': 0,
-          'shards': 1,
-        },
-      },
       # chromium.memory
       'Linux ASan LSan Tests (1)': {
         # These are very slow on the ASAN trybot for some reason.
@@ -674,50 +403,7 @@
   },
   'content_browsertests': {
     'modifications': {
-      # chromium.android
-      'android-marshmallow-arm64-rel': {
-        'swarming': {
-          'hard_timeout': 1200,
-          'shards': 6,
-        },
-      },
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 1800,
-          'shards': 6,
-        },
-      },
-      'Lollipop Phone Tester': {
-        'swarming': {
-          'hard_timeout': 1800,
-          'shards': 6,
-        },
-      },
-      'Lollipop Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 1800,
-          'shards': 6,
-        },
-      },
-      'Marshmallow 64 bit Tester': {
-        'swarming': {
-          'hard_timeout': 1200,
-          'shards': 6,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 1800,
-          'shards': 6,
-        },
-      },
       # chromium.android.fyi
-      'Nougat Phone Tester': {
-        'swarming': {
-          'hard_timeout': 1200,
-          'shards': 6,
-        },
-      },
       'Unswarmed N5 Tests Dummy Builder': {
         'args': [
           '--shard-timeout',
@@ -730,18 +416,6 @@
           '600',
         ],
       },
-      'x64 Device Tester': {
-        'swarming': {
-          'hard_timeout': 0,
-          'shards': 1,
-        },
-      },
-      'x86 Cloud Tester': {
-        'swarming': {
-          'hard_timeout': 960,
-          'shards': 1,
-        },
-      },
       # chromium.chromiumos
       'linux-chromeos-dbg': {
         'swarming': {
@@ -848,119 +522,9 @@
         'args',
       ],
     },
-    'modifications': {
-      # chromium.android
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 1800,
-          'shards': 2,
-        },
-      },
-      'Lollipop Phone Tester': {
-        'swarming': {
-          'shards': 2,
-        },
-      },
-      'Lollipop Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 1200,
-          'shards': 2,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 1500,
-          'shards': 2,
-        },
-      },
-      # chromium.android.fyi
-      'Nougat Phone Tester': {
-        'swarming': {
-          'hard_timeout': 1200,
-          'shards': 4,
-        },
-      },
-      'x64 Device Tester': {
-        'swarming': {
-          'hard_timeout': 0,
-          'shards': 1,
-        },
-      },
-      'x86 Cloud Tester': {
-        'swarming': {
-          'hard_timeout': 1920,
-          'shards': 1,
-        },
-      },
-      # chromium.clang
-      'ToTAndroid x64': {
-        'swarming': {
-          'hard_timeout': 0,
-          'shards': 1,
-        },
-      },
-      'ToTAndroidCFI': {
-        'swarming': {
-          'hard_timeout': 0,
-          'shards': 1,
-        },
-      },
-      # chromium.memory
-      'Android CFI': {
-        'swarming': {
-          'hard_timeout': 0,
-          'shards': 1,
-        },
-      },
-    },
   },
   'content_unittests': {
     'modifications': {
-      # TODO(dpranke) - on chromium.swarm, remove this exception.
-      'Android N5X Swarm': {
-        'swarming': {
-          'shards': 4,
-        },
-      },
-      # chromium.android
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 1200,
-        },
-      },
-      'Lollipop Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 1200,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 1500,
-        },
-      },
-      # chromium.android.fyi
-      'Nougat Phone Tester': {
-        'swarming': {
-          'hard_timeout': 1200,
-          'shards': 2,
-        },
-      },
-      'x64 Device Tester': {
-        'swarming': {
-          'hard_timeout': 0,
-        },
-      },
-      'x86 Cloud Tester': {
-        'swarming': {
-          'hard_timeout': 0,
-        },
-      },
-      # chromium.fyi
-      'Site Isolation Android': {
-        'swarming': {
-          'hard_timeout': 0,
-        },
-      },
       # chromium.memory
       'Linux ASan LSan Tests (1)': {
         # These are slow on the ASAN trybot for some reason.
@@ -986,60 +550,6 @@
       'linux-win_cross-rel', # https://crbug.com/762167
     ],
   },
-  'cronet_test_instrumentation_apk': {
-    'modifications': {
-      'Android Cronet Builder (dbg) chromium.android.fyi': {
-        'swarming': {
-          'hard_timeout': 1200,
-          'shards': 2,
-        },
-      },
-      'Android Cronet KitKat Builder chromium.android.fyi': {
-        'swarming': {
-          'hard_timeout': 1200,
-          'shards': 2,
-        },
-      },
-    },
-  },
-  'device_unittests': {
-    'modifications': {
-      'android-marshmallow-arm64-rel': {
-        'swarming': {
-          'hard_timeout': 960,
-        },
-      },
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 120,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 120,
-        },
-      },
-    },
-  },
-  'events_unittests': {
-    'modifications': {
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 60,
-        },
-      },
-      'Lollipop Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 60,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 120,
-        },
-      },
-    },
-  },
   'gin_unittests': {
     'remove_from': [
       # chromium.clang
@@ -1064,16 +574,6 @@
       'Linux MSan Tests',
     ],
     'modifications': {
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 120,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 120,
-        },
-      },
       # chromium.memory
       # TODO(kbr): figure out a better way to specify blocks of
       # arguments like this for tests on multiple machines.
@@ -1153,28 +653,6 @@
       'Linux FYI Release (AMD R7 240)',
     ],
     'modifications': {
-      # chromium.android
-      'android-marshmallow-arm64-rel': {
-        'swarming': {
-          'hard_timeout': 120,
-        },
-      },
-      'Lollipop Phone Tester': {
-        'swarming': {
-          'hard_timeout': 960,
-        },
-      },
-      'Marshmallow 64 bit Tester': {
-        'swarming': {
-          'hard_timeout': 960,
-        },
-      },
-      # chromium.android.fyi
-      'Nougat Phone Tester': {
-        'swarming': {
-          'hard_timeout': 960,
-        },
-      },
       # chromium.clang
       'CFI Linux (icall)': {
         'args': [
@@ -1298,48 +776,6 @@
       },
     },
   },
-  'ipc_tests': {
-    'modifications': {
-      # chromium.android
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 60,
-        },
-      },
-      'Lollipop Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 60,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 120,
-        },
-      },
-      # chromium.android.fyi
-      'Unswarmed N5 Tests Dummy Builder': {
-        'args': [
-          '--shard-timeout',
-          '600',
-        ],
-      },
-      'Unswarmed N5X Tests Dummy Builder': {
-        'args': [
-          '--shard-timeout',
-          '600',
-        ],
-      },
-    },
-  },
-  'latency_unittests': {
-    'modifications': {
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 60,
-        },
-      },
-    },
-  },
   'mash_browser_tests': {
     'remove_from': [
       # Not needed on chromium.fyi because suite is on main waterfall.
@@ -1371,36 +807,6 @@
       'Mojo ChromiumOS',
     ],
   },
-  'media_blink_unittests': {
-    'modifications': {
-      'Lollipop Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 300,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 300,
-        },
-      },
-    },
-  },
-  'mojo_test_apk': {
-    'modifications': {
-      # chromium.clang
-      'ToTAndroidCFI': {
-        'swarming': {
-          'hard_timeout': 0,
-        },
-      },
-      # chromium.clang
-      'Android CFI': {
-        'swarming': {
-          'hard_timeout': 0,
-        },
-      },
-    },
-  },
   'nacl_helper_nonsfi_unittests': {
     'remove_from': [
       # chromium.memory
@@ -1560,16 +966,6 @@
   },
   'sandbox_linux_unittests': {
     'modifications': {
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 60,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 60,
-        },
-      },
       'linux-chromeos-dbg': {
         'args': [
           '--test-launcher-print-test-stdio=always',
@@ -1590,11 +986,6 @@
           '--test-launcher-print-test-stdio=always',
         ],
       },
-      'Lollipop Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 60,
-        },
-      },
     },
   },
   'services_unittests': {
@@ -1764,65 +1155,6 @@
       },
     },
   },
-  'sql_unittests': {
-    'modifications': {
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 60,
-        },
-      },
-      'Lollipop Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 60,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 120,
-        },
-      },
-    },
-  },
-  'storage_unittests': {
-    'modifications': {
-      # chromium.android
-      'android-kitkat-arm-rel': {
-        'swarming': {
-          'hard_timeout': 180,
-        },
-      },
-      'KitKat Phone Tester (dbg)': {
-        'swarming': {
-          'hard_timeout': 180,
-        },
-      },
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 120,
-        },
-      },
-      'Lollipop Phone Tester': {
-        'swarming': {
-          'hard_timeout': 960,
-        },
-      },
-      'Lollipop Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 300,
-        },
-      },
-      'Marshmallow 64 bit Tester': {
-        'swarming': {
-          'hard_timeout': 960,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 300,
-        },
-      },
-    },
-  },
   'sync_integration_tests': {
     'modifications': {
       'Win7 Tests (dbg)(1)': {
@@ -1892,7 +1224,6 @@
               'temp_band': '<30',
             },
           ],
-          'hard_timeout': 1500,
           'shards': 15,
         },
       },
@@ -1907,7 +1238,6 @@
               'temp_band': '<30',
             },
           ],
-          'hard_timeout': 1500,
           'shards': 15,
         },
       },
@@ -1998,48 +1328,6 @@
       'Linux Tests (dbg)(1)(32)',
     ],
   },
-  'ui_android_unittests': {
-    'modifications': {
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 120,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 120,
-        },
-      },
-    },
-  },
-  'ui_base_unittests': {
-    'modifications': {
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 120,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 120,
-        },
-      },
-    },
-  },
-  'ui_touch_selection_unittests': {
-    'modifications': {
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 120,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 120,
-        },
-      },
-    },
-  },
   'unit_tests': {
     'remove_from': [
       # On chromium.linux, unclear why these aren't run on Cast.
@@ -2049,60 +1337,6 @@
       'Win10 Tests x64 (dbg)',
     ],
     'modifications': {
-      # chromium.android
-      'android-marshmallow-arm64-rel': {
-        'swarming': {
-          'hard_timeout': 960,
-          'shards': 2,
-        },
-      },
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 1200,
-          'shards': 2,
-        },
-      },
-      'Lollipop Phone Tester': {
-        'swarming': {
-          'hard_timeout': 960,
-          'shards': 2,
-        },
-      },
-      'Lollipop Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 1200,
-          'shards': 2,
-        },
-      },
-      'Marshmallow 64 bit Tester': {
-        'swarming': {
-          'hard_timeout': 960,
-          'shards': 2,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 1200,
-          'shards': 2,
-        },
-      },
-      # chromium.android.fyi
-      'Nougat Phone Tester': {
-        'swarming': {
-          'hard_timeout': 1200,
-          'shards': 2,
-        },
-      },
-      'x64 Device Tester': {
-        'swarming': {
-          'hard_timeout': 0,
-        },
-      },
-      'x86 Cloud Tester': {
-        'swarming': {
-          'hard_timeout': 0,
-        },
-      },
       # chromium.clang
       'ToTLinuxASan': {
         'swarming': {
@@ -2238,28 +1472,6 @@
       # chromium.win
       'Win10 Tests x64',
     ],
-    'modifications': {
-      'android-marshmallow-arm64-rel': {
-        'swarming': {
-          'hard_timeout': 960,
-        },
-      },
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 300,
-        },
-      },
-      'Lollipop Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 300,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 300,
-        },
-      },
-    },
   },
   'vr_common_unittests': {
     'remove_from': [
@@ -2267,28 +1479,6 @@
       'Win 7 Tests x64 (1)',
       'Win10 Tests x64',
     ],
-    'modifications': {
-      'android-marshmallow-arm64-rel': {
-        'swarming': {
-          'hard_timeout': 960,
-        },
-      },
-      'KitKat Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 300,
-        },
-      },
-      'Lollipop Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 300,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 300,
-        },
-      },
-    },
   },
   'vr_browser_tests': {
     'remove_from': [
@@ -2713,49 +1903,5 @@
         'args',
       ],
     },
-    'modifications': {
-      # chromium.android
-      'android-marshmallow-arm64-rel': {
-        'swarming': {
-          'hard_timeout': 1200,
-          'shards': 8,
-        },
-      },
-      'Lollipop Phone Tester': {
-        'swarming': {
-          'shards': 6,
-        },
-      },
-      'Lollipop Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 1800,
-          'shards': 6,
-        },
-      },
-      'Marshmallow 64 bit Tester': {
-        'swarming': {
-          'hard_timeout': 1200,
-          'shards': 8,
-        },
-      },
-      'Marshmallow Tablet Tester': {
-        'swarming': {
-          'hard_timeout': 1800,
-          'shards': 6,
-        },
-      },
-      # chromium.android.fyi
-      'Nougat Phone Tester': {
-        'swarming': {
-          'hard_timeout': 1500,
-          'shards': 6,
-        },
-      },
-      'x86 Cloud Tester': {
-        'swarming': {
-          'hard_timeout': 960,
-        },
-      },
-    },
   },
 }
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 5ac9c829..36e056d 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -1831,8 +1831,6 @@
   'linux_specific_chromium_gtests': {
     # Linux only.
     # TODO(kbr): unclear why some of these aren't run more broadly.
-    'filesystem_service_unittests': {},
-    'leveldb_service_unittests': {},
     'traffic_annotation_auditor_unittests': {},
   },
 
@@ -1889,11 +1887,13 @@
     'chromedriver_unittests': {},
     'extensions_browsertests': {},
     'extensions_unittests': {},
+    'filesystem_service_unittests': {},  # https://crbug.com/862712
     'interactive_ui_tests': {
       'swarming': {
         'shards': 3,
       },
     },
+    'leveldb_service_unittests': {},  # https://crbug.com/862709
     'message_center_unittests': {},
     'nacl_loader_unittests': {},
     'native_theme_unittests': {},
diff --git a/testing/libfuzzer/fuzzer_test.gni b/testing/libfuzzer/fuzzer_test.gni
index fdcf6fe2..71bae180 100644
--- a/testing/libfuzzer/fuzzer_test.gni
+++ b/testing/libfuzzer/fuzzer_test.gni
@@ -136,7 +136,7 @@
       ]
 
       if (defined(invoker.sources) && invoker.sources != []) {
-        args += [ "--sources" ] + rebase_path(invoker.sources, root_build_dir)
+        args += [ "--sources" ] + rebase_path(invoker.sources, "//")
       } else if (defined(invoker.deps) && invoker.deps != []) {
         _full_deps = []
         foreach(_dep, invoker.deps) {
diff --git a/testing/libfuzzer/gen_fuzzer_owners.py b/testing/libfuzzer/gen_fuzzer_owners.py
index 6a268ad..af0f04f 100755
--- a/testing/libfuzzer/gen_fuzzer_owners.py
+++ b/testing/libfuzzer/gen_fuzzer_owners.py
@@ -70,7 +70,9 @@
         source_content):
       # Found the fuzzer source (and not dependency of fuzzer).
 
-      is_git_file = bool(subprocess.check_output(['git', 'ls-files', source]))
+      git_dir = os.path.join(CHROMIUM_SRC_DIR, '.git')
+      is_git_file = bool(subprocess.check_output(
+          ['git', '--git-dir', git_dir, 'ls-files', source]))
       if not is_git_file:
         # File is not in working tree. Return owners for third_party.
         return GetOwnersIfThirdParty(source)
@@ -80,7 +82,8 @@
       # the original author has authored line 1 which is usually the
       # copyright line and does not change even with file rename / move.
       blame_output = subprocess.check_output(
-          ['git', 'blame', '--porcelain', '-L1,1', source])
+          ['git', '--git-dir', git_dir,
+           'blame', '--porcelain', '-L1,1', source])
       return GetAuthorFromGitBlame(blame_output)
 
   return None
@@ -155,8 +158,7 @@
     for source in output.splitlines():
       if source.startswith('//'):
         source = source[2:]
-      actual_source = os.path.join(CHROMIUM_SRC_DIR, source)
-      all_sources.append(actual_source)
+      all_sources.append(source)
 
   return all_sources
 
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index 145915a..ad63c2d 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -525,8 +525,6 @@
 crbug.com/591099 fast/css-intrinsic-dimensions/fixed-height-stf-img-inline-child-percent-height.html [ Failure ]
 crbug.com/591099 fast/css-intrinsic-dimensions/height-positioned.html [ Failure ]
 crbug.com/807708 fast/css-intrinsic-dimensions/width-avoid-floats.html [ Failure ]
-crbug.com/591099 fast/css/abs-pos-child-inside-rel-pos-inline-001.html [ Failure ]
-crbug.com/591099 fast/css/abs-pos-child-inside-rel-pos-inline-offset-001.html [ Failure ]
 crbug.com/591099 fast/css/absolute-inline-alignment-2.html [ Pass ]
 crbug.com/714962 fast/css/absolute-inline-alignment.html [ Failure ]
 crbug.com/591099 fast/css/case-transform.html [ Failure ]
@@ -544,9 +542,6 @@
 crbug.com/591099 fast/css3-text/css3-text-indent/text-indent-leading-out-of-flow.html [ Failure ]
 crbug.com/591099 fast/css3-text/css3-text-indent/text-indent-out-of-flow-each-line-hanging.html [ Failure ]
 crbug.com/591099 fast/css3-text/css3-text-justify/text-justify-distribute.html [ Failure ]
-crbug.com/591099 fast/doctypes/001.html [ Failure ]
-crbug.com/591099 fast/doctypes/003.html [ Failure ]
-crbug.com/591099 fast/doctypes/004.html [ Failure ]
 crbug.com/591099 fast/dom/HTMLAreaElement/area-download.html [ Failure ]
 crbug.com/714962 fast/dom/Range/getBoundingClientRect-linebreak-character.html [ Failure ]
 crbug.com/591099 fast/dom/nodesFromRect/nodesFromRect-basic.html [ Failure ]
@@ -583,7 +578,6 @@
 crbug.com/591099 fast/lists/003-vertical.html [ Failure ]
 crbug.com/591099 fast/lists/004.html [ Failure ]
 crbug.com/591099 fast/lists/list-item-line-height.html [ Failure ]
-crbug.com/591099 fast/lists/marker-before-empty-inline.html [ Failure ]
 crbug.com/591099 fast/masking/clip-path-selection.html [ Failure ]
 crbug.com/860415 fast/multicol/out-of-flow/abspos-auto-position-on-line-rtl.html [ Failure ]
 crbug.com/591099 fast/overflow/overflow-update-transform.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 4dc48cf0..b7638e4 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1584,7 +1584,6 @@
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_rtl-flow-reverse.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_rtl-flow.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_rtl-order.html [ Skip ]
-crbug.com/857185 [ Mac ] virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_stf-table-caption.html [ Crash ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_stf-table-singleline-2.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_stf-table-singleline.html [ Failure ]
 crbug.com/336604 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_visibility-collapse-line-wrapping.html [ Failure ]
@@ -1733,6 +1732,12 @@
 
 crbug.com/841922 [ Linux Win Mac ] virtual/video-surface-layer/media/video-controls-focus-movement-on-hide.html [ Pass Failure ]
 
+
+crbug.com/862716 [ Mac ] css3/filters/effect-brightness-clamping-hw.html [ Failure Pass ]
+crbug.com/862729 [ Mac ] virtual/gpu/fast/canvas/canvas-blending-image-over-image.html [ Failure Pass ]
+crbug.com/862806 [ Mac ] css3/filters/effect-drop-shadow-hw.html [ Failure Pass ]
+crbug.com/862826 [ Mac Linux ] external/wpt/html/syntax/parsing/template/creating-an-element-for-the-token/template-owner-document.html [ Failure Pass ]
+
 # gpuBenchmarking.pinchBy is busted on desktops for touchscreen pinch
 crbug.com/787615 [ Win Linux Fuchsia ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchscreen-zoom-in-slow.html [ Failure Pass ]
 crbug.com/787615 [ Win Linux Fuchsia ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchscreen-zoom-out-slow.html [ Failure Pass ]
@@ -2270,6 +2275,12 @@
 crbug.com/595206 inspector-protocol/sessions/runtime-evaluate.js [ Skip ]
 crbug.com/595206 inspector-protocol/target/target-send-message.js [ Skip ]
 
+# after skia roll these should be removed
+crbug.com/863042 fast/gradients/crash-on-zero-radius.html [ Failure Pass ]
+crbug.com/863042 fast/gradients/generated-gradients.html [ Failure Pass ]
+crbug.com/863042 fast/gradients/simple-gradients.html [ Failure Pass ]
+crbug.com/863042 svg/W3C-SVG-1.1/pservers-grad-13-b.svg [ Failure Pass ]
+
 # Not implemented yet
 crbug.com/336604 external/wpt/css/css-flexbox/flexbox_visibility-collapse-line-wrapping.html [ Failure ]
 crbug.com/336604 external/wpt/css/css-flexbox/flexbox_visibility-collapse.html [ Failure ]
@@ -2625,9 +2636,7 @@
 crbug.com/849737 virtual/mojo-blob-urls/external/wpt/FileAPI/url/url-format.any.worker.html [ Pass Timeout ]
 
 # Websockets
-crbug.com/803558 external/wpt/websockets/opening-handshake/003-sets-origin.worker.html [ Timeout ]
 crbug.com/803358 virtual/off-main-thread-websocket/external/wpt/websockets/Create-Secure-extensions-empty.htm [ Timeout ]
-crbug.com/803558 virtual/off-main-thread-websocket/external/wpt/websockets/opening-handshake/003-sets-origin.worker.html [ Timeout ]
 # Cannot be rebaselined because the output contains a timestamp and a random number.
 crbug.com/803200 external/wpt/websockets/cookies/006.html?wss [ Failure ]
 crbug.com/803200 external/wpt/websockets/opening-handshake/005.html?wss [ Pass Failure ]
@@ -2654,6 +2663,9 @@
 crbug.com/849859 external/wpt/web-animations/timing-model/animations/pausing-an-animation.html [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 external/wpt/streams/piping/then-interception.dedicatedworker.html [ Timeout ]
+crbug.com/626703 [ Linux Mac10.10 Mac10.11 Mac10.12 Mac10.13 Win ] external/wpt/streams/piping/then-interception.serviceworker.https.html [ Timeout ]
+crbug.com/626703 [ Linux Mac10.10 Mac10.11 Mac10.12 Mac10.13 Win ] external/wpt/streams/piping/then-interception.sharedworker.html [ Timeout ]
 crbug.com/626703 [ Win7 ] external/wpt/resource-timing/resource_timing_buffer_full_eventually.html [ Timeout ]
 crbug.com/626703 external/wpt/svg/rendering/order/z-index.svg [ Failure ]
 crbug.com/626703 external/wpt/websockets/Create-on-worker-shutdown.any.html [ Timeout ]
@@ -3483,6 +3495,9 @@
 
 crbug.com/785940 external/wpt/web-animations/timing-model/timelines/document-timelines.html [ Failure Pass ]
 
+# Decoding test timeout on Win7. Marked flaky to get imported in case it's flaky timeout everywhere.
+crbug.com/862938 external/wpt/encoding/textdecoder-fatal-single-byte.any.worker.html [ Pass Timeout ]
+
 crbug.com/655458 external/wpt/workers/constructors/SharedWorker/undefined-arguments.html [ Failure ]
 crbug.com/655458 external/wpt/workers/interfaces/SharedWorkerGlobalScope/onconnect.html [ Failure ]
 crbug.com/655458 external/wpt/workers/constructors/SharedWorker/setting-port-members.html [ Failure ]
@@ -3982,6 +3997,9 @@
 crbug.com/757165 [ Win ] virtual/gpu/fast/canvas/canvas-strokeRect-alpha-shadow.html [ Skip ]
 crbug.com/757165 [ Win ] virtual/gpu/fast/canvas/image-object-in-canvas.html [ Skip ]
 
+crbug.com/862907 [ Mac ] virtual/gpu/fast/canvas/canvas-blending-gradient-over-pattern.html [ Pass Failure ]
+
+
 crbug.com/766129 svg/wicd/test-rightsizing-b.xhtml [ Failure Pass ]
 
 # Antialiasing error
diff --git a/third_party/WebKit/LayoutTests/accessibility/children-changed-in-canvas.html b/third_party/WebKit/LayoutTests/accessibility/children-changed-in-canvas.html
new file mode 100644
index 0000000..3848008b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/accessibility/children-changed-in-canvas.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+
+<canvas>
+  <ul id="container"><li>One</li><li>Two</li><li>Three</li></ul>
+</canvas>
+
+<script>
+test(function(t) {
+    var container = document.getElementById("container");
+    var axContainer = accessibilityController.accessibleElementById("container");
+    assert_equals(axContainer.childrenCount, 3, "Initial");
+
+    var newNode = document.createElement("li");
+    newNode.innerText = "Four";
+    container.appendChild(newNode);
+    assert_equals(axContainer.childrenCount, 4, "After appendChild");
+
+    container.removeChild(newNode);
+    assert_equals(axContainer.childrenCount, 3, "After removeChild");
+}, "Children count is correct inside a canvas");
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
index 929ec848..d0be2203 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -95499,6 +95499,18 @@
      {}
     ]
    ],
+   "svg/extensibility/foreignObject/foreign-object-margin-collapsing.html": [
+    [
+     "/svg/extensibility/foreignObject/foreign-object-margin-collapsing.html",
+     [
+      [
+       "/svg/extensibility/foreignObject/foreign-object-size-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "svg/extensibility/foreignObject/foreign-object-paints-before-rect.html": [
     [
      "/svg/extensibility/foreignObject/foreign-object-paints-before-rect.html",
@@ -103104,11 +103116,6 @@
      {}
     ]
    ],
-   "appmanifest/idlharness.window-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "async-local-storage/META.yml": [
     [
      {}
@@ -140689,6 +140696,16 @@
      {}
     ]
    ],
+   "encoding/iso-2022-jp-decoder.any-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "encoding/iso-2022-jp-decoder.any.worker-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "encoding/legacy-mb-japanese/euc-jp/eucjp-decoder.js": [
     [
      {}
@@ -154464,6 +154481,11 @@
      {}
     ]
    ],
+   "html/semantics/embedded-content/the-object-element/object-setcustomvalidity-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "html/semantics/embedded-content/the-object-element/test0.html": [
     [
      {}
@@ -154689,6 +154711,11 @@
      {}
     ]
    ],
+   "html/semantics/forms/the-fieldset-element/fieldset-setcustomvalidity-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "html/semantics/forms/the-form-element/.gitkeep": [
     [
      {}
@@ -154819,6 +154846,11 @@
      {}
     ]
    ],
+   "html/semantics/forms/the-output-element/output-setcustomvalidity-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "html/semantics/forms/the-progress-element/.gitkeep": [
     [
      {}
@@ -167714,6 +167746,16 @@
      {}
     ]
    ],
+   "streams/piping/then-interception-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "streams/piping/then-interception.js": [
+    [
+     {}
+    ]
+   ],
    "streams/piping/transform-streams.js": [
     [
      {}
@@ -201895,29 +201937,47 @@
      {}
     ]
    ],
-   "encoding/api-basics.html": [
+   "encoding/api-basics.any.js": [
     [
-     "/encoding/api-basics.html",
+     "/encoding/api-basics.any.html",
+     {}
+    ],
+    [
+     "/encoding/api-basics.any.worker.html",
      {}
     ]
    ],
-   "encoding/api-invalid-label.html": [
+   "encoding/api-invalid-label.any.js": [
     [
-     "/encoding/api-invalid-label.html",
+     "/encoding/api-invalid-label.any.html",
+     {
+      "timeout": "long"
+     }
+    ],
+    [
+     "/encoding/api-invalid-label.any.worker.html",
      {
       "timeout": "long"
      }
     ]
    ],
-   "encoding/api-replacement-encodings.html": [
+   "encoding/api-replacement-encodings.any.js": [
     [
-     "/encoding/api-replacement-encodings.html",
+     "/encoding/api-replacement-encodings.any.html",
+     {}
+    ],
+    [
+     "/encoding/api-replacement-encodings.any.worker.html",
      {}
     ]
    ],
-   "encoding/api-surrogates-utf8.html": [
+   "encoding/api-surrogates-utf8.any.js": [
     [
-     "/encoding/api-surrogates-utf8.html",
+     "/encoding/api-surrogates-utf8.any.html",
+     {}
+    ],
+    [
+     "/encoding/api-surrogates-utf8.any.worker.html",
      {}
     ]
    ],
@@ -201957,9 +202017,13 @@
      {}
     ]
    ],
-   "encoding/iso-2022-jp-decoder.html": [
+   "encoding/iso-2022-jp-decoder.any.js": [
     [
-     "/encoding/iso-2022-jp-decoder.html",
+     "/encoding/iso-2022-jp-decoder.any.html",
+     {}
+    ],
+    [
+     "/encoding/iso-2022-jp-decoder.any.worker.html",
      {}
     ]
    ],
@@ -209265,9 +209329,13 @@
      }
     ]
    ],
-   "encoding/replacement-encodings.html": [
+   "encoding/replacement-encodings.any.js": [
     [
-     "/encoding/replacement-encodings.html",
+     "/encoding/replacement-encodings.any.html",
+     {}
+    ],
+    [
+     "/encoding/replacement-encodings.any.worker.html",
      {}
     ]
    ],
@@ -209291,9 +209359,13 @@
      }
     ]
    ],
-   "encoding/textdecoder-byte-order-marks.html": [
+   "encoding/textdecoder-byte-order-marks.any.js": [
     [
-     "/encoding/textdecoder-byte-order-marks.html",
+     "/encoding/textdecoder-byte-order-marks.any.html",
+     {}
+    ],
+    [
+     "/encoding/textdecoder-byte-order-marks.any.worker.html",
      {}
     ]
    ],
@@ -209307,63 +209379,103 @@
      {}
     ]
    ],
-   "encoding/textdecoder-fatal-single-byte.html": [
+   "encoding/textdecoder-fatal-single-byte.any.js": [
     [
-     "/encoding/textdecoder-fatal-single-byte.html",
+     "/encoding/textdecoder-fatal-single-byte.any.html",
+     {}
+    ],
+    [
+     "/encoding/textdecoder-fatal-single-byte.any.worker.html",
      {}
     ]
    ],
-   "encoding/textdecoder-fatal-streaming.html": [
+   "encoding/textdecoder-fatal-streaming.any.js": [
     [
-     "/encoding/textdecoder-fatal-streaming.html",
+     "/encoding/textdecoder-fatal-streaming.any.html",
+     {}
+    ],
+    [
+     "/encoding/textdecoder-fatal-streaming.any.worker.html",
      {}
     ]
    ],
-   "encoding/textdecoder-fatal.html": [
+   "encoding/textdecoder-fatal.any.js": [
     [
-     "/encoding/textdecoder-fatal.html",
+     "/encoding/textdecoder-fatal.any.html",
+     {}
+    ],
+    [
+     "/encoding/textdecoder-fatal.any.worker.html",
      {}
     ]
    ],
-   "encoding/textdecoder-ignorebom.html": [
+   "encoding/textdecoder-ignorebom.any.js": [
     [
-     "/encoding/textdecoder-ignorebom.html",
+     "/encoding/textdecoder-ignorebom.any.html",
+     {}
+    ],
+    [
+     "/encoding/textdecoder-ignorebom.any.worker.html",
      {}
     ]
    ],
-   "encoding/textdecoder-labels.html": [
+   "encoding/textdecoder-labels.any.js": [
     [
-     "/encoding/textdecoder-labels.html",
+     "/encoding/textdecoder-labels.any.html",
+     {}
+    ],
+    [
+     "/encoding/textdecoder-labels.any.worker.html",
      {}
     ]
    ],
-   "encoding/textdecoder-streaming.html": [
+   "encoding/textdecoder-streaming.any.js": [
     [
-     "/encoding/textdecoder-streaming.html",
+     "/encoding/textdecoder-streaming.any.html",
+     {}
+    ],
+    [
+     "/encoding/textdecoder-streaming.any.worker.html",
      {}
     ]
    ],
-   "encoding/textdecoder-utf16-surrogates.html": [
+   "encoding/textdecoder-utf16-surrogates.any.js": [
     [
-     "/encoding/textdecoder-utf16-surrogates.html",
+     "/encoding/textdecoder-utf16-surrogates.any.html",
+     {}
+    ],
+    [
+     "/encoding/textdecoder-utf16-surrogates.any.worker.html",
      {}
     ]
    ],
-   "encoding/textencoder-constructor-non-utf.html": [
+   "encoding/textencoder-constructor-non-utf.any.js": [
     [
-     "/encoding/textencoder-constructor-non-utf.html",
+     "/encoding/textencoder-constructor-non-utf.any.html",
+     {}
+    ],
+    [
+     "/encoding/textencoder-constructor-non-utf.any.worker.html",
      {}
     ]
    ],
-   "encoding/textencoder-utf16-surrogates.html": [
+   "encoding/textencoder-utf16-surrogates.any.js": [
     [
-     "/encoding/textencoder-utf16-surrogates.html",
+     "/encoding/textencoder-utf16-surrogates.any.html",
+     {}
+    ],
+    [
+     "/encoding/textencoder-utf16-surrogates.any.worker.html",
      {}
     ]
    ],
-   "encoding/unsupported-encodings.html": [
+   "encoding/unsupported-encodings.any.js": [
     [
-     "/encoding/unsupported-encodings.html",
+     "/encoding/unsupported-encodings.any.html",
+     {}
+    ],
+    [
+     "/encoding/unsupported-encodings.any.worker.html",
      {}
     ]
    ],
@@ -219179,6 +219291,12 @@
      {}
     ]
    ],
+   "html/semantics/embedded-content/the-object-element/object-setcustomvalidity.html": [
+    [
+     "/html/semantics/embedded-content/the-object-element/object-setcustomvalidity.html",
+     {}
+    ]
+   ],
    "html/semantics/embedded-content/the-object-element/usemap-casing.html": [
     [
      "/html/semantics/embedded-content/the-object-element/usemap-casing.html",
@@ -220157,6 +220275,12 @@
      {}
     ]
    ],
+   "html/semantics/forms/the-output-element/output-setcustomvalidity.html": [
+    [
+     "/html/semantics/forms/the-output-element/output-setcustomvalidity.html",
+     {}
+    ]
+   ],
    "html/semantics/forms/the-output-element/output.html": [
     [
      "/html/semantics/forms/the-output-element/output.html",
@@ -220235,6 +220359,12 @@
      {}
     ]
    ],
+   "html/semantics/forms/the-select-element/select-setcustomvalidity.html": [
+    [
+     "/html/semantics/forms/the-select-element/select-setcustomvalidity.html",
+     {}
+    ]
+   ],
    "html/semantics/forms/the-select-element/select-validity.html": [
     [
      "/html/semantics/forms/the-select-element/select-validity.html",
@@ -220259,6 +220389,12 @@
      {}
     ]
    ],
+   "html/semantics/forms/the-textarea-element/textarea-setcustomvalidity.html": [
+    [
+     "/html/semantics/forms/the-textarea-element/textarea-setcustomvalidity.html",
+     {}
+    ]
+   ],
    "html/semantics/forms/the-textarea-element/textarea-type.html": [
     [
      "/html/semantics/forms/the-textarea-element/textarea-type.html",
@@ -247203,9 +247339,9 @@
      {}
     ]
    ],
-   "screen-orientation/interfaces.html": [
+   "screen-orientation/idlharness.window.js": [
     [
-     "/screen-orientation/interfaces.html",
+     "/screen-orientation/idlharness.window.html",
      {}
     ]
    ],
@@ -249937,6 +250073,30 @@
      {}
     ]
    ],
+   "streams/piping/then-interception.dedicatedworker.html": [
+    [
+     "/streams/piping/then-interception.dedicatedworker.html",
+     {}
+    ]
+   ],
+   "streams/piping/then-interception.html": [
+    [
+     "/streams/piping/then-interception.html",
+     {}
+    ]
+   ],
+   "streams/piping/then-interception.serviceworker.https.html": [
+    [
+     "/streams/piping/then-interception.serviceworker.https.html",
+     {}
+    ]
+   ],
+   "streams/piping/then-interception.sharedworker.html": [
+    [
+     "/streams/piping/then-interception.sharedworker.html",
+     {}
+    ]
+   ],
    "streams/piping/transform-streams.dedicatedworker.html": [
     [
      "/streams/piping/transform-streams.dedicatedworker.html",
@@ -274268,12 +274428,8 @@
    "aac79ed89a59f6a493a44e8572900abae41893e1",
    "support"
   ],
-  "appmanifest/idlharness.window-expected.txt": [
-   "66803b74f3ce564e9e6c66f4a6899348e424c7e9",
-   "support"
-  ],
   "appmanifest/idlharness.window.js": [
-   "4bc6cda0fb4b635886a289ecea963043fb59b177",
+   "6eb9bb3e49ba21dd5635631ad3a847ea85614697",
    "testharness"
   ],
   "async-local-storage/META.yml": [
@@ -336541,7 +336697,7 @@
    "support"
   ],
   "css/css-writing-modes/block-flow-direction-004.xht": [
-   "66b0ad0e881ee030d1ff2e4d023fe89570c227a5",
+   "f36725844f5497c5e72033d8ea307bc6b1d80e97",
    "reftest"
   ],
   "css/css-writing-modes/block-flow-direction-025-ref.xht": [
@@ -336557,91 +336713,91 @@
    "support"
   ],
   "css/css-writing-modes/block-flow-direction-htb-001.xht": [
-   "28c62daca6d3d58fdcc905b02db5c660751b8583",
+   "af01e9c8383adc0e16664d4f1b3a1260c3d7c89b",
    "reftest"
   ],
   "css/css-writing-modes/block-flow-direction-vlr-003.xht": [
-   "5dea9e46db6a1a7cfca1dbddaec5ea444e9a53a1",
+   "42642a5a4f79fa2644a8fbc8fabd6306908438e5",
    "reftest"
   ],
   "css/css-writing-modes/block-flow-direction-vlr-007.xht": [
-   "c001fb295db4af06e9ccc743fe8b4603d630eb61",
+   "8c86d2747a036dd2933edecb611b15c6092be6ec",
    "reftest"
   ],
   "css/css-writing-modes/block-flow-direction-vlr-008.xht": [
-   "0c9c705742c39cda3f571607d82f1244569cc214",
+   "7f97622d7bba144c580fee00a64baec2e5f5b457",
    "reftest"
   ],
   "css/css-writing-modes/block-flow-direction-vlr-010.xht": [
-   "2eea469e73b2b1d5149d37bce03e33518b4f266f",
+   "5808322647edd5737f730489770f864e38f75355",
    "reftest"
   ],
   "css/css-writing-modes/block-flow-direction-vlr-014.xht": [
-   "8e24fef507df335aaa413d288860a1c3de7cf689",
+   "3938c611d2fdf2724cfcdb8970e724e8eb79a439",
    "reftest"
   ],
   "css/css-writing-modes/block-flow-direction-vlr-015.xht": [
-   "13670aac581dfaecf838fd221da472e4fa53a487",
+   "08d7013acc55c7d462b4a666f73fcf79c9f9f542",
    "reftest"
   ],
   "css/css-writing-modes/block-flow-direction-vlr-016.xht": [
-   "752650cb1a15642c4365ab946a6a52610fe937df",
+   "20d40e65661774ac1f140a7433c870634767831e",
    "reftest"
   ],
   "css/css-writing-modes/block-flow-direction-vlr-020.xht": [
-   "c03d56b8df971d271427c01d4b5a41e29fd3d756",
+   "1178fc793fad4ad619234a8854f84f3e3094f2e6",
    "reftest"
   ],
   "css/css-writing-modes/block-flow-direction-vlr-022.xht": [
-   "aa6ab50f0ce6a327fd2ef9adc625f38bfa0b7f6d",
+   "e5852a9bc7f87031f4dae8c9ff181108f1c9abcb",
    "reftest"
   ],
   "css/css-writing-modes/block-flow-direction-vlr-023.xht": [
-   "829dea4e46f9782bf49d95ada4f0955584214642",
+   "58f82986e40821439cde1461346c423b42e2429e",
    "reftest"
   ],
   "css/css-writing-modes/block-flow-direction-vrl-002.xht": [
-   "55a206442c2df0fb43e2349d4ad6b4eca138555e",
+   "c857f8eb2f05605adfd26723d9fb4fc2185edc67",
    "reftest"
   ],
   "css/css-writing-modes/block-flow-direction-vrl-005.xht": [
-   "3fb7ef304bf35ad6afa1b9247dd0379bcfa949ca",
+   "5eebd5ea61ea5c49d510dcd82a1793a75163f26f",
    "reftest"
   ],
   "css/css-writing-modes/block-flow-direction-vrl-006.xht": [
-   "f9973a916464bb0100844cd656a027418b610040",
+   "20918e127f293b8d939e0735ec3f177a8a9a649a",
    "reftest"
   ],
   "css/css-writing-modes/block-flow-direction-vrl-009.xht": [
-   "6ec62f4e3123f4c5df36b58bd4cc264399a9d6db",
+   "2011eb597c17e47e2fce60b5aac17bfa5066b357",
    "reftest"
   ],
   "css/css-writing-modes/block-flow-direction-vrl-011.xht": [
-   "d210a659115b952357667ff1a8c5f36588b49b94",
+   "7a2218ec10f4be425a6c1a479c5d84c652cf7ca4",
    "reftest"
   ],
   "css/css-writing-modes/block-flow-direction-vrl-012.xht": [
-   "6f0e1dc09645cfcb93d1db7e9c39baaf1ebb2fda",
+   "f01cd29abb907368ce09b183b2caee4db7b2f5ab",
    "reftest"
   ],
   "css/css-writing-modes/block-flow-direction-vrl-013.xht": [
-   "11d6a8d9b56f9867efff2d97393fa573390aeea6",
+   "91e918041078784abf6c87e6ed7f33a2bf73777f",
    "reftest"
   ],
   "css/css-writing-modes/block-flow-direction-vrl-019.xht": [
-   "ca941f4f212574bca79b2ecbbf845a9e1a1300e5",
+   "eff1bc87d4f00ed6342ba32ffb935c176ee4df15",
    "reftest"
   ],
   "css/css-writing-modes/block-flow-direction-vrl-021.xht": [
-   "8bb72a04021c167d87e5410f325be70a3bc7600b",
+   "19f6c84ca649aec9c11c4a86350ec8d24a7e3110",
    "reftest"
   ],
   "css/css-writing-modes/block-flow-direction-vrl-024.xht": [
-   "70e732a6c3ed7355f1e569bb5d26ad3aca6a3795",
+   "6a1d8c1dea0a560392db12f63d082e2fc548fe1a",
    "reftest"
   ],
   "css/css-writing-modes/block-flow-direction-vrl-025.xht": [
-   "cfd1af31de29fd70657c90414b74a9873e1b3752",
+   "9525ba870d3ecc44713753319608525ae9ed4f60",
    "reftest"
   ],
   "css/css-writing-modes/block-flow-direction-vrl-026-ref.xht": [
@@ -337013,11 +337169,11 @@
    "reftest"
   ],
   "css/css-writing-modes/different-block-flow-dir-001.xht": [
-   "82d0132930dc4dc701acf668270fe4f709bc3f36",
+   "2465b680cd72989ba06bfef872e149f9c00c7ef5",
    "reftest"
   ],
   "css/css-writing-modes/different-block-flow-dir-002.xht": [
-   "f37b7b088091f4e8176497064738272dc4dc0b22",
+   "b004bfe8dac431f5881923f61c06b11c5872d009",
    "reftest"
   ],
   "css/css-writing-modes/direction-vlr-003-ref.xht": [
@@ -337049,11 +337205,11 @@
    "reftest"
   ],
   "css/css-writing-modes/first-page-vlr-003.xht": [
-   "7456c20a91dfd80a5901eeff41e260c6dac4942b",
+   "a95c7f84d0a90d91420564fc4f26b67e6bf39939",
    "manual"
   ],
   "css/css-writing-modes/first-page-vrl-002.xht": [
-   "d649d5ff1f8a0703742f03da59884842ce27e1a1",
+   "53b0ca9d958d836e36a02fee82202c4449ea5278",
    "manual"
   ],
   "css/css-writing-modes/flexbox_align-items-stretch-writing-modes-ref.html": [
@@ -337061,7 +337217,7 @@
    "support"
   ],
   "css/css-writing-modes/flexbox_align-items-stretch-writing-modes.html": [
-   "21607233c9a23a074991d16d6ed9c9aca0f9ae03",
+   "ab67b2f3d7c04d9b5895690e58d87b7876a67337",
    "reftest"
   ],
   "css/css-writing-modes/float-clear-vlr-003.xht": [
@@ -337317,19 +337473,19 @@
    "reftest"
   ],
   "css/css-writing-modes/form-controls-vlr-004.xht": [
-   "6914d51d54ecb957151ec4b28c78e36aafa39d91",
+   "74a61f01611e8ee94a7876f0fc25f23072f7a4d7",
    "visual"
   ],
   "css/css-writing-modes/form-controls-vlr-005.xht": [
-   "e60cc92bf66c08e736e9de42789656bce2f051fc",
+   "b0e1c215ef2109b6c368c797230c598fb0f3b1c5",
    "visual"
   ],
   "css/css-writing-modes/form-controls-vrl-004.xht": [
-   "07ce37a0f414c992b2fce54e4a99083b60211eae",
+   "fe1bc2ba6661cfd81522daa662fb7afba72a52bf",
    "visual"
   ],
   "css/css-writing-modes/form-controls-vrl-005.xht": [
-   "66d70d81b3989e4c09e810fb60b338683a84eeca",
+   "d832533f2ebb2920825042369c41d69b80a90200",
    "visual"
   ],
   "css/css-writing-modes/height-width-inline-non-replaced-vlr-003.xht": [
@@ -337425,7 +337581,7 @@
    "reftest"
   ],
   "css/css-writing-modes/inline-replaced-vlr-003.xht": [
-   "9b9c4467b7f28b260b17ac4369a77a3f3a3e817d",
+   "f72cb8a3248bf77609a22ee3a34391523de4fd83",
    "reftest"
   ],
   "css/css-writing-modes/inline-replaced-vlr-005.xht": [
@@ -337437,7 +337593,7 @@
    "support"
   ],
   "css/css-writing-modes/inline-replaced-vrl-002.xht": [
-   "f44978eebcabf37ed58cd2348822f3d1f2e94eed",
+   "31b7b141bc3aec07518c8137e45cc5b26ff6be53",
    "reftest"
   ],
   "css/css-writing-modes/inline-replaced-vrl-004-ref.xht": [
@@ -337473,71 +337629,71 @@
    "reftest"
   ],
   "css/css-writing-modes/line-box-direction-htb-001.xht": [
-   "a290e316833ade62bf428b46a2898a84affc7272",
+   "453f463c4a6d86a8e805cc8e86dc8525bf94dab8",
    "reftest"
   ],
   "css/css-writing-modes/line-box-direction-vlr-003.xht": [
-   "752e434c451fc3b0bb9986e746d64d628fa42c28",
+   "fce65a4408f730996e2fc0123542d1f964e474a8",
    "reftest"
   ],
   "css/css-writing-modes/line-box-direction-vlr-007.xht": [
-   "e5e880f141c5969bace944e1faa3a5d08d502f48",
+   "f50d16f39494e45d5e19f8519914a2b14c78b627",
    "reftest"
   ],
   "css/css-writing-modes/line-box-direction-vlr-008.xht": [
-   "6973ed1a53be85662ee35373c6c804a4cd4a6c5b",
+   "f5727ca40ae082d57cb9efbd1c654d06818d2748",
    "reftest"
   ],
   "css/css-writing-modes/line-box-direction-vlr-010.xht": [
-   "ba4512801fa678640e87d8056bfb32b24fc85ad1",
+   "2eb7988ae985d3af8fca7737a4fabc34da374fc5",
    "reftest"
   ],
   "css/css-writing-modes/line-box-direction-vlr-013.xht": [
-   "5e524c292d28a1bf91ccb55773d86bb27d64c569",
+   "2c151c06a84c6c2ff13da6e5d1afe771812c9610",
    "reftest"
   ],
   "css/css-writing-modes/line-box-direction-vlr-014.xht": [
-   "770e05aec411188ef3d4b219972f749c36fe61bb",
+   "53844bbf614e17a93f91a34fb26fa18ee317f3d1",
    "reftest"
   ],
   "css/css-writing-modes/line-box-direction-vlr-018.xht": [
-   "7f208ddb5aaaa2fefabaa2cb4fd135457b21db63",
+   "b830252470915b490a685838e2ac1cfe812f3248",
    "reftest"
   ],
   "css/css-writing-modes/line-box-direction-vlr-020.xht": [
-   "945936bfdff6e2875b55f01dd5ceb486e69e0b5f",
+   "00259ba5c73b3ae61536ecf2fd3c4c7e3f5255dd",
    "reftest"
   ],
   "css/css-writing-modes/line-box-direction-vrl-002.xht": [
-   "b2ebf107af357829a42aa642a82455e2c6036b66",
+   "1358b346b6c09e4603723b9fe839cd2f4d561130",
    "reftest"
   ],
   "css/css-writing-modes/line-box-direction-vrl-005.xht": [
-   "2ea9dba0b281414ead01c5acfb9d6fd077f7070c",
+   "2511bc1dd70fb0c37a30bcbb9b63fe7a1a46c374",
    "reftest"
   ],
   "css/css-writing-modes/line-box-direction-vrl-006.xht": [
-   "5c5511f825591ae3be851db77bb67421240d18f0",
+   "02df1e861cf1207f870940122391cad086804215",
    "reftest"
   ],
   "css/css-writing-modes/line-box-direction-vrl-009.xht": [
-   "f0965007e97854378823213907ca4376c88b8cee",
+   "bafc126591617e5569b844013b928911d42e9f84",
    "reftest"
   ],
   "css/css-writing-modes/line-box-direction-vrl-011.xht": [
-   "f20641a146a85a1643d747841c9c84695213b40b",
+   "68959ef10aba7b87a2a455bbca3d8c7c2232ae48",
    "reftest"
   ],
   "css/css-writing-modes/line-box-direction-vrl-012.xht": [
-   "92eaddce8d6556cd1d4766fed5f7d3f3e134e848",
+   "3c265d1f51b76ff5693fc489307fa7771f3fcc5a",
    "reftest"
   ],
   "css/css-writing-modes/line-box-direction-vrl-017.xht": [
-   "1f75a216320a8a09ac4f7ebe5725f71d2ce84735",
+   "a80fbbbf0df8db4d5e1a280fcb849bb54b94e0c2",
    "reftest"
   ],
   "css/css-writing-modes/line-box-direction-vrl-019.xht": [
-   "4836379e962c1639e7daebfa3097dfa9d4a6c0aa",
+   "41f7a933fd56af25f1d5792ebd226ddea004b68e",
    "reftest"
   ],
   "css/css-writing-modes/line-box-height-vlr-003-ref.xht": [
@@ -337981,11 +338137,11 @@
    "reftest"
   ],
   "css/css-writing-modes/page-flow-direction-002.xht": [
-   "0c7a122aba02a19d18678d898cbf542308926899",
+   "fc754c098e80c833dcc65bd487c86852660632a5",
    "manual"
   ],
   "css/css-writing-modes/page-flow-direction-003.xht": [
-   "6dfa1c5e24ea58513813792cfa7c7091a28c3a23",
+   "2b7da0ba95a5bf1ecc55ccb1bcb58deb719f3a5e",
    "manual"
   ],
   "css/css-writing-modes/parsing/direction-invalid.html": [
@@ -338637,23 +338793,23 @@
    "support"
   ],
   "css/css-writing-modes/replaced-content-image-002.xht": [
-   "e3e5d876a430b49d3ddbfe44c057c880840fce1c",
+   "545b4a4a6ad2c9e0232cc1e8d754b12fa0ccd510",
    "visual"
   ],
   "css/css-writing-modes/replaced-content-image-003.xht": [
-   "722a6ee09ef7417bee82100c39c674fda50a9bf2",
+   "ab5034f039a5c28757579dd9f42ab687aaf97578",
    "visual"
   ],
   "css/css-writing-modes/row-progression-vlr-003.xht": [
-   "de0c9334397de5b2798a90a478821eb9adbad491",
+   "11905b092d1fa51d14a0c8838f1f51dde1a6cbe6",
    "reftest"
   ],
   "css/css-writing-modes/row-progression-vlr-005.xht": [
-   "56f0b8948c01323a65f0c023984597fceab5fecf",
+   "d326feb8a33c287f288c6e6cc47953dc43390069",
    "reftest"
   ],
   "css/css-writing-modes/row-progression-vlr-007.xht": [
-   "a035d4d9748c8050897258d617a1e829675a31e4",
+   "cf4607991e228d0ca0877cc272408d21a8fc17b4",
    "reftest"
   ],
   "css/css-writing-modes/row-progression-vlr-009.xht": [
@@ -338661,19 +338817,19 @@
    "reftest"
   ],
   "css/css-writing-modes/row-progression-vrl-002.xht": [
-   "4b11e6f2d3199d4f4239b6237d34ac7406664087",
+   "8cfac808190e35b6b5f2c5016a71da8713946eaa",
    "reftest"
   ],
   "css/css-writing-modes/row-progression-vrl-004.xht": [
-   "240faf15565dc5c03178996b5c2a55198a5ec4a6",
+   "8bd65f967ed35065e8972bf6c79e6d7319923e3e",
    "reftest"
   ],
   "css/css-writing-modes/row-progression-vrl-006.xht": [
-   "d8f9e2fee9f0ec8e43eb532b77752f9dd54be70f",
+   "e56aa0af6bdb2646dea0eb572ac99d984965efdb",
    "reftest"
   ],
   "css/css-writing-modes/row-progression-vrl-008.xht": [
-   "252c877b6b62e93b69b97a9dcc99498c5f56db65",
+   "d17f3101adf8dd24a79649ee9325f929fc8f135e",
    "reftest"
   ],
   "css/css-writing-modes/scrollbar-vertical-rl.html": [
@@ -340993,7 +341149,7 @@
    "support"
   ],
   "css/css-writing-modes/writing-mode-vertical-rl-003.htm": [
-   "3735deb43fa19541fd22e4080e6b85eef8b8abb3",
+   "ef816cc85f7fc02801caeb47f43e6b5937f9539c",
    "reftest"
   ],
   "css/cssom-view/CaretPosition-001.html": [
@@ -350960,20 +351116,20 @@
    "29ee125119887c3be725caaafb58fdadc674a53a",
    "support"
   ],
-  "encoding/api-basics.html": [
-   "f941c016bd9f6117af2e28652c770613c475b064",
+  "encoding/api-basics.any.js": [
+   "1d6388311365567f7cfef142517c1d6d6dab8a69",
    "testharness"
   ],
-  "encoding/api-invalid-label.html": [
-   "38912a0e00f769ff9c116a5871b3691d059a4ef9",
+  "encoding/api-invalid-label.any.js": [
+   "292df0f5ce44492e166f71a8b1b3b9312cf508fd",
    "testharness"
   ],
-  "encoding/api-replacement-encodings.html": [
-   "ea956ff139f386abf52226d981dbb5ec0e3f2a38",
+  "encoding/api-replacement-encodings.any.js": [
+   "81fd6d2552cf0be770143cf322a581aabe762c7e",
    "testharness"
   ],
-  "encoding/api-surrogates-utf8.html": [
-   "e44be4c30e9c65a4b51972efab2e161f166d58a5",
+  "encoding/api-surrogates-utf8.any.js": [
+   "3714e4020601bc5f50de7ddd7d0dfb6fd2471a28",
    "testharness"
   ],
   "encoding/big5-encoder.html": [
@@ -351028,10 +351184,18 @@
    "013a9bc497cb31ba25af2a28e391ebde3cf56d97",
    "support"
   ],
-  "encoding/iso-2022-jp-decoder.html": [
-   "c189c2f99ee066e9419fdebef5d620edf97cd785",
+  "encoding/iso-2022-jp-decoder.any-expected.txt": [
+   "013a9bc497cb31ba25af2a28e391ebde3cf56d97",
+   "support"
+  ],
+  "encoding/iso-2022-jp-decoder.any.js": [
+   "65fcb01cb4ade9d7ba4745ab59933d3a14c675ed",
    "testharness"
   ],
+  "encoding/iso-2022-jp-decoder.any.worker-expected.txt": [
+   "013a9bc497cb31ba25af2a28e391ebde3cf56d97",
+   "support"
+  ],
   "encoding/iso-2022-jp-encoder.html": [
    "771631eca687f2d4abbf7cb9337af4ecded432e4",
    "testharness"
@@ -352184,8 +352348,8 @@
    "22f0299c5a8741c6585c3f56b471d6970d0bb499",
    "support"
   ],
-  "encoding/replacement-encodings.html": [
-   "10ebae214ee7307c8087206a318ce8b5765ed8e9",
+  "encoding/replacement-encodings.any.js": [
+   "06219fcf2f4098266bef3c5730058644b137a942",
    "testharness"
   ],
   "encoding/resources/decode-common.js": [
@@ -352256,52 +352420,52 @@
    "60eb39cc7d5115ee50611e81bbd332228ef4e03b",
    "testharness"
   ],
-  "encoding/textdecoder-byte-order-marks.html": [
-   "d53e5217cd1cfe73c01b1136449a6dd2a0ef0c21",
+  "encoding/textdecoder-byte-order-marks.any.js": [
+   "317b4196f7c52a15d00d565470667b9a6b789e5e",
    "testharness"
   ],
   "encoding/textdecoder-copy.any.js": [
    "50a59f2691a7f483b262239935d9dbcc6b918d9d",
    "testharness"
   ],
-  "encoding/textdecoder-fatal-single-byte.html": [
-   "e34be18ce290ac5dbf8eaf27adba0d1bec001b1e",
+  "encoding/textdecoder-fatal-single-byte.any.js": [
+   "30228b150f17c781d2eaf58e428e9b470bc286e8",
    "testharness"
   ],
-  "encoding/textdecoder-fatal-streaming.html": [
-   "17dc6a268ec850dcb6556e0cda75a29ce610ec4a",
+  "encoding/textdecoder-fatal-streaming.any.js": [
+   "7c278fd666b97dc21fae8d76b164c24f1031b098",
    "testharness"
   ],
-  "encoding/textdecoder-fatal.html": [
-   "c9305f447d904cbc1931666ec419f995346afee2",
+  "encoding/textdecoder-fatal.any.js": [
+   "92c9d56e23b58a4a5c1a4b72e039befd1cb3414f",
    "testharness"
   ],
-  "encoding/textdecoder-ignorebom.html": [
-   "6ed76e3d1b164c16aa2a1162c39250195af42c92",
+  "encoding/textdecoder-ignorebom.any.js": [
+   "8d38a52fa000d54d948b4a1edb657ee58848bf5b",
    "testharness"
   ],
-  "encoding/textdecoder-labels.html": [
-   "e1eda76bf8bed9a0e8778fad772fa0504089c919",
+  "encoding/textdecoder-labels.any.js": [
+   "e141d33d966a3573fd6f90df30bb3922c6979129",
    "testharness"
   ],
-  "encoding/textdecoder-streaming.html": [
-   "b20e902062c9e6612920e176e2856a7081eb72ef",
+  "encoding/textdecoder-streaming.any.js": [
+   "e33fdc5ad4a34bb93ae447e5b52377b58fc3c937",
    "testharness"
   ],
-  "encoding/textdecoder-utf16-surrogates.html": [
-   "b38d339610e7bc19d000d545243508a6eb01725d",
+  "encoding/textdecoder-utf16-surrogates.any.js": [
+   "6f29d469e96f67ebf4f56427e45aed187d2c7669",
    "testharness"
   ],
-  "encoding/textencoder-constructor-non-utf.html": [
-   "9b727c86e718400dcc4bec2a4b4a974cce81a66b",
+  "encoding/textencoder-constructor-non-utf.any.js": [
+   "5a01c63d25c2d3aacd9c5afa54f4a6b27ad7403e",
    "testharness"
   ],
-  "encoding/textencoder-utf16-surrogates.html": [
-   "2a65ef4f2ef610cffcb121998b7397568c197afb",
+  "encoding/textencoder-utf16-surrogates.any.js": [
+   "e286db5cac8fe7dd9da7fe1ef1a761e3195d3c7e",
    "testharness"
   ],
-  "encoding/unsupported-encodings.html": [
-   "7fecb06dda9672e97759aaa8bc18e636b6b1480a",
+  "encoding/unsupported-encodings.any.js": [
+   "31de34ff3955a9cf96310ccb51cfa1f376546831",
    "testharness"
   ],
   "encoding/utf-32.html": [
@@ -370304,6 +370468,14 @@
    "a5bb885111ac7ea02241957ee7233491c2277516",
    "testharness"
   ],
+  "html/semantics/embedded-content/the-object-element/object-setcustomvalidity-expected.txt": [
+   "aac3ac9039300c55f9e40ead529b9daa0baa2f90",
+   "support"
+  ],
+  "html/semantics/embedded-content/the-object-element/object-setcustomvalidity.html": [
+   "66b9c49899cf1bbc8f5061f5f515ed5ba46d5655",
+   "testharness"
+  ],
   "html/semantics/embedded-content/the-object-element/test0.html": [
    "04319dea2f1e0b00e8db1703f2072ec22f1a82ad",
    "support"
@@ -370777,7 +370949,7 @@
    "testharness"
   ],
   "html/semantics/forms/the-button-element/button-setcustomvalidity.html": [
-   "1db71a5bee8a77768dc54cbd1dc3ef000c2eaa6b",
+   "219360aaa6a24afe3632e3db54608fe14626c78d",
    "testharness"
   ],
   "html/semantics/forms/the-button-element/button-type.html": [
@@ -370832,8 +371004,12 @@
    "9fcfee0f0149cb35b4ea59a858639bb966be51d5",
    "testharness"
   ],
+  "html/semantics/forms/the-fieldset-element/fieldset-setcustomvalidity-expected.txt": [
+   "2cfebd1e92b6d2a384a38c296b0fb6c9ed7f8f6a",
+   "support"
+  ],
   "html/semantics/forms/the-fieldset-element/fieldset-setcustomvalidity.html": [
-   "4954cc5b7e1c170a6ac3c815c8c1566be9da25d4",
+   "c4b8cc27c30bb1400d16b765097e7c9fac50d7db",
    "testharness"
   ],
   "html/semantics/forms/the-fieldset-element/fieldset-validationmessage.html": [
@@ -371037,7 +371213,7 @@
    "testharness"
   ],
   "html/semantics/forms/the-input-element/input-setcustomvalidity.html": [
-   "8397448c6a8fc9371303266671c0a1d17d488d5c",
+   "48cac09f2febd3c0101eb0003bb56a403bbeac71",
    "testharness"
   ],
   "html/semantics/forms/the-input-element/input-stepdown.html": [
@@ -371300,6 +371476,14 @@
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
+  "html/semantics/forms/the-output-element/output-setcustomvalidity-expected.txt": [
+   "c076054ab20670a2849a0b7d201e76b6c0b01db6",
+   "support"
+  ],
+  "html/semantics/forms/the-output-element/output-setcustomvalidity.html": [
+   "2c8bb59995da6ec060ebfe0adece54da652c0246",
+   "testharness"
+  ],
   "html/semantics/forms/the-output-element/output.html": [
    "10685b8d6e5e3c7d17f4f8b702bcd9672c5c02a7",
    "testharness"
@@ -371360,6 +371544,10 @@
    "81805a8f0b1f0c6dbf056d370b96472309ffe36d",
    "testharness"
   ],
+  "html/semantics/forms/the-select-element/select-setcustomvalidity.html": [
+   "ea33791943736b4439a03eba1025765ac1279ace",
+   "testharness"
+  ],
   "html/semantics/forms/the-select-element/select-validity.html": [
    "f1cf30c31b0bfeacbe5ef4cfe863a32ff198ad14",
    "testharness"
@@ -371396,6 +371584,10 @@
    "7b513a17599ea93eb430a81bbff8d5aa94d07c3c",
    "manual"
   ],
+  "html/semantics/forms/the-textarea-element/textarea-setcustomvalidity.html": [
+   "5f5932aeba8a0a7da66ee006a6e604780210d57b",
+   "testharness"
+  ],
   "html/semantics/forms/the-textarea-element/textarea-type.html": [
    "81a270bc3c9304f8b2e7dd526519f4eab7d94f45",
    "testharness"
@@ -376861,7 +377053,7 @@
    "support"
   ],
   "interfaces/appmanifest.idl": [
-   "e42ed8ea5d51f072985ecfc177deb9753abe167e",
+   "c02f559945c71a19257be24b7aa260ee235da2c2",
    "support"
   ],
   "interfaces/audio-output.idl": [
@@ -377141,7 +377333,7 @@
    "support"
   ],
   "interfaces/screen-orientation.idl": [
-   "80c719557dd4495a15c11585dbeaa570afafe144",
+   "c3d267a479600e83e4782e4a80126e3c4467920f",
    "support"
   ],
   "interfaces/scroll-animations.idl": [
@@ -397456,8 +397648,8 @@
    "970c0e5b33815109f17231ffeaf4cea22cf9096c",
    "support"
   ],
-  "screen-orientation/interfaces.html": [
-   "d54475008731fafd00c3cae73f11eac94dba0883",
+  "screen-orientation/idlharness.window.js": [
+   "aa0cc22de907288f4b8a175fb9e8963f4892179f",
    "testharness"
   ],
   "screen-orientation/lock-bad-argument.html": [
@@ -402080,6 +402272,30 @@
    "8ecb019e754fd4239cb35c27787897efc2dacccb",
    "testharness"
   ],
+  "streams/piping/then-interception-expected.txt": [
+   "d746cd0efa1a9d74202ad76af42b6a8ba447c345",
+   "support"
+  ],
+  "streams/piping/then-interception.dedicatedworker.html": [
+   "e24c52c003d867037b0a0fd021a02f6abac10e57",
+   "testharness"
+  ],
+  "streams/piping/then-interception.html": [
+   "a4955e1a66e8ac39cebec8183e6a1295a7af4c78",
+   "testharness"
+  ],
+  "streams/piping/then-interception.js": [
+   "536f96e405ee9c36bc9f5bf75053a6136affc1f5",
+   "support"
+  ],
+  "streams/piping/then-interception.serviceworker.https.html": [
+   "e7a05ba2bccd31c1ff284a81c08f229d34af40bb",
+   "testharness"
+  ],
+  "streams/piping/then-interception.sharedworker.html": [
+   "b6b6fdd9ddd4ae5f61fa26f6facd82ab1227f165",
+   "testharness"
+  ],
   "streams/piping/transform-streams.dedicatedworker.html": [
    "bd73374617b11acfcaecbf478ad050ab8621754a",
    "testharness"
@@ -403432,6 +403648,10 @@
    "a5fbcba1ea5ba32d55210b0a87b6ecdeafbae5fe",
    "testharness"
   ],
+  "svg/extensibility/foreignObject/foreign-object-margin-collapsing.html": [
+   "d84bd1ca6b8e62557191b5fbf365b03969adc3bd",
+   "reftest"
+  ],
   "svg/extensibility/foreignObject/foreign-object-paints-before-rect-ref.html": [
    "18e188a6279e64cbabdd4bb638b06d4a5b22fca8",
    "support"
@@ -409837,7 +410057,7 @@
    "support"
   ],
   "webvr/OWNERS": [
-   "32a501c9277b2b748a57afa66a65f3613aa5f56f",
+   "aac4c3d6122dccab717c254f795989fb82c978de",
    "support"
   ],
   "webvr/idlharness-expected.txt": [
@@ -412757,7 +412977,7 @@
    "support"
   ],
   "webxr/OWNERS": [
-   "2489a3403480e9521eb130f91a8178aa7dfd35e9",
+   "7b93efb43b3ff46cab0cb4b7eb88b4b021003218",
    "support"
   ],
   "webxr/interfaces.https-expected.txt": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/appmanifest/idlharness.window.js b/third_party/WebKit/LayoutTests/external/wpt/appmanifest/idlharness.window.js
index 2b633bf..a877c76 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/appmanifest/idlharness.window.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/appmanifest/idlharness.window.js
@@ -5,18 +5,14 @@
 
 'use strict';
 
-promise_test(async () => {
-  const srcs = ['appmanifest', 'dom', 'html'];
-  const [idl, dom, html] = await Promise.all(
-    srcs.map(i => fetch(`/interfaces/${i}.idl`).then(r => r.text())));
-
-  const idl_array = new IdlArray();
-  idl_array.add_idls(idl);
-  idl_array.add_dependency_idls(html);
-  idl_array.add_dependency_idls(dom);
-  idl_array.add_objects({
-    Window: ['window'],
-    BeforeInstallPromptEvent: ['new BeforeInstallPromptEvent("type")'],
-  });
-  idl_array.test();
-}, 'appmanifest interfaces');
+idl_test(
+  ['appmanifest'],
+  ['html', 'dom'],
+  idl_array => {
+    idl_array.add_objects({
+      Window: ['window'],
+      BeforeInstallPromptEvent: ['new BeforeInstallPromptEvent("type")'],
+    });
+  },
+  'appmanifest interfaces'
+);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/compat/webkit-appearance.tentative.html b/third_party/WebKit/LayoutTests/external/wpt/compat/webkit-appearance.tentative.html
deleted file mode 100644
index 8c0273dc..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/compat/webkit-appearance.tentative.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!DOCTYPE html>
-<title>-webkit-appearance support</title>
-<!-- There is no spec for -webkit-appearance. It is supported in Opera, Safari,
-     Chrome, and Edge. Firefox has expressed intent to support it. -->
-<link rel="help" href="https://github.com/whatwg/compat/issues/6">
-<meta name="assert" content="This test checks for support of the -webkit-appearance CSS attribute." />
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-
-<div id="tester"></div>
-
-<script>
-const WEBKIT_APPEARANCE_VALUES = [
-  'none',
-  'checkbox',
-  'radio',
-  'push-button',
-  'square-button',
-  'button',
-  'button-bevel',
-  'inner-spin-button',
-  'listbox',
-  'listitem',
-  'media-enter-fullscreen-button',
-  'media-exit-fullscreen-button',
-  'media-mute-button',
-  'media-play-button',
-  'media-overlay-play-button',
-  'media-toggle-closed-captions-button',
-  'media-slider',
-  'media-sliderthumb',
-  'media-volume-slider-container',
-  'media-volume-slider',
-  'media-volume-sliderthumb',
-  'media-controls-background',
-  'media-controls-fullscreen-background',
-  'media-current-time-display',
-  'media-time-remaining-display',
-  'menulist',
-  'menulist-button',
-  'menulist-text',
-  'menulist-textfield',
-  'meter',
-  'progress-bar',
-  'progress-bar-value',
-  'slider-horizontal',
-  'slider-vertical',
-  'sliderthumb-horizontal',
-  'sliderthumb-vertical',
-  'caret',
-  'searchfield',
-  'searchfield-cancel-button',
-  'textfield',
-  'textarea',
-];
-
-for (const appearance_value of WEBKIT_APPEARANCE_VALUES) {
-  test(() => {
-    const div = document.getElementById('tester');
-    div.style = `-webkit-appearance: ${appearance_value}`;
-    assert_equals(getComputedStyle(div).webkitAppearance, appearance_value);
-  });
-}
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-004.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-004.xht
index bc53bc6..5670da7 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-004.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-004.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: 'writing-mode' - initial value is 'horizontal-tb'</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-htb-001.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-htb-001.xht
index f594210..f6186b2 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-htb-001.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-htb-001.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: horizontal-tb - block flow direction of block-level boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-003.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-003.xht
index 23ccb69..fabe8f9 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-003.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-003.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: vertical-lr - block flow direction of block-level boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-007.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-007.xht
index c30d1ce..5853d828 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-007.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-007.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: 'float: right' and 'vertical-lr' - block flow direction of block-level boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-002-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-008.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-008.xht
index cb1b2a35..4a07092 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-008.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-008.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: 'float: right' and 'vertical-lr' - block flow direction of block-level boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-002-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-010.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-010.xht
index bec4e63..5c0ed27eb 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-010.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-010.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: position absolute and 'vertical-lr' - block flow direction of block-level boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-014.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-014.xht
index b5cde2d..ea2f25c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-014.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-014.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: inline-block and 'vertical-lr' - block flow direction of block-level boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-015.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-015.xht
index fcef14f..da1b1af 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-015.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-015.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: inline-block and 'vertical-lr' - block flow direction of block-level boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-016.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-016.xht
index 5dc58f0..d75986b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-016.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-016.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: inline-block and 'vertical-lr' - block flow direction of block-level boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-020.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-020.xht
index c2bbfce..6139289 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-020.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-020.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: table-caption and 'vertical-lr' - block flow direction of block-level boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-022.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-022.xht
index 9fa9ae27..4e577483 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-022.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-022.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: list and vertical-lr - block flow direction of block-level boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem image" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-023.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-023.xht
index fc65bcc..7ac79b94 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-023.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-023.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: vertical-lr - block flow direction of block-level boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-002.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-002.xht
index 26042d06..134570f9 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-002.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-002.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: vertical-rl - block flow direction of block-level boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-002-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-005.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-005.xht
index 7755a3ee..49f843e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-005.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-005.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: 'float: left' and 'vertical-rl' - block flow direction of block-level boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-006.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-006.xht
index b8c0581b..7affbc98 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-006.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-006.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: 'float: left' and 'vertical-rl' - block flow direction of block-level boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-009.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-009.xht
index 0eddd2b2..06382cf 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-009.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-009.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: position absolute and 'vertical-rl' - block flow direction of block-level boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-011.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-011.xht
index 22621de9..5fb7da2e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-011.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-011.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: inline-block and 'vertical-rl' - block flow direction of block-level boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-012.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-012.xht
index b8c0415..23b29860 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-012.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-012.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: inline-block and 'vertical-rl' - block flow direction of block-level boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-013.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-013.xht
index 3badfbd2..b3c6489b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-013.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-013.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: inline-block and 'vertical-rl' - block flow direction of block-level boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-019.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-019.xht
index 24967343..6f6b7abb 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-019.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-019.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: table-caption and 'vertical-rl' - block flow direction of block-level boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-021.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-021.xht
index daec06c..139bacd 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-021.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-021.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: list and vertical-rl - block flow direction of block-level boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-002-ref.xht" />
 
   <meta content="ahem image" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-024.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-024.xht
index 10b43b1..4012889d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-024.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-024.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: vertical-rl - block flow direction of block-level boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-002-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-025.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-025.xht
index 998cb41..92685d3d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-025.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-025.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: writing mode of document - horizontal position of first block</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="help" href="http://www.w3.org/TR/2011/REC-CSS2-20110607/visuren.html#block-formatting" title="9.4.1 Block formatting contexts" />
   <link rel="match" href="block-flow-direction-025-ref.xht" />
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/different-block-flow-dir-001.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/different-block-flow-dir-001.xht
index 1df6039..d885e1a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/different-block-flow-dir-001.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/different-block-flow-dir-001.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: descendant inline with a different 'writing-mode' value</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="../reference/ref-filled-green-100px-square.xht" />
 
   <meta content="" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/different-block-flow-dir-002.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/different-block-flow-dir-002.xht
index 93811d4..a02095a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/different-block-flow-dir-002.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/different-block-flow-dir-002.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: descendant inline with a different 'writing-mode' value</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="../reference/ref-filled-green-100px-square.xht" />
 
   <meta content="" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/first-page-vlr-003.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/first-page-vlr-003.xht
index d89d560..ce94a079 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/first-page-vlr-003.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/first-page-vlr-003.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: first page of a document with vertical-lr writing-mode</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#page-selectors" title="13.2.2 Page selectors: selecting left, right, and first pages" />
 
   <meta content="paged" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/first-page-vrl-002.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/first-page-vrl-002.xht
index f035d6f..8ba53e2 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/first-page-vrl-002.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/first-page-vrl-002.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: first page of a document with vertical-rl writing-mode</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="help" href="http://www.w3.org/TR/CSS21/page.html#page-selectors" title="13.2.2 Page selectors: selecting left, right, and first pages" />
 
   <meta content="image paged" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/flexbox_align-items-stretch-writing-modes.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/flexbox_align-items-stretch-writing-modes.html
index 5c59a31..0f013e3 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/flexbox_align-items-stretch-writing-modes.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/flexbox_align-items-stretch-writing-modes.html
@@ -5,7 +5,7 @@
     <link rel="author" title="Mitsuteru Sawa" href="mailto:mitsuteru.s@gmail.com">
     <link rel="reviewer" title="Tab Atkins Jr." href="mailto:jackalmage@gmail.com">
     <link rel="help" href="http://www.w3.org/TR/css-flexbox-1/#propdef-align-items">
-    <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode">
+    <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow">
     <link rel="match" href="flexbox_align-items-stretch-writing-modes-ref.html">
     <meta name="assert" content="vertical-writing-mode flex items should stretch">
     <style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-vlr-004.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-vlr-004.xht
index 0579cdf..8d5f5c9 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-vlr-004.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-vlr-004.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: order, orientation and layout of form controls in 'vertical-lr' writing-mode</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
 
   <meta content="image should" name="flags" />
   <meta content="This test checks the order, the flow, the orientation and layout of form controls used in Example 4 of section 3.1 when the 'writing-mode' of the whole form element is set to 'vertical-lr'." name="assert" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-vlr-005.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-vlr-005.xht
index c2269bc..9f103e10 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-vlr-005.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-vlr-005.xht
@@ -8,7 +8,7 @@
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
 
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
 
   <meta content="should" name="flags" />
   <meta content="This test checks the rendering of various form controls (select, optgroup, options, various types of input and buttons) written with latin text in 'vertical-lr' writing mode. The text of replaced content should match the replaced element's writing mode and line orientation; therefore, in this test, a) the text's inline base direction must be from top to bottom, b) the glyphs must be rotated 90° clockwise and c) the block flow direction must be from left to right." name="assert" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-vrl-004.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-vrl-004.xht
index 5512439..89ad197a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-vrl-004.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-vrl-004.xht
@@ -8,7 +8,7 @@
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
   <link rel="bookmark" type="image/png" href="http://www.w3.org/TR/css-writing-modes-3/vertical-form.png" title="Screenshot of vertical layout of form controls and characters" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
 
   <meta content="image should" name="flags" />
   <meta content="This test checks the order, the flow, the orientation and layout of form controls used in Example 4 of section 3.1 when the 'writing-mode' of the whole form element is set to 'vertical-rl'." name="assert" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-vrl-005.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-vrl-005.xht
index 2ce0800..f873373 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-vrl-005.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-vrl-005.xht
@@ -8,7 +8,7 @@
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
 
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
 
   <meta content="should" name="flags" />
   <meta content="This test checks the rendering of various form controls (select, optgroup, options, various types of input and buttons) written with latin text in 'vertical-rl' writing mode. The text of replaced content should match the replaced element's writing mode and line orientation; therefore, in this test, a) the text's inline base direction must be from top to bottom, b) the glyphs must be rotated 90° clockwise and c) the block flow direction must be from right to left." name="assert" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/inline-replaced-vlr-003.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/inline-replaced-vlr-003.xht
index b3788b6..1c33d6e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/inline-replaced-vlr-003.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/inline-replaced-vlr-003.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: inline replaced element and 'vertical-lr'</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="inline-replaced-vrl-002-ref.xht" />
 
   <meta content="image" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/inline-replaced-vrl-002.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/inline-replaced-vrl-002.xht
index 2db65b0e..fd09531c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/inline-replaced-vrl-002.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/inline-replaced-vrl-002.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: inline replaced element and 'vertical-rl'</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="inline-replaced-vrl-002-ref.xht" />
 
   <meta content="image" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-htb-001.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-htb-001.xht
index adc21b45..18555bc1 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-htb-001.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-htb-001.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: horizontal-tb - ordering direction of line boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-003.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-003.xht
index fd253bbf..b6d866d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-003.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-003.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: vertical-lr - ordering direction of line boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-007.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-007.xht
index e8af788..50dd3c5 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-007.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-007.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: 'float: right' and 'vertical-lr' - ordering direction of line boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-002-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-008.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-008.xht
index 241f7ee2..504e61e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-008.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-008.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: 'float: right' and 'vertical-lr' - ordering direction of line boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-002-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-010.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-010.xht
index d16daa1..6979913d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-010.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-010.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: position absolute and 'vertical-lr' - ordering direction of line boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-013.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-013.xht
index f210416..f1e6067c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-013.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-013.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: inline-block and 'vertical-lr' - ordering direction of line boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-014.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-014.xht
index 05cd7ff5..03f7850 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-014.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-014.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: inline-block and 'vertical-lr' - ordering direction of line boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-018.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-018.xht
index 60962ea..f539f92 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-018.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-018.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: table-caption and 'vertical-lr' - ordering direction of line boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-020.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-020.xht
index 7c6f2a7..e201d63a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-020.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vlr-020.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: list and 'vertical-lr' - ordering direction of line boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-002.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-002.xht
index 7ddc724..39ba7e44 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-002.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-002.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: vertical-rl - ordering direction of line boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-005.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-005.xht
index 8a6c80c..34d40e1 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-005.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-005.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: 'float: left' and 'vertical-rl' - ordering direction of line boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-006.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-006.xht
index ce76d52a..414a989 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-006.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-006.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: 'float: left' and 'vertical-rl' - ordering direction of line boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-009.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-009.xht
index 3e39595..2c3e1c70 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-009.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-009.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: position absolute and 'vertical-rl' - ordering direction of line boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-011.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-011.xht
index 11342cb..94b05b19 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-011.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-011.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: inline-block and 'vertical-rl' - ordering direction of line boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-012.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-012.xht
index 364d025..2f57f298 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-012.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-012.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: inline-block and 'vertical-rl' - ordering direction of line boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-017.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-017.xht
index ce71e1fd..0dd4442 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-017.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-017.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: table-caption and 'vertical-rl' - ordering direction of line boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-019.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-019.xht
index 774bf92..f9e1015 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-019.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/line-box-direction-vrl-019.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: list and 'vertical-rl' - ordering direction of line boxes</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/page-flow-direction-002.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/page-flow-direction-002.xht
index 00e756bc..4472d61 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/page-flow-direction-002.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/page-flow-direction-002.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: 'writing-mode: vertical-rl' - default page flow (progression) direction</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
 
   <meta content="image paged" name="flags" />
   <meta content="This test checks that when 'writing-mode' is set on the root element, then it determines the default page flow (or progression) direction. In this test, the page flow (or progression) direction is right-to-left." name="assert" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/page-flow-direction-003.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/page-flow-direction-003.xht
index a9da487..1694d08 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/page-flow-direction-003.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/page-flow-direction-003.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: 'writing-mode: vertical-lr' - default page flow (progression) direction</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
 
   <meta content="image paged" name="flags" />
   <meta content="This test checks that when 'writing-mode' is set on the root element, then it determines the default page flow (or progression) direction. In this test, the page flow (or progression) direction is left-to-right." name="assert" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/replaced-content-image-002.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/replaced-content-image-002.xht
index f42bff3..ef650ee 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/replaced-content-image-002.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/replaced-content-image-002.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: alternate text of image and vertical writing mode</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
 
   <meta content="should" name="flags" />
   <meta content="This test checks that alternate text (latin) of image rotates 90° clockwise in vertical writing mode." name="assert" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/replaced-content-image-003.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/replaced-content-image-003.xht
index 061f2c8..dbd9a23 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/replaced-content-image-003.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/replaced-content-image-003.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: alternate text of image and vertical writing mode</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
 
   <meta content="should" name="flags" />
   <meta content="This test checks that alternate text (latin) of image rotates 90° clockwise in vertical writing mode." name="assert" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vlr-003.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vlr-003.xht
index 3e00b48..b5028d28 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vlr-003.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vlr-003.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: vertical-lr - table rows progression</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vlr-005.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vlr-005.xht
index 77ae272..c0e65fb 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vlr-005.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vlr-005.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: vertical-lr - table rows progression and colspan</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vlr-007.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vlr-007.xht
index 6fd85b7ec..0ed4f07 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vlr-007.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vlr-007.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: vertical-lr - table rows progression and rowspan</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vrl-002.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vrl-002.xht
index ed998c5..b01ca7a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vrl-002.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vrl-002.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: vertical-rl - table rows progression</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vrl-004.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vrl-004.xht
index 35086f01..aff135262 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vrl-004.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vrl-004.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: vertical-rl - table rows progression and colspan</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vrl-006.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vrl-006.xht
index dfc9a93..e9c5e729 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vrl-006.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vrl-006.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: vertical-rl - table rows progression and rowspan</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vrl-008.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vrl-008.xht
index 48ec5744..c953e96 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vrl-008.xht
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/row-progression-vrl-008.xht
@@ -7,7 +7,7 @@
   <title>CSS Writing Modes Test: vertical-rl - table rows progression (thead, 2 tbodies, tfoot)</title>
 
   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
+  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" />
   <link rel="match" href="block-flow-direction-001-ref.xht" />
 
   <meta content="ahem" name="flags" />
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/writing-mode-vertical-rl-003.htm b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/writing-mode-vertical-rl-003.htm
index 1f0b43b..cd84413 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/writing-mode-vertical-rl-003.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/writing-mode-vertical-rl-003.htm
@@ -5,7 +5,7 @@
     <link rel="author" title="KISAKA Toshihiro" href="mailto:toshihiro@kisaka.jp">
     <!-- You must have at least one spec link, but may have as many as are covered in the test. -->
     <!-- Be sure to make the main testing area first in the order -->
-    <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode">
+    <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow">
     <!-- The match link is only required if this is a reftest -->
     <link rel="match" href="writing-mode-vertical-rl-003-ref.htm">
     <meta name="flags" content="ahem">
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/api-basics.html b/third_party/WebKit/LayoutTests/external/wpt/encoding/api-basics.any.js
similarity index 91%
rename from third_party/WebKit/LayoutTests/external/wpt/encoding/api-basics.html
rename to third_party/WebKit/LayoutTests/external/wpt/encoding/api-basics.any.js
index 83670ce..941b878 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/encoding/api-basics.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/api-basics.any.js
@@ -1,8 +1,4 @@
-<!DOCTYPE html>
-<title>Encoding API: Basics</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
+// META: title=Encoding API: Basics
 
 test(function() {
     assert_equals((new TextEncoder).encoding, 'utf-8', 'default encoding is utf-8');
@@ -54,5 +50,3 @@
   sample,
   [0x7A, 0x00, 0xA2, 0x00, 0x34, 0x6C, 0x34, 0xD8, 0x1E, 0xDD, 0xFF, 0xF8, 0xFF, 0xDB, 0xFD, 0xDF, 0xFE, 0xFF]
 );
-
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/api-invalid-label.html b/third_party/WebKit/LayoutTests/external/wpt/encoding/api-invalid-label.any.js
similarity index 70%
rename from third_party/WebKit/LayoutTests/external/wpt/encoding/api-invalid-label.html
rename to third_party/WebKit/LayoutTests/external/wpt/encoding/api-invalid-label.any.js
index 3c7486fa..38c0e9a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/encoding/api-invalid-label.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/api-invalid-label.any.js
@@ -1,10 +1,7 @@
-<!DOCTYPE html>
-<title>Encoding API: invalid label</title>
-<meta name="timeout" content="long">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/encodings.js"></script>
-<script>
+// META: title=Encoding API: invalid label
+// META: timeout=long
+// META: script=resources/encodings.js
+
 var tests = ["invalid-invalidLabel"];
 setup(function() {
   encodings_table.forEach(function(section) {
@@ -25,4 +22,3 @@
     assert_throws(new RangeError(), function() { new TextDecoder(input); });
   }, 'Invalid label ' + format_value(input) + ' should be rejected by TextDecoder.');
 });
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/api-replacement-encodings.html b/third_party/WebKit/LayoutTests/external/wpt/encoding/api-replacement-encodings.any.js
similarity index 65%
rename from third_party/WebKit/LayoutTests/external/wpt/encoding/api-replacement-encodings.html
rename to third_party/WebKit/LayoutTests/external/wpt/encoding/api-replacement-encodings.any.js
index 6340263..6d1e494a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/encoding/api-replacement-encodings.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/api-replacement-encodings.any.js
@@ -1,9 +1,5 @@
-<!DOCTYPE html>
-<title>Encoding API: replacement encoding</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/encodings.js"></script>
-<script>
+// META: title=Encoding API: replacement encoding
+// META: script=resources/encodings.js
 
 encodings_table.forEach(function(section) {
     section.encodings.filter(function(encoding) {
@@ -17,4 +13,3 @@
     });
 });
 
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/api-surrogates-utf8.html b/third_party/WebKit/LayoutTests/external/wpt/encoding/api-surrogates-utf8.any.js
similarity index 85%
rename from third_party/WebKit/LayoutTests/external/wpt/encoding/api-surrogates-utf8.html
rename to third_party/WebKit/LayoutTests/external/wpt/encoding/api-surrogates-utf8.any.js
index ef0ad40..a4ced03 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/encoding/api-surrogates-utf8.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/api-surrogates-utf8.any.js
@@ -1,8 +1,4 @@
-<!DOCTYPE html>
-<title>Encoding API: Invalid UTF-16 surrogates with UTF-8 encoding</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
+// META: title=Encoding API: Invalid UTF-16 surrogates with UTF-8 encoding
 
 var badStrings = [
     {
@@ -50,5 +46,3 @@
         assert_equals(new TextDecoder('utf-8').decode(encoded), t.decoded);
     }, 'Invalid surrogates encoded into UTF-8: ' + t.name);
 });
-
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/iso-2022-jp-decoder.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/encoding/iso-2022-jp-decoder.any-expected.txt
new file mode 100644
index 0000000..e2530320
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/iso-2022-jp-decoder.any-expected.txt
@@ -0,0 +1,37 @@
+This is a testharness.js-based test.
+FAIL iso-2022-jp decoder: Error ESC assert_equals: expected "\ufffd$" but got "\ufffd"
+PASS iso-2022-jp decoder: Error ESC, character
+PASS iso-2022-jp decoder: ASCII ESC, character
+PASS iso-2022-jp decoder: Double ASCII ESC, character
+PASS iso-2022-jp decoder: character, ASCII ESC, character
+PASS iso-2022-jp decoder: characters
+PASS iso-2022-jp decoder: SO / SI
+PASS iso-2022-jp decoder: Roman ESC, characters
+PASS iso-2022-jp decoder: Roman ESC, SO / SI
+PASS iso-2022-jp decoder: Roman ESC, error ESC, Katakana ESC
+PASS iso-2022-jp decoder: Katakana ESC, character
+PASS iso-2022-jp decoder: Katakana ESC, multibyte ESC, character
+PASS iso-2022-jp decoder: Katakana ESC, error ESC, character
+PASS iso-2022-jp decoder: Katakana ESC, error ESC #2, character
+PASS iso-2022-jp decoder: Katakana ESC, character, Katakana ESC, character
+FAIL iso-2022-jp decoder: Katakana ESC, SO / SI assert_equals: expected "\ufffd\ufffd\ufffd\ufffd" but got "\r\ufffd\ufffd\x10"
+PASS iso-2022-jp decoder: Multibyte ESC, character
+PASS iso-2022-jp decoder: Multibyte ESC #2, character
+PASS iso-2022-jp decoder: Multibyte ESC, error ESC, character
+PASS iso-2022-jp decoder: Double multibyte ESC
+PASS iso-2022-jp decoder: Double multibyte ESC, character
+PASS iso-2022-jp decoder: Double multibyte ESC #2, character
+PASS iso-2022-jp decoder: Multibyte ESC, error ESC #2, character
+PASS iso-2022-jp decoder: Multibyte ESC, single byte, multibyte ESC, character
+PASS iso-2022-jp decoder: Multibyte ESC, lead error byte
+PASS iso-2022-jp decoder: Multibyte ESC, trail error byte
+PASS iso-2022-jp decoder: character, error ESC
+FAIL iso-2022-jp decoder: character, error ESC #2 assert_equals: expected "P\ufffd$" but got "P\ufffd"
+PASS iso-2022-jp decoder: character, error ESC #3
+PASS iso-2022-jp decoder: character, ASCII ESC
+PASS iso-2022-jp decoder: character, Roman ESC
+PASS iso-2022-jp decoder: character, Katakana ESC
+PASS iso-2022-jp decoder: character, Multibyte ESC
+PASS iso-2022-jp decoder: character, Multibyte ESC #2
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/iso-2022-jp-decoder.any.js b/third_party/WebKit/LayoutTests/external/wpt/encoding/iso-2022-jp-decoder.any.js
new file mode 100644
index 0000000..b02259b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/iso-2022-jp-decoder.any.js
@@ -0,0 +1,50 @@
+function decode(input, output, desc) {
+  test(function() {
+    var d = new TextDecoder("iso-2022-jp"),
+        buffer = new ArrayBuffer(input.length),
+        view = new Int8Array(buffer)
+    for(var i = 0, l = input.length; i < l; i++) {
+      view[i] = input[i]
+    }
+    assert_equals(d.decode(view), output)
+  }, "iso-2022-jp decoder: " + desc)
+}
+decode([0x1b, 0x24], "�$", "Error ESC")
+decode([0x1b, 0x24, 0x50], "�$P", "Error ESC, character")
+decode([0x1b, 0x28, 0x42, 0x50], "P", "ASCII ESC, character")
+decode([0x1b, 0x28, 0x42, 0x1b, 0x28, 0x42, 0x50], "�P", "Double ASCII ESC, character")
+decode([0x50, 0x1b, 0x28, 0x42, 0x50], "PP", "character, ASCII ESC, character")
+decode([0x5C, 0x5D, 0x7E], "\\]~", "characters")
+decode([0x0D, 0x0E, 0x0F, 0x10], "\x0D��\x10", "SO / SI")
+
+decode([0x1b, 0x28, 0x4A, 0x5C, 0x5D, 0x7E], "¥]‾", "Roman ESC, characters")
+decode([0x1b, 0x28, 0x4A, 0x0D, 0x0E, 0x0F, 0x10], "\x0D��\x10", "Roman ESC, SO / SI")
+decode([0x1b, 0x28, 0x4A, 0x1b, 0x1b, 0x28, 0x49, 0x50], "�ミ", "Roman ESC, error ESC, Katakana ESC")
+
+decode([0x1b, 0x28, 0x49, 0x50], "ミ", "Katakana ESC, character")
+decode([0x1b, 0x28, 0x49, 0x1b, 0x24, 0x40, 0x50, 0x50], "�佩", "Katakana ESC, multibyte ESC, character")
+decode([0x1b, 0x28, 0x49, 0x1b, 0x50], "�ミ", "Katakana ESC, error ESC, character")
+decode([0x1b, 0x28, 0x49, 0x1b, 0x24, 0x50], "�、ミ", "Katakana ESC, error ESC #2, character")
+decode([0x1b, 0x28, 0x49, 0x50, 0x1b, 0x28, 0x49, 0x50], "ミミ", "Katakana ESC, character, Katakana ESC, character")
+decode([0x1b, 0x28, 0x49, 0x0D, 0x0E, 0x0F, 0x10], "����", "Katakana ESC, SO / SI")
+
+decode([0x1b, 0x24, 0x40, 0x50, 0x50], "佩", "Multibyte ESC, character")
+decode([0x1b, 0x24, 0x42, 0x50, 0x50], "佩", "Multibyte ESC #2, character")
+decode([0x1b, 0x24, 0x42, 0x1b, 0x50, 0x50], "�佩", "Multibyte ESC, error ESC, character")
+decode([0x1b, 0x24, 0x40, 0x1b, 0x24, 0x40], "�", "Double multibyte ESC")
+decode([0x1b, 0x24, 0x40, 0x1b, 0x24, 0x40, 0x50, 0x50], "�佩", "Double multibyte ESC, character")
+decode([0x1b, 0x24, 0x40, 0x1b, 0x24, 0x42, 0x50, 0x50], "�佩", "Double multibyte ESC #2, character")
+decode([0x1b, 0x24, 0x40, 0x1b, 0x24, 0x50, 0x50], "�ば�", "Multibyte ESC, error ESC #2, character")
+
+decode([0x1b, 0x24, 0x40, 0x50, 0x1b, 0x24, 0x40, 0x50, 0x50], "�佩", "Multibyte ESC, single byte, multibyte ESC, character")
+decode([0x1b, 0x24, 0x40, 0x20, 0x50], "��", "Multibyte ESC, lead error byte")
+decode([0x1b, 0x24, 0x40, 0x50, 0x20], "�", "Multibyte ESC, trail error byte")
+
+decode([0x50, 0x1b], "P�", "character, error ESC")
+decode([0x50, 0x1b, 0x24], "P�$", "character, error ESC #2")
+decode([0x50, 0x1b, 0x50], "P�P", "character, error ESC #3")
+decode([0x50, 0x1b, 0x28, 0x42], "P", "character, ASCII ESC")
+decode([0x50, 0x1b, 0x28, 0x4A], "P", "character, Roman ESC")
+decode([0x50, 0x1b, 0x28, 0x49], "P", "character, Katakana ESC")
+decode([0x50, 0x1b, 0x24, 0x40], "P", "character, Multibyte ESC")
+decode([0x50, 0x1b, 0x24, 0x42], "P", "character, Multibyte ESC #2")
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/iso-2022-jp-decoder.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/encoding/iso-2022-jp-decoder.any.worker-expected.txt
new file mode 100644
index 0000000..e2530320
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/iso-2022-jp-decoder.any.worker-expected.txt
@@ -0,0 +1,37 @@
+This is a testharness.js-based test.
+FAIL iso-2022-jp decoder: Error ESC assert_equals: expected "\ufffd$" but got "\ufffd"
+PASS iso-2022-jp decoder: Error ESC, character
+PASS iso-2022-jp decoder: ASCII ESC, character
+PASS iso-2022-jp decoder: Double ASCII ESC, character
+PASS iso-2022-jp decoder: character, ASCII ESC, character
+PASS iso-2022-jp decoder: characters
+PASS iso-2022-jp decoder: SO / SI
+PASS iso-2022-jp decoder: Roman ESC, characters
+PASS iso-2022-jp decoder: Roman ESC, SO / SI
+PASS iso-2022-jp decoder: Roman ESC, error ESC, Katakana ESC
+PASS iso-2022-jp decoder: Katakana ESC, character
+PASS iso-2022-jp decoder: Katakana ESC, multibyte ESC, character
+PASS iso-2022-jp decoder: Katakana ESC, error ESC, character
+PASS iso-2022-jp decoder: Katakana ESC, error ESC #2, character
+PASS iso-2022-jp decoder: Katakana ESC, character, Katakana ESC, character
+FAIL iso-2022-jp decoder: Katakana ESC, SO / SI assert_equals: expected "\ufffd\ufffd\ufffd\ufffd" but got "\r\ufffd\ufffd\x10"
+PASS iso-2022-jp decoder: Multibyte ESC, character
+PASS iso-2022-jp decoder: Multibyte ESC #2, character
+PASS iso-2022-jp decoder: Multibyte ESC, error ESC, character
+PASS iso-2022-jp decoder: Double multibyte ESC
+PASS iso-2022-jp decoder: Double multibyte ESC, character
+PASS iso-2022-jp decoder: Double multibyte ESC #2, character
+PASS iso-2022-jp decoder: Multibyte ESC, error ESC #2, character
+PASS iso-2022-jp decoder: Multibyte ESC, single byte, multibyte ESC, character
+PASS iso-2022-jp decoder: Multibyte ESC, lead error byte
+PASS iso-2022-jp decoder: Multibyte ESC, trail error byte
+PASS iso-2022-jp decoder: character, error ESC
+FAIL iso-2022-jp decoder: character, error ESC #2 assert_equals: expected "P\ufffd$" but got "P\ufffd"
+PASS iso-2022-jp decoder: character, error ESC #3
+PASS iso-2022-jp decoder: character, ASCII ESC
+PASS iso-2022-jp decoder: character, Roman ESC
+PASS iso-2022-jp decoder: character, Katakana ESC
+PASS iso-2022-jp decoder: character, Multibyte ESC
+PASS iso-2022-jp decoder: character, Multibyte ESC #2
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/iso-2022-jp-decoder.html b/third_party/WebKit/LayoutTests/external/wpt/encoding/iso-2022-jp-decoder.html
deleted file mode 100644
index c0b858c..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/encoding/iso-2022-jp-decoder.html
+++ /dev/null
@@ -1,57 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<div id=log></div>
-<script>
- function decode(input, output, desc) {
-   test(function() {
-     var d = new TextDecoder("iso-2022-jp"),
-         buffer = new ArrayBuffer(input.length),
-         view = new Int8Array(buffer)
-     for(var i = 0, l = input.length; i < l; i++) {
-       view[i] = input[i]
-     }
-     assert_equals(d.decode(view), output)
-   }, "iso-2022-jp decoder: " + desc)
- }
- decode([0x1b, 0x24], "�$", "Error ESC")
- decode([0x1b, 0x24, 0x50], "�$P", "Error ESC, character")
- decode([0x1b, 0x28, 0x42, 0x50], "P", "ASCII ESC, character")
- decode([0x1b, 0x28, 0x42, 0x1b, 0x28, 0x42, 0x50], "�P", "Double ASCII ESC, character")
- decode([0x50, 0x1b, 0x28, 0x42, 0x50], "PP", "character, ASCII ESC, character")
- decode([0x5C, 0x5D, 0x7E], "\\]~", "characters")
- decode([0x0D, 0x0E, 0x0F, 0x10], "\x0D��\x10", "SO / SI")
-
- decode([0x1b, 0x28, 0x4A, 0x5C, 0x5D, 0x7E], "¥]‾", "Roman ESC, characters")
- decode([0x1b, 0x28, 0x4A, 0x0D, 0x0E, 0x0F, 0x10], "\x0D��\x10", "Roman ESC, SO / SI")
- decode([0x1b, 0x28, 0x4A, 0x1b, 0x1b, 0x28, 0x49, 0x50], "�ミ", "Roman ESC, error ESC, Katakana ESC")
-
- decode([0x1b, 0x28, 0x49, 0x50], "ミ", "Katakana ESC, character")
- decode([0x1b, 0x28, 0x49, 0x1b, 0x24, 0x40, 0x50, 0x50], "�佩", "Katakana ESC, multibyte ESC, character")
- decode([0x1b, 0x28, 0x49, 0x1b, 0x50], "�ミ", "Katakana ESC, error ESC, character")
- decode([0x1b, 0x28, 0x49, 0x1b, 0x24, 0x50], "�、ミ", "Katakana ESC, error ESC #2, character")
- decode([0x1b, 0x28, 0x49, 0x50, 0x1b, 0x28, 0x49, 0x50], "ミミ", "Katakana ESC, character, Katakana ESC, character")
- decode([0x1b, 0x28, 0x49, 0x0D, 0x0E, 0x0F, 0x10], "����", "Katakana ESC, SO / SI")
-
- decode([0x1b, 0x24, 0x40, 0x50, 0x50], "佩", "Multibyte ESC, character")
- decode([0x1b, 0x24, 0x42, 0x50, 0x50], "佩", "Multibyte ESC #2, character")
- decode([0x1b, 0x24, 0x42, 0x1b, 0x50, 0x50], "�佩", "Multibyte ESC, error ESC, character")
- decode([0x1b, 0x24, 0x40, 0x1b, 0x24, 0x40], "�", "Double multibyte ESC")
- decode([0x1b, 0x24, 0x40, 0x1b, 0x24, 0x40, 0x50, 0x50], "�佩", "Double multibyte ESC, character")
- decode([0x1b, 0x24, 0x40, 0x1b, 0x24, 0x42, 0x50, 0x50], "�佩", "Double multibyte ESC #2, character")
- decode([0x1b, 0x24, 0x40, 0x1b, 0x24, 0x50, 0x50], "�ば�", "Multibyte ESC, error ESC #2, character")
-
- decode([0x1b, 0x24, 0x40, 0x50, 0x1b, 0x24, 0x40, 0x50, 0x50], "�佩", "Multibyte ESC, single byte, multibyte ESC, character")
- decode([0x1b, 0x24, 0x40, 0x20, 0x50], "��", "Multibyte ESC, lead error byte")
- decode([0x1b, 0x24, 0x40, 0x50, 0x20], "�", "Multibyte ESC, trail error byte")
-
- decode([0x50, 0x1b], "P�", "character, error ESC")
- decode([0x50, 0x1b, 0x24], "P�$", "character, error ESC #2")
- decode([0x50, 0x1b, 0x50], "P�P", "character, error ESC #3")
- decode([0x50, 0x1b, 0x28, 0x42], "P", "character, ASCII ESC")
- decode([0x50, 0x1b, 0x28, 0x4A], "P", "character, Roman ESC")
- decode([0x50, 0x1b, 0x28, 0x49], "P", "character, Katakana ESC")
- decode([0x50, 0x1b, 0x24, 0x40], "P", "character, Multibyte ESC")
- decode([0x50, 0x1b, 0x24, 0x42], "P", "character, Multibyte ESC #2")
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/replacement-encodings.html b/third_party/WebKit/LayoutTests/external/wpt/encoding/replacement-encodings.any.js
similarity index 65%
rename from third_party/WebKit/LayoutTests/external/wpt/encoding/replacement-encodings.html
rename to third_party/WebKit/LayoutTests/external/wpt/encoding/replacement-encodings.any.js
index 4be3c85..784dd953 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/encoding/replacement-encodings.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/replacement-encodings.any.js
@@ -1,10 +1,6 @@
-<!DOCTYPE html>
-<title>Encoding API: replacement encoding</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/encodings.js"></script>
-<script src="resources/decoding-helpers.js"></script>
-<script>
+// META: title=Encoding API: replacement encoding
+// META: script=resources/encodings.js
+// META: script=resources/decoding-helpers.js
 
 const replacement_labels = [];
 encodings_table.forEach(section => {
@@ -27,4 +23,3 @@
     '',
     '', `${label} - empty input decodes to empty output.`);
 });
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-byte-order-marks.html b/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-byte-order-marks.any.js
similarity index 87%
rename from third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-byte-order-marks.html
rename to third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-byte-order-marks.any.js
index 8ef1679..9ef0d73 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-byte-order-marks.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-byte-order-marks.any.js
@@ -1,8 +1,4 @@
-<!DOCTYPE html>
-<title>Encoding API: Byte-order marks</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
+// META: title=Encoding API: Byte-order marks
 
 var testCases = [
     {
@@ -44,5 +40,3 @@
 
     }, 'Byte-order marks: ' + t.encoding);
 });
-
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-fatal-single-byte.html b/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-fatal-single-byte.any.js
similarity index 92%
rename from third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-fatal-single-byte.html
rename to third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-fatal-single-byte.any.js
index d9bf412..9d12134 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-fatal-single-byte.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-fatal-single-byte.any.js
@@ -1,8 +1,4 @@
-<!DOCTYPE html>
-<title>Encoding API: Fatal flag for single byte encodings</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
+// META: title=Encoding API: Fatal flag for single byte encodings
 
 var singleByteEncodings = [
      {encoding: 'IBM866', bad: []},
@@ -51,5 +47,3 @@
         }
     }
 });
-
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-fatal-streaming.html b/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-fatal-streaming.any.js
similarity index 88%
rename from third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-fatal-streaming.html
rename to third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-fatal-streaming.any.js
index 2ccac9f2..e4fa64d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-fatal-streaming.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-fatal-streaming.any.js
@@ -1,8 +1,4 @@
-<!DOCTYPE html>
-<title>Encoding API: End-of-file</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
+// META: title=Encoding API: End-of-file
 
 test(function() {
     [
@@ -46,5 +42,3 @@
     assert_equals(decoder.decode(even), '\u0000');
 
 }, 'Fatal flag, streaming cases');
-
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-fatal.html b/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-fatal.any.js
similarity index 95%
rename from third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-fatal.html
rename to third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-fatal.any.js
index e8cc9f6..3cb7573 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-fatal.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-fatal.any.js
@@ -1,8 +1,4 @@
-<!DOCTYPE html>
-<title>Encoding API: Fatal flag</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
+// META: title=Encoding API: Fatal flag
 
 var bad = [
     { encoding: 'utf-8', input: [0xFF], name: 'invalid code' },
@@ -68,5 +64,3 @@
     assert_true(new TextDecoder('utf-8', {fatal: true}).fatal, 'The fatal attribute can be set using an option.');
 
 }, 'The fatal attribute of TextDecoder');
-
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-ignorebom.html b/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-ignorebom.any.js
similarity index 89%
rename from third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-ignorebom.html
rename to third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-ignorebom.any.js
index 2638156..1f5dabd 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-ignorebom.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-ignorebom.any.js
@@ -1,8 +1,4 @@
-<!DOCTYPE html>
-<title>Encoding API: TextDecoder ignoreBOM option</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
+// META: title=Encoding API: TextDecoder ignoreBOM option
 
 var cases = [
     {encoding: 'utf-8', bytes: [0xEF, 0xBB, 0xBF, 0x61, 0x62, 0x63]},
@@ -41,5 +37,3 @@
     assert_true(new TextDecoder('utf-8', {ignoreBOM: true}).ignoreBOM, 'The ignoreBOM attribute can be set using an option.');
 
 }, 'The ignoreBOM attribute of TextDecoder');
-
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-labels.html b/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-labels.any.js
similarity index 84%
rename from third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-labels.html
rename to third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-labels.any.js
index 67dc333..ed407a3 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-labels.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-labels.any.js
@@ -1,9 +1,6 @@
-<!DOCTYPE html>
-<title>Encoding API: Encoding labels</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/encodings.js"></script>
-<script>
+// META: title=Encoding API: Encoding labels
+// META: script=resources/encodings.js
+
 var whitespace = [' ', '\t', '\n', '\f', '\r'];
 encodings_table.forEach(function(section) {
   section.encodings.filter(function(encoding) {
@@ -33,4 +30,3 @@
     });
   });
 });
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-streaming.html b/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-streaming.any.js
similarity index 86%
rename from third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-streaming.html
rename to third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-streaming.any.js
index 2b567aa..0863385b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-streaming.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-streaming.any.js
@@ -1,9 +1,5 @@
-<!DOCTYPE html>
-<title>Encoding API: Streaming decode</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/encodings.js"></script>
-<script>
+// META: title=Encoding API: Streaming decode
+// META: script=resources/encodings.js
 
 var string = '\x00123ABCabc\x80\xFF\u0100\u1000\uFFFD\uD800\uDC00\uDBFF\uDFFF';
 var octets = {
@@ -38,5 +34,3 @@
         }, 'Streaming decode: ' + encoding + ', ' + len + ' byte window');
     }
 });
-
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-utf16-surrogates.html b/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-utf16-surrogates.any.js
similarity index 85%
rename from third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-utf16-surrogates.html
rename to third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-utf16-surrogates.any.js
index 207cf37..3b84187 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-utf16-surrogates.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/textdecoder-utf16-surrogates.any.js
@@ -1,8 +1,4 @@
-<!DOCTYPE html>
-<title>Encoding API: UTF-16 surrogate handling</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
+// META: title=Encoding API: UTF-16 surrogate handling
 
 var bad = [
     {
@@ -47,5 +43,3 @@
         });
     }, t.encoding + ' - ' + t.name + ' (fatal flag set)');
 });
-
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/textencoder-constructor-non-utf.html b/third_party/WebKit/LayoutTests/external/wpt/encoding/textencoder-constructor-non-utf.any.js
similarity index 71%
rename from third_party/WebKit/LayoutTests/external/wpt/encoding/textencoder-constructor-non-utf.html
rename to third_party/WebKit/LayoutTests/external/wpt/encoding/textencoder-constructor-non-utf.any.js
index 1fa1ffcc..c7136da4d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/encoding/textencoder-constructor-non-utf.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/textencoder-constructor-non-utf.any.js
@@ -1,9 +1,5 @@
-<!DOCTYPE html>
-<title>Encoding API: Legacy encodings</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/encodings.js"></script>
-<script>
+// META: title=Encoding API: Legacy encodings
+// META: script=resources/encodings.js
 
 encodings_table.forEach(function(section) {
     section.encodings.forEach(function(encoding) {
@@ -18,5 +14,3 @@
         }, 'Encoding argument not considered for encode: ' + encoding.name);
     });
 });
-
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/textencoder-utf16-surrogates.html b/third_party/WebKit/LayoutTests/external/wpt/encoding/textencoder-utf16-surrogates.any.js
similarity index 83%
rename from third_party/WebKit/LayoutTests/external/wpt/encoding/textencoder-utf16-surrogates.html
rename to third_party/WebKit/LayoutTests/external/wpt/encoding/textencoder-utf16-surrogates.any.js
index 4640752..014a0ebb 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/encoding/textencoder-utf16-surrogates.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/textencoder-utf16-surrogates.any.js
@@ -1,8 +1,4 @@
-<!DOCTYPE html>
-<title>Encoding API: USVString surrogate handling when encoding</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
+// META: title=Encoding API: USVString surrogate handling when encoding
 
 var bad = [
     {
@@ -48,5 +44,3 @@
 test(function() {
     assert_equals(new TextEncoder().encode().length, 0, 'Should default to empty string');
 }, 'USVString default');
-
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/unsupported-encodings.html b/third_party/WebKit/LayoutTests/external/wpt/encoding/unsupported-encodings.any.js
similarity index 83%
rename from third_party/WebKit/LayoutTests/external/wpt/encoding/unsupported-encodings.html
rename to third_party/WebKit/LayoutTests/external/wpt/encoding/unsupported-encodings.any.js
index 7584d3d1..461188e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/encoding/unsupported-encodings.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/unsupported-encodings.any.js
@@ -1,9 +1,5 @@
-<!DOCTYPE html>
-<title>Encoding API: unsupported encodings</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/decoding-helpers.js"></script>
-<script>
+// META: title=Encoding API: unsupported encodings
+// META: script=resources/decoding-helpers.js
 
 // Attempting to decode '<' as UTF-7 (+AD4) ends up as '+AD4'.
 ['UTF-7', 'utf-7'].forEach(label => {
@@ -34,4 +30,3 @@
               'U+0000/U+0000/U+00FE/U+00FF/U+0000/U+0000/U+0000/U+0041/U+0000/U+0000/U+0000/U+0042',
               `${label} with BOM should decode as windows-1252`);
 });
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/the-object-element/object-setcustomvalidity-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/the-object-element/object-setcustomvalidity-expected.txt
new file mode 100644
index 0000000..4419ccf6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/the-object-element/object-setcustomvalidity-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL object setCustomValidity is correct assert_true: expected true got false
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/the-object-element/object-setcustomvalidity.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/the-object-element/object-setcustomvalidity.html
new file mode 100644
index 0000000..44574ff
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/the-object-element/object-setcustomvalidity.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<title>object setCustomValidity</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<object id='object_test'></object>
+
+<script>
+
+test(() => {
+  let elem = document.getElementById("object_test");
+  assert_false(elem.validity.customError);
+  elem.setCustomValidity("custom error");
+  assert_true(elem.validity.customError);
+}, "object setCustomValidity is correct")
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-button-element/button-setcustomvalidity.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-button-element/button-setcustomvalidity.html
index 64406ab..1747bd7 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-button-element/button-setcustomvalidity.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-button-element/button-setcustomvalidity.html
@@ -1,43 +1,17 @@
 <!DOCTYPE HTML>
-<html>
- <head>
-  <title>Forms</title>
-  <script src="/resources/testharness.js"></script>
-  <script src="/resources/testharnessreport.js"></script>
- </head>
- <body>
-  <p>
-    <h3>button_setCustomValidity</h3>
-  </p>
+<title>button setCustomValidity</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
 
-  <hr>
+<button id='button_test'></button>
 
-  <div id="log"></div>
+<script>
 
-  <form method="post"
-      enctype="application/x-www-form-urlencoded"
-      action=""
-      id="input_form">
-    <p><button id='button_id'>button</button></p>
-  </form>
-  <script>
+test(() => {
+  let elem = document.getElementById("button_test");
+  assert_false(elem.validity.customError);
+  elem.setCustomValidity("custom error");
+  assert_true(elem.validity.customError);
+}, "button setCustomValidity is correct")
 
-    var button = document.getElementById("button_id");
-
-    try
-    {
-      button.setCustomValidity("custom error");
-      test(function() {
-        assert_true(true, "calling of setCustomValidity method is successed.");
-      });
-    }
-    catch (e) {
-      test(function() {
-        assert_unreached("Error is raised.");
-      });
-    }
-
-  </script>
-
- </body>
-</html>
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-fieldset-element/fieldset-setcustomvalidity-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-fieldset-element/fieldset-setcustomvalidity-expected.txt
new file mode 100644
index 0000000..003b401
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-fieldset-element/fieldset-setcustomvalidity-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL fieldset setCustomValidity is correct assert_true: expected true got false
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-fieldset-element/fieldset-setcustomvalidity.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-fieldset-element/fieldset-setcustomvalidity.html
index 6a6d445..64aa374 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-fieldset-element/fieldset-setcustomvalidity.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-fieldset-element/fieldset-setcustomvalidity.html
@@ -1,44 +1,17 @@
 <!DOCTYPE HTML>
-<html>
- <head>
-  <title>Forms</title>
-  <script src="/resources/testharness.js"></script>
-  <script src="/resources/testharnessreport.js"></script>
- </head>
- <body>
-  <p>
-    <h3>FieldSet_setCustomValidity</h3>
-  </p>
+<title>fieldset setCustomValidity</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
 
-  <hr>
+<fieldset id='fieldset_test'></fieldset>
 
-  <div id="log"></div>
+<script>
 
-  <form method="post"
-      enctype="application/x-www-form-urlencoded"
-      action=""
-      id="input_form">
-    <fieldset id="input_field">
-     </fieldset>
-  </form>
-  <script>
+test(() => {
+  let elem = document.getElementById("fieldset_test");
+  assert_false(elem.validity.customError);
+  elem.setCustomValidity("custom error");
+  assert_true(elem.validity.customError);
+}, "fieldset setCustomValidity is correct")
 
-    var field = document.getElementById("input_field");
-
-    try
-    {
-      field.setCustomValidity("custom error");
-      test(function() {
-        assert_true(true, "calling of setCustomValidity method is successed.");
-      });
-    }
-    catch (e) {
-      test(function() {
-        assert_unreached("Error is raised.");
-      });
-    }
-
-  </script>
-
- </body>
-</html>
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/input-setcustomvalidity.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/input-setcustomvalidity.html
index 7d21097..accb24d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/input-setcustomvalidity.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-input-element/input-setcustomvalidity.html
@@ -1,43 +1,17 @@
 <!DOCTYPE HTML>
-<html>
- <head>
-  <title>Forms</title>
-  <script src="/resources/testharness.js"></script>
-  <script src="/resources/testharnessreport.js"></script>
- </head>
- <body>
-  <p>
-    <h3>input_setCustomValidity</h3>
-  </p>
+<title>input setCustomValidity</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
 
-  <hr>
+<input id='input_test'>
 
-  <div id="log"></div>
+<script>
 
-  <form method="post"
-      enctype="application/x-www-form-urlencoded"
-      action=""
-      id="input_form">
-    <p><input type='hidden' id='input_text'></p>
-  </form>
-  <script>
+test(() => {
+  let elem = document.getElementById("input_test");
+  assert_false(elem.validity.customError);
+  elem.setCustomValidity("custom error");
+  assert_true(elem.validity.customError);
+}, "input setCustomValidity is correct")
 
-    var input = document.getElementById("input_text");
-
-    try
-    {
-      input.setCustomValidity("custom error");
-      test(function() {
-        assert_true(true, "calling of setCustomValidity method is successed.");
-      });
-    }
-    catch (e) {
-      test(function() {
-        assert_unreached("Error is raised.");
-      });
-    }
-
-  </script>
-
- </body>
-</html>
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-output-element/output-setcustomvalidity-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-output-element/output-setcustomvalidity-expected.txt
new file mode 100644
index 0000000..e5d2579
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-output-element/output-setcustomvalidity-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL output setCustomValidity is correct assert_true: expected true got false
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-output-element/output-setcustomvalidity.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-output-element/output-setcustomvalidity.html
new file mode 100644
index 0000000..1166eeb6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-output-element/output-setcustomvalidity.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<title>output setCustomValidity</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<output id='output_test'></output>
+
+<script>
+
+test(() => {
+  let elem = document.getElementById("output_test");
+  assert_false(elem.validity.customError);
+  elem.setCustomValidity("custom error");
+  assert_true(elem.validity.customError);
+}, "output setCustomValidity is correct")
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-select-element/select-setcustomvalidity.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-select-element/select-setcustomvalidity.html
new file mode 100644
index 0000000..15308c1a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-select-element/select-setcustomvalidity.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<title>select setCustomValidity</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<select id='select_test'></select>
+
+<script>
+
+test(() => {
+  let elem = document.getElementById("select_test");
+  assert_false(elem.validity.customError);
+  elem.setCustomValidity("custom error");
+  assert_true(elem.validity.customError);
+}, "select setCustomValidity is correct")
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-textarea-element/textarea-setcustomvalidity.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-textarea-element/textarea-setcustomvalidity.html
new file mode 100644
index 0000000..922a1e7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-textarea-element/textarea-setcustomvalidity.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<title>textarea setCustomValidity</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<textarea id='textarea_test'></textarea>
+
+<script>
+
+test(() => {
+  let elem = document.getElementById("textarea_test");
+  assert_false(elem.validity.customError);
+  elem.setCustomValidity("custom error");
+  assert_true(elem.validity.customError);
+}, "textarea setCustomValidity is correct")
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/appmanifest.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/appmanifest.idl
index 60f5e14..3ebe6cf 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/appmanifest.idl
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/appmanifest.idl
@@ -7,7 +7,8 @@
   "accepted",
   "dismissed"
 };
-[Constructor, Exposed=Window]
+[Constructor(DOMString type, optional EventInit eventInitDict),
+ Exposed=Window]
 interface BeforeInstallPromptEvent : Event {
     Promise<PromptResponseObject> prompt();
 };
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/screen-orientation.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/screen-orientation.idl
index 1e93671..7420248 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/screen-orientation.idl
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/screen-orientation.idl
@@ -4,30 +4,32 @@
 // See: https://w3c.github.io/screen-orientation/
 
 partial interface Screen {
-    [SameObject]
-    readonly attribute ScreenOrientation orientation;
+  [SameObject] readonly attribute ScreenOrientation orientation;
 };
+
 [Exposed=Window]
 interface ScreenOrientation : EventTarget {
-    Promise<void> lock(OrientationLockType orientation);
-    void          unlock();
-    readonly attribute OrientationType type;
-    readonly attribute unsigned short  angle;
-             attribute EventHandler    onchange;
+  Promise<void> lock(OrientationLockType orientation);
+  void unlock();
+  readonly attribute OrientationType type;
+  readonly attribute unsigned short angle;
+  attribute EventHandler onchange;
 };
+
 enum OrientationType {
-    "portrait-primary",
-    "portrait-secondary",
-    "landscape-primary",
-    "landscape-secondary"
+  "portrait-primary",
+  "portrait-secondary",
+  "landscape-primary",
+  "landscape-secondary"
 };
+
 enum OrientationLockType {
-    "any",
-    "natural",
-    "landscape",
-    "portrait",
-    "portrait-primary",
-    "portrait-secondary",
-    "landscape-primary",
-    "landscape-secondary"
+  "any",
+  "natural",
+  "landscape",
+  "portrait",
+  "portrait-primary",
+  "portrait-secondary",
+  "landscape-primary",
+  "landscape-secondary"
 };
diff --git a/third_party/WebKit/LayoutTests/external/wpt/screen-orientation/idlharness.window.js b/third_party/WebKit/LayoutTests/external/wpt/screen-orientation/idlharness.window.js
new file mode 100644
index 0000000..d4b80de3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/screen-orientation/idlharness.window.js
@@ -0,0 +1,18 @@
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+
+'use strict';
+
+// https://w3c.github.io/screen-orientation/
+
+idl_test(
+  ['screen-orientation'],
+  ['dom', 'cssom-view', 'html'],
+  idl_array => {
+    idl_array.add_objects({
+      Screen: ['screen'],
+      ScreenOrientation: ['screen.orientation']
+    });
+  },
+  'Test IDL implementation of Screen Orientation API'
+);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/screen-orientation/interfaces.html b/third_party/WebKit/LayoutTests/external/wpt/screen-orientation/interfaces.html
deleted file mode 100644
index 26d46ae..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/screen-orientation/interfaces.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>Screen Orientation API IDL tests</title>
-<link rel="help" href="https://w3c.github.io/screen-orientation/">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/resources/WebIDLParser.js"></script>
-<script src="/resources/idlharness.js"></script>
-<script>
-"use strict";
-
-promise_test(async () => {
-  const idl_array = new IdlArray();
-  const dom_idl = await fetch("/interfaces/dom.idl").then(r => r.text());
-  const screenorientation_idl = await fetch("/interfaces/screen-orientation.idl").then(r => r.text());
-
-  idl_array.add_untested_idls(dom_idl);
-  idl_array.add_untested_idls('interface EventHandler {};');
-  idl_array.add_untested_idls('interface Screen {};');
-  idl_array.add_idls(screenorientation_idl);
-
-  idl_array.add_objects({
-    Screen: ['screen'],
-    ScreenOrientation: ['screen.orientation']
-  });
-  idl_array.test();
-}, "Test IDL implementation of Screen Orientation API");
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/then-interception-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/then-interception-expected.txt
new file mode 100644
index 0000000..42478b6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/then-interception-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+FAIL piping should not be observable promise_test: Unhandled rejection with value: undefined
+FAIL tee should not be observable promise_test: Unhandled rejection with value: object "TypeError: Assignment to constant variable."
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/then-interception.dedicatedworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/then-interception.dedicatedworker.html
new file mode 100644
index 0000000..8859076
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/then-interception.dedicatedworker.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>then-interception.js dedicated worker wrapper file</title>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<script>
+'use strict';
+fetch_tests_from_worker(new Worker('then-interception.js'));
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/then-interception.html b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/then-interception.html
new file mode 100644
index 0000000..156d3a4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/then-interception.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>then-interception.js browser context wrapper file</title>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<script src="../resources/test-utils.js"></script>
+<script src="../resources/recording-streams.js"></script>
+
+<script src="then-interception.js"></script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/then-interception.js b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/then-interception.js
new file mode 100644
index 0000000..2c4fd54
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/then-interception.js
@@ -0,0 +1,64 @@
+'use strict';
+
+if (self.importScripts) {
+  self.importScripts('/resources/testharness.js');
+  self.importScripts('../resources/test-utils.js');
+  self.importScripts('../resources/recording-streams.js');
+}
+
+function interceptThen() {
+  const intercepted = [];
+  const callCount = 0;
+  Object.prototype.then = function(resolver) {
+    if (!this.done) {
+      intercepted.push(this.value);
+    }
+    const retval = Object.create(null);
+    retval.done = ++callCount === 3;
+    retval.value = callCount;
+    resolver(retval);
+    if (retval.done) {
+      delete Object.prototype.then;
+    }
+  }
+  return intercepted;
+}
+
+promise_test(async () => {
+  const rs = new ReadableStream({
+    start(controller) {
+      controller.enqueue('a');
+      controller.close();
+    }
+  });
+  const ws = recordingWritableStream();
+
+  const intercepted = interceptThen();
+
+  await rs.pipeTo(ws);
+
+  assert_array_equals(intercepted, [], 'nothing should have been intercepted');
+  assert_array_equals(ws.events, ['write', 'a', 'close'], 'written chunk should be "a"');
+}, 'piping should not be observable');
+
+promise_test(async () => {
+  const rs = new ReadableStream({
+    start(controller) {
+      controller.enqueue('a');
+      controller.close();
+    }
+  });
+  const ws = recordingWritableStream();
+
+  const [ branch1, branch2 ] = rs.tee();
+
+  const intercepted = interceptThen();
+
+  await branch1.pipeTo(ws);
+  branch2.cancel();
+
+  assert_array_equals(intercepted, [], 'nothing should have been intercepted');
+  assert_array_equals(ws.events, ['write', 'a', 'close'], 'written chunk should be "a"');
+}, 'tee should not be observable');
+
+done();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/then-interception.serviceworker.https.html b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/then-interception.serviceworker.https.html
new file mode 100644
index 0000000..d12f6e16
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/then-interception.serviceworker.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>then-interception.js service worker wrapper file</title>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
+
+<script>
+'use strict';
+service_worker_test('then-interception.js', 'Service worker test setup');
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/streams/piping/then-interception.sharedworker.html b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/then-interception.sharedworker.html
new file mode 100644
index 0000000..bc284274
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/streams/piping/then-interception.sharedworker.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>then-interception.js shared worker wrapper file</title>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<script>
+'use strict';
+fetch_tests_from_worker(new SharedWorker('then-interception.js'));
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/trusted-types/DOMParser-requiresTrustedTypes.tentative.html b/third_party/WebKit/LayoutTests/external/wpt/trusted-types/DOMParser-requiresTrustedTypes.tentative.html
new file mode 100644
index 0000000..2541c496
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/trusted-types/DOMParser-requiresTrustedTypes.tentative.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="./support/helper.js"></script>
+
+<meta http-equiv="Content-Security-Policy" content="require-trusted-types">
+<body>
+<script>
+  //HTML assignments don't throw
+  test(t => {
+    var html = TrustedHTML.escape(STRINGS.unescapedHTML);
+
+    var parser = new DOMParser();
+    var doc = parser.parseFromString(html, "text/html");
+    assert_equals(doc.body.innerText, STRINGS.unescapedHTML);
+  }, "innerTextOfDoc = TrustedHTML.escape().");
+
+  test(t => {
+    var html = TrustedHTML.unsafelyCreate(STRINGS.unescapedHTML);
+
+    var parser = new DOMParser();
+    var doc = parser.parseFromString(html, "text/html");
+    assert_equals(doc.body.innerText, STRINGS.unescapedText);
+  }, "innerTextOfDoc = TrustedHTML.unsafelyCreate().");
+
+  //Null assignment throws
+  test(t => {
+    var parser = new DOMParser();
+    assert_throws(new TypeError(), _ => {
+      var doc = parser.parseFromString(null, "text/html");
+    });
+  }, "'innerTextOfDoc = null' throws");
+
+  // String assignments throw.
+  test(t => {
+    var parser = new DOMParser();
+    assert_throws(new TypeError(), _ => {
+      var doc = parser.parseFromString("Fail", "text/html");
+    });
+  }, "`innerTextOfDoc = string` throws.");
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/trusted-types/DOMParser.tentative.html b/third_party/WebKit/LayoutTests/external/wpt/trusted-types/DOMParser.tentative.html
new file mode 100644
index 0000000..9541ba6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/trusted-types/DOMParser.tentative.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="./support/helper.js"></script>
+<body>
+<script>
+  test(t => {
+    var html = TrustedHTML.escape(STRINGS.unescapedHTML);
+
+    var parser = new DOMParser();
+    var doc = parser.parseFromString(html, "text/html");
+    assert_equals(doc.body.innerText, STRINGS.unescapedHTML);
+  }, "innerTextOfDoc = TrustedHTML.escape().");
+
+  test(t => {
+    var html = TrustedHTML.unsafelyCreate(STRINGS.unescapedHTML);
+
+    var parser = new DOMParser();
+    var doc = parser.parseFromString(html, "text/html");
+    assert_equals(doc.body.innerText, STRINGS.unescapedText);
+  }, "innerTextOfDoc = TrustedHTML.unsafelyCreate().");
+
+  test(t => {
+    var parser = new DOMParser();
+    var doc = parser.parseFromString(null, "text/html");
+    assert_equals(doc.body.innerText, "null");
+  }, "innerTextOfDoc = null.");
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/events/hr-timestamp/context-menu-event.html b/third_party/WebKit/LayoutTests/fast/events/hr-timestamp/context-menu-event.html
new file mode 100644
index 0000000..bfeee7a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/events/hr-timestamp/context-menu-event.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script type="text/javascript">
+async_test(function(t) {
+  document.addEventListener('contextmenu', t.step_func(function(e) {
+      const platformTimestamp = eventSender.lastEventTimestamp(); // in seconds
+      const expectedUnclampedTimestamp = internals.monotonicTimeToZeroBasedDocumentTime(platformTimestamp) * 1000; // in milliseconds
+      // Time clamping logic in Blink can introduce at most 2*100us of
+      // difference. Use 0.200001 instead of 0.2 to deal with floating
+      // point comparison issues.
+      assert_approx_equals(e.timeStamp, expectedUnclampedTimestamp, 0.200001);
+      t.done();
+  }));
+  eventSender.contextClick();
+}, "ContextMenu event timestamp should be equal to the timestamp provided by the platform");
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/events/hr-timestamp/input-events.html b/third_party/WebKit/LayoutTests/fast/events/hr-timestamp/input-events.html
index e91d1b9f..e189d5e 100644
--- a/third_party/WebKit/LayoutTests/fast/events/hr-timestamp/input-events.html
+++ b/third_party/WebKit/LayoutTests/fast/events/hr-timestamp/input-events.html
@@ -13,7 +13,6 @@
         eventSender.touchStart();
     },
     'click': () => eventSender.gestureTap(1, 1),
-    'contextmenu': () => eventSender.contextClick(),
     'wheel': () => eventSender.mouseScrollBy(0, -50),
 };
 
diff --git a/third_party/WebKit/LayoutTests/fast/table/caption-min-greater-than-max-crash.html b/third_party/WebKit/LayoutTests/fast/table/caption-min-greater-than-max-crash.html
new file mode 100644
index 0000000..61c3ae7f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/table/caption-min-greater-than-max-crash.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+
+<div style="width:fit-content">
+  <!-- To use just one tag, it has to be display:table-caption instead of <caption>
+    to reproduce. I suppose the parser's fix-up algorithm is different than Layout's.
+    Parser turns <caption> into a normal BlockFlow. Layout surrounds this with a table.
+  -->
+  <div style="display:table-caption">some content</div>
+</div>
+
+<script>
+  test(() => {
+  }, "No crash or assertion failure. crbug.com/857185");
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/table/spans-min-greater-than-max-crash.html b/third_party/WebKit/LayoutTests/fast/table/spans-min-greater-than-max-crash.html
new file mode 100644
index 0000000..ee963608
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/table/spans-min-greater-than-max-crash.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+
+<div style="width:fit-content">
+  <table>
+    <tr><td style="width:1%">texttesttest</td><td style="width:99%"></td></tr>
+    <tr><td colspan="2">texttesttexttesttesttextte</td></tr>
+  </table>
+</div>
+
+<script>
+  test(() => {
+  }, "No crash or assertion failure. crbug.com/857185");
+</script>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/doctypes/001-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/doctypes/001-expected.txt
new file mode 100644
index 0000000..7c39814
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/doctypes/001-expected.txt
@@ -0,0 +1,23 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x576
+      LayoutNGBlockFlow {DIV} at (0,0) size 784x100
+      LayoutNGBlockFlow (anonymous) at (0,100) size 784x20
+        LayoutText {#text} at (0,0) size 347x19
+          text run at (0,0) width 347: "This file has no doctype. We should be in quirks mode."
+      LayoutNGBlockFlow {UL} at (0,136) size 784x40
+        LayoutNGListItem {LI} at (40,0) size 744x40
+          LayoutNGListMarker (anonymous) at (-18,0) size 7x20
+            LayoutText (anonymous) at (0,0) size 7x19
+              text run at (0,0) width 7: "\x{2022} "
+          LayoutNGBlockFlow {UL} at (0,20) size 744x20
+            LayoutNGListItem {LI} at (40,0) size 704x20
+              LayoutNGListMarker (anonymous) at (-18,0) size 7x20
+                LayoutText (anonymous) at (0,0) size 7x19
+                  text run at (0,0) width 7: "\x{25E6} "
+              LayoutText {#text} at (0,0) size 238x19
+                text run at (0,0) width 238: "I should be underneath the first bullet."
+layer at (10,10) size 80x80
+  LayoutNGBlockFlow (positioned) {DIV} at (10,10) size 80x80 [bgcolor=#008000]
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/doctypes/003-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/doctypes/003-expected.txt
new file mode 100644
index 0000000..5b0f3214
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/doctypes/003-expected.txt
@@ -0,0 +1,23 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x576
+      LayoutNGBlockFlow {DIV} at (0,0) size 784x100
+      LayoutNGBlockFlow (anonymous) at (0,100) size 784x20
+        LayoutText {#text} at (0,0) size 487x19
+          text run at (0,0) width 487: "This file has a doc type with an internal subset. We should be in quirks mode."
+      LayoutNGBlockFlow {UL} at (0,136) size 784x40
+        LayoutNGListItem {LI} at (40,0) size 744x40
+          LayoutNGListMarker (anonymous) at (-18,0) size 7x20
+            LayoutText (anonymous) at (0,0) size 7x19
+              text run at (0,0) width 7: "\x{2022} "
+          LayoutNGBlockFlow {UL} at (0,20) size 744x20
+            LayoutNGListItem {LI} at (40,0) size 704x20
+              LayoutNGListMarker (anonymous) at (-18,0) size 7x20
+                LayoutText (anonymous) at (0,0) size 7x19
+                  text run at (0,0) width 7: "\x{25E6} "
+              LayoutText {#text} at (0,0) size 253x19
+                text run at (0,0) width 253: "Both bullets should be on separate lines."
+layer at (10,10) size 80x80
+  LayoutNGBlockFlow (positioned) {DIV} at (10,10) size 80x80 [bgcolor=#008000]
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/doctypes/004-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/doctypes/004-expected.txt
new file mode 100644
index 0000000..7c39814
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/doctypes/004-expected.txt
@@ -0,0 +1,23 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
+    LayoutNGBlockFlow {BODY} at (8,8) size 784x576
+      LayoutNGBlockFlow {DIV} at (0,0) size 784x100
+      LayoutNGBlockFlow (anonymous) at (0,100) size 784x20
+        LayoutText {#text} at (0,0) size 347x19
+          text run at (0,0) width 347: "This file has no doctype. We should be in quirks mode."
+      LayoutNGBlockFlow {UL} at (0,136) size 784x40
+        LayoutNGListItem {LI} at (40,0) size 744x40
+          LayoutNGListMarker (anonymous) at (-18,0) size 7x20
+            LayoutText (anonymous) at (0,0) size 7x19
+              text run at (0,0) width 7: "\x{2022} "
+          LayoutNGBlockFlow {UL} at (0,20) size 744x20
+            LayoutNGListItem {LI} at (40,0) size 704x20
+              LayoutNGListMarker (anonymous) at (-18,0) size 7x20
+                LayoutText (anonymous) at (0,0) size 7x19
+                  text run at (0,0) width 7: "\x{25E6} "
+              LayoutText {#text} at (0,0) size 238x19
+                text run at (0,0) width 238: "I should be underneath the first bullet."
+layer at (10,10) size 80x80
+  LayoutNGBlockFlow (positioned) {DIV} at (10,10) size 80x80 [bgcolor=#008000]
diff --git a/third_party/WebKit/LayoutTests/http/tests/fetch/chromium/body-wrapper-tracing.html b/third_party/WebKit/LayoutTests/http/tests/fetch/chromium/body-wrapper-tracing.html
new file mode 100644
index 0000000..5108ac5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/fetch/chromium/body-wrapper-tracing.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+function wait(ms) {
+  return new Promise(resolve => step_timeout(resolve, ms));
+}
+
+promise_test(async () => {
+  const req = new Request('/', {method: 'POST', body: 'hello'});
+  await wait(10);
+  gc();
+  // TODO(yhirano): Use .body here once it has been exposed.
+  const text = await req.text()
+  assert_equals(text, 'hello');
+}, 'request.body should be kept');
+
+promise_test(async () => {
+  const expected = [1, 8, 2, 4, 5];
+  const res = new Response(new Uint8Array(expected));
+  await wait(10);
+  gc();
+  assert_false(res.bodyUsed);
+  const decoder = new TextDecoder();
+  let actual = [];
+  const reader = res.body.getReader();
+  while (true) {
+    const v = await reader.read();
+    if (v.done) {
+      break;
+    }
+    actual = actual.concat(Array.from(v.value))
+  }
+  assert_array_equals(actual, expected);
+}, 'response.body should be kept');
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/appmanifest/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-retina/external/wpt/appmanifest/idlharness.window-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/appmanifest/idlharness.window-expected.txt
rename to third_party/WebKit/LayoutTests/platform/mac-retina/external/wpt/appmanifest/idlharness.window-expected.txt
diff --git a/third_party/WebKit/LayoutTests/platform/mac/external/wpt/compat/webkit-appearance.tentative-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/external/wpt/compat/webkit-appearance.tentative-expected.txt
deleted file mode 100644
index 70850b5..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/external/wpt/compat/webkit-appearance.tentative-expected.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-This is a testharness.js-based test.
-PASS -webkit-appearance support
-PASS -webkit-appearance support 1
-PASS -webkit-appearance support 2
-PASS -webkit-appearance support 3
-PASS -webkit-appearance support 4
-PASS -webkit-appearance support 5
-PASS -webkit-appearance support 6
-PASS -webkit-appearance support 7
-PASS -webkit-appearance support 8
-PASS -webkit-appearance support 9
-PASS -webkit-appearance support 10
-PASS -webkit-appearance support 11
-PASS -webkit-appearance support 12
-PASS -webkit-appearance support 13
-PASS -webkit-appearance support 14
-PASS -webkit-appearance support 15
-PASS -webkit-appearance support 16
-PASS -webkit-appearance support 17
-PASS -webkit-appearance support 18
-PASS -webkit-appearance support 19
-PASS -webkit-appearance support 20
-PASS -webkit-appearance support 21
-PASS -webkit-appearance support 22
-PASS -webkit-appearance support 23
-PASS -webkit-appearance support 24
-FAIL -webkit-appearance support 25 assert_equals: expected "menulist" but got "menulist-button"
-PASS -webkit-appearance support 26
-PASS -webkit-appearance support 27
-PASS -webkit-appearance support 28
-PASS -webkit-appearance support 29
-PASS -webkit-appearance support 30
-PASS -webkit-appearance support 31
-PASS -webkit-appearance support 32
-PASS -webkit-appearance support 33
-PASS -webkit-appearance support 34
-PASS -webkit-appearance support 35
-PASS -webkit-appearance support 36
-PASS -webkit-appearance support 37
-PASS -webkit-appearance support 38
-PASS -webkit-appearance support 39
-PASS -webkit-appearance support 40
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/common/service_worker/README.md b/third_party/blink/common/service_worker/README.md
new file mode 100644
index 0000000..23f44014
--- /dev/null
+++ b/third_party/blink/common/service_worker/README.md
@@ -0,0 +1,6 @@
+[content/browser/service_worker]: /content/browser/service_worker/README.md
+
+Common process code for service workers. Contains the implementation of
+[third_party/blink/public/common/service_worker](/third_party/blink/public/common/service_worker).
+
+See the main service worker documentation in [content/browser/service_worker].
diff --git a/third_party/blink/public/common/service_worker/README.md b/third_party/blink/public/common/service_worker/README.md
new file mode 100644
index 0000000..08ffb3d
--- /dev/null
+++ b/third_party/blink/public/common/service_worker/README.md
@@ -0,0 +1,6 @@
+[content/browser/service_worker]: /content/browser/service_worker/README.md
+
+Header files for common process code that can be used by both inside Blink and
+outside Blink.
+
+See the main service worker documentation in [content/browser/service_worker].
diff --git a/third_party/blink/public/mojom/service_worker/README.md b/third_party/blink/public/mojom/service_worker/README.md
index 570b660..664c6ce0 100644
--- a/third_party/blink/public/mojom/service_worker/README.md
+++ b/third_party/blink/public/mojom/service_worker/README.md
@@ -1,2 +1,4 @@
 Public mojom files that are referenced both from browser-side and renderer-side
 for [service workers](https://w3c.github.io/ServiceWorker/).
+
+See the main service worker documentation in [content/browser/service_worker].
diff --git a/third_party/blink/public/platform/modules/service_worker/README.md b/third_party/blink/public/platform/modules/service_worker/README.md
new file mode 100644
index 0000000..7c37607
--- /dev/null
+++ b/third_party/blink/public/platform/modules/service_worker/README.md
@@ -0,0 +1,8 @@
+[content/browser/service_worker]: /content/browser/service_worker/README.md
+[Blink Public API]: /third_party/blink/public
+[Onion Soup]: https://docs.google.com/document/d/1K1nO8G9dO9kNSmtVz2gJ2GG9gQOTgm65sJlV3Fga4jE/edit?usp=sharing
+
+[Blink Public API] header files for service workers. This should be removed per
+[Onion Soup].
+
+See the main service worker documentation in [content/browser/service_worker].
diff --git a/third_party/blink/public/web/modules/service_worker/README.md b/third_party/blink/public/web/modules/service_worker/README.md
new file mode 100644
index 0000000..7c37607
--- /dev/null
+++ b/third_party/blink/public/web/modules/service_worker/README.md
@@ -0,0 +1,8 @@
+[content/browser/service_worker]: /content/browser/service_worker/README.md
+[Blink Public API]: /third_party/blink/public
+[Onion Soup]: https://docs.google.com/document/d/1K1nO8G9dO9kNSmtVz2gJ2GG9gQOTgm65sJlV3Fga4jE/edit?usp=sharing
+
+[Blink Public API] header files for service workers. This should be removed per
+[Onion Soup].
+
+See the main service worker documentation in [content/browser/service_worker].
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 4d1f81e..e3438d5 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -305,6 +305,7 @@
     "testing/type_conversions.h",
     "testing/union_types_test.cc",
     "testing/union_types_test.h",
+    "testing/use_mock_scrollbar_settings.h",
     "testing/v8/web_core_test_support.cc",
     "testing/v8/web_core_test_support.h",
     "testing/worker_internals.cc",
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index 6a9f241..049daaa 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -4647,6 +4647,8 @@
   if (ChildNeedsDistributionRecalc() &&
       !insertion_point->ChildNeedsDistributionRecalc())
     insertion_point->MarkAncestorsWithChildNeedsDistributionRecalc();
+  if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache())
+    cache->ChildrenChanged(insertion_point);
   return kInsertionDone;
 }
 
@@ -4659,8 +4661,10 @@
   }
   if (IsInShadowTree() && !ContainingTreeScope().RootNode().IsShadowRoot())
     ClearFlag(kIsInShadowTreeFlag);
-  if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache())
+  if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache()) {
     cache->Remove(this);
+    cache->ChildrenChanged(insertion_point);
+  }
 }
 
 void Element::WillRecalcStyle(StyleRecalcChange) {
diff --git a/third_party/blink/renderer/core/editing/rendered_position_test.cc b/third_party/blink/renderer/core/editing/rendered_position_test.cc
index f2c8217e..f3c86170 100644
--- a/third_party/blink/renderer/core/editing/rendered_position_test.cc
+++ b/third_party/blink/renderer/core/editing/rendered_position_test.cc
@@ -15,7 +15,7 @@
 #include "third_party/blink/renderer/core/layout/layout_box.h"
 #include "third_party/blink/renderer/core/paint/compositing/composited_selection.h"
 #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
-#include "third_party/blink/renderer/platform/testing/use_mock_scrollbar_settings.h"
+#include "third_party/blink/renderer/core/testing/use_mock_scrollbar_settings.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/core/fetch/body_stream_buffer.cc b/third_party/blink/renderer/core/fetch/body_stream_buffer.cc
index b3ae0c7..063ffe63 100644
--- a/third_party/blink/renderer/core/fetch/body_stream_buffer.cc
+++ b/third_party/blink/renderer/core/fetch/body_stream_buffer.cc
@@ -16,11 +16,11 @@
 #include "third_party/blink/renderer/platform/bindings/exception_code.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
-#include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
 #include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
 #include "third_party/blink/renderer/platform/blob/blob_data.h"
 #include "third_party/blink/renderer/platform/network/encoded_form_data.h"
 #include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 
 namespace blink {
 
@@ -99,10 +99,7 @@
       consumer_(consumer),
       signal_(signal),
       made_from_readable_stream_(false) {
-  v8::Local<v8::Value> body_value = ToV8(this, script_state);
-  DCHECK(!body_value.IsEmpty());
-  DCHECK(body_value->IsObject());
-  v8::Local<v8::Object> body = body_value.As<v8::Object>();
+  RetainWrapperUntilV8WrapperGetReturnedToV8(script_state);
 
   {
     // Leaving an exception pending will cause Blink to crash in the bindings
@@ -115,8 +112,8 @@
           ReadableStreamOperations::CreateReadableStream(script_state, this,
                                                          strategy);
       if (!readable_stream.IsEmpty()) {
-        V8PrivateProperty::GetInternalBodyStream(script_state->GetIsolate())
-            .Set(body, readable_stream.V8Value());
+        stream_.Set(script_state->GetIsolate(),
+                    readable_stream.V8Value().As<v8::Object>());
       } else {
         stream_broken_ = true;
       }
@@ -144,16 +141,11 @@
       script_state_(script_state),
       signal_(nullptr),
       made_from_readable_stream_(true) {
+  RetainWrapperUntilV8WrapperGetReturnedToV8(script_state);
   DCHECK(ReadableStreamOperations::IsReadableStreamForDCheck(script_state,
                                                              stream));
 
-  v8::Local<v8::Value> body_value = ToV8(this, script_state);
-  DCHECK(!body_value.IsEmpty());
-  DCHECK(body_value->IsObject());
-  v8::Local<v8::Object> body = body_value.As<v8::Object>();
-
-  V8PrivateProperty::GetInternalBodyStream(script_state->GetIsolate())
-      .Set(body, stream.V8Value());
+  stream_.Set(script_state->GetIsolate(), stream.V8Value().As<v8::Object>());
 }
 
 ScriptValue BodyStreamBuffer::Stream() {
@@ -161,14 +153,8 @@
   // even if |stream_broken_| is true, so that expected JavaScript attribute
   // behaviour is not changed. User code is still permitted to access the
   // stream even when it has thrown an exception.
-  ScriptState::Scope scope(script_state_);
-  v8::Local<v8::Value> body_value = ToV8(this, script_state_);
-  DCHECK(!body_value.IsEmpty());
-  DCHECK(body_value->IsObject());
-  v8::Local<v8::Object> body = body_value.As<v8::Object>();
-  return ScriptValue(script_state_, V8PrivateProperty::GetInternalBodyStream(
-                                        script_state_->GetIsolate())
-                                        .GetOrUndefined(body));
+  return ScriptValue(script_state_,
+                     stream_.NewLocal(script_state_->GetIsolate()));
 }
 
 scoped_refptr<BlobDataHandle> BodyStreamBuffer::DrainAsBlobDataHandle(
@@ -419,6 +405,7 @@
 
 void BodyStreamBuffer::Trace(blink::Visitor* visitor) {
   visitor->Trace(script_state_);
+  visitor->Trace(stream_);
   visitor->Trace(consumer_);
   visitor->Trace(loader_);
   visitor->Trace(signal_);
@@ -534,6 +521,15 @@
   return result;
 }
 
+void BodyStreamBuffer::RetainWrapperUntilV8WrapperGetReturnedToV8(
+    ScriptState* script_state) {
+  ExecutionContext::From(script_state)
+      ->GetTaskRunner(TaskType::kInternalDefault)
+      ->PostTask(
+          FROM_HERE,
+          WTF::Bind(Noop, ScriptValue(script_state, ToV8(this, script_state))));
+}
+
 BytesConsumer* BodyStreamBuffer::ReleaseHandle(
     ExceptionState& exception_state) {
   DCHECK(!IsStreamLockedForDCheck());
diff --git a/third_party/blink/renderer/core/fetch/body_stream_buffer.h b/third_party/blink/renderer/core/fetch/body_stream_buffer.h
index f3e8e08..4e5e782 100644
--- a/third_party/blink/renderer/core/fetch/body_stream_buffer.h
+++ b/third_party/blink/renderer/core/fetch/body_stream_buffer.h
@@ -16,6 +16,7 @@
 #include "third_party/blink/renderer/core/fetch/bytes_consumer.h"
 #include "third_party/blink/renderer/core/fetch/fetch_data_loader.h"
 #include "third_party/blink/renderer/core/streams/underlying_source_base.h"
+#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
@@ -79,6 +80,14 @@
  private:
   class LoaderClient;
 
+  // We need to keep the wrapper alive in order to make
+  // |Stream()| alive. We can create a wrapper in the constructor, but there is
+  // a chance that GC happens after construction happens before the wrapper is
+  // connected to the value returned to the user in the JS world. This function
+  // posts a task with a ScriptPromise containing the wrapper to avoid that.
+  // TODO(yhirano): Remove this once the unified GC is available.
+  void RetainWrapperUntilV8WrapperGetReturnedToV8(ScriptState*);
+
   BytesConsumer* ReleaseHandle(ExceptionState&);
   void Abort();
   void Close();
@@ -98,7 +107,10 @@
                                         ExceptionState&),
       ExceptionState& exception_state);
 
+  static void Noop(ScriptValue) {}
+
   Member<ScriptState> script_state_;
+  TraceWrapperV8Reference<v8::Object> stream_;
   Member<BytesConsumer> consumer_;
   // We need this member to keep it alive while loading.
   Member<FetchDataLoader> loader_;
diff --git a/third_party/blink/renderer/core/fetch/fetch_request_data.cc b/third_party/blink/renderer/core/fetch/fetch_request_data.cc
index 865d7a6a..de775ac 100644
--- a/third_party/blink/renderer/core/fetch/fetch_request_data.cc
+++ b/third_party/blink/renderer/core/fetch/fetch_request_data.cc
@@ -9,7 +9,6 @@
 #include "third_party/blink/public/platform/web_url_request.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/fetch/blob_bytes_consumer.h"
-#include "third_party/blink/renderer/core/fetch/body_stream_buffer.h"
 #include "third_party/blink/renderer/core/fetch/bytes_consumer.h"
 #include "third_party/blink/renderer/core/fetch/fetch_header_list.h"
 #include "third_party/blink/renderer/core/fetch/form_data_bytes_consumer.h"
diff --git a/third_party/blink/renderer/core/fetch/fetch_request_data.h b/third_party/blink/renderer/core/fetch/fetch_request_data.h
index 2d05fb8..9db2e75 100644
--- a/third_party/blink/renderer/core/fetch/fetch_request_data.h
+++ b/third_party/blink/renderer/core/fetch/fetch_request_data.h
@@ -12,6 +12,7 @@
 #include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h"
 #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h"
 #include "third_party/blink/public/platform/web_url_request.h"
+#include "third_party/blink/renderer/core/fetch/body_stream_buffer.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 #include "third_party/blink/renderer/platform/weborigin/referrer.h"
@@ -22,7 +23,6 @@
 
 namespace blink {
 
-class BodyStreamBuffer;
 class ExceptionState;
 class FetchHeaderList;
 class SecurityOrigin;
@@ -144,7 +144,7 @@
   // FIXME: Support m_useURLCredentialsFlag;
   // FIXME: Support m_redirectCount;
   Tainting response_tainting_;
-  Member<BodyStreamBuffer> buffer_;
+  TraceWrapperMember<BodyStreamBuffer> buffer_;
   String mime_type_;
   String integrity_;
   bool keepalive_;
diff --git a/third_party/blink/renderer/core/fetch/fetch_response_data.cc b/third_party/blink/renderer/core/fetch/fetch_response_data.cc
index e2dc3a0..53ef2e15 100644
--- a/third_party/blink/renderer/core/fetch/fetch_response_data.cc
+++ b/third_party/blink/renderer/core/fetch/fetch_response_data.cc
@@ -5,7 +5,6 @@
 #include "third_party/blink/renderer/core/fetch/fetch_response_data.h"
 
 #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_response.h"
-#include "third_party/blink/renderer/core/fetch/body_stream_buffer.h"
 #include "third_party/blink/renderer/core/fetch/fetch_header_list.h"
 #include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
diff --git a/third_party/blink/renderer/core/fetch/fetch_response_data.h b/third_party/blink/renderer/core/fetch/fetch_response_data.h
index e6f8766..5810fcd 100644
--- a/third_party/blink/renderer/core/fetch/fetch_response_data.h
+++ b/third_party/blink/renderer/core/fetch/fetch_response_data.h
@@ -15,6 +15,7 @@
 #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h"
 #include "third_party/blink/public/platform/web_cors.h"
 #include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/fetch/body_stream_buffer.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
@@ -23,7 +24,6 @@
 
 namespace blink {
 
-class BodyStreamBuffer;
 class ExceptionState;
 class FetchHeaderList;
 class ScriptState;
@@ -116,8 +116,8 @@
   unsigned short status_;
   AtomicString status_message_;
   Member<FetchHeaderList> header_list_;
-  Member<FetchResponseData> internal_response_;
-  Member<BodyStreamBuffer> buffer_;
+  TraceWrapperMember<FetchResponseData> internal_response_;
+  TraceWrapperMember<BodyStreamBuffer> buffer_;
   String mime_type_;
   Time response_time_;
   String cache_storage_cache_name_;
diff --git a/third_party/blink/renderer/core/fetch/form_data_bytes_consumer.cc b/third_party/blink/renderer/core/fetch/form_data_bytes_consumer.cc
index 78783242..48bb0a5 100644
--- a/third_party/blink/renderer/core/fetch/form_data_bytes_consumer.cc
+++ b/third_party/blink/renderer/core/fetch/form_data_bytes_consumer.cc
@@ -13,6 +13,7 @@
 #include "third_party/blink/renderer/platform/blob/blob_data.h"
 #include "third_party/blink/renderer/platform/network/encoded_form_data.h"
 #include "third_party/blink/renderer/platform/network/form_data_encoder.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "third_party/blink/renderer/platform/wtf/text/text_codec.h"
 #include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/third_party/blink/renderer/core/fetch/request.cc b/third_party/blink/renderer/core/fetch/request.cc
index eb639a94..02ec1862 100644
--- a/third_party/blink/renderer/core/fetch/request.cc
+++ b/third_party/blink/renderer/core/fetch/request.cc
@@ -29,7 +29,6 @@
 #include "third_party/blink/renderer/core/loader/threadable_loader.h"
 #include "third_party/blink/renderer/core/url/url_search_params.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
 #include "third_party/blink/renderer/platform/blob/blob_data.h"
 #include "third_party/blink/renderer/platform/loader/cors/cors.h"
 #include "third_party/blink/renderer/platform/loader/fetch/fetch_utils.h"
@@ -548,10 +547,8 @@
   }
 
   // "Set |r|'s request's body to |temporaryBody|.
-  if (temporary_body) {
+  if (temporary_body)
     r->request_->SetBuffer(temporary_body);
-    r->RefreshBody(script_state);
-  }
 
   // "Set |r|'s MIME type to the result of extracting a MIME type from |r|'s
   // request's header list."
@@ -566,7 +563,6 @@
     // "Set |input|'s request's body to a new body whose stream is
     // |dummyStream|."
     input_request->request_->SetBuffer(dummy_stream);
-    input_request->RefreshBody(script_state);
     // "Let |reader| be the result of getting reader from |dummyStream|."
     // "Read all bytes from |dummyStream| with |reader|."
     input_request->BodyBuffer()->CloseAndLockAndDisturb(exception_state);
@@ -653,7 +649,6 @@
       request_(request),
       headers_(headers),
       signal_(signal) {
-  RefreshBody(script_state);
 }
 
 Request::Request(ScriptState* script_state, FetchRequestData* request)
@@ -865,7 +860,6 @@
   FetchRequestData* request = request_->Clone(script_state, exception_state);
   if (exception_state.HadException())
     return nullptr;
-  RefreshBody(script_state);
   Headers* headers = Headers::Create(request->HeaderList());
   headers->SetGuard(headers_->GetGuard());
   auto* signal = new AbortSignal(ExecutionContext::From(script_state));
@@ -879,7 +873,6 @@
   FetchRequestData* data = request_->Pass(script_state, exception_state);
   if (exception_state.HadException())
     return nullptr;
-  RefreshBody(script_state);
   // |data|'s buffer('s js wrapper) has no retainer, but it's OK because
   // the only caller is the fetch function and it uses the body buffer
   // immediately.
@@ -931,21 +924,6 @@
   return result;
 }
 
-void Request::RefreshBody(ScriptState* script_state) {
-  v8::Local<v8::Value> request = ToV8(this, script_state);
-  if (request.IsEmpty()) {
-    // |toV8| can return an empty handle when the worker is terminating.
-    // We don't want the renderer to crash in such cases.
-    // TODO(yhirano): Delete this block after the graceful shutdown
-    // mechanism is introduced.
-    return;
-  }
-  DCHECK(request->IsObject());
-  v8::Local<v8::Value> body_buffer = ToV8(this->BodyBuffer(), script_state);
-  V8PrivateProperty::GetInternalBodyBuffer(script_state->GetIsolate())
-      .Set(request.As<v8::Object>(), body_buffer);
-}
-
 void Request::Trace(blink::Visitor* visitor) {
   Body::Trace(visitor);
   visitor->Trace(request_);
diff --git a/third_party/blink/renderer/core/fetch/request.h b/third_party/blink/renderer/core/fetch/request.h
index f9eea3f9..a4a4471 100644
--- a/third_party/blink/renderer/core/fetch/request.h
+++ b/third_party/blink/renderer/core/fetch/request.h
@@ -101,9 +101,8 @@
 
   String ContentType() const override;
   String MimeType() const override;
-  void RefreshBody(ScriptState*);
 
-  const Member<FetchRequestData> request_;
+  const TraceWrapperMember<FetchRequestData> request_;
   const Member<Headers> headers_;
   const Member<AbortSignal> signal_;
   DISALLOW_COPY_AND_ASSIGN(Request);
diff --git a/third_party/blink/renderer/core/fetch/response.cc b/third_party/blink/renderer/core/fetch/response.cc
index a318ca6..61d0c955 100644
--- a/third_party/blink/renderer/core/fetch/response.cc
+++ b/third_party/blink/renderer/core/fetch/response.cc
@@ -33,7 +33,6 @@
 #include "third_party/blink/renderer/platform/bindings/exception_messages.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
-#include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
 #include "third_party/blink/renderer/platform/loader/cors/cors.h"
 #include "third_party/blink/renderer/platform/loader/fetch/fetch_utils.h"
 #include "third_party/blink/renderer/platform/network/encoded_form_data.h"
@@ -325,7 +324,6 @@
       return nullptr;
     }
     r->response_->ReplaceBodyStreamBuffer(body);
-    r->RefreshBody(script_state);
     if (!content_type.IsEmpty() &&
         !r->response_->HeaderList()->Has("Content-Type"))
       r->response_->HeaderList()->Append("Content-Type", content_type);
@@ -465,7 +463,6 @@
   FetchResponseData* response = response_->Clone(script_state, exception_state);
   if (exception_state.HadException())
     return nullptr;
-  RefreshBody(script_state);
   Headers* headers = Headers::Create(response->HeaderList());
   headers->SetGuard(headers_->GetGuard());
   return new Response(GetExecutionContext(), response, headers);
@@ -501,9 +498,7 @@
 Response::Response(ExecutionContext* context,
                    FetchResponseData* response,
                    Headers* headers)
-    : Body(context), response_(response), headers_(headers) {
-  InstallBody();
-}
+    : Body(context), response_(response), headers_(headers) {}
 
 bool Response::HasBody() const {
   return response_->InternalBuffer();
@@ -539,27 +534,6 @@
   return response_->InternalURLList();
 }
 
-void Response::InstallBody() {
-  if (!InternalBodyBuffer())
-    return;
-  RefreshBody(InternalBodyBuffer()->GetScriptState());
-}
-
-void Response::RefreshBody(ScriptState* script_state) {
-  v8::Local<v8::Value> body_buffer = ToV8(InternalBodyBuffer(), script_state);
-  v8::Local<v8::Value> response = ToV8(this, script_state);
-  if (response.IsEmpty()) {
-    // |toV8| can return an empty handle when the worker is terminating.
-    // We don't want the renderer to crash in such cases.
-    // TODO(yhirano): Delete this block after the graceful shutdown
-    // mechanism is introduced.
-    return;
-  }
-  DCHECK(response->IsObject());
-  V8PrivateProperty::GetInternalBodyBuffer(script_state->GetIsolate())
-      .Set(response.As<v8::Object>(), body_buffer);
-}
-
 void Response::Trace(blink::Visitor* visitor) {
   Body::Trace(visitor);
   visitor->Trace(response_);
diff --git a/third_party/blink/renderer/core/fetch/response.h b/third_party/blink/renderer/core/fetch/response.h
index 24a50fa..33463f8 100644
--- a/third_party/blink/renderer/core/fetch/response.h
+++ b/third_party/blink/renderer/core/fetch/response.h
@@ -113,10 +113,7 @@
   Response(ExecutionContext*, FetchResponseData*);
   Response(ExecutionContext*, FetchResponseData*, Headers*);
 
-  void InstallBody();
-  void RefreshBody(ScriptState*);
-
-  const Member<FetchResponseData> response_;
+  const TraceWrapperMember<FetchResponseData> response_;
   const Member<Headers> headers_;
   DISALLOW_COPY_AND_ASSIGN(Response);
 };
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.h b/third_party/blink/renderer/core/frame/frame_test_helpers.h
index 14dae42b..76bf5d08 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.h
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.h
@@ -55,9 +55,9 @@
 #include "third_party/blink/public/web/web_view_client.h"
 #include "third_party/blink/renderer/core/exported/web_view_impl.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
+#include "third_party/blink/renderer/core/testing/use_mock_scrollbar_settings.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/scroll/scrollbar_theme.h"
-#include "third_party/blink/renderer/platform/testing/use_mock_scrollbar_settings.h"
 
 #define EXPECT_FLOAT_POINT_EQ(expected, actual)    \
   do {                                             \
diff --git a/third_party/blink/renderer/core/frame/visual_viewport.cc b/third_party/blink/renderer/core/frame/visual_viewport.cc
index ef85c8c8..512a3209 100644
--- a/third_party/blink/renderer/core/frame/visual_viewport.cc
+++ b/third_party/blink/renderer/core/frame/visual_viewport.cc
@@ -992,6 +992,10 @@
   return GetPage().GetScrollbarTheme();
 }
 
+void VisualViewport::SetOverlayScrollbarsHidden(bool hidden) {
+  ScrollableArea::SetScrollbarsHiddenIfOverlay(hidden);
+}
+
 String VisualViewport::DebugName(const GraphicsLayer* graphics_layer) const {
   String name;
   if (graphics_layer == inner_viewport_container_layer_.get()) {
@@ -1015,4 +1019,11 @@
   return name;
 }
 
+const ScrollableArea* VisualViewport::GetScrollableAreaForTesting(
+    const GraphicsLayer* layer) const {
+  if (layer == inner_viewport_scroll_layer_.get())
+    return this;
+  return nullptr;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/visual_viewport.h b/third_party/blink/renderer/core/frame/visual_viewport.h
index 77fdb9a3..6f10824 100644
--- a/third_party/blink/renderer/core/frame/visual_viewport.h
+++ b/third_party/blink/renderer/core/frame/visual_viewport.h
@@ -286,8 +286,12 @@
                      GraphicsContext&,
                      GraphicsLayerPaintingPhase,
                      const IntRect&) const override;
+  void SetOverlayScrollbarsHidden(bool) override;
   String DebugName(const GraphicsLayer*) const override;
 
+  const ScrollableArea* GetScrollableAreaForTesting(
+      const GraphicsLayer*) const override;
+
   void SetupScrollbar(ScrollbarOrientation);
 
   void NotifyRootFrameViewport() const;
diff --git a/third_party/blink/renderer/core/layout/layout_table.cc b/third_party/blink/renderer/core/layout/layout_table.cc
index ea02f9a..d123137 100644
--- a/third_party/blink/renderer/core/layout/layout_table.cc
+++ b/third_party/blink/renderer/core/layout/layout_table.cc
@@ -1008,9 +1008,13 @@
   table_layout_->ApplyPreferredLogicalWidthQuirks(min_preferred_logical_width_,
                                                   max_preferred_logical_width_);
 
-  for (unsigned i = 0; i < captions_.size(); i++)
+  for (unsigned i = 0; i < captions_.size(); i++) {
     min_preferred_logical_width_ = std::max(
         min_preferred_logical_width_, captions_[i]->MinPreferredLogicalWidth());
+    // Note: using captions' min-width is intentional here:
+    max_preferred_logical_width_ = std::max(
+        max_preferred_logical_width_, captions_[i]->MinPreferredLogicalWidth());
+  }
 
   const ComputedStyle& style_to_use = StyleRef();
   // FIXME: This should probably be checking for isSpecified since you should be
@@ -1036,10 +1040,17 @@
         std::min(max_preferred_logical_width_,
                  AdjustContentBoxLogicalWidthForBoxSizing(
                      style_to_use.LogicalMaxWidth().Value()));
-    max_preferred_logical_width_ =
-        std::max(min_preferred_logical_width_, max_preferred_logical_width_);
   }
 
+  // 2 cases need this:
+  // 1. When max_preferred_logical_width is shrunk to the specified max-width in
+  //    the block above but max-width < min_preferred_logical_width.
+  // 2. We buggily calculate min > max for some tables with colspans and
+  //    percent widths. See fast/table/spans-min-greater-than-max-crash.html and
+  //    http://crbug.com/857185
+  max_preferred_logical_width_ =
+      std::max(min_preferred_logical_width_, max_preferred_logical_width_);
+
   // FIXME: We should be adding borderAndPaddingLogicalWidth here, but
   // m_tableLayout->computePreferredLogicalWidths already does, so a bunch of
   // tests break doing this naively.
diff --git a/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.cc b/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.cc
index e541c50e..b7cd49d 100644
--- a/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.cc
+++ b/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.cc
@@ -69,4 +69,17 @@
   return ToLayoutText(FirstChild())->GetText();
 }
 
+bool LayoutNGListMarker::NeedsOccupyWholeLine() const {
+  if (!GetDocument().InQuirksMode())
+    return false;
+
+  LayoutObject* next_sibling = NextSibling();
+  if (next_sibling && next_sibling->GetNode() &&
+      (IsHTMLUListElement(*next_sibling->GetNode()) ||
+       IsHTMLOListElement(*next_sibling->GetNode())))
+    return true;
+
+  return false;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.h b/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.h
index 059ff29..469de1b 100644
--- a/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.h
+++ b/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.h
@@ -42,6 +42,8 @@
 
   LayoutNGListItem* ListItem() const;
 
+  bool NeedsOccupyWholeLine() const;
+
  private:
   bool IsOfType(LayoutObjectType) const override;
 };
diff --git a/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.h b/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.h
index d80de887..e6166ea6 100644
--- a/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.h
+++ b/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.h
@@ -59,10 +59,10 @@
   LayoutUnit AddToBoxWithoutLineBoxes(const NGConstraintSpace&,
                                       FontBaseline,
                                       NGFragmentBuilder*) const;
+  LayoutUnit InlineOffset(const LayoutUnit marker_inline_size) const;
 
  private:
   bool IsImage() const;
-  LayoutUnit InlineOffset(const LayoutUnit marker_inline_size) const;
 
   scoped_refptr<NGLayoutResult> Layout(const NGConstraintSpace&,
                                        FontBaseline) const;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
index 1107ae9..7620a8a 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
@@ -12,6 +12,7 @@
 #include "third_party/blink/renderer/core/layout/layout_object.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.h"
 #include "third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
@@ -257,10 +258,7 @@
           Style().GetWritingMode(), child, child_input,
           optional_constraint_space);
     }
-    // TODO(crbug.com/857185): The following DCHECK can't be enabled because
-    // tables keep hitting it.
-    // DCHECK_LE(child_sizes.min_size, child_sizes.max_size)
-    //     << child.ToString();
+    DCHECK_LE(child_sizes.min_size, child_sizes.max_size) << child.ToString();
 
     // Determine the max inline contribution of the child.
     NGBoxStrut margins = ComputeMinMaxMargins(Style(), child);
@@ -503,7 +501,9 @@
     } else if (child.IsFloating()) {
       HandleFloat(previous_inflow_position, ToNGBlockNode(child),
                   ToNGBlockBreakToken(child_break_token));
-    } else if (child.IsListMarker()) {
+    } else if (child.IsListMarker() &&
+               !ToLayoutNGListMarker(child.GetLayoutBox())
+                    ->NeedsOccupyWholeLine()) {
       container_builder_.SetUnpositionedListMarker(
           NGUnpositionedListMarker(ToNGBlockNode(child)));
     } else {
@@ -889,8 +889,18 @@
   // pretend that computed margins are 0 here, as they have already been
   // excluded from the layout opportunity rectangle.
   NGBoxStrut auto_margins;
-  ResolveInlineMargins(child_style, Style(), opportunity.rect.InlineSize(),
-                       fragment.InlineSize(), &auto_margins);
+  if (child.IsListMarker() &&
+      ToLayoutNGListMarker(child.GetLayoutBox())->NeedsOccupyWholeLine()) {
+    // Deal with marker's margin. It happens only when marker
+    // NeedsOccupyWholeLine().
+    auto_margins.inline_start = NGUnpositionedListMarker(ToNGBlockNode(child))
+                                    .InlineOffset(fragment.InlineSize());
+    auto_margins.inline_end = opportunity.rect.InlineSize() -
+                              fragment.InlineSize() - auto_margins.inline_start;
+  } else {
+    ResolveInlineMargins(child_style, Style(), opportunity.rect.InlineSize(),
+                         fragment.InlineSize(), &auto_margins);
+  }
 
   NGBfcOffset child_bfc_offset(opportunity.rect.start_offset.line_offset +
                                    auto_margins.LineLeft(direction),
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
index ab09f620..ecc0b55 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
@@ -293,11 +293,27 @@
   WritingMode container_writing_mode(container_info.style->GetWritingMode());
   WritingMode descendant_writing_mode(descendant.node.Style().GetWritingMode());
 
-  // Adjust the static_position origin. The static_position coordinate origin is
-  // relative to the container's border box, ng_absolute_utils expects it to be
-  // relative to the container's padding box.
+  // Adjust the static_position origin.
+  // The static_position coordinate origin is relative to default_container's
+  // border box.
+  // ng_absolute_utils expects static position to be relative to
+  // the container's padding box.
+  // Adjust static position by offset of container from default container,
+  // and default_container border width.
   NGStaticPosition static_position(descendant.static_position);
-  static_position.offset -= default_containing_block_.content_physical_offset;
+  NGPhysicalSize default_containing_block_physical_size =
+      default_containing_block_.content_size.ConvertToPhysical(
+          default_containing_block_.style->GetWritingMode());
+  NGPhysicalOffset default_container_physical_offset =
+      container_info.default_container_offset.ConvertToPhysical(
+          default_containing_block_.style->GetWritingMode(),
+          default_containing_block_.style->Direction(),
+          default_containing_block_physical_size,
+          default_containing_block_physical_size);
+
+  static_position.offset = static_position.offset -
+                           default_containing_block_.content_physical_offset -
+                           default_container_physical_offset;
 
   // The block estimate is in the descendant's writing mode.
   scoped_refptr<NGConstraintSpace> descendant_constraint_space =
diff --git a/third_party/blink/renderer/core/layout/scrollbars_test.cc b/third_party/blink/renderer/core/layout/scrollbars_test.cc
index 376a48caf..e35ef1a 100644
--- a/third_party/blink/renderer/core/layout/scrollbars_test.cc
+++ b/third_party/blink/renderer/core/layout/scrollbars_test.cc
@@ -1898,7 +1898,6 @@
   document.UpdateStyleAndLayout();
 
   EXPECT_FALSE(paint_layer->GetScrollableArea());
-  EXPECT_FALSE(graphics_layer->GetScrollableArea());
 }
 
 TEST_F(ScrollbarsTest, OverlayScrollbarHitTest) {
diff --git a/third_party/blink/renderer/core/loader/image_loader.cc b/third_party/blink/renderer/core/loader/image_loader.cc
index 678a3cc0..59be0be3 100644
--- a/third_party/blink/renderer/core/loader/image_loader.cc
+++ b/third_party/blink/renderer/core/loader/image_loader.cc
@@ -111,7 +111,7 @@
       return;
     ExecutionContext& context = loader_->GetElement()->GetDocument();
     probe::AsyncTask async_task(&context, this);
-    if (script_state_->ContextIsValid()) {
+    if (script_state_ && script_state_->ContextIsValid()) {
       ScriptState::Scope scope(script_state_);
       loader_->DoUpdateFromElement(should_bypass_main_world_csp_,
                                    update_behavior_, request_url_,
@@ -135,8 +135,7 @@
   WeakPersistent<ImageLoader> loader_;
   BypassMainWorldBehavior should_bypass_main_world_csp_;
   UpdateFromElementBehavior update_behavior_;
-  // TODO(peria): Make |script_state_| WeakPersistent.
-  Persistent<ScriptState> script_state_;
+  WeakPersistent<ScriptState> script_state_;
   ReferrerPolicy referrer_policy_;
   KURL request_url_;
   base::WeakPtrFactory<Task> weak_factory_;
diff --git a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc
index c084ec5..191e2407 100644
--- a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc
+++ b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc
@@ -514,7 +514,7 @@
 bool ScrollingCoordinator::UpdateCompositedScrollOffset(
     ScrollableArea* scrollable_area) {
   GraphicsLayer* scroll_layer = scrollable_area->LayerForScrolling();
-  if (!scroll_layer || scroll_layer->GetScrollableArea() != scrollable_area)
+  if (!scroll_layer)
     return false;
 
   cc::Layer* cc_layer =
@@ -532,10 +532,6 @@
   if (!page_ || !page_->MainFrame())
     return false;
 
-  GraphicsLayer* scroll_layer = scrollable_area->LayerForScrolling();
-  if (scroll_layer)
-    scroll_layer->SetScrollableArea(scrollable_area);
-
   UpdateUserInputScrollable(scrollable_area);
 
   cc::Layer* cc_layer =
@@ -957,29 +953,26 @@
 void ScrollingCoordinator::SetShouldUpdateScrollLayerPositionOnMainThread(
     LocalFrame* frame,
     MainThreadScrollingReasons main_thread_scrolling_reasons) {
-  GraphicsLayer* visual_viewport_layer =
-      frame->GetPage()->GetVisualViewport().ScrollLayer();
+  VisualViewport& visual_viewport = frame->GetPage()->GetVisualViewport();
+  GraphicsLayer* visual_viewport_layer = visual_viewport.ScrollLayer();
   cc::Layer* visual_viewport_scroll_layer =
       GraphicsLayerToCcLayer(visual_viewport_layer);
-  GraphicsLayer* layer = frame->View()->LayoutViewport()->LayerForScrolling();
+  ScrollableArea* scrollable_area = frame->View()->LayoutViewport();
+  GraphicsLayer* layer = scrollable_area->LayerForScrolling();
   if (cc::Layer* scroll_layer = GraphicsLayerToCcLayer(layer)) {
     if (main_thread_scrolling_reasons) {
-      ScrollableArea* scrollable_area = layer->GetScrollableArea();
-      if (scrollable_area) {
-        if (ScrollAnimatorBase* scroll_animator =
-                scrollable_area->ExistingScrollAnimator()) {
-          DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled() ||
-                 frame->GetDocument()->Lifecycle().GetState() >=
-                     DocumentLifecycle::kCompositingClean);
-          scroll_animator->TakeOverCompositorAnimation();
-        }
+      if (ScrollAnimatorBase* scroll_animator =
+              scrollable_area->ExistingScrollAnimator()) {
+        DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled() ||
+               frame->GetDocument()->Lifecycle().GetState() >=
+                   DocumentLifecycle::kCompositingClean);
+        scroll_animator->TakeOverCompositorAnimation();
       }
       scroll_layer->AddMainThreadScrollingReasons(
           main_thread_scrolling_reasons);
       if (visual_viewport_scroll_layer) {
         if (ScrollAnimatorBase* scroll_animator =
-                visual_viewport_layer->GetScrollableArea()
-                    ->ExistingScrollAnimator()) {
+                visual_viewport.ExistingScrollAnimator()) {
           DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled() ||
                  frame->GetDocument()->Lifecycle().GetState() >=
                      DocumentLifecycle::kCompositingClean);
diff --git a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc
index 910895af..1e48ae9 100644
--- a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc
@@ -1125,11 +1125,6 @@
   ASSERT_TRUE(composited_layer_mapping->HasScrollingLayer());
   DCHECK(composited_layer_mapping->ScrollingContentsLayer());
 
-  GraphicsLayer* graphics_layer =
-      composited_layer_mapping->ScrollingContentsLayer();
-  ASSERT_EQ(box->Layer()->GetScrollableArea(),
-            graphics_layer->GetScrollableArea());
-
   cc::Layer* cc_scroll_layer =
       composited_layer_mapping->ScrollingContentsLayer()->CcLayer();
   ASSERT_TRUE(cc_scroll_layer->scrollable());
@@ -1171,11 +1166,6 @@
   ASSERT_TRUE(composited_layer_mapping->HasScrollingLayer());
   DCHECK(composited_layer_mapping->ScrollingContentsLayer());
 
-  GraphicsLayer* graphics_layer =
-      composited_layer_mapping->ScrollingContentsLayer();
-  ASSERT_EQ(box->Layer()->GetScrollableArea(),
-            graphics_layer->GetScrollableArea());
-
   cc::Layer* cc_scroll_layer =
       composited_layer_mapping->ScrollingContentsLayer()->CcLayer();
   ASSERT_TRUE(cc_scroll_layer->scrollable());
@@ -1198,10 +1188,6 @@
   ASSERT_TRUE(composited_layer_mapping->HasScrollingLayer());
   DCHECK(composited_layer_mapping->ScrollingContentsLayer());
 
-  graphics_layer = composited_layer_mapping->ScrollingContentsLayer();
-  ASSERT_EQ(box->Layer()->GetScrollableArea(),
-            graphics_layer->GetScrollableArea());
-
   cc_scroll_layer =
       composited_layer_mapping->ScrollingContentsLayer()->CcLayer();
   ASSERT_TRUE(cc_scroll_layer->scrollable());
@@ -1242,8 +1228,6 @@
   GraphicsLayer* scroll_layer =
       inner_frame_view->LayoutViewport()->LayerForScrolling();
   ASSERT_TRUE(scroll_layer);
-  ASSERT_EQ(inner_frame_view->LayoutViewport(),
-            scroll_layer->GetScrollableArea());
 
   cc::Layer* cc_scroll_layer = scroll_layer->CcLayer();
   ASSERT_TRUE(cc_scroll_layer->scrollable());
@@ -1294,8 +1278,6 @@
   GraphicsLayer* scroll_layer =
       inner_frame_view->LayoutViewport()->LayerForScrolling();
   ASSERT_TRUE(scroll_layer);
-  ASSERT_EQ(inner_frame_view->LayoutViewport(),
-            scroll_layer->GetScrollableArea());
 
   cc::Layer* cc_scroll_layer = scroll_layer->CcLayer();
   ASSERT_TRUE(cc_scroll_layer->scrollable());
@@ -1475,8 +1457,6 @@
   GraphicsLayer* scroll_layer =
       inner_frame_view->LayoutViewport()->LayerForScrolling();
   ASSERT_TRUE(scroll_layer);
-  ASSERT_EQ(inner_frame_view->LayoutViewport(),
-            scroll_layer->GetScrollableArea());
 
   cc::Layer* cc_scroll_layer = scroll_layer->CcLayer();
   ASSERT_TRUE(cc_scroll_layer->scrollable());
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
index 8b6e787..6f21725a 100644
--- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
+++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
@@ -3516,6 +3516,11 @@
       ->IsTrackingPaintInvalidations();
 }
 
+void CompositedLayerMapping::SetOverlayScrollbarsHidden(bool hidden) {
+  if (ScrollableArea* scrollable_area = owning_layer_.GetScrollableArea())
+    scrollable_area->SetScrollbarsHiddenIfOverlay(hidden);
+}
+
 #if DCHECK_IS_ON()
 void CompositedLayerMapping::VerifyNotPainting() {
   DCHECK(!GetLayoutObject().GetFrame()->GetPage() ||
@@ -3707,4 +3712,11 @@
   return name;
 }
 
+const ScrollableArea* CompositedLayerMapping::GetScrollableAreaForTesting(
+    const GraphicsLayer* layer) const {
+  if (layer == scrolling_contents_layer_.get())
+    return owning_layer_.GetScrollableArea();
+  return nullptr;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h
index 30da522..36ca4fc 100644
--- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h
+++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h
@@ -214,6 +214,7 @@
                      const IntRect& interest_rect) const override;
   bool ShouldThrottleRendering() const override;
   bool IsTrackingRasterInvalidations() const override;
+  void SetOverlayScrollbarsHidden(bool) override;
 
 #if DCHECK_IS_ON()
   void VerifyNotPainting() override;
@@ -271,6 +272,9 @@
 
   String DebugName(const GraphicsLayer*) const override;
 
+  const ScrollableArea* GetScrollableAreaForTesting(
+      const GraphicsLayer*) const override;
+
   LayoutSize ContentOffsetInCompositingLayer() const;
 
   // Returned value does not include any composited scroll offset of
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater_test.cc b/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater_test.cc
index 61ef996..3e99fbd 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater_test.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater_test.cc
@@ -10,8 +10,8 @@
 #include "third_party/blink/renderer/core/paint/paint_layer.h"
 #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
 #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
+#include "third_party/blink/renderer/core/testing/use_mock_scrollbar_settings.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
-#include "third_party/blink/renderer/platform/testing/use_mock_scrollbar_settings.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.cc b/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.cc
index f029c2a..ee6e788 100644
--- a/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.cc
+++ b/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.cc
@@ -17,12 +17,20 @@
 
 typedef HashMap<int, int> RenderingContextMap;
 
-static String PointerAsString(const void* ptr) {
+String PointerAsString(const void* ptr) {
   WTF::TextStream ts;
   ts << ptr;
   return ts.Release();
 }
 
+FloatPoint ScrollPosition(const GraphicsLayer& layer) {
+  if (const auto* scrollable_area =
+          layer.Client().GetScrollableAreaForTesting(&layer)) {
+    return scrollable_area->ScrollPosition();
+  }
+  return FloatPoint();
+}
+
 void AddFlattenInheritedTransformJSON(const GraphicsLayer* layer,
                                       JSONObject& json) {
   if (layer->Parent() && !layer->Parent()->ShouldFlattenTransform())
@@ -112,11 +120,9 @@
     AddTransformJSONProperties(layer, *json, rendering_context_map);
     if (!layer->ShouldFlattenTransform())
       json->SetBoolean("shouldFlattenTransform", false);
-    ScrollableArea* scrollable_area = layer->GetScrollableArea();
-    if (scrollable_area && scrollable_area->ScrollPosition() != FloatPoint()) {
-      json->SetArray("scrollPosition",
-                     PointAsJSONArray(scrollable_area->ScrollPosition()));
-    }
+    FloatPoint scroll_position(ScrollPosition(*layer));
+    if (scroll_position != FloatPoint())
+      json->SetArray("scrollPosition", PointAsJSONArray(scroll_position));
   }
 
   if ((flags & kLayerTreeIncludesPaintInvalidations) &&
@@ -248,12 +254,6 @@
     return result;
   }
 
-  static FloatPoint ScrollPosition(const GraphicsLayer& layer) {
-    if (const auto* scrollable_area = layer.GetScrollableArea())
-      return scrollable_area->ScrollPosition();
-    return FloatPoint();
-  }
-
   void AddLayer(const GraphicsLayer& layer,
                 int& transform_id,
                 FloatPoint& position) {
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
index 9e15562..67dc662 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
@@ -695,7 +695,10 @@
       ToNGPhysicalTextFragment(text_fragment.PhysicalFragment());
   if (physical_text_fragment.TextType() ==
       NGPhysicalTextFragment::kSymbolMarker) {
-    PaintSymbol(text_fragment, paint_info, paint_offset);
+    // The NGInlineItem of marker might be Split(). So PaintSymbol only if the
+    // StartOffset is 0, or it might be painted several times.
+    if (!physical_text_fragment.StartOffset())
+      PaintSymbol(text_fragment, paint_info, paint_offset);
   } else {
     NGTextFragmentPainter text_painter(text_fragment);
     text_painter.Paint(paint_info, paint_offset);
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
index 3cd9fed1..4bf307f 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -221,16 +221,6 @@
   if (SmoothScrollSequencer* sequencer = GetSmoothScrollSequencer())
     sequencer->DidDisposeScrollableArea(*this);
 
-  {
-    // Here using the stale compositing data is in fact what we want to do
-    // because the graphics layer which hasn't been removed yet may be used in
-    // the meantime to try to deliver scroll related updates.
-    DisableCompositingQueryAsserts disabler;
-    GraphicsLayer* graphics_layer = LayerForScrolling();
-    if (graphics_layer)
-      graphics_layer->ScrollableAreaDisposed();
-  }
-
   layer_ = nullptr;
 }
 
diff --git a/third_party/blink/renderer/core/testing/core_unit_test_helper.h b/third_party/blink/renderer/core/testing/core_unit_test_helper.h
index 6cd9a46..1708ced4 100644
--- a/third_party/blink/renderer/core/testing/core_unit_test_helper.h
+++ b/third_party/blink/renderer/core/testing/core_unit_test_helper.h
@@ -16,7 +16,7 @@
 #include "third_party/blink/renderer/core/layout/layout_view.h"
 #include "third_party/blink/renderer/core/loader/empty_clients.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
-#include "third_party/blink/renderer/platform/testing/use_mock_scrollbar_settings.h"
+#include "third_party/blink/renderer/core/testing/use_mock_scrollbar_settings.h"
 #include "third_party/blink/renderer/platform/wtf/allocator.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/platform/testing/use_mock_scrollbar_settings.h b/third_party/blink/renderer/core/testing/use_mock_scrollbar_settings.h
similarity index 88%
rename from third_party/blink/renderer/platform/testing/use_mock_scrollbar_settings.h
rename to third_party/blink/renderer/core/testing/use_mock_scrollbar_settings.h
index 64cb943a..45e00a5 100644
--- a/third_party/blink/renderer/platform/testing/use_mock_scrollbar_settings.h
+++ b/third_party/blink/renderer/core/testing/use_mock_scrollbar_settings.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_USE_MOCK_SCROLLBAR_SETTINGS_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_USE_MOCK_SCROLLBAR_SETTINGS_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_USE_MOCK_SCROLLBAR_SETTINGS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_USE_MOCK_SCROLLBAR_SETTINGS_H_
 
 #include "third_party/blink/renderer/platform/scroll/scrollbar_theme.h"
 #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
@@ -48,4 +48,4 @@
 
 }  // namespace blink
 
-#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_USE_MOCK_SCROLLBAR_SETTINGS_H_
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_USE_MOCK_SCROLLBAR_SETTINGS_H_
diff --git a/third_party/blink/renderer/core/xml/dom_parser.cc b/third_party/blink/renderer/core/xml/dom_parser.cc
index 9676c56..b322ad3a 100644
--- a/third_party/blink/renderer/core/xml/dom_parser.cc
+++ b/third_party/blink/renderer/core/xml/dom_parser.cc
@@ -18,15 +18,39 @@
  */
 
 #include "third_party/blink/renderer/core/xml/dom_parser.h"
-
+#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_html.h"
+#include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/document_init.h"
 #include "third_party/blink/renderer/core/dom/dom_implementation.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_html.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
 namespace blink {
 
-Document* DOMParser::parseFromString(const String& str, const String& type) {
+Document* DOMParser::parseFromString(const StringOrTrustedHTML& stringOrHTML,
+                                     const String& type,
+                                     ExceptionState& exception_state) {
+  DCHECK(stringOrHTML.IsString() ||
+         RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
+  DCHECK(!stringOrHTML.IsNull());
+  if (context_document_ && stringOrHTML.IsString() &&
+      context_document_->RequireTrustedTypes()) {
+    exception_state.ThrowTypeError(
+        "This document requires `TrustedHTML` assignment.");
+    return nullptr;
+  }
+
+  String valueString = stringOrHTML.IsString()
+                           ? stringOrHTML.GetAsString()
+                           : stringOrHTML.GetAsTrustedHTML()->toString();
+
+  return parseFromStringInternal(valueString, type);
+}
+
+Document* DOMParser::parseFromStringInternal(const String& str,
+                                             const String& type) {
   Document* doc = DOMImplementation::createDocument(
       type, DocumentInit::Create().WithContextDocument(context_document_),
       false);
diff --git a/third_party/blink/renderer/core/xml/dom_parser.h b/third_party/blink/renderer/core/xml/dom_parser.h
index cea414f..868e1f9b 100644
--- a/third_party/blink/renderer/core/xml/dom_parser.h
+++ b/third_party/blink/renderer/core/xml/dom_parser.h
@@ -27,6 +27,8 @@
 namespace blink {
 
 class Document;
+class StringOrTrustedHTML;
+class ExceptionState;
 
 class DOMParser final : public ScriptWrappable {
   DEFINE_WRAPPERTYPEINFO();
@@ -35,12 +37,15 @@
   static DOMParser* Create(Document& document) {
     return new DOMParser(document);
   }
-
-  Document* parseFromString(const String&, const String& type);
+  Document* parseFromString(const StringOrTrustedHTML&,
+                            const String& type,
+                            ExceptionState& exception_state);
+  Document* parseFromString(const StringOrTrustedHTML&, const String& type);
 
   void Trace(blink::Visitor*) override;
 
  private:
+  Document* parseFromStringInternal(const String&, const String& type);
   explicit DOMParser(Document&);
 
   WeakMember<Document> context_document_;
diff --git a/third_party/blink/renderer/core/xml/dom_parser.idl b/third_party/blink/renderer/core/xml/dom_parser.idl
index 110d1ee..b478df5 100644
--- a/third_party/blink/renderer/core/xml/dom_parser.idl
+++ b/third_party/blink/renderer/core/xml/dom_parser.idl
@@ -18,6 +18,9 @@
  */
 
 // https://w3c.github.io/DOM-Parsing/#the-domparser-interface
+// The `HTMLString` reference below is from Trusted Types:
+// https://github.com/WICG/trusted-types/, which is still WIP.
+// https://crbug.com/739170.
 
 enum SupportedType {
     "text/html",
@@ -32,5 +35,5 @@
     ConstructorCallWith=Document,
     Exposed=Window
 ] interface DOMParser {
-    [NewObject] Document parseFromString(DOMString str, SupportedType type);
+    [NewObject, RaisesException] Document parseFromString(HTMLString str, SupportedType type);
 };
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
index b76fd3d3..53269b7 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
@@ -1915,18 +1915,6 @@
   return AXNodeObject::CanHaveChildren();
 }
 
-void AXLayoutObject::UpdateChildrenIfNecessary() {
-  if (NeedsToUpdateChildren())
-    ClearChildren();
-
-  AXObject::UpdateChildrenIfNecessary();
-}
-
-void AXLayoutObject::ClearChildren() {
-  AXObject::ClearChildren();
-  children_dirty_ = false;
-}
-
 //
 // Properties of the object's owning document or page.
 //
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.h b/third_party/blink/renderer/modules/accessibility/ax_layout_object.h
index 13ae790..7c97731 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.h
@@ -165,10 +165,6 @@
   AXObject* RawNextSibling() const override;
   void AddChildren() override;
   bool CanHaveChildren() const override;
-  void UpdateChildrenIfNecessary() override;
-  bool NeedsToUpdateChildren() const override { return children_dirty_; }
-  void SetNeedsToUpdateChildren() override { children_dirty_ = true; }
-  void ClearChildren() override;
 
   // Properties of the object's owning document or page.
   double EstimatedLoadingProgress() const override;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
index 571f1e2..6f1ee44 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -2137,6 +2137,11 @@
   }
 }
 
+void AXNodeObject::ClearChildren() {
+  AXObject::ClearChildren();
+  children_dirty_ = false;
+}
+
 bool AXNodeObject::CanHaveChildren() const {
   // If this is an AXLayoutObject, then it's okay if this object
   // doesn't have a node - there are some layoutObjects that don't have
@@ -2422,6 +2427,13 @@
   }
 }
 
+void AXNodeObject::UpdateChildrenIfNecessary() {
+  if (NeedsToUpdateChildren())
+    ClearChildren();
+
+  AXObject::UpdateChildrenIfNecessary();
+}
+
 void AXNodeObject::SelectionChanged() {
   // Post the selected text changed event on the first ancestor that's
   // focused (to handle form controls, ARIA text boxes and contentEditable),
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.h b/third_party/blink/renderer/modules/accessibility/ax_node_object.h
index cfe6489..840aa9c 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_node_object.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.h
@@ -191,6 +191,10 @@
   bool CanHaveChildren() const override;
   void AddChild(AXObject*);
   void InsertChild(AXObject*, unsigned index);
+  void ClearChildren() override;
+  bool NeedsToUpdateChildren() const override { return children_dirty_; }
+  void SetNeedsToUpdateChildren() override { children_dirty_ = true; }
+  void UpdateChildrenIfNecessary() override;
 
   // DOM and Render tree access.
   Element* ActionElement() const override;
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_descriptor.cc b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_descriptor.cc
index 06902813..6e37ea0 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_descriptor.cc
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_descriptor.cc
@@ -11,6 +11,7 @@
 #include "third_party/blink/renderer/modules/bluetooth/bluetooth_error.h"
 #include "third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.h"
 #include "third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_utils.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.cc b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.cc
index 84845cdcf..5f04057 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.cc
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.cc
@@ -13,6 +13,7 @@
 #include "third_party/blink/renderer/modules/bluetooth/bluetooth_error.h"
 #include "third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.h"
 #include "third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/modules/budget/budget_service.cc b/third_party/blink/renderer/modules/budget/budget_service.cc
index ff00240..97471dab 100644
--- a/third_party/blink/renderer/modules/budget/budget_service.cc
+++ b/third_party/blink/renderer/modules/budget/budget_service.cc
@@ -13,6 +13,7 @@
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/modules/budget/budget_state.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 
 namespace blink {
 namespace {
diff --git a/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.h b/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.h
index 9425fce..bf83aeb 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.h
+++ b/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.h
@@ -17,6 +17,7 @@
 #include "third_party/blink/public/platform/modules/device_orientation/web_device_motion_listener.h"
 #include "third_party/blink/public/platform/modules/device_orientation/web_device_orientation_listener.h"
 #include "third_party/blink/renderer/platform/timer.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/modules/filesystem/directory_reader.cc b/third_party/blink/renderer/modules/filesystem/directory_reader.cc
index e723ce3e..607b4444 100644
--- a/third_party/blink/renderer/modules/filesystem/directory_reader.cc
+++ b/third_party/blink/renderer/modules/filesystem/directory_reader.cc
@@ -33,6 +33,7 @@
 #include "third_party/blink/renderer/core/fileapi/file_error.h"
 #include "third_party/blink/renderer/modules/filesystem/entry.h"
 #include "third_party/blink/renderer/modules/filesystem/file_system_callbacks.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/modules/filesystem/file_system_callbacks.cc b/third_party/blink/renderer/modules/filesystem/file_system_callbacks.cc
index dd225f05..49f8b95 100644
--- a/third_party/blink/renderer/modules/filesystem/file_system_callbacks.cc
+++ b/third_party/blink/renderer/modules/filesystem/file_system_callbacks.cc
@@ -47,6 +47,7 @@
 #include "third_party/blink/renderer/modules/filesystem/file_writer.h"
 #include "third_party/blink/renderer/modules/filesystem/metadata.h"
 #include "third_party/blink/renderer/platform/file_metadata.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.cc b/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.cc
index c8aef48b..9b353880 100644
--- a/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.cc
+++ b/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.cc
@@ -6,6 +6,7 @@
 
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 
 namespace {
 
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.cc b/third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.cc
index 89cb7b0..cfbe57f 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <utility>
 
+#include "base/callback.h"
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/public/platform/modules/indexeddb/web_idb_cursor.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.h b/third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.h
index a02b249..2cb8f84e 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.h
+++ b/third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "base/callback.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/third_party/blink/renderer/modules/locks/lock.cc b/third_party/blink/renderer/modules/locks/lock.cc
index 5f6be721..05f7c0c5 100644
--- a/third_party/blink/renderer/modules/locks/lock.cc
+++ b/third_party/blink/renderer/modules/locks/lock.cc
@@ -11,6 +11,7 @@
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/modules/locks/lock_manager.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/modules/mediastream/media_devices_test.cc b/third_party/blink/renderer/modules/mediastream/media_devices_test.cc
index e9ba9a0b..8752d09 100644
--- a/third_party/blink/renderer/modules/mediastream/media_devices_test.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_devices_test.cc
@@ -17,6 +17,7 @@
 #include "third_party/blink/renderer/modules/mediastream/media_stream_constraints.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 
 using blink::mojom::blink::MediaDeviceInfoPtr;
 using blink::mojom::blink::MediaDeviceType;
diff --git a/third_party/blink/renderer/modules/payments/payment_manager.cc b/third_party/blink/renderer/modules/payments/payment_manager.cc
index 520b54ad..29517bb 100644
--- a/third_party/blink/renderer/modules/payments/payment_manager.cc
+++ b/third_party/blink/renderer/modules/payments/payment_manager.cc
@@ -10,6 +10,7 @@
 #include "third_party/blink/renderer/modules/payments/payment_instruments.h"
 #include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/modules/service_worker/README.md b/third_party/blink/renderer/modules/service_worker/README.md
new file mode 100644
index 0000000..29fe7fb
--- /dev/null
+++ b/third_party/blink/renderer/modules/service_worker/README.md
@@ -0,0 +1,6 @@
+[content/browser/service_worker]: /content/browser/service_worker/README.md
+
+Renderer process code in Blink for service workers. This is the closest code
+to the web-exposed Service Worker API.
+
+See the main service worker documentation in [content/browser/service_worker].
diff --git a/third_party/blink/renderer/modules/service_worker/fetch_event.cc b/third_party/blink/renderer/modules/service_worker/fetch_event.cc
index 5069bcf..a499d4c 100644
--- a/third_party/blink/renderer/modules/service_worker/fetch_event.cc
+++ b/third_party/blink/renderer/modules/service_worker/fetch_event.cc
@@ -19,7 +19,6 @@
 #include "third_party/blink/renderer/modules/service_worker/service_worker_error.h"
 #include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
-#include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h"
 #include "third_party/blink/renderer/platform/network/network_utils.h"
 
@@ -100,27 +99,7 @@
 
   client_id_ = initializer.clientId();
   is_reload_ = initializer.isReload();
-  if (initializer.hasRequest()) {
-    ScriptState::Scope scope(script_state);
-    request_ = initializer.request();
-    v8::Local<v8::Value> request = ToV8(request_, script_state);
-    v8::Local<v8::Value> event = ToV8(this, script_state);
-    if (event.IsEmpty()) {
-      // |toV8| can return an empty handle when the worker is terminating.
-      // We don't want the renderer to crash in such cases.
-      // TODO(yhirano): Replace this branch with an assertion when the
-      // graceful shutdown mechanism is introduced.
-      return;
-    }
-    DCHECK(event->IsObject());
-    // Sets a hidden value in order to teach V8 the dependency from
-    // the event to the request.
-    V8PrivateProperty::GetFetchEventRequest(script_state->GetIsolate())
-        .Set(event.As<v8::Object>(), request);
-    // From the same reason as above, setHiddenValue can return false.
-    // TODO(yhirano): Add an assertion that it returns true once the
-    // graceful shutdown mechanism is introduced.
-  }
+  request_ = initializer.request();
 }
 
 FetchEvent::~FetchEvent() = default;
diff --git a/third_party/blink/renderer/modules/service_worker/fetch_event.h b/third_party/blink/renderer/modules/service_worker/fetch_event.h
index 5de2dc2d..1bf70d44 100644
--- a/third_party/blink/renderer/modules/service_worker/fetch_event.h
+++ b/third_party/blink/renderer/modules/service_worker/fetch_event.h
@@ -93,7 +93,7 @@
 
  private:
   Member<FetchRespondWithObserver> observer_;
-  Member<Request> request_;
+  TraceWrapperMember<Request> request_;
   Member<PreloadResponseProperty> preload_response_property_;
   std::unique_ptr<WebURLResponse> preload_response_;
   String client_id_;
diff --git a/third_party/blink/renderer/modules/service_worker/respond_with_observer.cc b/third_party/blink/renderer/modules/service_worker/respond_with_observer.cc
index 345ddff..564b748a 100644
--- a/third_party/blink/renderer/modules/service_worker/respond_with_observer.cc
+++ b/third_party/blink/renderer/modules/service_worker/respond_with_observer.cc
@@ -11,6 +11,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/modules/service_worker/wait_until_observer.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "v8/include/v8.h"
 
 using blink::mojom::ServiceWorkerResponseError;
diff --git a/third_party/blink/renderer/modules/webusb/usb_device.cc b/third_party/blink/renderer/modules/webusb/usb_device.cc
index 68601cdc..f74584f 100644
--- a/third_party/blink/renderer/modules/webusb/usb_device.cc
+++ b/third_party/blink/renderer/modules/webusb/usb_device.cc
@@ -22,6 +22,7 @@
 #include "third_party/blink/renderer/modules/webusb/usb_out_transfer_result.h"
 #include "third_party/blink/renderer/platform/mojo/mojo_helper.h"
 #include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 
 using device::mojom::blink::UsbControlTransferParamsPtr;
 using device::mojom::blink::UsbControlTransferType;
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index 2597fd7..28a743a 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -2224,7 +2224,6 @@
     "graphics/offscreen_canvas_frame_dispatcher_test.cc",
     "graphics/test/fake_canvas_resource_host.h",
     "graphics/test/fake_gles2_interface.h",
-    "graphics/test/fake_scrollable_area.h",
     "graphics/test/fake_web_graphics_context_3d_provider.h",
     "graphics/test/mock_image_decoder.h",
     "graphics/test/mock_paint_canvas.h",
diff --git a/third_party/blink/renderer/platform/bindings/v8_private_property.h b/third_party/blink/renderer/platform/bindings/v8_private_property.h
index 128bd76..34ac3831 100644
--- a/third_party/blink/renderer/platform/bindings/v8_private_property.h
+++ b/third_party/blink/renderer/platform/bindings/v8_private_property.h
@@ -20,8 +20,7 @@
 class ScriptWrappable;
 
 // TODO(peria): Remove properties just to keep V8 objects alive.
-// e.g. InternalBody.Buffer, InternalBody.Stream, IDBCursor.Request,
-// FetchEvent.Request.
+// e.g. IDBCursor.Request.
 // Apply |X| for each pair of (InterfaceName, PrivateKeyName).
 #define V8_PRIVATE_PROPERTY_FOR_EACH(X)               \
   X(CustomElement, Document)                          \
@@ -35,11 +34,8 @@
   X(CustomElementLifecycle, DetachedCallback)         \
   X(DOMException, Error)                              \
   X(ErrorEvent, Error)                                \
-  X(FetchEvent, Request)                              \
   X(Global, Event)                                    \
   X(IDBCursor, Request)                               \
-  X(InternalBody, Buffer)                             \
-  X(InternalBody, Stream)                             \
   X(IntersectionObserver, Callback)                   \
   X(MessageChannel, Port1)                            \
   X(MessageChannel, Port2)                            \
diff --git a/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image_test.cc b/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image_test.cc
index ca4a16c2..c806f7e 100644
--- a/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image_test.cc
+++ b/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image_test.cc
@@ -2,12 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h"
+
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h"
 #include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
 #include "third_party/blink/renderer/platform/graphics/test/fake_gles2_interface.h"
 #include "third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "third_party/skia/include/core/SkSurface.h"
 
 using testing::ElementsAreArray;
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.cc b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
index 335fd50e..badd210 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
@@ -15,6 +15,7 @@
 #include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
 #include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
 #include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "third_party/skia/include/gpu/GrContext.h"
 #include "ui/gfx/buffer_format_util.h"
 #include "ui/gfx/color_space.h"
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
index 6787fae0..3218616 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
@@ -55,6 +55,7 @@
 #include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_provider_wrapper.h"
 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h"
 #include "third_party/skia/include/core/SkColorSpaceXform.h"
 #include "third_party/skia/include/core/SkSurface.h"
diff --git a/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc b/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc
index 82deca3..10ff62a 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc
@@ -19,6 +19,7 @@
 #include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
 #include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "ui/gfx/geometry/size.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc b/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc
index c5ba58f..d1f6510 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc
@@ -14,6 +14,7 @@
 #include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
 #include "third_party/blink/renderer/platform/graphics/test/fake_gles2_interface.h"
 #include "third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "third_party/khronos/GLES2/gl2ext.h"
 
 using testing::_;
diff --git a/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc b/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc
index 9a8437c..1cd44fc 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h"
 #include "third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.h"
 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "third_party/skia/include/core/SkSurface.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.cc b/third_party/blink/renderer/platform/graphics/graphics_layer.cc
index c0327d18..07dc0da0 100644
--- a/third_party/blink/renderer/platform/graphics/graphics_layer.cc
+++ b/third_party/blink/renderer/platform/graphics/graphics_layer.cc
@@ -62,7 +62,6 @@
 #include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
 #include "third_party/blink/renderer/platform/scroll/scroll_snap_data.h"
-#include "third_party/blink/renderer/platform/scroll/scrollable_area.h"
 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
 #include "third_party/blink/renderer/platform/wtf/hash_set.h"
 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
@@ -104,7 +103,6 @@
       paint_count_(0),
       contents_layer_(nullptr),
       contents_layer_id_(0),
-      scrollable_area_(nullptr),
       rendering_context3d_(0),
       weak_ptr_factory_(this) {
 #if DCHECK_IS_ON()
@@ -932,16 +930,6 @@
   UpdateChildList();
 }
 
-void GraphicsLayer::SetScrollableArea(ScrollableArea* scrollable_area) {
-  if (scrollable_area_ == scrollable_area)
-    return;
-  scrollable_area_ = scrollable_area;
-}
-
-void GraphicsLayer::ScrollableAreaDisposed() {
-  scrollable_area_.Clear();
-}
-
 std::unique_ptr<base::trace_event::TracedValue> GraphicsLayer::TakeDebugInfo(
     cc::Layer* layer) {
   auto traced_value = std::make_unique<base::trace_event::TracedValue>();
@@ -973,8 +961,7 @@
 }
 
 void GraphicsLayer::DidChangeScrollbarsHiddenIfOverlay(bool hidden) {
-  if (scrollable_area_)
-    scrollable_area_->SetScrollbarsHiddenIfOverlay(hidden);
+  client_.SetOverlayScrollbarsHidden(hidden);
 }
 
 PaintController& GraphicsLayer::GetPaintController() const {
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.h b/third_party/blink/renderer/platform/graphics/graphics_layer.h
index fb91ad52..f675e99 100644
--- a/third_party/blink/renderer/platform/graphics/graphics_layer.h
+++ b/third_party/blink/renderer/platform/graphics/graphics_layer.h
@@ -72,7 +72,6 @@
 class PaintController;
 class RasterInvalidationTracking;
 class RasterInvalidator;
-class ScrollableArea;
 
 typedef Vector<GraphicsLayer*, 64> GraphicsLayerVector;
 
@@ -250,10 +249,6 @@
   unsigned NumLinkHighlights() { return link_highlights_.size(); }
   LinkHighlight* GetLinkHighlight(int i) { return link_highlights_[i]; }
 
-  void SetScrollableArea(ScrollableArea*);
-  ScrollableArea* GetScrollableArea() const { return scrollable_area_; }
-  void ScrollableAreaDisposed();
-
   int GetRenderingContext3D() const { return rendering_context3d_; }
 
   cc::PictureLayer* ContentLayer() const { return layer_.get(); }
@@ -429,7 +424,6 @@
 
   Vector<LinkHighlight*> link_highlights_;
 
-  WeakPersistent<ScrollableArea> scrollable_area_;
   int rendering_context3d_;
 
   CompositingReasons compositing_reasons_ = CompositingReason::kNone;
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer_client.h b/third_party/blink/renderer/platform/graphics/graphics_layer_client.h
index 11e38dc4..7561489f 100644
--- a/third_party/blink/renderer/platform/graphics/graphics_layer_client.h
+++ b/third_party/blink/renderer/platform/graphics/graphics_layer_client.h
@@ -35,6 +35,7 @@
 class GraphicsContext;
 class GraphicsLayer;
 class IntRect;
+class ScrollableArea;
 
 enum GraphicsLayerPaintingPhaseFlags {
   kGraphicsLayerPaintBackground = (1 << 0),
@@ -94,8 +95,15 @@
 
   virtual bool IsTrackingRasterInvalidations() const { return false; }
 
+  virtual void SetOverlayScrollbarsHidden(bool) {}
+
   virtual String DebugName(const GraphicsLayer*) const = 0;
 
+  virtual const ScrollableArea* GetScrollableAreaForTesting(
+      const GraphicsLayer*) const {
+    return nullptr;
+  }
+
 #if DCHECK_IS_ON()
   // CompositedLayerMapping overrides this to verify that it is not
   // currently painting contents. An ASSERT fails, if it is.
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc b/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc
index d2fd8f5..b4aaada 100644
--- a/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc
+++ b/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc
@@ -45,9 +45,7 @@
 #include "third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h"
 #include "third_party/blink/renderer/platform/graphics/paint/property_tree_state.h"
 #include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h"
-#include "third_party/blink/renderer/platform/graphics/test/fake_scrollable_area.h"
 #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
-#include "third_party/blink/renderer/platform/scroll/scrollable_area.h"
 #include "third_party/blink/renderer/platform/testing/fake_graphics_layer.h"
 #include "third_party/blink/renderer/platform/testing/fake_graphics_layer_client.h"
 #include "third_party/blink/renderer/platform/testing/layer_tree_host_embedder.h"
diff --git a/third_party/blink/renderer/platform/graphics/skia_texture_holder.h b/third_party/blink/renderer/platform/graphics/skia_texture_holder.h
index 0cd6ea1..9ccde9d 100644
--- a/third_party/blink/renderer/platform/graphics/skia_texture_holder.h
+++ b/third_party/blink/renderer/platform/graphics/skia_texture_holder.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_SKIA_TEXTURE_HOLDER_H_
 
 #include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
 #include "third_party/blink/renderer/platform/graphics/texture_holder.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 
diff --git a/third_party/blink/renderer/platform/graphics/test/fake_scrollable_area.h b/third_party/blink/renderer/platform/graphics/test/fake_scrollable_area.h
deleted file mode 100644
index 04625e3..0000000
--- a/third_party/blink/renderer/platform/graphics/test/fake_scrollable_area.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_TEST_FAKE_SCROLLABLE_AREA_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_TEST_FAKE_SCROLLABLE_AREA_H_
-
-#include "base/single_thread_task_runner.h"
-#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
-#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
-#include "third_party/blink/renderer/platform/scroll/scrollable_area.h"
-#include "third_party/blink/renderer/platform/scroll/scrollbar_theme_mock.h"
-
-namespace {
-blink::ScrollbarThemeMock scrollbar_theme_;
-}
-
-namespace blink {
-
-class FakeScrollableArea : public GarbageCollectedFinalized<FakeScrollableArea>,
-                           public ScrollableArea {
-  USING_GARBAGE_COLLECTED_MIXIN(FakeScrollableArea);
-
- public:
-  static FakeScrollableArea* Create() { return new FakeScrollableArea; }
-
-  CompositorElementId GetCompositorElementId() const override {
-    return CompositorElementId();
-  }
-  bool IsActive() const override { return false; }
-  bool IsThrottled() const override { return false; }
-  int ScrollSize(ScrollbarOrientation) const override { return 100; }
-  bool IsScrollCornerVisible() const override { return false; }
-  IntRect ScrollCornerRect() const override { return IntRect(); }
-  IntRect VisibleContentRect(
-      IncludeScrollbarsInRect = kExcludeScrollbars) const override {
-    return IntRect(ScrollOffsetInt().Width(), ScrollOffsetInt().Height(), 10,
-                   10);
-  }
-  IntSize ContentsSize() const override { return IntSize(100, 100); }
-  bool ScrollbarsCanBeActive() const override { return false; }
-  IntRect ScrollableAreaBoundingBox() const override { return IntRect(); }
-  void ScrollControlWasSetNeedsPaintInvalidation() override {}
-  bool UserInputScrollable(ScrollbarOrientation) const override { return true; }
-  bool ShouldPlaceVerticalScrollbarOnLeft() const override { return false; }
-  int PageStep(ScrollbarOrientation) const override { return 0; }
-  IntSize MinimumScrollOffsetInt() const override { return IntSize(); }
-  IntSize MaximumScrollOffsetInt() const override {
-    return ContentsSize() - IntSize(VisibleWidth(), VisibleHeight());
-  }
-
-  void UpdateScrollOffset(const ScrollOffset& offset, ScrollType) override {
-    scroll_offset_ = offset;
-  }
-  ScrollOffset GetScrollOffset() const override { return scroll_offset_; }
-  IntSize ScrollOffsetInt() const override {
-    return FlooredIntSize(scroll_offset_);
-  }
-
-  scoped_refptr<base::SingleThreadTaskRunner> GetTimerTaskRunner() const final {
-    if (!timer_task_runner_) {
-      timer_task_runner_ =
-          blink::scheduler::GetSingleThreadTaskRunnerForTesting();
-    }
-    return timer_task_runner_;
-  }
-
-  ScrollbarTheme& GetPageScrollbarTheme() const override {
-    return scrollbar_theme_;
-  }
-
-  void Trace(blink::Visitor* visitor) override {
-    ScrollableArea::Trace(visitor);
-  }
-
- private:
-  ScrollOffset scroll_offset_;
-  mutable scoped_refptr<base::SingleThreadTaskRunner> timer_task_runner_;
-};
-
-}  // namespace blink
-
-#endif  // FakeScrollableArea
diff --git a/third_party/blink/renderer/platform/heap/persistent.h b/third_party/blink/renderer/platform/heap/persistent.h
index 3fbeab3..0b62143 100644
--- a/third_party/blink/renderer/platform/heap/persistent.h
+++ b/third_party/blink/renderer/platform/heap/persistent.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_PERSISTENT_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_PERSISTENT_H_
 
+#include "base/bind.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
 #include "third_party/blink/renderer/platform/heap/member.h"
 #include "third_party/blink/renderer/platform/heap/persistent_node.h"
diff --git a/third_party/blink/renderer/platform/heap/thread_state.h b/third_party/blink/renderer/platform/heap/thread_state.h
index 6ba1d02..063439b2 100644
--- a/third_party/blink/renderer/platform/heap/thread_state.h
+++ b/third_party/blink/renderer/platform/heap/thread_state.h
@@ -42,7 +42,6 @@
 #include "third_party/blink/renderer/platform/wtf/address_sanitizer.h"
 #include "third_party/blink/renderer/platform/wtf/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
-#include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
 #include "third_party/blink/renderer/platform/wtf/hash_set.h"
 #include "third_party/blink/renderer/platform/wtf/linked_hash_set.h"
diff --git a/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc b/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc
index 44de6e79..9a63f9b 100644
--- a/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc
@@ -4,13 +4,14 @@
 
 #include "third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h"
 
+#include "base/metrics/histogram_macros.h"
 #include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
 
 namespace blink {
 
 StaleRevalidationResourceClient::StaleRevalidationResourceClient(
     Resource* stale_resource)
-    : stale_resource_(stale_resource) {}
+    : start_time_(CurrentTimeTicks()), stale_resource_(stale_resource) {}
 
 StaleRevalidationResourceClient::~StaleRevalidationResourceClient() = default;
 
@@ -19,6 +20,13 @@
   if (stale_resource_ && IsMainThread())
     GetMemoryCache()->Remove(stale_resource_);
   ClearResource();
+
+  TimeTicks finish_time = resource->LoadFinishTime();
+  if (!finish_time.is_null()) {
+    UMA_HISTOGRAM_LONG_TIMES(
+        "Blink.ResourceFetcher.StaleWhileRevalidateDuration",
+        finish_time - start_time_);
+  }
 }
 
 void StaleRevalidationResourceClient::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h b/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h
index 2ee9adc9d..6a7b729f 100644
--- a/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h
+++ b/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h
@@ -28,6 +28,7 @@
   String DebugName() const override;
 
  private:
+  base::TimeTicks start_time_;
   // |stale_resource_| is the original resource that will be removed from the
   // MemoryCache when this revalidation request is completed. Note that it is
   // different than the active resource for this resource client which accessed
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index b45c9e3f..4fec277 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1218,7 +1218,7 @@
     {
       name: "StaleWhileRevalidate",
       origin_trial_feature_name: "StaleWhileRevalidate",
-      status: "test",
+      status: "experimental",
     },
     {
       name: "StopInBackground",
diff --git a/third_party/blink/renderer/platform/testing/empty_web_media_player.h b/third_party/blink/renderer/platform/testing/empty_web_media_player.h
index a17044a..ef7511a 100644
--- a/third_party/blink/renderer/platform/testing/empty_web_media_player.h
+++ b/third_party/blink/renderer/platform/testing/empty_web_media_player.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_EMPTY_WEB_MEDIA_PLAYER_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_EMPTY_WEB_MEDIA_PLAYER_H_
 
+#include "base/callback.h"
 #include "third_party/blink/public/platform/web_media_player.h"
 
 namespace cc {
diff --git a/third_party/blink/renderer/platform/testing/unit_test_helpers.cc b/third_party/blink/renderer/platform/testing/unit_test_helpers.cc
index 60235e9..05c5480d3 100644
--- a/third_party/blink/renderer/platform/testing/unit_test_helpers.cc
+++ b/third_party/blink/renderer/platform/testing/unit_test_helpers.cc
@@ -36,6 +36,7 @@
 #include "third_party/blink/public/platform/web_thread.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/shared_buffer.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/platform/wtf/text/movable_string.cc b/third_party/blink/renderer/platform/wtf/text/movable_string.cc
index fdfa440..c193c423 100644
--- a/third_party/blink/renderer/platform/wtf/text/movable_string.cc
+++ b/third_party/blink/renderer/platform/wtf/text/movable_string.cc
@@ -4,13 +4,16 @@
 
 #include "third_party/blink/renderer/platform/wtf/text/movable_string.h"
 
+#include <string.h>
+
 #include "base/metrics/histogram_macros.h"
 
 namespace WTF {
 
 namespace {
 
-bool IsLargeEnough(const StringImpl* impl) {
+template <typename T>
+bool IsLargeEnough(const T* impl) {
   // Don't attempt to park strings smaller than this size.
   static constexpr unsigned int kSizeThreshold = 10000;
   return impl && impl->length() > kSizeThreshold;
@@ -25,18 +28,28 @@
 MovableStringImpl::MovableStringImpl() = default;
 
 MovableStringImpl::MovableStringImpl(scoped_refptr<StringImpl>&& impl)
-    : string_(std::move(impl)), is_parked_(false) {}
+    : is_parked_(false),
+      string_(std::move(impl))
+#if DCHECK_IS_ON()
+      ,
+      parked_string_()
+#endif
+{
+  is_null_ = string_.IsNull();
+  is_8bit_ = is_null_ ? false : string_.Is8Bit();
+  length_ = is_null_ ? 0 : string_.length();
+}
 
 MovableStringImpl::~MovableStringImpl() {
-  MovableStringTable::Instance().Remove(string_.Impl());
+  MovableStringTable::Instance().Remove(this, string_.Impl());
 }
 
 bool MovableStringImpl::Is8Bit() const {
-  return string_.Is8Bit();
+  return is_8bit_;
 }
 
 bool MovableStringImpl::IsNull() const {
-  return string_.IsNull();
+  return is_null_;
 }
 
 const String& MovableStringImpl::ToString() {
@@ -45,13 +58,24 @@
 }
 
 unsigned MovableStringImpl::CharactersSizeInBytes() const {
-  return string_.CharactersSizeInBytes();
+  return length() * (Is8Bit() ? sizeof(LChar) : sizeof(UChar));
 }
 
 bool MovableStringImpl::Park() {
   // Cannot park strings with several references.
-  if (string_.Impl()->HasOneRef()) {
+  if (!is_parked_ && string_.Impl()->HasOneRef()) {
     RecordParkingAction(ParkingAction::kParkedInBackground);
+#if DCHECK_IS_ON()
+    // Since the copy is done before freeing the original data, the two strings
+    // are guaranteed to not have the same address.
+    parked_string_ = string_.IsolatedCopy();
+    // Poison the previous allocation.
+    // |string_| is kept as is to make sure the memory isn't reused.
+    const void* data = Is8Bit()
+                           ? static_cast<const void*>(string_.Characters8())
+                           : static_cast<const void*>(string_.Characters16());
+    memset(const_cast<void*>(data), 0xcc, string_.CharactersSizeInBytes());
+#endif
     is_parked_ = true;
   }
   return is_parked_;
@@ -65,15 +89,20 @@
   RecordParkingAction(backgrounded ? ParkingAction::kUnparkedInBackground
                                    : ParkingAction::kUnparkedInForeground);
   is_parked_ = false;
+#if DCHECK_IS_ON()
+  // string_'s data has the same address as parked_string_.
+  // This enforces MovableStringImpl.ToString().Characthers{8,16}() returning
+  // a different value after Park() / Unpark().
+  string_ = parked_string_;
+  parked_string_ = String();
+#endif
+  MovableStringTable::Instance().OnUnpark(this, string_.Impl());
 }
 
 MovableString::MovableString(scoped_refptr<StringImpl>&& impl) {
-  // Don't move small strings.
-  if (IsLargeEnough(impl.get())) {
-    impl_ = MovableStringTable::Instance().Add(std::move(impl));
-  } else {
+  impl_ = MovableStringTable::Instance().Add(std::move(impl));
+  if (!impl_)
     impl_ = base::MakeRefCounted<MovableStringImpl>(std::move(impl));
-  }
 }
 
 MovableString::~MovableString() = default;
@@ -98,24 +127,45 @@
 
 scoped_refptr<MovableStringImpl> MovableStringTable::Add(
     scoped_refptr<StringImpl>&& string) {
-  StringImpl* raw_ptr = string.get();
-  auto it = table_.find(raw_ptr);
-  if (it != table_.end()) {
+  StringImpl* impl = string.get();
+  if (!IsLargeEnough(impl))
+    return nullptr;
+
+  auto it = unparked_strings_.find(impl);
+  if (it != unparked_strings_.end()) {
     return it->second;
   }
   auto new_movable_string =
       base::MakeRefCounted<MovableStringImpl>(std::move(string));
-  table_.emplace(raw_ptr, new_movable_string.get());
+  unparked_strings_.emplace(impl, new_movable_string.get());
   return new_movable_string;
 }
 
-void MovableStringTable::Remove(StringImpl* string) {
-  if (!IsLargeEnough(string))
+void MovableStringTable::OnUnpark(MovableStringImpl* movable_impl,
+                                  StringImpl* impl) {
+  if (!IsLargeEnough(movable_impl))
     return;
 
-  auto it = table_.find(string);
-  DCHECK(it != table_.end());
-  table_.erase(it);
+  auto it = parked_strings_.find(movable_impl);
+  DCHECK(it != parked_strings_.end());
+  parked_strings_.erase(it);
+  unparked_strings_.emplace(impl, movable_impl);
+}
+
+void MovableStringTable::Remove(MovableStringImpl* movable_impl,
+                                StringImpl* string) {
+  if (!IsLargeEnough(movable_impl))
+    return;
+
+  if (movable_impl->is_parked()) {
+    auto it = parked_strings_.find(movable_impl);
+    DCHECK(it != parked_strings_.end());
+    parked_strings_.erase(it);
+  } else {
+    auto it = unparked_strings_.find(string);
+    DCHECK(it != unparked_strings_.end());
+    unparked_strings_.erase(it);
+  }
 }
 
 void MovableStringTable::SetRendererBackgrounded(bool backgrounded) {
@@ -131,9 +181,20 @@
     return;
 
   size_t total_size = 0, count = 0;
-  for (auto& kv : table_) {
-    MovableStringImpl* str = kv.second;
-    str->Park();
+  for (auto it = unparked_strings_.begin(); it != unparked_strings_.end();) {
+    MovableStringImpl* str = it->second;
+    bool parked = str->Park();
+    if (parked) {
+      parked_strings_.insert(str);
+      it = unparked_strings_.erase(it);
+    } else {
+      ++it;
+      total_size += str->CharactersSizeInBytes();
+      count += 1;
+    }
+  }
+  for (const auto* str : parked_strings_) {
+    DCHECK(str);
     total_size += str->CharactersSizeInBytes();
     count += 1;
   }
@@ -141,7 +202,11 @@
   size_t total_size_kb = total_size / 1000;
   UMA_HISTOGRAM_COUNTS_100000("Memory.MovableStringsTotalSizeKb",
                               total_size_kb);
-  UMA_HISTOGRAM_COUNTS_1000("Memory.MovableStringsCount", table_.size());
+  UMA_HISTOGRAM_COUNTS_1000("Memory.MovableStringsCount", count);
+}
+
+size_t MovableStringTable::Size() const {
+  return parked_strings_.size() + unparked_strings_.size();
 }
 
 }  // namespace WTF
diff --git a/third_party/blink/renderer/platform/wtf/text/movable_string.h b/third_party/blink/renderer/platform/wtf/text/movable_string.h
index 7b943e9b..739de55 100644
--- a/third_party/blink/renderer/platform/wtf/text/movable_string.h
+++ b/third_party/blink/renderer/platform/wtf/text/movable_string.h
@@ -50,7 +50,7 @@
   // See the matching String methods.
   bool Is8Bit() const;
   bool IsNull() const;
-  unsigned length() const { return string_.length(); }
+  unsigned length() const { return length_; }
   unsigned CharactersSizeInBytes() const;
 
   // A parked string cannot be accessed until it has been |Unpark()|-ed.
@@ -62,8 +62,15 @@
  private:
   void Unpark();
 
-  String string_;
+  bool is_null_;
+  bool is_8bit_;
   bool is_parked_;
+  unsigned length_;
+
+  String string_;
+#if DCHECK_IS_ON()
+  String parked_string_;
+#endif
 
   DISALLOW_COPY_AND_ASSIGN(MovableStringImpl);
 };
@@ -106,11 +113,12 @@
   }
 
   scoped_refptr<MovableStringImpl> Add(scoped_refptr<StringImpl>&&);
+  void OnUnpark(MovableStringImpl*, StringImpl*);
 
-  // This is for ~MovableStringImpl to unregister a string before
+  // This is for ~MovableStringImpl() to unregister a string before
   // destruction since the table is holding raw pointers. It should not be used
   // directly.
-  void Remove(StringImpl*);
+  void Remove(MovableStringImpl*, StringImpl*);
 
   void SetRendererBackgrounded(bool backgrounded);
   bool IsRendererBackgrounded() const;
@@ -119,13 +127,17 @@
   void MaybeParkAll();
 
  private:
+  size_t Size() const;
+
   bool backgrounded_;
   // Could bet a set where the hashing function is
   // MovableStringImpl::string_.Impl(), but clearer this way.
-  std::map<StringImpl*, MovableStringImpl*> table_;
+  std::map<StringImpl*, MovableStringImpl*> unparked_strings_;
+  std::set<MovableStringImpl*> parked_strings_;
 
   FRIEND_TEST_ALL_PREFIXES(MovableStringTest, TableSimple);
   FRIEND_TEST_ALL_PREFIXES(MovableStringTest, TableMultiple);
+  FRIEND_TEST_ALL_PREFIXES(MovableStringTest, TableDeduplication);
 
   DISALLOW_COPY_AND_ASSIGN(MovableStringTable);
 };
diff --git a/third_party/blink/renderer/platform/wtf/text/movable_string_test.cc b/third_party/blink/renderer/platform/wtf/text/movable_string_test.cc
index 6eebafc..0451bce 100644
--- a/third_party/blink/renderer/platform/wtf/text/movable_string_test.cc
+++ b/third_party/blink/renderer/platform/wtf/text/movable_string_test.cc
@@ -57,11 +57,22 @@
   base::HistogramTester histogram_tester;
 
   MovableString movable(String("abc").Impl());
+  auto before_address =
+      reinterpret_cast<uintptr_t>(movable.ToString().Characters8());
   EXPECT_FALSE(movable.Impl()->is_parked());
   EXPECT_TRUE(movable.Impl()->Park());
   EXPECT_TRUE(movable.Impl()->is_parked());
 
   String unparked = movable.ToString();
+  auto after_address = reinterpret_cast<uintptr_t>(unparked.Characters8());
+#if DCHECK_IS_ON()
+  // See comments in Park() and Unpark() for why the addresses are guaranteed to
+  // be different.
+  EXPECT_NE(before_address, after_address);
+#else
+  // Strings are not actually moved.
+  EXPECT_EQ(before_address, after_address);
+#endif
   EXPECT_EQ(String("abc"), unparked);
   EXPECT_FALSE(movable.Impl()->is_parked());
 
@@ -77,16 +88,18 @@
 TEST_F(MovableStringTest, TableSimple) {
   base::HistogramTester histogram_tester;
 
+  auto& table = MovableStringTable::Instance();
+  EXPECT_EQ(0u, table.Size());
+
   std::vector<char> data(20000, 'a');
   MovableString movable(String(data.data(), data.size()).ReleaseImpl());
   ASSERT_FALSE(movable.Impl()->is_parked());
 
-  auto& table = MovableStringTable::Instance();
-  EXPECT_EQ(1u, table.table_.size());
+  EXPECT_EQ(1u, table.Size());
 
   // Small strings are not in the table.
   MovableString small(String("abc").ReleaseImpl());
-  EXPECT_EQ(1u, table.table_.size());
+  EXPECT_EQ(1u, table.Size());
 
   // No parking as the current state is not "backgrounded".
   table.SetRendererBackgrounded(false);
@@ -141,23 +154,23 @@
   MovableString movable2(String(data.data(), data.size()).ReleaseImpl());
 
   auto& table = MovableStringTable::Instance();
-  EXPECT_EQ(2u, table.table_.size());
+  EXPECT_EQ(2u, table.Size());
 
   movable2 = MovableString();
-  EXPECT_EQ(1u, table.table_.size());
+  EXPECT_EQ(1u, table.Size());
 
   MovableString copy = movable;
   movable = MovableString();
-  EXPECT_EQ(1u, table.table_.size());
+  EXPECT_EQ(1u, table.Size());
   copy = MovableString();
-  EXPECT_EQ(0u, table.table_.size());
+  EXPECT_EQ(0u, table.Size());
 
   String str(data.data(), data.size());
   MovableString movable3(str.Impl());
-  EXPECT_EQ(1u, table.table_.size());
+  EXPECT_EQ(1u, table.Size());
   // De-duplicated.
   MovableString other_movable3(str.Impl());
-  EXPECT_EQ(1u, table.table_.size());
+  EXPECT_EQ(1u, table.Size());
   EXPECT_EQ(movable3.Impl(), other_movable3.Impl());
 
   // If all the references to a string are in the table, park it.
@@ -169,9 +182,9 @@
 
   // Only drop it from the table when the last one is gone.
   movable3 = MovableString();
-  EXPECT_EQ(1u, table.table_.size());
+  EXPECT_EQ(1u, table.Size());
   other_movable3 = MovableString();
-  EXPECT_EQ(0u, table.table_.size());
+  EXPECT_EQ(0u, table.Size());
 
   histogram_tester.ExpectUniqueSample("Memory.MovableStringsCount", 1, 1);
   histogram_tester.ExpectUniqueSample("Memory.MovableStringsTotalSizeKb",
@@ -182,4 +195,26 @@
       MovableStringImpl::ParkingAction::kParkedInBackground, 1);
 }
 
+TEST_F(MovableStringTest, TableDeduplication) {
+  auto& table = MovableStringTable::Instance();
+  size_t size_kb = 20;
+  std::vector<char> data(size_kb * 1000, 'a');
+
+  String a(data.data(), data.size());
+  String b = a;
+  {
+    MovableString movable_a(a.Impl());
+    EXPECT_EQ(1u, table.Size());
+    {
+      MovableString movable_b(b.Impl());
+      // De-duplicated, as a and b share the same |Impl()|.
+      EXPECT_EQ(1u, table.Size());
+      EXPECT_EQ(movable_a.Impl(), movable_b.Impl());
+    }
+    // |movable_a| still in scope.
+    EXPECT_EQ(1u, table.Size());
+  }
+  EXPECT_EQ(0u, table.Size());
+}
+
 }  // namespace WTF
diff --git a/third_party/tcmalloc/BUILD.gn b/third_party/tcmalloc/BUILD.gn
index 4249264..ea10b28 100644
--- a/third_party/tcmalloc/BUILD.gn
+++ b/third_party/tcmalloc/BUILD.gn
@@ -6,7 +6,7 @@
 
 executable("addr2line-pdb") {
   sources = [
-    "gperftools-2.0/chromium/src/windows/addr2line-pdb.c",
+    "chromium/src/windows/addr2line-pdb.c",
   ]
 
   configs -= [ "//build/config/compiler:chromium_code" ]
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/OWNERS b/third_party/tcmalloc/chromium/src/OWNERS
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/OWNERS
rename to third_party/tcmalloc/chromium/src/OWNERS
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/addressmap-inl.h b/third_party/tcmalloc/chromium/src/addressmap-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/addressmap-inl.h
rename to third_party/tcmalloc/chromium/src/addressmap-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/abort.cc b/third_party/tcmalloc/chromium/src/base/abort.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/abort.cc
rename to third_party/tcmalloc/chromium/src/base/abort.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/abort.h b/third_party/tcmalloc/chromium/src/base/abort.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/abort.h
rename to third_party/tcmalloc/chromium/src/base/abort.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/arm_instruction_set_select.h b/third_party/tcmalloc/chromium/src/base/arm_instruction_set_select.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/arm_instruction_set_select.h
rename to third_party/tcmalloc/chromium/src/base/arm_instruction_set_select.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/atomicops-internals-arm-generic.h b/third_party/tcmalloc/chromium/src/base/atomicops-internals-arm-generic.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/atomicops-internals-arm-generic.h
rename to third_party/tcmalloc/chromium/src/base/atomicops-internals-arm-generic.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/atomicops-internals-arm-v6plus.h b/third_party/tcmalloc/chromium/src/base/atomicops-internals-arm-v6plus.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/atomicops-internals-arm-v6plus.h
rename to third_party/tcmalloc/chromium/src/base/atomicops-internals-arm-v6plus.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/atomicops-internals-linuxppc.h b/third_party/tcmalloc/chromium/src/base/atomicops-internals-linuxppc.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/atomicops-internals-linuxppc.h
rename to third_party/tcmalloc/chromium/src/base/atomicops-internals-linuxppc.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/atomicops-internals-macosx.h b/third_party/tcmalloc/chromium/src/base/atomicops-internals-macosx.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/atomicops-internals-macosx.h
rename to third_party/tcmalloc/chromium/src/base/atomicops-internals-macosx.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/atomicops-internals-mips.h b/third_party/tcmalloc/chromium/src/base/atomicops-internals-mips.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/atomicops-internals-mips.h
rename to third_party/tcmalloc/chromium/src/base/atomicops-internals-mips.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/atomicops-internals-windows.h b/third_party/tcmalloc/chromium/src/base/atomicops-internals-windows.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/atomicops-internals-windows.h
rename to third_party/tcmalloc/chromium/src/base/atomicops-internals-windows.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/atomicops-internals-x86.cc b/third_party/tcmalloc/chromium/src/base/atomicops-internals-x86.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/atomicops-internals-x86.cc
rename to third_party/tcmalloc/chromium/src/base/atomicops-internals-x86.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/atomicops-internals-x86.h b/third_party/tcmalloc/chromium/src/base/atomicops-internals-x86.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/atomicops-internals-x86.h
rename to third_party/tcmalloc/chromium/src/base/atomicops-internals-x86.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/atomicops.h b/third_party/tcmalloc/chromium/src/base/atomicops.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/atomicops.h
rename to third_party/tcmalloc/chromium/src/base/atomicops.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/basictypes.h b/third_party/tcmalloc/chromium/src/base/basictypes.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/basictypes.h
rename to third_party/tcmalloc/chromium/src/base/basictypes.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/commandlineflags.h b/third_party/tcmalloc/chromium/src/base/commandlineflags.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/commandlineflags.h
rename to third_party/tcmalloc/chromium/src/base/commandlineflags.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/cycleclock.h b/third_party/tcmalloc/chromium/src/base/cycleclock.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/cycleclock.h
rename to third_party/tcmalloc/chromium/src/base/cycleclock.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/dynamic_annotations.c b/third_party/tcmalloc/chromium/src/base/dynamic_annotations.c
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/dynamic_annotations.c
rename to third_party/tcmalloc/chromium/src/base/dynamic_annotations.c
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/dynamic_annotations.h b/third_party/tcmalloc/chromium/src/base/dynamic_annotations.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/dynamic_annotations.h
rename to third_party/tcmalloc/chromium/src/base/dynamic_annotations.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/elf_mem_image.cc b/third_party/tcmalloc/chromium/src/base/elf_mem_image.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/elf_mem_image.cc
rename to third_party/tcmalloc/chromium/src/base/elf_mem_image.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/elf_mem_image.h b/third_party/tcmalloc/chromium/src/base/elf_mem_image.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/elf_mem_image.h
rename to third_party/tcmalloc/chromium/src/base/elf_mem_image.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/elfcore.h b/third_party/tcmalloc/chromium/src/base/elfcore.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/elfcore.h
rename to third_party/tcmalloc/chromium/src/base/elfcore.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/googleinit.h b/third_party/tcmalloc/chromium/src/base/googleinit.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/googleinit.h
rename to third_party/tcmalloc/chromium/src/base/googleinit.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/linux_syscall_support.h b/third_party/tcmalloc/chromium/src/base/linux_syscall_support.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/linux_syscall_support.h
rename to third_party/tcmalloc/chromium/src/base/linux_syscall_support.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/linuxthreads.cc b/third_party/tcmalloc/chromium/src/base/linuxthreads.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/linuxthreads.cc
rename to third_party/tcmalloc/chromium/src/base/linuxthreads.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/linuxthreads.h b/third_party/tcmalloc/chromium/src/base/linuxthreads.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/linuxthreads.h
rename to third_party/tcmalloc/chromium/src/base/linuxthreads.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/logging.cc b/third_party/tcmalloc/chromium/src/base/logging.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/logging.cc
rename to third_party/tcmalloc/chromium/src/base/logging.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/logging.h b/third_party/tcmalloc/chromium/src/base/logging.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/logging.h
rename to third_party/tcmalloc/chromium/src/base/logging.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/low_level_alloc.cc b/third_party/tcmalloc/chromium/src/base/low_level_alloc.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/low_level_alloc.cc
rename to third_party/tcmalloc/chromium/src/base/low_level_alloc.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/low_level_alloc.h b/third_party/tcmalloc/chromium/src/base/low_level_alloc.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/low_level_alloc.h
rename to third_party/tcmalloc/chromium/src/base/low_level_alloc.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/simple_mutex.h b/third_party/tcmalloc/chromium/src/base/simple_mutex.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/simple_mutex.h
rename to third_party/tcmalloc/chromium/src/base/simple_mutex.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/spinlock.cc b/third_party/tcmalloc/chromium/src/base/spinlock.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/spinlock.cc
rename to third_party/tcmalloc/chromium/src/base/spinlock.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/spinlock.h b/third_party/tcmalloc/chromium/src/base/spinlock.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/spinlock.h
rename to third_party/tcmalloc/chromium/src/base/spinlock.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/spinlock_internal.cc b/third_party/tcmalloc/chromium/src/base/spinlock_internal.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/spinlock_internal.cc
rename to third_party/tcmalloc/chromium/src/base/spinlock_internal.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/spinlock_internal.h b/third_party/tcmalloc/chromium/src/base/spinlock_internal.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/spinlock_internal.h
rename to third_party/tcmalloc/chromium/src/base/spinlock_internal.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/spinlock_linux-inl.h b/third_party/tcmalloc/chromium/src/base/spinlock_linux-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/spinlock_linux-inl.h
rename to third_party/tcmalloc/chromium/src/base/spinlock_linux-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/spinlock_posix-inl.h b/third_party/tcmalloc/chromium/src/base/spinlock_posix-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/spinlock_posix-inl.h
rename to third_party/tcmalloc/chromium/src/base/spinlock_posix-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/spinlock_win32-inl.h b/third_party/tcmalloc/chromium/src/base/spinlock_win32-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/spinlock_win32-inl.h
rename to third_party/tcmalloc/chromium/src/base/spinlock_win32-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/stl_allocator.h b/third_party/tcmalloc/chromium/src/base/stl_allocator.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/stl_allocator.h
rename to third_party/tcmalloc/chromium/src/base/stl_allocator.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/synchronization_profiling.h b/third_party/tcmalloc/chromium/src/base/synchronization_profiling.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/synchronization_profiling.h
rename to third_party/tcmalloc/chromium/src/base/synchronization_profiling.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/sysinfo.cc b/third_party/tcmalloc/chromium/src/base/sysinfo.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/sysinfo.cc
rename to third_party/tcmalloc/chromium/src/base/sysinfo.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/sysinfo.h b/third_party/tcmalloc/chromium/src/base/sysinfo.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/sysinfo.h
rename to third_party/tcmalloc/chromium/src/base/sysinfo.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/thread_annotations.h b/third_party/tcmalloc/chromium/src/base/thread_annotations.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/thread_annotations.h
rename to third_party/tcmalloc/chromium/src/base/thread_annotations.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/thread_lister.c b/third_party/tcmalloc/chromium/src/base/thread_lister.c
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/thread_lister.c
rename to third_party/tcmalloc/chromium/src/base/thread_lister.c
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/thread_lister.h b/third_party/tcmalloc/chromium/src/base/thread_lister.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/thread_lister.h
rename to third_party/tcmalloc/chromium/src/base/thread_lister.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/vdso_support.cc b/third_party/tcmalloc/chromium/src/base/vdso_support.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/vdso_support.cc
rename to third_party/tcmalloc/chromium/src/base/vdso_support.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/base/vdso_support.h b/third_party/tcmalloc/chromium/src/base/vdso_support.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/base/vdso_support.h
rename to third_party/tcmalloc/chromium/src/base/vdso_support.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/central_freelist.cc b/third_party/tcmalloc/chromium/src/central_freelist.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/central_freelist.cc
rename to third_party/tcmalloc/chromium/src/central_freelist.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/central_freelist.h b/third_party/tcmalloc/chromium/src/central_freelist.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/central_freelist.h
rename to third_party/tcmalloc/chromium/src/central_freelist.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/common.cc b/third_party/tcmalloc/chromium/src/common.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/common.cc
rename to third_party/tcmalloc/chromium/src/common.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/common.h b/third_party/tcmalloc/chromium/src/common.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/common.h
rename to third_party/tcmalloc/chromium/src/common.h
diff --git a/third_party/tcmalloc/chromium/src/config.h b/third_party/tcmalloc/chromium/src/config.h
new file mode 100644
index 0000000..f2ac8f69
--- /dev/null
+++ b/third_party/tcmalloc/chromium/src/config.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2009 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 CONFIG_H_
+
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include "third_party/tcmalloc/chromium/src/config_win.h"
+#elif defined(OS_ANDROID)
+#include "third_party/tcmalloc/chromium/src/config_android.h"
+#elif defined(OS_LINUX)
+#include "third_party/tcmalloc/chromium/src/config_linux.h"
+#elif defined(OS_FREEBSD)
+#include "third_party/tcmalloc/chromium/src/config_freebsd.h"
+#endif
+
+#endif // CONFIG_H_
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/config.h.in b/third_party/tcmalloc/chromium/src/config.h.in
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/config.h.in
rename to third_party/tcmalloc/chromium/src/config.h.in
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/config_android.h b/third_party/tcmalloc/chromium/src/config_android.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/config_android.h
rename to third_party/tcmalloc/chromium/src/config_android.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/config_for_unittests.h b/third_party/tcmalloc/chromium/src/config_for_unittests.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/config_for_unittests.h
rename to third_party/tcmalloc/chromium/src/config_for_unittests.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/config_freebsd.h b/third_party/tcmalloc/chromium/src/config_freebsd.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/config_freebsd.h
rename to third_party/tcmalloc/chromium/src/config_freebsd.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/config_linux.h b/third_party/tcmalloc/chromium/src/config_linux.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/config_linux.h
rename to third_party/tcmalloc/chromium/src/config_linux.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/config_win.h b/third_party/tcmalloc/chromium/src/config_win.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/config_win.h
rename to third_party/tcmalloc/chromium/src/config_win.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/debugallocation.cc b/third_party/tcmalloc/chromium/src/debugallocation.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/debugallocation.cc
rename to third_party/tcmalloc/chromium/src/debugallocation.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/free_list.cc b/third_party/tcmalloc/chromium/src/free_list.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/free_list.cc
rename to third_party/tcmalloc/chromium/src/free_list.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/free_list.h b/third_party/tcmalloc/chromium/src/free_list.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/free_list.h
rename to third_party/tcmalloc/chromium/src/free_list.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/getpc.h b/third_party/tcmalloc/chromium/src/getpc.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/getpc.h
rename to third_party/tcmalloc/chromium/src/getpc.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/google/heap-checker.h b/third_party/tcmalloc/chromium/src/google/heap-checker.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/google/heap-checker.h
rename to third_party/tcmalloc/chromium/src/google/heap-checker.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/google/heap-profiler.h b/third_party/tcmalloc/chromium/src/google/heap-profiler.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/google/heap-profiler.h
rename to third_party/tcmalloc/chromium/src/google/heap-profiler.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/google/malloc_extension.h b/third_party/tcmalloc/chromium/src/google/malloc_extension.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/google/malloc_extension.h
rename to third_party/tcmalloc/chromium/src/google/malloc_extension.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/google/malloc_extension_c.h b/third_party/tcmalloc/chromium/src/google/malloc_extension_c.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/google/malloc_extension_c.h
rename to third_party/tcmalloc/chromium/src/google/malloc_extension_c.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/google/malloc_hook.h b/third_party/tcmalloc/chromium/src/google/malloc_hook.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/google/malloc_hook.h
rename to third_party/tcmalloc/chromium/src/google/malloc_hook.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/google/malloc_hook_c.h b/third_party/tcmalloc/chromium/src/google/malloc_hook_c.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/google/malloc_hook_c.h
rename to third_party/tcmalloc/chromium/src/google/malloc_hook_c.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/google/profiler.h b/third_party/tcmalloc/chromium/src/google/profiler.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/google/profiler.h
rename to third_party/tcmalloc/chromium/src/google/profiler.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/google/stacktrace.h b/third_party/tcmalloc/chromium/src/google/stacktrace.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/google/stacktrace.h
rename to third_party/tcmalloc/chromium/src/google/stacktrace.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/google/tcmalloc.h b/third_party/tcmalloc/chromium/src/google/tcmalloc.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/google/tcmalloc.h
rename to third_party/tcmalloc/chromium/src/google/tcmalloc.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/heap-checker.h b/third_party/tcmalloc/chromium/src/gperftools/heap-checker.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/heap-checker.h
rename to third_party/tcmalloc/chromium/src/gperftools/heap-checker.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/heap-profiler.h b/third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/heap-profiler.h
rename to third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/malloc_extension.h b/third_party/tcmalloc/chromium/src/gperftools/malloc_extension.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/malloc_extension.h
rename to third_party/tcmalloc/chromium/src/gperftools/malloc_extension.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/malloc_extension_c.h b/third_party/tcmalloc/chromium/src/gperftools/malloc_extension_c.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/malloc_extension_c.h
rename to third_party/tcmalloc/chromium/src/gperftools/malloc_extension_c.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/malloc_hook.h b/third_party/tcmalloc/chromium/src/gperftools/malloc_hook.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/malloc_hook.h
rename to third_party/tcmalloc/chromium/src/gperftools/malloc_hook.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/malloc_hook_c.h b/third_party/tcmalloc/chromium/src/gperftools/malloc_hook_c.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/malloc_hook_c.h
rename to third_party/tcmalloc/chromium/src/gperftools/malloc_hook_c.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/profiler.h b/third_party/tcmalloc/chromium/src/gperftools/profiler.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/profiler.h
rename to third_party/tcmalloc/chromium/src/gperftools/profiler.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/stacktrace.h b/third_party/tcmalloc/chromium/src/gperftools/stacktrace.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/stacktrace.h
rename to third_party/tcmalloc/chromium/src/gperftools/stacktrace.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/tcmalloc.h b/third_party/tcmalloc/chromium/src/gperftools/tcmalloc.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/tcmalloc.h
rename to third_party/tcmalloc/chromium/src/gperftools/tcmalloc.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/tcmalloc.h.in b/third_party/tcmalloc/chromium/src/gperftools/tcmalloc.h.in
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/tcmalloc.h.in
rename to third_party/tcmalloc/chromium/src/gperftools/tcmalloc.h.in
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/heap-checker-bcad.cc b/third_party/tcmalloc/chromium/src/heap-checker-bcad.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/heap-checker-bcad.cc
rename to third_party/tcmalloc/chromium/src/heap-checker-bcad.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/heap-checker.cc b/third_party/tcmalloc/chromium/src/heap-checker.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/heap-checker.cc
rename to third_party/tcmalloc/chromium/src/heap-checker.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/heap-profile-stats.h b/third_party/tcmalloc/chromium/src/heap-profile-stats.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/heap-profile-stats.h
rename to third_party/tcmalloc/chromium/src/heap-profile-stats.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/heap-profile-table.cc b/third_party/tcmalloc/chromium/src/heap-profile-table.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/heap-profile-table.cc
rename to third_party/tcmalloc/chromium/src/heap-profile-table.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/heap-profile-table.h b/third_party/tcmalloc/chromium/src/heap-profile-table.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/heap-profile-table.h
rename to third_party/tcmalloc/chromium/src/heap-profile-table.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/heap-profiler.cc b/third_party/tcmalloc/chromium/src/heap-profiler.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/heap-profiler.cc
rename to third_party/tcmalloc/chromium/src/heap-profiler.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/internal_logging.cc b/third_party/tcmalloc/chromium/src/internal_logging.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/internal_logging.cc
rename to third_party/tcmalloc/chromium/src/internal_logging.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/internal_logging.h b/third_party/tcmalloc/chromium/src/internal_logging.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/internal_logging.h
rename to third_party/tcmalloc/chromium/src/internal_logging.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/libc_override.h b/third_party/tcmalloc/chromium/src/libc_override.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/libc_override.h
rename to third_party/tcmalloc/chromium/src/libc_override.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/libc_override_gcc_and_weak.h b/third_party/tcmalloc/chromium/src/libc_override_gcc_and_weak.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/libc_override_gcc_and_weak.h
rename to third_party/tcmalloc/chromium/src/libc_override_gcc_and_weak.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/libc_override_glibc.h b/third_party/tcmalloc/chromium/src/libc_override_glibc.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/libc_override_glibc.h
rename to third_party/tcmalloc/chromium/src/libc_override_glibc.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/libc_override_osx.h b/third_party/tcmalloc/chromium/src/libc_override_osx.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/libc_override_osx.h
rename to third_party/tcmalloc/chromium/src/libc_override_osx.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/libc_override_redefine.h b/third_party/tcmalloc/chromium/src/libc_override_redefine.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/libc_override_redefine.h
rename to third_party/tcmalloc/chromium/src/libc_override_redefine.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/linked_list.h b/third_party/tcmalloc/chromium/src/linked_list.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/linked_list.h
rename to third_party/tcmalloc/chromium/src/linked_list.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/linux_shadow_stacks.cc b/third_party/tcmalloc/chromium/src/linux_shadow_stacks.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/linux_shadow_stacks.cc
rename to third_party/tcmalloc/chromium/src/linux_shadow_stacks.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/linux_shadow_stacks.h b/third_party/tcmalloc/chromium/src/linux_shadow_stacks.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/linux_shadow_stacks.h
rename to third_party/tcmalloc/chromium/src/linux_shadow_stacks.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/malloc_extension.cc b/third_party/tcmalloc/chromium/src/malloc_extension.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/malloc_extension.cc
rename to third_party/tcmalloc/chromium/src/malloc_extension.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/malloc_hook-inl.h b/third_party/tcmalloc/chromium/src/malloc_hook-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/malloc_hook-inl.h
rename to third_party/tcmalloc/chromium/src/malloc_hook-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/malloc_hook.cc b/third_party/tcmalloc/chromium/src/malloc_hook.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/malloc_hook.cc
rename to third_party/tcmalloc/chromium/src/malloc_hook.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/malloc_hook_mmap_freebsd.h b/third_party/tcmalloc/chromium/src/malloc_hook_mmap_freebsd.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/malloc_hook_mmap_freebsd.h
rename to third_party/tcmalloc/chromium/src/malloc_hook_mmap_freebsd.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/malloc_hook_mmap_linux.h b/third_party/tcmalloc/chromium/src/malloc_hook_mmap_linux.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/malloc_hook_mmap_linux.h
rename to third_party/tcmalloc/chromium/src/malloc_hook_mmap_linux.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/maybe_threads.cc b/third_party/tcmalloc/chromium/src/maybe_threads.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/maybe_threads.cc
rename to third_party/tcmalloc/chromium/src/maybe_threads.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/maybe_threads.h b/third_party/tcmalloc/chromium/src/maybe_threads.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/maybe_threads.h
rename to third_party/tcmalloc/chromium/src/maybe_threads.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/memfs_malloc.cc b/third_party/tcmalloc/chromium/src/memfs_malloc.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/memfs_malloc.cc
rename to third_party/tcmalloc/chromium/src/memfs_malloc.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/memory_region_map.cc b/third_party/tcmalloc/chromium/src/memory_region_map.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/memory_region_map.cc
rename to third_party/tcmalloc/chromium/src/memory_region_map.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/memory_region_map.h b/third_party/tcmalloc/chromium/src/memory_region_map.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/memory_region_map.h
rename to third_party/tcmalloc/chromium/src/memory_region_map.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/packed-cache-inl.h b/third_party/tcmalloc/chromium/src/packed-cache-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/packed-cache-inl.h
rename to third_party/tcmalloc/chromium/src/packed-cache-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/page_heap.cc b/third_party/tcmalloc/chromium/src/page_heap.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/page_heap.cc
rename to third_party/tcmalloc/chromium/src/page_heap.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/page_heap.h b/third_party/tcmalloc/chromium/src/page_heap.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/page_heap.h
rename to third_party/tcmalloc/chromium/src/page_heap.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/page_heap_allocator.h b/third_party/tcmalloc/chromium/src/page_heap_allocator.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/page_heap_allocator.h
rename to third_party/tcmalloc/chromium/src/page_heap_allocator.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/pagemap.h b/third_party/tcmalloc/chromium/src/pagemap.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/pagemap.h
rename to third_party/tcmalloc/chromium/src/pagemap.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/pprof b/third_party/tcmalloc/chromium/src/pprof
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/pprof
rename to third_party/tcmalloc/chromium/src/pprof
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/profile-handler.cc b/third_party/tcmalloc/chromium/src/profile-handler.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/profile-handler.cc
rename to third_party/tcmalloc/chromium/src/profile-handler.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/profile-handler.h b/third_party/tcmalloc/chromium/src/profile-handler.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/profile-handler.h
rename to third_party/tcmalloc/chromium/src/profile-handler.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/profiledata.cc b/third_party/tcmalloc/chromium/src/profiledata.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/profiledata.cc
rename to third_party/tcmalloc/chromium/src/profiledata.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/profiledata.h b/third_party/tcmalloc/chromium/src/profiledata.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/profiledata.h
rename to third_party/tcmalloc/chromium/src/profiledata.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/profiler.cc b/third_party/tcmalloc/chromium/src/profiler.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/profiler.cc
rename to third_party/tcmalloc/chromium/src/profiler.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/raw_printer.cc b/third_party/tcmalloc/chromium/src/raw_printer.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/raw_printer.cc
rename to third_party/tcmalloc/chromium/src/raw_printer.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/raw_printer.h b/third_party/tcmalloc/chromium/src/raw_printer.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/raw_printer.h
rename to third_party/tcmalloc/chromium/src/raw_printer.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/sampler.cc b/third_party/tcmalloc/chromium/src/sampler.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/sampler.cc
rename to third_party/tcmalloc/chromium/src/sampler.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/sampler.h b/third_party/tcmalloc/chromium/src/sampler.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/sampler.h
rename to third_party/tcmalloc/chromium/src/sampler.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/solaris/libstdc++.la b/third_party/tcmalloc/chromium/src/solaris/libstdc++.la
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/solaris/libstdc++.la
rename to third_party/tcmalloc/chromium/src/solaris/libstdc++.la
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/span.cc b/third_party/tcmalloc/chromium/src/span.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/span.cc
rename to third_party/tcmalloc/chromium/src/span.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/span.h b/third_party/tcmalloc/chromium/src/span.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/span.h
rename to third_party/tcmalloc/chromium/src/span.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/stack_trace_table.cc b/third_party/tcmalloc/chromium/src/stack_trace_table.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/stack_trace_table.cc
rename to third_party/tcmalloc/chromium/src/stack_trace_table.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/stack_trace_table.h b/third_party/tcmalloc/chromium/src/stack_trace_table.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/stack_trace_table.h
rename to third_party/tcmalloc/chromium/src/stack_trace_table.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/stacktrace.cc b/third_party/tcmalloc/chromium/src/stacktrace.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/stacktrace.cc
rename to third_party/tcmalloc/chromium/src/stacktrace.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/stacktrace_android-inl.h b/third_party/tcmalloc/chromium/src/stacktrace_android-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/stacktrace_android-inl.h
rename to third_party/tcmalloc/chromium/src/stacktrace_android-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/stacktrace_arm-inl.h b/third_party/tcmalloc/chromium/src/stacktrace_arm-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/stacktrace_arm-inl.h
rename to third_party/tcmalloc/chromium/src/stacktrace_arm-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/stacktrace_config.h b/third_party/tcmalloc/chromium/src/stacktrace_config.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/stacktrace_config.h
rename to third_party/tcmalloc/chromium/src/stacktrace_config.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/stacktrace_generic-inl.h b/third_party/tcmalloc/chromium/src/stacktrace_generic-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/stacktrace_generic-inl.h
rename to third_party/tcmalloc/chromium/src/stacktrace_generic-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/stacktrace_libunwind-inl.h b/third_party/tcmalloc/chromium/src/stacktrace_libunwind-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/stacktrace_libunwind-inl.h
rename to third_party/tcmalloc/chromium/src/stacktrace_libunwind-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/stacktrace_mips-inl.h b/third_party/tcmalloc/chromium/src/stacktrace_mips-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/stacktrace_mips-inl.h
rename to third_party/tcmalloc/chromium/src/stacktrace_mips-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/stacktrace_powerpc-inl.h b/third_party/tcmalloc/chromium/src/stacktrace_powerpc-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/stacktrace_powerpc-inl.h
rename to third_party/tcmalloc/chromium/src/stacktrace_powerpc-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/stacktrace_win32-inl.h b/third_party/tcmalloc/chromium/src/stacktrace_win32-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/stacktrace_win32-inl.h
rename to third_party/tcmalloc/chromium/src/stacktrace_win32-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/stacktrace_with_context.cc b/third_party/tcmalloc/chromium/src/stacktrace_with_context.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/stacktrace_with_context.cc
rename to third_party/tcmalloc/chromium/src/stacktrace_with_context.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/stacktrace_x86-inl.h b/third_party/tcmalloc/chromium/src/stacktrace_x86-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/stacktrace_x86-inl.h
rename to third_party/tcmalloc/chromium/src/stacktrace_x86-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/static_vars.cc b/third_party/tcmalloc/chromium/src/static_vars.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/static_vars.cc
rename to third_party/tcmalloc/chromium/src/static_vars.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/static_vars.h b/third_party/tcmalloc/chromium/src/static_vars.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/static_vars.h
rename to third_party/tcmalloc/chromium/src/static_vars.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/symbolize.cc b/third_party/tcmalloc/chromium/src/symbolize.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/symbolize.cc
rename to third_party/tcmalloc/chromium/src/symbolize.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/symbolize.h b/third_party/tcmalloc/chromium/src/symbolize.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/symbolize.h
rename to third_party/tcmalloc/chromium/src/symbolize.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/system-alloc.cc b/third_party/tcmalloc/chromium/src/system-alloc.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/system-alloc.cc
rename to third_party/tcmalloc/chromium/src/system-alloc.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/system-alloc.h b/third_party/tcmalloc/chromium/src/system-alloc.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/system-alloc.h
rename to third_party/tcmalloc/chromium/src/system-alloc.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tcmalloc.cc b/third_party/tcmalloc/chromium/src/tcmalloc.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tcmalloc.cc
rename to third_party/tcmalloc/chromium/src/tcmalloc.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tcmalloc.h b/third_party/tcmalloc/chromium/src/tcmalloc.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tcmalloc.h
rename to third_party/tcmalloc/chromium/src/tcmalloc.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tcmalloc_guard.h b/third_party/tcmalloc/chromium/src/tcmalloc_guard.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tcmalloc_guard.h
rename to third_party/tcmalloc/chromium/src/tcmalloc_guard.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/addressmap_unittest.cc b/third_party/tcmalloc/chromium/src/tests/addressmap_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/addressmap_unittest.cc
rename to third_party/tcmalloc/chromium/src/tests/addressmap_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/atomicops_unittest.cc b/third_party/tcmalloc/chromium/src/tests/atomicops_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/atomicops_unittest.cc
rename to third_party/tcmalloc/chromium/src/tests/atomicops_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/current_allocated_bytes_test.cc b/third_party/tcmalloc/chromium/src/tests/current_allocated_bytes_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/current_allocated_bytes_test.cc
rename to third_party/tcmalloc/chromium/src/tests/current_allocated_bytes_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/debugallocation_test.cc b/third_party/tcmalloc/chromium/src/tests/debugallocation_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/debugallocation_test.cc
rename to third_party/tcmalloc/chromium/src/tests/debugallocation_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/debugallocation_test.sh b/third_party/tcmalloc/chromium/src/tests/debugallocation_test.sh
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/debugallocation_test.sh
rename to third_party/tcmalloc/chromium/src/tests/debugallocation_test.sh
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/frag_unittest.cc b/third_party/tcmalloc/chromium/src/tests/frag_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/frag_unittest.cc
rename to third_party/tcmalloc/chromium/src/tests/frag_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/getpc_test.cc b/third_party/tcmalloc/chromium/src/tests/getpc_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/getpc_test.cc
rename to third_party/tcmalloc/chromium/src/tests/getpc_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/heap-checker-death_unittest.sh b/third_party/tcmalloc/chromium/src/tests/heap-checker-death_unittest.sh
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/heap-checker-death_unittest.sh
rename to third_party/tcmalloc/chromium/src/tests/heap-checker-death_unittest.sh
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/heap-checker_unittest.cc b/third_party/tcmalloc/chromium/src/tests/heap-checker_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/heap-checker_unittest.cc
rename to third_party/tcmalloc/chromium/src/tests/heap-checker_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/heap-checker_unittest.sh b/third_party/tcmalloc/chromium/src/tests/heap-checker_unittest.sh
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/heap-checker_unittest.sh
rename to third_party/tcmalloc/chromium/src/tests/heap-checker_unittest.sh
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/heap-profiler_unittest.cc b/third_party/tcmalloc/chromium/src/tests/heap-profiler_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/heap-profiler_unittest.cc
rename to third_party/tcmalloc/chromium/src/tests/heap-profiler_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/heap-profiler_unittest.sh b/third_party/tcmalloc/chromium/src/tests/heap-profiler_unittest.sh
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/heap-profiler_unittest.sh
rename to third_party/tcmalloc/chromium/src/tests/heap-profiler_unittest.sh
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/low_level_alloc_unittest.cc b/third_party/tcmalloc/chromium/src/tests/low_level_alloc_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/low_level_alloc_unittest.cc
rename to third_party/tcmalloc/chromium/src/tests/low_level_alloc_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/malloc_extension_c_test.c b/third_party/tcmalloc/chromium/src/tests/malloc_extension_c_test.c
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/malloc_extension_c_test.c
rename to third_party/tcmalloc/chromium/src/tests/malloc_extension_c_test.c
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/malloc_extension_test.cc b/third_party/tcmalloc/chromium/src/tests/malloc_extension_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/malloc_extension_test.cc
rename to third_party/tcmalloc/chromium/src/tests/malloc_extension_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/malloc_hook_test.cc b/third_party/tcmalloc/chromium/src/tests/malloc_hook_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/malloc_hook_test.cc
rename to third_party/tcmalloc/chromium/src/tests/malloc_hook_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/markidle_unittest.cc b/third_party/tcmalloc/chromium/src/tests/markidle_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/markidle_unittest.cc
rename to third_party/tcmalloc/chromium/src/tests/markidle_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/maybe_threads_unittest.sh b/third_party/tcmalloc/chromium/src/tests/maybe_threads_unittest.sh
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/maybe_threads_unittest.sh
rename to third_party/tcmalloc/chromium/src/tests/maybe_threads_unittest.sh
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/memalign_unittest.cc b/third_party/tcmalloc/chromium/src/tests/memalign_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/memalign_unittest.cc
rename to third_party/tcmalloc/chromium/src/tests/memalign_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/packed-cache_test.cc b/third_party/tcmalloc/chromium/src/tests/packed-cache_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/packed-cache_test.cc
rename to third_party/tcmalloc/chromium/src/tests/packed-cache_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/page_heap_test.cc b/third_party/tcmalloc/chromium/src/tests/page_heap_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/page_heap_test.cc
rename to third_party/tcmalloc/chromium/src/tests/page_heap_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/pagemap_unittest.cc b/third_party/tcmalloc/chromium/src/tests/pagemap_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/pagemap_unittest.cc
rename to third_party/tcmalloc/chromium/src/tests/pagemap_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/profile-handler_unittest.cc b/third_party/tcmalloc/chromium/src/tests/profile-handler_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/profile-handler_unittest.cc
rename to third_party/tcmalloc/chromium/src/tests/profile-handler_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/profiledata_unittest.cc b/third_party/tcmalloc/chromium/src/tests/profiledata_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/profiledata_unittest.cc
rename to third_party/tcmalloc/chromium/src/tests/profiledata_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/profiler_unittest.cc b/third_party/tcmalloc/chromium/src/tests/profiler_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/profiler_unittest.cc
rename to third_party/tcmalloc/chromium/src/tests/profiler_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/profiler_unittest.sh b/third_party/tcmalloc/chromium/src/tests/profiler_unittest.sh
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/profiler_unittest.sh
rename to third_party/tcmalloc/chromium/src/tests/profiler_unittest.sh
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/raw_printer_test.cc b/third_party/tcmalloc/chromium/src/tests/raw_printer_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/raw_printer_test.cc
rename to third_party/tcmalloc/chromium/src/tests/raw_printer_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/realloc_unittest.cc b/third_party/tcmalloc/chromium/src/tests/realloc_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/realloc_unittest.cc
rename to third_party/tcmalloc/chromium/src/tests/realloc_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/sampler_test.cc b/third_party/tcmalloc/chromium/src/tests/sampler_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/sampler_test.cc
rename to third_party/tcmalloc/chromium/src/tests/sampler_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/sampling_test.cc b/third_party/tcmalloc/chromium/src/tests/sampling_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/sampling_test.cc
rename to third_party/tcmalloc/chromium/src/tests/sampling_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/sampling_test.sh b/third_party/tcmalloc/chromium/src/tests/sampling_test.sh
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/sampling_test.sh
rename to third_party/tcmalloc/chromium/src/tests/sampling_test.sh
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/simple_compat_test.cc b/third_party/tcmalloc/chromium/src/tests/simple_compat_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/simple_compat_test.cc
rename to third_party/tcmalloc/chromium/src/tests/simple_compat_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/stack_trace_table_test.cc b/third_party/tcmalloc/chromium/src/tests/stack_trace_table_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/stack_trace_table_test.cc
rename to third_party/tcmalloc/chromium/src/tests/stack_trace_table_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/stacktrace_unittest.cc b/third_party/tcmalloc/chromium/src/tests/stacktrace_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/stacktrace_unittest.cc
rename to third_party/tcmalloc/chromium/src/tests/stacktrace_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/system-alloc_unittest.cc b/third_party/tcmalloc/chromium/src/tests/system-alloc_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/system-alloc_unittest.cc
rename to third_party/tcmalloc/chromium/src/tests/system-alloc_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/tcmalloc_large_unittest.cc b/third_party/tcmalloc/chromium/src/tests/tcmalloc_large_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/tcmalloc_large_unittest.cc
rename to third_party/tcmalloc/chromium/src/tests/tcmalloc_large_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/tcmalloc_unittest.cc b/third_party/tcmalloc/chromium/src/tests/tcmalloc_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/tcmalloc_unittest.cc
rename to third_party/tcmalloc/chromium/src/tests/tcmalloc_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/testutil.cc b/third_party/tcmalloc/chromium/src/tests/testutil.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/testutil.cc
rename to third_party/tcmalloc/chromium/src/tests/testutil.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/testutil.h b/third_party/tcmalloc/chromium/src/tests/testutil.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/testutil.h
rename to third_party/tcmalloc/chromium/src/tests/testutil.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/tests/thread_dealloc_unittest.cc b/third_party/tcmalloc/chromium/src/tests/thread_dealloc_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/tests/thread_dealloc_unittest.cc
rename to third_party/tcmalloc/chromium/src/tests/thread_dealloc_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/thread_cache.cc b/third_party/tcmalloc/chromium/src/thread_cache.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/thread_cache.cc
rename to third_party/tcmalloc/chromium/src/thread_cache.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/thread_cache.h b/third_party/tcmalloc/chromium/src/thread_cache.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/thread_cache.h
rename to third_party/tcmalloc/chromium/src/thread_cache.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/TODO b/third_party/tcmalloc/chromium/src/windows/TODO
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/TODO
rename to third_party/tcmalloc/chromium/src/windows/TODO
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/addr2line-pdb.c b/third_party/tcmalloc/chromium/src/windows/addr2line-pdb.c
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/addr2line-pdb.c
rename to third_party/tcmalloc/chromium/src/windows/addr2line-pdb.c
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/auto_testing_hook.h b/third_party/tcmalloc/chromium/src/windows/auto_testing_hook.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/auto_testing_hook.h
rename to third_party/tcmalloc/chromium/src/windows/auto_testing_hook.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/config.h b/third_party/tcmalloc/chromium/src/windows/config.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/config.h
rename to third_party/tcmalloc/chromium/src/windows/config.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/get_mangled_names.cc b/third_party/tcmalloc/chromium/src/windows/get_mangled_names.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/get_mangled_names.cc
rename to third_party/tcmalloc/chromium/src/windows/get_mangled_names.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/google/tcmalloc.h b/third_party/tcmalloc/chromium/src/windows/google/tcmalloc.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/google/tcmalloc.h
rename to third_party/tcmalloc/chromium/src/windows/google/tcmalloc.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/gperftools/tcmalloc.h b/third_party/tcmalloc/chromium/src/windows/gperftools/tcmalloc.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/gperftools/tcmalloc.h
rename to third_party/tcmalloc/chromium/src/windows/gperftools/tcmalloc.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/gperftools/tcmalloc.h.in b/third_party/tcmalloc/chromium/src/windows/gperftools/tcmalloc.h.in
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/gperftools/tcmalloc.h.in
rename to third_party/tcmalloc/chromium/src/windows/gperftools/tcmalloc.h.in
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/ia32_modrm_map.cc b/third_party/tcmalloc/chromium/src/windows/ia32_modrm_map.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/ia32_modrm_map.cc
rename to third_party/tcmalloc/chromium/src/windows/ia32_modrm_map.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/ia32_opcode_map.cc b/third_party/tcmalloc/chromium/src/windows/ia32_opcode_map.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/ia32_opcode_map.cc
rename to third_party/tcmalloc/chromium/src/windows/ia32_opcode_map.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/mingw.h b/third_party/tcmalloc/chromium/src/windows/mingw.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/mingw.h
rename to third_party/tcmalloc/chromium/src/windows/mingw.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/mini_disassembler.cc b/third_party/tcmalloc/chromium/src/windows/mini_disassembler.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/mini_disassembler.cc
rename to third_party/tcmalloc/chromium/src/windows/mini_disassembler.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/mini_disassembler.h b/third_party/tcmalloc/chromium/src/windows/mini_disassembler.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/mini_disassembler.h
rename to third_party/tcmalloc/chromium/src/windows/mini_disassembler.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/mini_disassembler_types.h b/third_party/tcmalloc/chromium/src/windows/mini_disassembler_types.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/mini_disassembler_types.h
rename to third_party/tcmalloc/chromium/src/windows/mini_disassembler_types.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/nm-pdb.c b/third_party/tcmalloc/chromium/src/windows/nm-pdb.c
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/nm-pdb.c
rename to third_party/tcmalloc/chromium/src/windows/nm-pdb.c
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/override_functions.cc b/third_party/tcmalloc/chromium/src/windows/override_functions.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/override_functions.cc
rename to third_party/tcmalloc/chromium/src/windows/override_functions.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/patch_functions.cc b/third_party/tcmalloc/chromium/src/windows/patch_functions.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/patch_functions.cc
rename to third_party/tcmalloc/chromium/src/windows/patch_functions.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/port.cc b/third_party/tcmalloc/chromium/src/windows/port.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/port.cc
rename to third_party/tcmalloc/chromium/src/windows/port.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/port.h b/third_party/tcmalloc/chromium/src/windows/port.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/port.h
rename to third_party/tcmalloc/chromium/src/windows/port.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/preamble_patcher.cc b/third_party/tcmalloc/chromium/src/windows/preamble_patcher.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/preamble_patcher.cc
rename to third_party/tcmalloc/chromium/src/windows/preamble_patcher.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/preamble_patcher.h b/third_party/tcmalloc/chromium/src/windows/preamble_patcher.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/preamble_patcher.h
rename to third_party/tcmalloc/chromium/src/windows/preamble_patcher.h
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/preamble_patcher_test.cc b/third_party/tcmalloc/chromium/src/windows/preamble_patcher_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/preamble_patcher_test.cc
rename to third_party/tcmalloc/chromium/src/windows/preamble_patcher_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/preamble_patcher_with_stub.cc b/third_party/tcmalloc/chromium/src/windows/preamble_patcher_with_stub.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/preamble_patcher_with_stub.cc
rename to third_party/tcmalloc/chromium/src/windows/preamble_patcher_with_stub.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/windows/shortproc.asm b/third_party/tcmalloc/chromium/src/windows/shortproc.asm
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/chromium/src/windows/shortproc.asm
rename to third_party/tcmalloc/chromium/src/windows/shortproc.asm
diff --git a/third_party/tcmalloc/gperftools-2.0/chromium/src/config.h b/third_party/tcmalloc/gperftools-2.0/chromium/src/config.h
deleted file mode 100644
index 66bacfa..0000000
--- a/third_party/tcmalloc/gperftools-2.0/chromium/src/config.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2009 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 CONFIG_H_
-
-#include "build/build_config.h"
-
-#if defined(OS_WIN)
-#include "third_party/tcmalloc/gperftools-2.0/chromium/src/config_win.h"
-#elif defined(OS_ANDROID)
-#include "third_party/tcmalloc/gperftools-2.0/chromium/src/config_android.h"
-#elif defined(OS_LINUX)
-#include "third_party/tcmalloc/gperftools-2.0/chromium/src/config_linux.h"
-#elif defined(OS_FREEBSD)
-#include "third_party/tcmalloc/gperftools-2.0/chromium/src/config_freebsd.h"
-#endif
-
-#endif // CONFIG_H_
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/AUTHORS b/third_party/tcmalloc/vendor/AUTHORS
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/AUTHORS
rename to third_party/tcmalloc/vendor/AUTHORS
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/COPYING b/third_party/tcmalloc/vendor/COPYING
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/COPYING
rename to third_party/tcmalloc/vendor/COPYING
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/ChangeLog b/third_party/tcmalloc/vendor/ChangeLog
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/ChangeLog
rename to third_party/tcmalloc/vendor/ChangeLog
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/INSTALL b/third_party/tcmalloc/vendor/INSTALL
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/INSTALL
rename to third_party/tcmalloc/vendor/INSTALL
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/Makefile.am b/third_party/tcmalloc/vendor/Makefile.am
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/Makefile.am
rename to third_party/tcmalloc/vendor/Makefile.am
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/Makefile.in b/third_party/tcmalloc/vendor/Makefile.in
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/Makefile.in
rename to third_party/tcmalloc/vendor/Makefile.in
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/NEWS b/third_party/tcmalloc/vendor/NEWS
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/NEWS
rename to third_party/tcmalloc/vendor/NEWS
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/README b/third_party/tcmalloc/vendor/README
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/README
rename to third_party/tcmalloc/vendor/README
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/README_windows.txt b/third_party/tcmalloc/vendor/README_windows.txt
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/README_windows.txt
rename to third_party/tcmalloc/vendor/README_windows.txt
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/TODO b/third_party/tcmalloc/vendor/TODO
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/TODO
rename to third_party/tcmalloc/vendor/TODO
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/aclocal.m4 b/third_party/tcmalloc/vendor/aclocal.m4
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/aclocal.m4
rename to third_party/tcmalloc/vendor/aclocal.m4
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/autogen.sh b/third_party/tcmalloc/vendor/autogen.sh
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/autogen.sh
rename to third_party/tcmalloc/vendor/autogen.sh
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/compile b/third_party/tcmalloc/vendor/compile
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/compile
rename to third_party/tcmalloc/vendor/compile
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/config.guess b/third_party/tcmalloc/vendor/config.guess
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/config.guess
rename to third_party/tcmalloc/vendor/config.guess
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/config.sub b/third_party/tcmalloc/vendor/config.sub
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/config.sub
rename to third_party/tcmalloc/vendor/config.sub
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/configure b/third_party/tcmalloc/vendor/configure
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/configure
rename to third_party/tcmalloc/vendor/configure
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/configure.ac b/third_party/tcmalloc/vendor/configure.ac
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/configure.ac
rename to third_party/tcmalloc/vendor/configure.ac
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/depcomp b/third_party/tcmalloc/vendor/depcomp
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/depcomp
rename to third_party/tcmalloc/vendor/depcomp
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/cpuprofile-fileformat.html b/third_party/tcmalloc/vendor/doc/cpuprofile-fileformat.html
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/cpuprofile-fileformat.html
rename to third_party/tcmalloc/vendor/doc/cpuprofile-fileformat.html
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/cpuprofile.html b/third_party/tcmalloc/vendor/doc/cpuprofile.html
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/cpuprofile.html
rename to third_party/tcmalloc/vendor/doc/cpuprofile.html
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/designstyle.css b/third_party/tcmalloc/vendor/doc/designstyle.css
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/designstyle.css
rename to third_party/tcmalloc/vendor/doc/designstyle.css
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/heap-example1.png b/third_party/tcmalloc/vendor/doc/heap-example1.png
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/heap-example1.png
rename to third_party/tcmalloc/vendor/doc/heap-example1.png
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/heap_checker.html b/third_party/tcmalloc/vendor/doc/heap_checker.html
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/heap_checker.html
rename to third_party/tcmalloc/vendor/doc/heap_checker.html
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/heapprofile.html b/third_party/tcmalloc/vendor/doc/heapprofile.html
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/heapprofile.html
rename to third_party/tcmalloc/vendor/doc/heapprofile.html
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/index.html b/third_party/tcmalloc/vendor/doc/index.html
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/index.html
rename to third_party/tcmalloc/vendor/doc/index.html
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/overview.dot b/third_party/tcmalloc/vendor/doc/overview.dot
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/overview.dot
rename to third_party/tcmalloc/vendor/doc/overview.dot
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/overview.gif b/third_party/tcmalloc/vendor/doc/overview.gif
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/overview.gif
rename to third_party/tcmalloc/vendor/doc/overview.gif
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/pageheap.dot b/third_party/tcmalloc/vendor/doc/pageheap.dot
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/pageheap.dot
rename to third_party/tcmalloc/vendor/doc/pageheap.dot
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/pageheap.gif b/third_party/tcmalloc/vendor/doc/pageheap.gif
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/pageheap.gif
rename to third_party/tcmalloc/vendor/doc/pageheap.gif
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/pprof-test-big.gif b/third_party/tcmalloc/vendor/doc/pprof-test-big.gif
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/pprof-test-big.gif
rename to third_party/tcmalloc/vendor/doc/pprof-test-big.gif
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/pprof-test.gif b/third_party/tcmalloc/vendor/doc/pprof-test.gif
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/pprof-test.gif
rename to third_party/tcmalloc/vendor/doc/pprof-test.gif
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/pprof-vsnprintf-big.gif b/third_party/tcmalloc/vendor/doc/pprof-vsnprintf-big.gif
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/pprof-vsnprintf-big.gif
rename to third_party/tcmalloc/vendor/doc/pprof-vsnprintf-big.gif
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/pprof-vsnprintf.gif b/third_party/tcmalloc/vendor/doc/pprof-vsnprintf.gif
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/pprof-vsnprintf.gif
rename to third_party/tcmalloc/vendor/doc/pprof-vsnprintf.gif
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/pprof.1 b/third_party/tcmalloc/vendor/doc/pprof.1
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/pprof.1
rename to third_party/tcmalloc/vendor/doc/pprof.1
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/pprof.see_also b/third_party/tcmalloc/vendor/doc/pprof.see_also
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/pprof.see_also
rename to third_party/tcmalloc/vendor/doc/pprof.see_also
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/pprof_remote_servers.html b/third_party/tcmalloc/vendor/doc/pprof_remote_servers.html
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/pprof_remote_servers.html
rename to third_party/tcmalloc/vendor/doc/pprof_remote_servers.html
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/spanmap.dot b/third_party/tcmalloc/vendor/doc/spanmap.dot
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/spanmap.dot
rename to third_party/tcmalloc/vendor/doc/spanmap.dot
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/spanmap.gif b/third_party/tcmalloc/vendor/doc/spanmap.gif
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/spanmap.gif
rename to third_party/tcmalloc/vendor/doc/spanmap.gif
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/t-test1.times.txt b/third_party/tcmalloc/vendor/doc/t-test1.times.txt
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/t-test1.times.txt
rename to third_party/tcmalloc/vendor/doc/t-test1.times.txt
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.1024.bytes.png b/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.1024.bytes.png
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.1024.bytes.png
rename to third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.1024.bytes.png
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.128.bytes.png b/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.128.bytes.png
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.128.bytes.png
rename to third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.128.bytes.png
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.131072.bytes.png b/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.131072.bytes.png
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.131072.bytes.png
rename to third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.131072.bytes.png
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.16384.bytes.png b/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.16384.bytes.png
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.16384.bytes.png
rename to third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.16384.bytes.png
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.2048.bytes.png b/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.2048.bytes.png
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.2048.bytes.png
rename to third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.2048.bytes.png
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.256.bytes.png b/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.256.bytes.png
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.256.bytes.png
rename to third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.256.bytes.png
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.32768.bytes.png b/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.32768.bytes.png
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.32768.bytes.png
rename to third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.32768.bytes.png
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.4096.bytes.png b/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.4096.bytes.png
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.4096.bytes.png
rename to third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.4096.bytes.png
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.512.bytes.png b/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.512.bytes.png
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.512.bytes.png
rename to third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.512.bytes.png
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.64.bytes.png b/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.64.bytes.png
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.64.bytes.png
rename to third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.64.bytes.png
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.65536.bytes.png b/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.65536.bytes.png
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.65536.bytes.png
rename to third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.65536.bytes.png
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.8192.bytes.png b/third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.8192.bytes.png
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspercpusec.vs.threads.8192.bytes.png
rename to third_party/tcmalloc/vendor/doc/tcmalloc-opspercpusec.vs.threads.8192.bytes.png
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspersec.vs.size.1.threads.png b/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.1.threads.png
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspersec.vs.size.1.threads.png
rename to third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.1.threads.png
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspersec.vs.size.12.threads.png b/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.12.threads.png
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspersec.vs.size.12.threads.png
rename to third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.12.threads.png
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspersec.vs.size.16.threads.png b/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.16.threads.png
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspersec.vs.size.16.threads.png
rename to third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.16.threads.png
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspersec.vs.size.2.threads.png b/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.2.threads.png
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspersec.vs.size.2.threads.png
rename to third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.2.threads.png
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspersec.vs.size.20.threads.png b/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.20.threads.png
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspersec.vs.size.20.threads.png
rename to third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.20.threads.png
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspersec.vs.size.3.threads.png b/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.3.threads.png
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspersec.vs.size.3.threads.png
rename to third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.3.threads.png
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspersec.vs.size.4.threads.png b/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.4.threads.png
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspersec.vs.size.4.threads.png
rename to third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.4.threads.png
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspersec.vs.size.5.threads.png b/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.5.threads.png
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspersec.vs.size.5.threads.png
rename to third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.5.threads.png
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspersec.vs.size.8.threads.png b/third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.8.threads.png
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc-opspersec.vs.size.8.threads.png
rename to third_party/tcmalloc/vendor/doc/tcmalloc-opspersec.vs.size.8.threads.png
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc.html b/third_party/tcmalloc/vendor/doc/tcmalloc.html
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/tcmalloc.html
rename to third_party/tcmalloc/vendor/doc/tcmalloc.html
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/threadheap.dot b/third_party/tcmalloc/vendor/doc/threadheap.dot
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/threadheap.dot
rename to third_party/tcmalloc/vendor/doc/threadheap.dot
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/doc/threadheap.gif b/third_party/tcmalloc/vendor/doc/threadheap.gif
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/doc/threadheap.gif
rename to third_party/tcmalloc/vendor/doc/threadheap.gif
Binary files differ
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/install-sh b/third_party/tcmalloc/vendor/install-sh
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/install-sh
rename to third_party/tcmalloc/vendor/install-sh
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/ltmain.sh b/third_party/tcmalloc/vendor/ltmain.sh
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/ltmain.sh
rename to third_party/tcmalloc/vendor/ltmain.sh
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/m4/ac_have_attribute.m4 b/third_party/tcmalloc/vendor/m4/ac_have_attribute.m4
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/m4/ac_have_attribute.m4
rename to third_party/tcmalloc/vendor/m4/ac_have_attribute.m4
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/m4/acx_nanosleep.m4 b/third_party/tcmalloc/vendor/m4/acx_nanosleep.m4
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/m4/acx_nanosleep.m4
rename to third_party/tcmalloc/vendor/m4/acx_nanosleep.m4
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/m4/acx_pthread.m4 b/third_party/tcmalloc/vendor/m4/acx_pthread.m4
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/m4/acx_pthread.m4
rename to third_party/tcmalloc/vendor/m4/acx_pthread.m4
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/m4/compiler_characteristics.m4 b/third_party/tcmalloc/vendor/m4/compiler_characteristics.m4
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/m4/compiler_characteristics.m4
rename to third_party/tcmalloc/vendor/m4/compiler_characteristics.m4
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/m4/install_prefix.m4 b/third_party/tcmalloc/vendor/m4/install_prefix.m4
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/m4/install_prefix.m4
rename to third_party/tcmalloc/vendor/m4/install_prefix.m4
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/m4/libtool.m4 b/third_party/tcmalloc/vendor/m4/libtool.m4
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/m4/libtool.m4
rename to third_party/tcmalloc/vendor/m4/libtool.m4
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/m4/ltoptions.m4 b/third_party/tcmalloc/vendor/m4/ltoptions.m4
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/m4/ltoptions.m4
rename to third_party/tcmalloc/vendor/m4/ltoptions.m4
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/m4/ltsugar.m4 b/third_party/tcmalloc/vendor/m4/ltsugar.m4
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/m4/ltsugar.m4
rename to third_party/tcmalloc/vendor/m4/ltsugar.m4
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/m4/ltversion.m4 b/third_party/tcmalloc/vendor/m4/ltversion.m4
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/m4/ltversion.m4
rename to third_party/tcmalloc/vendor/m4/ltversion.m4
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/m4/lt~obsolete.m4 b/third_party/tcmalloc/vendor/m4/lt~obsolete.m4
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/m4/lt~obsolete.m4
rename to third_party/tcmalloc/vendor/m4/lt~obsolete.m4
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/m4/namespaces.m4 b/third_party/tcmalloc/vendor/m4/namespaces.m4
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/m4/namespaces.m4
rename to third_party/tcmalloc/vendor/m4/namespaces.m4
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/m4/pc_from_ucontext.m4 b/third_party/tcmalloc/vendor/m4/pc_from_ucontext.m4
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/m4/pc_from_ucontext.m4
rename to third_party/tcmalloc/vendor/m4/pc_from_ucontext.m4
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/m4/program_invocation_name.m4 b/third_party/tcmalloc/vendor/m4/program_invocation_name.m4
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/m4/program_invocation_name.m4
rename to third_party/tcmalloc/vendor/m4/program_invocation_name.m4
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/m4/stl_namespace.m4 b/third_party/tcmalloc/vendor/m4/stl_namespace.m4
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/m4/stl_namespace.m4
rename to third_party/tcmalloc/vendor/m4/stl_namespace.m4
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/missing b/third_party/tcmalloc/vendor/missing
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/missing
rename to third_party/tcmalloc/vendor/missing
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/mkinstalldirs b/third_party/tcmalloc/vendor/mkinstalldirs
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/mkinstalldirs
rename to third_party/tcmalloc/vendor/mkinstalldirs
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/packages/deb.sh b/third_party/tcmalloc/vendor/packages/deb.sh
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/packages/deb.sh
rename to third_party/tcmalloc/vendor/packages/deb.sh
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/README b/third_party/tcmalloc/vendor/packages/deb/README
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/README
rename to third_party/tcmalloc/vendor/packages/deb/README
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/changelog b/third_party/tcmalloc/vendor/packages/deb/changelog
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/changelog
rename to third_party/tcmalloc/vendor/packages/deb/changelog
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/compat b/third_party/tcmalloc/vendor/packages/deb/compat
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/compat
rename to third_party/tcmalloc/vendor/packages/deb/compat
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/control b/third_party/tcmalloc/vendor/packages/deb/control
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/control
rename to third_party/tcmalloc/vendor/packages/deb/control
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/copyright b/third_party/tcmalloc/vendor/packages/deb/copyright
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/copyright
rename to third_party/tcmalloc/vendor/packages/deb/copyright
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/docs b/third_party/tcmalloc/vendor/packages/deb/docs
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/docs
rename to third_party/tcmalloc/vendor/packages/deb/docs
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/libgperftools-dev.dirs b/third_party/tcmalloc/vendor/packages/deb/libgperftools-dev.dirs
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/libgperftools-dev.dirs
rename to third_party/tcmalloc/vendor/packages/deb/libgperftools-dev.dirs
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/libgperftools-dev.install b/third_party/tcmalloc/vendor/packages/deb/libgperftools-dev.install
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/libgperftools-dev.install
rename to third_party/tcmalloc/vendor/packages/deb/libgperftools-dev.install
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/libgperftools0.dirs b/third_party/tcmalloc/vendor/packages/deb/libgperftools0.dirs
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/libgperftools0.dirs
rename to third_party/tcmalloc/vendor/packages/deb/libgperftools0.dirs
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/libgperftools0.install b/third_party/tcmalloc/vendor/packages/deb/libgperftools0.install
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/libgperftools0.install
rename to third_party/tcmalloc/vendor/packages/deb/libgperftools0.install
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/libgperftools0.manpages b/third_party/tcmalloc/vendor/packages/deb/libgperftools0.manpages
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/libgperftools0.manpages
rename to third_party/tcmalloc/vendor/packages/deb/libgperftools0.manpages
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/rules b/third_party/tcmalloc/vendor/packages/deb/rules
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/packages/deb/rules
rename to third_party/tcmalloc/vendor/packages/deb/rules
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/packages/rpm.sh b/third_party/tcmalloc/vendor/packages/rpm.sh
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/packages/rpm.sh
rename to third_party/tcmalloc/vendor/packages/rpm.sh
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/packages/rpm/rpm.spec b/third_party/tcmalloc/vendor/packages/rpm/rpm.spec
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/packages/rpm/rpm.spec
rename to third_party/tcmalloc/vendor/packages/rpm/rpm.spec
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/addressmap-inl.h b/third_party/tcmalloc/vendor/src/addressmap-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/addressmap-inl.h
rename to third_party/tcmalloc/vendor/src/addressmap-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/arm_instruction_set_select.h b/third_party/tcmalloc/vendor/src/base/arm_instruction_set_select.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/arm_instruction_set_select.h
rename to third_party/tcmalloc/vendor/src/base/arm_instruction_set_select.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/atomicops-internals-arm-generic.h b/third_party/tcmalloc/vendor/src/base/atomicops-internals-arm-generic.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/atomicops-internals-arm-generic.h
rename to third_party/tcmalloc/vendor/src/base/atomicops-internals-arm-generic.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/atomicops-internals-arm-v6plus.h b/third_party/tcmalloc/vendor/src/base/atomicops-internals-arm-v6plus.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/atomicops-internals-arm-v6plus.h
rename to third_party/tcmalloc/vendor/src/base/atomicops-internals-arm-v6plus.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/atomicops-internals-linuxppc.h b/third_party/tcmalloc/vendor/src/base/atomicops-internals-linuxppc.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/atomicops-internals-linuxppc.h
rename to third_party/tcmalloc/vendor/src/base/atomicops-internals-linuxppc.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/atomicops-internals-macosx.h b/third_party/tcmalloc/vendor/src/base/atomicops-internals-macosx.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/atomicops-internals-macosx.h
rename to third_party/tcmalloc/vendor/src/base/atomicops-internals-macosx.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/atomicops-internals-windows.h b/third_party/tcmalloc/vendor/src/base/atomicops-internals-windows.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/atomicops-internals-windows.h
rename to third_party/tcmalloc/vendor/src/base/atomicops-internals-windows.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/atomicops-internals-x86.cc b/third_party/tcmalloc/vendor/src/base/atomicops-internals-x86.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/atomicops-internals-x86.cc
rename to third_party/tcmalloc/vendor/src/base/atomicops-internals-x86.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/atomicops-internals-x86.h b/third_party/tcmalloc/vendor/src/base/atomicops-internals-x86.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/atomicops-internals-x86.h
rename to third_party/tcmalloc/vendor/src/base/atomicops-internals-x86.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/atomicops.h b/third_party/tcmalloc/vendor/src/base/atomicops.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/atomicops.h
rename to third_party/tcmalloc/vendor/src/base/atomicops.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/basictypes.h b/third_party/tcmalloc/vendor/src/base/basictypes.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/basictypes.h
rename to third_party/tcmalloc/vendor/src/base/basictypes.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/commandlineflags.h b/third_party/tcmalloc/vendor/src/base/commandlineflags.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/commandlineflags.h
rename to third_party/tcmalloc/vendor/src/base/commandlineflags.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/cycleclock.h b/third_party/tcmalloc/vendor/src/base/cycleclock.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/cycleclock.h
rename to third_party/tcmalloc/vendor/src/base/cycleclock.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/dynamic_annotations.c b/third_party/tcmalloc/vendor/src/base/dynamic_annotations.c
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/dynamic_annotations.c
rename to third_party/tcmalloc/vendor/src/base/dynamic_annotations.c
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/dynamic_annotations.h b/third_party/tcmalloc/vendor/src/base/dynamic_annotations.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/dynamic_annotations.h
rename to third_party/tcmalloc/vendor/src/base/dynamic_annotations.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/elf_mem_image.cc b/third_party/tcmalloc/vendor/src/base/elf_mem_image.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/elf_mem_image.cc
rename to third_party/tcmalloc/vendor/src/base/elf_mem_image.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/elf_mem_image.h b/third_party/tcmalloc/vendor/src/base/elf_mem_image.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/elf_mem_image.h
rename to third_party/tcmalloc/vendor/src/base/elf_mem_image.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/elfcore.h b/third_party/tcmalloc/vendor/src/base/elfcore.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/elfcore.h
rename to third_party/tcmalloc/vendor/src/base/elfcore.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/googleinit.h b/third_party/tcmalloc/vendor/src/base/googleinit.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/googleinit.h
rename to third_party/tcmalloc/vendor/src/base/googleinit.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/linux_syscall_support.h b/third_party/tcmalloc/vendor/src/base/linux_syscall_support.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/linux_syscall_support.h
rename to third_party/tcmalloc/vendor/src/base/linux_syscall_support.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/linuxthreads.cc b/third_party/tcmalloc/vendor/src/base/linuxthreads.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/linuxthreads.cc
rename to third_party/tcmalloc/vendor/src/base/linuxthreads.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/linuxthreads.h b/third_party/tcmalloc/vendor/src/base/linuxthreads.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/linuxthreads.h
rename to third_party/tcmalloc/vendor/src/base/linuxthreads.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/logging.cc b/third_party/tcmalloc/vendor/src/base/logging.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/logging.cc
rename to third_party/tcmalloc/vendor/src/base/logging.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/logging.h b/third_party/tcmalloc/vendor/src/base/logging.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/logging.h
rename to third_party/tcmalloc/vendor/src/base/logging.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/low_level_alloc.cc b/third_party/tcmalloc/vendor/src/base/low_level_alloc.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/low_level_alloc.cc
rename to third_party/tcmalloc/vendor/src/base/low_level_alloc.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/low_level_alloc.h b/third_party/tcmalloc/vendor/src/base/low_level_alloc.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/low_level_alloc.h
rename to third_party/tcmalloc/vendor/src/base/low_level_alloc.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/simple_mutex.h b/third_party/tcmalloc/vendor/src/base/simple_mutex.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/simple_mutex.h
rename to third_party/tcmalloc/vendor/src/base/simple_mutex.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/spinlock.cc b/third_party/tcmalloc/vendor/src/base/spinlock.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/spinlock.cc
rename to third_party/tcmalloc/vendor/src/base/spinlock.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/spinlock.h b/third_party/tcmalloc/vendor/src/base/spinlock.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/spinlock.h
rename to third_party/tcmalloc/vendor/src/base/spinlock.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/spinlock_internal.cc b/third_party/tcmalloc/vendor/src/base/spinlock_internal.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/spinlock_internal.cc
rename to third_party/tcmalloc/vendor/src/base/spinlock_internal.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/spinlock_internal.h b/third_party/tcmalloc/vendor/src/base/spinlock_internal.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/spinlock_internal.h
rename to third_party/tcmalloc/vendor/src/base/spinlock_internal.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/spinlock_linux-inl.h b/third_party/tcmalloc/vendor/src/base/spinlock_linux-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/spinlock_linux-inl.h
rename to third_party/tcmalloc/vendor/src/base/spinlock_linux-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/spinlock_posix-inl.h b/third_party/tcmalloc/vendor/src/base/spinlock_posix-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/spinlock_posix-inl.h
rename to third_party/tcmalloc/vendor/src/base/spinlock_posix-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/spinlock_win32-inl.h b/third_party/tcmalloc/vendor/src/base/spinlock_win32-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/spinlock_win32-inl.h
rename to third_party/tcmalloc/vendor/src/base/spinlock_win32-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/stl_allocator.h b/third_party/tcmalloc/vendor/src/base/stl_allocator.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/stl_allocator.h
rename to third_party/tcmalloc/vendor/src/base/stl_allocator.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/synchronization_profiling.h b/third_party/tcmalloc/vendor/src/base/synchronization_profiling.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/synchronization_profiling.h
rename to third_party/tcmalloc/vendor/src/base/synchronization_profiling.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/sysinfo.cc b/third_party/tcmalloc/vendor/src/base/sysinfo.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/sysinfo.cc
rename to third_party/tcmalloc/vendor/src/base/sysinfo.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/sysinfo.h b/third_party/tcmalloc/vendor/src/base/sysinfo.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/sysinfo.h
rename to third_party/tcmalloc/vendor/src/base/sysinfo.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/thread_annotations.h b/third_party/tcmalloc/vendor/src/base/thread_annotations.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/thread_annotations.h
rename to third_party/tcmalloc/vendor/src/base/thread_annotations.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/thread_lister.c b/third_party/tcmalloc/vendor/src/base/thread_lister.c
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/thread_lister.c
rename to third_party/tcmalloc/vendor/src/base/thread_lister.c
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/thread_lister.h b/third_party/tcmalloc/vendor/src/base/thread_lister.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/thread_lister.h
rename to third_party/tcmalloc/vendor/src/base/thread_lister.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/vdso_support.cc b/third_party/tcmalloc/vendor/src/base/vdso_support.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/vdso_support.cc
rename to third_party/tcmalloc/vendor/src/base/vdso_support.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/base/vdso_support.h b/third_party/tcmalloc/vendor/src/base/vdso_support.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/base/vdso_support.h
rename to third_party/tcmalloc/vendor/src/base/vdso_support.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/central_freelist.cc b/third_party/tcmalloc/vendor/src/central_freelist.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/central_freelist.cc
rename to third_party/tcmalloc/vendor/src/central_freelist.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/central_freelist.h b/third_party/tcmalloc/vendor/src/central_freelist.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/central_freelist.h
rename to third_party/tcmalloc/vendor/src/central_freelist.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/common.cc b/third_party/tcmalloc/vendor/src/common.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/common.cc
rename to third_party/tcmalloc/vendor/src/common.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/common.h b/third_party/tcmalloc/vendor/src/common.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/common.h
rename to third_party/tcmalloc/vendor/src/common.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/config.h.in b/third_party/tcmalloc/vendor/src/config.h.in
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/config.h.in
rename to third_party/tcmalloc/vendor/src/config.h.in
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/config_for_unittests.h b/third_party/tcmalloc/vendor/src/config_for_unittests.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/config_for_unittests.h
rename to third_party/tcmalloc/vendor/src/config_for_unittests.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/debugallocation.cc b/third_party/tcmalloc/vendor/src/debugallocation.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/debugallocation.cc
rename to third_party/tcmalloc/vendor/src/debugallocation.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/getpc.h b/third_party/tcmalloc/vendor/src/getpc.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/getpc.h
rename to third_party/tcmalloc/vendor/src/getpc.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/google/heap-checker.h b/third_party/tcmalloc/vendor/src/google/heap-checker.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/google/heap-checker.h
rename to third_party/tcmalloc/vendor/src/google/heap-checker.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/google/heap-profiler.h b/third_party/tcmalloc/vendor/src/google/heap-profiler.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/google/heap-profiler.h
rename to third_party/tcmalloc/vendor/src/google/heap-profiler.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/google/malloc_extension.h b/third_party/tcmalloc/vendor/src/google/malloc_extension.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/google/malloc_extension.h
rename to third_party/tcmalloc/vendor/src/google/malloc_extension.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/google/malloc_extension_c.h b/third_party/tcmalloc/vendor/src/google/malloc_extension_c.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/google/malloc_extension_c.h
rename to third_party/tcmalloc/vendor/src/google/malloc_extension_c.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/google/malloc_hook.h b/third_party/tcmalloc/vendor/src/google/malloc_hook.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/google/malloc_hook.h
rename to third_party/tcmalloc/vendor/src/google/malloc_hook.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/google/malloc_hook_c.h b/third_party/tcmalloc/vendor/src/google/malloc_hook_c.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/google/malloc_hook_c.h
rename to third_party/tcmalloc/vendor/src/google/malloc_hook_c.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/google/profiler.h b/third_party/tcmalloc/vendor/src/google/profiler.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/google/profiler.h
rename to third_party/tcmalloc/vendor/src/google/profiler.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/google/stacktrace.h b/third_party/tcmalloc/vendor/src/google/stacktrace.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/google/stacktrace.h
rename to third_party/tcmalloc/vendor/src/google/stacktrace.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/google/tcmalloc.h b/third_party/tcmalloc/vendor/src/google/tcmalloc.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/google/tcmalloc.h
rename to third_party/tcmalloc/vendor/src/google/tcmalloc.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/gperftools/heap-checker.h b/third_party/tcmalloc/vendor/src/gperftools/heap-checker.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/gperftools/heap-checker.h
rename to third_party/tcmalloc/vendor/src/gperftools/heap-checker.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/gperftools/heap-profiler.h b/third_party/tcmalloc/vendor/src/gperftools/heap-profiler.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/gperftools/heap-profiler.h
rename to third_party/tcmalloc/vendor/src/gperftools/heap-profiler.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/gperftools/malloc_extension.h b/third_party/tcmalloc/vendor/src/gperftools/malloc_extension.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/gperftools/malloc_extension.h
rename to third_party/tcmalloc/vendor/src/gperftools/malloc_extension.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/gperftools/malloc_extension_c.h b/third_party/tcmalloc/vendor/src/gperftools/malloc_extension_c.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/gperftools/malloc_extension_c.h
rename to third_party/tcmalloc/vendor/src/gperftools/malloc_extension_c.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/gperftools/malloc_hook.h b/third_party/tcmalloc/vendor/src/gperftools/malloc_hook.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/gperftools/malloc_hook.h
rename to third_party/tcmalloc/vendor/src/gperftools/malloc_hook.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/gperftools/malloc_hook_c.h b/third_party/tcmalloc/vendor/src/gperftools/malloc_hook_c.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/gperftools/malloc_hook_c.h
rename to third_party/tcmalloc/vendor/src/gperftools/malloc_hook_c.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/gperftools/profiler.h b/third_party/tcmalloc/vendor/src/gperftools/profiler.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/gperftools/profiler.h
rename to third_party/tcmalloc/vendor/src/gperftools/profiler.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/gperftools/stacktrace.h b/third_party/tcmalloc/vendor/src/gperftools/stacktrace.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/gperftools/stacktrace.h
rename to third_party/tcmalloc/vendor/src/gperftools/stacktrace.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/gperftools/tcmalloc.h.in b/third_party/tcmalloc/vendor/src/gperftools/tcmalloc.h.in
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/gperftools/tcmalloc.h.in
rename to third_party/tcmalloc/vendor/src/gperftools/tcmalloc.h.in
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/heap-checker-bcad.cc b/third_party/tcmalloc/vendor/src/heap-checker-bcad.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/heap-checker-bcad.cc
rename to third_party/tcmalloc/vendor/src/heap-checker-bcad.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/heap-checker.cc b/third_party/tcmalloc/vendor/src/heap-checker.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/heap-checker.cc
rename to third_party/tcmalloc/vendor/src/heap-checker.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/heap-profile-table.cc b/third_party/tcmalloc/vendor/src/heap-profile-table.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/heap-profile-table.cc
rename to third_party/tcmalloc/vendor/src/heap-profile-table.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/heap-profile-table.h b/third_party/tcmalloc/vendor/src/heap-profile-table.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/heap-profile-table.h
rename to third_party/tcmalloc/vendor/src/heap-profile-table.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/heap-profiler.cc b/third_party/tcmalloc/vendor/src/heap-profiler.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/heap-profiler.cc
rename to third_party/tcmalloc/vendor/src/heap-profiler.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/internal_logging.cc b/third_party/tcmalloc/vendor/src/internal_logging.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/internal_logging.cc
rename to third_party/tcmalloc/vendor/src/internal_logging.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/internal_logging.h b/third_party/tcmalloc/vendor/src/internal_logging.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/internal_logging.h
rename to third_party/tcmalloc/vendor/src/internal_logging.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/libc_override.h b/third_party/tcmalloc/vendor/src/libc_override.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/libc_override.h
rename to third_party/tcmalloc/vendor/src/libc_override.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/libc_override_gcc_and_weak.h b/third_party/tcmalloc/vendor/src/libc_override_gcc_and_weak.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/libc_override_gcc_and_weak.h
rename to third_party/tcmalloc/vendor/src/libc_override_gcc_and_weak.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/libc_override_glibc.h b/third_party/tcmalloc/vendor/src/libc_override_glibc.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/libc_override_glibc.h
rename to third_party/tcmalloc/vendor/src/libc_override_glibc.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/libc_override_osx.h b/third_party/tcmalloc/vendor/src/libc_override_osx.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/libc_override_osx.h
rename to third_party/tcmalloc/vendor/src/libc_override_osx.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/libc_override_redefine.h b/third_party/tcmalloc/vendor/src/libc_override_redefine.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/libc_override_redefine.h
rename to third_party/tcmalloc/vendor/src/libc_override_redefine.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/linked_list.h b/third_party/tcmalloc/vendor/src/linked_list.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/linked_list.h
rename to third_party/tcmalloc/vendor/src/linked_list.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/malloc_extension.cc b/third_party/tcmalloc/vendor/src/malloc_extension.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/malloc_extension.cc
rename to third_party/tcmalloc/vendor/src/malloc_extension.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/malloc_hook-inl.h b/third_party/tcmalloc/vendor/src/malloc_hook-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/malloc_hook-inl.h
rename to third_party/tcmalloc/vendor/src/malloc_hook-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/malloc_hook.cc b/third_party/tcmalloc/vendor/src/malloc_hook.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/malloc_hook.cc
rename to third_party/tcmalloc/vendor/src/malloc_hook.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/malloc_hook_mmap_freebsd.h b/third_party/tcmalloc/vendor/src/malloc_hook_mmap_freebsd.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/malloc_hook_mmap_freebsd.h
rename to third_party/tcmalloc/vendor/src/malloc_hook_mmap_freebsd.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/malloc_hook_mmap_linux.h b/third_party/tcmalloc/vendor/src/malloc_hook_mmap_linux.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/malloc_hook_mmap_linux.h
rename to third_party/tcmalloc/vendor/src/malloc_hook_mmap_linux.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/maybe_threads.cc b/third_party/tcmalloc/vendor/src/maybe_threads.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/maybe_threads.cc
rename to third_party/tcmalloc/vendor/src/maybe_threads.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/maybe_threads.h b/third_party/tcmalloc/vendor/src/maybe_threads.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/maybe_threads.h
rename to third_party/tcmalloc/vendor/src/maybe_threads.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/memfs_malloc.cc b/third_party/tcmalloc/vendor/src/memfs_malloc.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/memfs_malloc.cc
rename to third_party/tcmalloc/vendor/src/memfs_malloc.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/memory_region_map.cc b/third_party/tcmalloc/vendor/src/memory_region_map.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/memory_region_map.cc
rename to third_party/tcmalloc/vendor/src/memory_region_map.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/memory_region_map.h b/third_party/tcmalloc/vendor/src/memory_region_map.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/memory_region_map.h
rename to third_party/tcmalloc/vendor/src/memory_region_map.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/packed-cache-inl.h b/third_party/tcmalloc/vendor/src/packed-cache-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/packed-cache-inl.h
rename to third_party/tcmalloc/vendor/src/packed-cache-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/page_heap.cc b/third_party/tcmalloc/vendor/src/page_heap.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/page_heap.cc
rename to third_party/tcmalloc/vendor/src/page_heap.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/page_heap.h b/third_party/tcmalloc/vendor/src/page_heap.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/page_heap.h
rename to third_party/tcmalloc/vendor/src/page_heap.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/page_heap_allocator.h b/third_party/tcmalloc/vendor/src/page_heap_allocator.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/page_heap_allocator.h
rename to third_party/tcmalloc/vendor/src/page_heap_allocator.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/pagemap.h b/third_party/tcmalloc/vendor/src/pagemap.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/pagemap.h
rename to third_party/tcmalloc/vendor/src/pagemap.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/pprof b/third_party/tcmalloc/vendor/src/pprof
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/pprof
rename to third_party/tcmalloc/vendor/src/pprof
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/profile-handler.cc b/third_party/tcmalloc/vendor/src/profile-handler.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/profile-handler.cc
rename to third_party/tcmalloc/vendor/src/profile-handler.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/profile-handler.h b/third_party/tcmalloc/vendor/src/profile-handler.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/profile-handler.h
rename to third_party/tcmalloc/vendor/src/profile-handler.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/profiledata.cc b/third_party/tcmalloc/vendor/src/profiledata.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/profiledata.cc
rename to third_party/tcmalloc/vendor/src/profiledata.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/profiledata.h b/third_party/tcmalloc/vendor/src/profiledata.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/profiledata.h
rename to third_party/tcmalloc/vendor/src/profiledata.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/profiler.cc b/third_party/tcmalloc/vendor/src/profiler.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/profiler.cc
rename to third_party/tcmalloc/vendor/src/profiler.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/raw_printer.cc b/third_party/tcmalloc/vendor/src/raw_printer.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/raw_printer.cc
rename to third_party/tcmalloc/vendor/src/raw_printer.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/raw_printer.h b/third_party/tcmalloc/vendor/src/raw_printer.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/raw_printer.h
rename to third_party/tcmalloc/vendor/src/raw_printer.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/sampler.cc b/third_party/tcmalloc/vendor/src/sampler.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/sampler.cc
rename to third_party/tcmalloc/vendor/src/sampler.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/sampler.h b/third_party/tcmalloc/vendor/src/sampler.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/sampler.h
rename to third_party/tcmalloc/vendor/src/sampler.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/solaris/libstdc++.la b/third_party/tcmalloc/vendor/src/solaris/libstdc++.la
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/solaris/libstdc++.la
rename to third_party/tcmalloc/vendor/src/solaris/libstdc++.la
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/span.cc b/third_party/tcmalloc/vendor/src/span.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/span.cc
rename to third_party/tcmalloc/vendor/src/span.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/span.h b/third_party/tcmalloc/vendor/src/span.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/span.h
rename to third_party/tcmalloc/vendor/src/span.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/stack_trace_table.cc b/third_party/tcmalloc/vendor/src/stack_trace_table.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/stack_trace_table.cc
rename to third_party/tcmalloc/vendor/src/stack_trace_table.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/stack_trace_table.h b/third_party/tcmalloc/vendor/src/stack_trace_table.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/stack_trace_table.h
rename to third_party/tcmalloc/vendor/src/stack_trace_table.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/stacktrace.cc b/third_party/tcmalloc/vendor/src/stacktrace.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/stacktrace.cc
rename to third_party/tcmalloc/vendor/src/stacktrace.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/stacktrace_arm-inl.h b/third_party/tcmalloc/vendor/src/stacktrace_arm-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/stacktrace_arm-inl.h
rename to third_party/tcmalloc/vendor/src/stacktrace_arm-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/stacktrace_config.h b/third_party/tcmalloc/vendor/src/stacktrace_config.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/stacktrace_config.h
rename to third_party/tcmalloc/vendor/src/stacktrace_config.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/stacktrace_generic-inl.h b/third_party/tcmalloc/vendor/src/stacktrace_generic-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/stacktrace_generic-inl.h
rename to third_party/tcmalloc/vendor/src/stacktrace_generic-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/stacktrace_libunwind-inl.h b/third_party/tcmalloc/vendor/src/stacktrace_libunwind-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/stacktrace_libunwind-inl.h
rename to third_party/tcmalloc/vendor/src/stacktrace_libunwind-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/stacktrace_powerpc-inl.h b/third_party/tcmalloc/vendor/src/stacktrace_powerpc-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/stacktrace_powerpc-inl.h
rename to third_party/tcmalloc/vendor/src/stacktrace_powerpc-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/stacktrace_win32-inl.h b/third_party/tcmalloc/vendor/src/stacktrace_win32-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/stacktrace_win32-inl.h
rename to third_party/tcmalloc/vendor/src/stacktrace_win32-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/stacktrace_x86-inl.h b/third_party/tcmalloc/vendor/src/stacktrace_x86-inl.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/stacktrace_x86-inl.h
rename to third_party/tcmalloc/vendor/src/stacktrace_x86-inl.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/static_vars.cc b/third_party/tcmalloc/vendor/src/static_vars.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/static_vars.cc
rename to third_party/tcmalloc/vendor/src/static_vars.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/static_vars.h b/third_party/tcmalloc/vendor/src/static_vars.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/static_vars.h
rename to third_party/tcmalloc/vendor/src/static_vars.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/symbolize.cc b/third_party/tcmalloc/vendor/src/symbolize.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/symbolize.cc
rename to third_party/tcmalloc/vendor/src/symbolize.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/symbolize.h b/third_party/tcmalloc/vendor/src/symbolize.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/symbolize.h
rename to third_party/tcmalloc/vendor/src/symbolize.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/system-alloc.cc b/third_party/tcmalloc/vendor/src/system-alloc.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/system-alloc.cc
rename to third_party/tcmalloc/vendor/src/system-alloc.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/system-alloc.h b/third_party/tcmalloc/vendor/src/system-alloc.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/system-alloc.h
rename to third_party/tcmalloc/vendor/src/system-alloc.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tcmalloc.cc b/third_party/tcmalloc/vendor/src/tcmalloc.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tcmalloc.cc
rename to third_party/tcmalloc/vendor/src/tcmalloc.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tcmalloc.h b/third_party/tcmalloc/vendor/src/tcmalloc.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tcmalloc.h
rename to third_party/tcmalloc/vendor/src/tcmalloc.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tcmalloc_guard.h b/third_party/tcmalloc/vendor/src/tcmalloc_guard.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tcmalloc_guard.h
rename to third_party/tcmalloc/vendor/src/tcmalloc_guard.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/addressmap_unittest.cc b/third_party/tcmalloc/vendor/src/tests/addressmap_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/addressmap_unittest.cc
rename to third_party/tcmalloc/vendor/src/tests/addressmap_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/atomicops_unittest.cc b/third_party/tcmalloc/vendor/src/tests/atomicops_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/atomicops_unittest.cc
rename to third_party/tcmalloc/vendor/src/tests/atomicops_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/current_allocated_bytes_test.cc b/third_party/tcmalloc/vendor/src/tests/current_allocated_bytes_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/current_allocated_bytes_test.cc
rename to third_party/tcmalloc/vendor/src/tests/current_allocated_bytes_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/debugallocation_test.cc b/third_party/tcmalloc/vendor/src/tests/debugallocation_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/debugallocation_test.cc
rename to third_party/tcmalloc/vendor/src/tests/debugallocation_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/debugallocation_test.sh b/third_party/tcmalloc/vendor/src/tests/debugallocation_test.sh
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/debugallocation_test.sh
rename to third_party/tcmalloc/vendor/src/tests/debugallocation_test.sh
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/frag_unittest.cc b/third_party/tcmalloc/vendor/src/tests/frag_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/frag_unittest.cc
rename to third_party/tcmalloc/vendor/src/tests/frag_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/getpc_test.cc b/third_party/tcmalloc/vendor/src/tests/getpc_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/getpc_test.cc
rename to third_party/tcmalloc/vendor/src/tests/getpc_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/heap-checker-death_unittest.sh b/third_party/tcmalloc/vendor/src/tests/heap-checker-death_unittest.sh
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/heap-checker-death_unittest.sh
rename to third_party/tcmalloc/vendor/src/tests/heap-checker-death_unittest.sh
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/heap-checker_unittest.cc b/third_party/tcmalloc/vendor/src/tests/heap-checker_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/heap-checker_unittest.cc
rename to third_party/tcmalloc/vendor/src/tests/heap-checker_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/heap-checker_unittest.sh b/third_party/tcmalloc/vendor/src/tests/heap-checker_unittest.sh
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/heap-checker_unittest.sh
rename to third_party/tcmalloc/vendor/src/tests/heap-checker_unittest.sh
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/heap-profiler_unittest.cc b/third_party/tcmalloc/vendor/src/tests/heap-profiler_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/heap-profiler_unittest.cc
rename to third_party/tcmalloc/vendor/src/tests/heap-profiler_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/heap-profiler_unittest.sh b/third_party/tcmalloc/vendor/src/tests/heap-profiler_unittest.sh
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/heap-profiler_unittest.sh
rename to third_party/tcmalloc/vendor/src/tests/heap-profiler_unittest.sh
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/low_level_alloc_unittest.cc b/third_party/tcmalloc/vendor/src/tests/low_level_alloc_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/low_level_alloc_unittest.cc
rename to third_party/tcmalloc/vendor/src/tests/low_level_alloc_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/malloc_extension_c_test.c b/third_party/tcmalloc/vendor/src/tests/malloc_extension_c_test.c
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/malloc_extension_c_test.c
rename to third_party/tcmalloc/vendor/src/tests/malloc_extension_c_test.c
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/malloc_extension_test.cc b/third_party/tcmalloc/vendor/src/tests/malloc_extension_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/malloc_extension_test.cc
rename to third_party/tcmalloc/vendor/src/tests/malloc_extension_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/malloc_hook_test.cc b/third_party/tcmalloc/vendor/src/tests/malloc_hook_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/malloc_hook_test.cc
rename to third_party/tcmalloc/vendor/src/tests/malloc_hook_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/markidle_unittest.cc b/third_party/tcmalloc/vendor/src/tests/markidle_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/markidle_unittest.cc
rename to third_party/tcmalloc/vendor/src/tests/markidle_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/maybe_threads_unittest.sh b/third_party/tcmalloc/vendor/src/tests/maybe_threads_unittest.sh
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/maybe_threads_unittest.sh
rename to third_party/tcmalloc/vendor/src/tests/maybe_threads_unittest.sh
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/memalign_unittest.cc b/third_party/tcmalloc/vendor/src/tests/memalign_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/memalign_unittest.cc
rename to third_party/tcmalloc/vendor/src/tests/memalign_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/packed-cache_test.cc b/third_party/tcmalloc/vendor/src/tests/packed-cache_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/packed-cache_test.cc
rename to third_party/tcmalloc/vendor/src/tests/packed-cache_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/page_heap_test.cc b/third_party/tcmalloc/vendor/src/tests/page_heap_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/page_heap_test.cc
rename to third_party/tcmalloc/vendor/src/tests/page_heap_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/pagemap_unittest.cc b/third_party/tcmalloc/vendor/src/tests/pagemap_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/pagemap_unittest.cc
rename to third_party/tcmalloc/vendor/src/tests/pagemap_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/profile-handler_unittest.cc b/third_party/tcmalloc/vendor/src/tests/profile-handler_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/profile-handler_unittest.cc
rename to third_party/tcmalloc/vendor/src/tests/profile-handler_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/profiledata_unittest.cc b/third_party/tcmalloc/vendor/src/tests/profiledata_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/profiledata_unittest.cc
rename to third_party/tcmalloc/vendor/src/tests/profiledata_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/profiler_unittest.cc b/third_party/tcmalloc/vendor/src/tests/profiler_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/profiler_unittest.cc
rename to third_party/tcmalloc/vendor/src/tests/profiler_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/profiler_unittest.sh b/third_party/tcmalloc/vendor/src/tests/profiler_unittest.sh
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/profiler_unittest.sh
rename to third_party/tcmalloc/vendor/src/tests/profiler_unittest.sh
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/raw_printer_test.cc b/third_party/tcmalloc/vendor/src/tests/raw_printer_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/raw_printer_test.cc
rename to third_party/tcmalloc/vendor/src/tests/raw_printer_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/realloc_unittest.cc b/third_party/tcmalloc/vendor/src/tests/realloc_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/realloc_unittest.cc
rename to third_party/tcmalloc/vendor/src/tests/realloc_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/sampler_test.cc b/third_party/tcmalloc/vendor/src/tests/sampler_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/sampler_test.cc
rename to third_party/tcmalloc/vendor/src/tests/sampler_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/sampling_test.cc b/third_party/tcmalloc/vendor/src/tests/sampling_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/sampling_test.cc
rename to third_party/tcmalloc/vendor/src/tests/sampling_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/sampling_test.sh b/third_party/tcmalloc/vendor/src/tests/sampling_test.sh
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/sampling_test.sh
rename to third_party/tcmalloc/vendor/src/tests/sampling_test.sh
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/simple_compat_test.cc b/third_party/tcmalloc/vendor/src/tests/simple_compat_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/simple_compat_test.cc
rename to third_party/tcmalloc/vendor/src/tests/simple_compat_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/stack_trace_table_test.cc b/third_party/tcmalloc/vendor/src/tests/stack_trace_table_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/stack_trace_table_test.cc
rename to third_party/tcmalloc/vendor/src/tests/stack_trace_table_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/stacktrace_unittest.cc b/third_party/tcmalloc/vendor/src/tests/stacktrace_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/stacktrace_unittest.cc
rename to third_party/tcmalloc/vendor/src/tests/stacktrace_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/system-alloc_unittest.cc b/third_party/tcmalloc/vendor/src/tests/system-alloc_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/system-alloc_unittest.cc
rename to third_party/tcmalloc/vendor/src/tests/system-alloc_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/tcmalloc_large_unittest.cc b/third_party/tcmalloc/vendor/src/tests/tcmalloc_large_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/tcmalloc_large_unittest.cc
rename to third_party/tcmalloc/vendor/src/tests/tcmalloc_large_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/tcmalloc_unittest.cc b/third_party/tcmalloc/vendor/src/tests/tcmalloc_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/tcmalloc_unittest.cc
rename to third_party/tcmalloc/vendor/src/tests/tcmalloc_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/testutil.cc b/third_party/tcmalloc/vendor/src/tests/testutil.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/testutil.cc
rename to third_party/tcmalloc/vendor/src/tests/testutil.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/testutil.h b/third_party/tcmalloc/vendor/src/tests/testutil.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/testutil.h
rename to third_party/tcmalloc/vendor/src/tests/testutil.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/tests/thread_dealloc_unittest.cc b/third_party/tcmalloc/vendor/src/tests/thread_dealloc_unittest.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/tests/thread_dealloc_unittest.cc
rename to third_party/tcmalloc/vendor/src/tests/thread_dealloc_unittest.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/third_party/valgrind.h b/third_party/tcmalloc/vendor/src/third_party/valgrind.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/third_party/valgrind.h
rename to third_party/tcmalloc/vendor/src/third_party/valgrind.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/thread_cache.cc b/third_party/tcmalloc/vendor/src/thread_cache.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/thread_cache.cc
rename to third_party/tcmalloc/vendor/src/thread_cache.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/thread_cache.h b/third_party/tcmalloc/vendor/src/thread_cache.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/thread_cache.h
rename to third_party/tcmalloc/vendor/src/thread_cache.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/TODO b/third_party/tcmalloc/vendor/src/windows/TODO
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/TODO
rename to third_party/tcmalloc/vendor/src/windows/TODO
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/addr2line-pdb.c b/third_party/tcmalloc/vendor/src/windows/addr2line-pdb.c
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/addr2line-pdb.c
rename to third_party/tcmalloc/vendor/src/windows/addr2line-pdb.c
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/auto_testing_hook.h b/third_party/tcmalloc/vendor/src/windows/auto_testing_hook.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/auto_testing_hook.h
rename to third_party/tcmalloc/vendor/src/windows/auto_testing_hook.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/config.h b/third_party/tcmalloc/vendor/src/windows/config.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/config.h
rename to third_party/tcmalloc/vendor/src/windows/config.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/get_mangled_names.cc b/third_party/tcmalloc/vendor/src/windows/get_mangled_names.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/get_mangled_names.cc
rename to third_party/tcmalloc/vendor/src/windows/get_mangled_names.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/google/tcmalloc.h b/third_party/tcmalloc/vendor/src/windows/google/tcmalloc.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/google/tcmalloc.h
rename to third_party/tcmalloc/vendor/src/windows/google/tcmalloc.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/gperftools/tcmalloc.h b/third_party/tcmalloc/vendor/src/windows/gperftools/tcmalloc.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/gperftools/tcmalloc.h
rename to third_party/tcmalloc/vendor/src/windows/gperftools/tcmalloc.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/gperftools/tcmalloc.h.in b/third_party/tcmalloc/vendor/src/windows/gperftools/tcmalloc.h.in
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/gperftools/tcmalloc.h.in
rename to third_party/tcmalloc/vendor/src/windows/gperftools/tcmalloc.h.in
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/ia32_modrm_map.cc b/third_party/tcmalloc/vendor/src/windows/ia32_modrm_map.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/ia32_modrm_map.cc
rename to third_party/tcmalloc/vendor/src/windows/ia32_modrm_map.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/ia32_opcode_map.cc b/third_party/tcmalloc/vendor/src/windows/ia32_opcode_map.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/ia32_opcode_map.cc
rename to third_party/tcmalloc/vendor/src/windows/ia32_opcode_map.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/mingw.h b/third_party/tcmalloc/vendor/src/windows/mingw.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/mingw.h
rename to third_party/tcmalloc/vendor/src/windows/mingw.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/mini_disassembler.cc b/third_party/tcmalloc/vendor/src/windows/mini_disassembler.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/mini_disassembler.cc
rename to third_party/tcmalloc/vendor/src/windows/mini_disassembler.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/mini_disassembler.h b/third_party/tcmalloc/vendor/src/windows/mini_disassembler.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/mini_disassembler.h
rename to third_party/tcmalloc/vendor/src/windows/mini_disassembler.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/mini_disassembler_types.h b/third_party/tcmalloc/vendor/src/windows/mini_disassembler_types.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/mini_disassembler_types.h
rename to third_party/tcmalloc/vendor/src/windows/mini_disassembler_types.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/nm-pdb.c b/third_party/tcmalloc/vendor/src/windows/nm-pdb.c
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/nm-pdb.c
rename to third_party/tcmalloc/vendor/src/windows/nm-pdb.c
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/override_functions.cc b/third_party/tcmalloc/vendor/src/windows/override_functions.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/override_functions.cc
rename to third_party/tcmalloc/vendor/src/windows/override_functions.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/patch_functions.cc b/third_party/tcmalloc/vendor/src/windows/patch_functions.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/patch_functions.cc
rename to third_party/tcmalloc/vendor/src/windows/patch_functions.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/port.cc b/third_party/tcmalloc/vendor/src/windows/port.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/port.cc
rename to third_party/tcmalloc/vendor/src/windows/port.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/port.h b/third_party/tcmalloc/vendor/src/windows/port.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/port.h
rename to third_party/tcmalloc/vendor/src/windows/port.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/preamble_patcher.cc b/third_party/tcmalloc/vendor/src/windows/preamble_patcher.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/preamble_patcher.cc
rename to third_party/tcmalloc/vendor/src/windows/preamble_patcher.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/preamble_patcher.h b/third_party/tcmalloc/vendor/src/windows/preamble_patcher.h
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/preamble_patcher.h
rename to third_party/tcmalloc/vendor/src/windows/preamble_patcher.h
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/preamble_patcher_test.cc b/third_party/tcmalloc/vendor/src/windows/preamble_patcher_test.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/preamble_patcher_test.cc
rename to third_party/tcmalloc/vendor/src/windows/preamble_patcher_test.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/preamble_patcher_with_stub.cc b/third_party/tcmalloc/vendor/src/windows/preamble_patcher_with_stub.cc
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/preamble_patcher_with_stub.cc
rename to third_party/tcmalloc/vendor/src/windows/preamble_patcher_with_stub.cc
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/src/windows/shortproc.asm b/third_party/tcmalloc/vendor/src/windows/shortproc.asm
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/src/windows/shortproc.asm
rename to third_party/tcmalloc/vendor/src/windows/shortproc.asm
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/addr2line-pdb/addr2line-pdb.vcproj b/third_party/tcmalloc/vendor/vsprojects/addr2line-pdb/addr2line-pdb.vcproj
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/addr2line-pdb/addr2line-pdb.vcproj
rename to third_party/tcmalloc/vendor/vsprojects/addr2line-pdb/addr2line-pdb.vcproj
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/addressmap_unittest/addressmap_unittest.vcproj b/third_party/tcmalloc/vendor/vsprojects/addressmap_unittest/addressmap_unittest.vcproj
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/addressmap_unittest/addressmap_unittest.vcproj
rename to third_party/tcmalloc/vendor/vsprojects/addressmap_unittest/addressmap_unittest.vcproj
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/frag_unittest/frag_unittest.vcproj b/third_party/tcmalloc/vendor/vsprojects/frag_unittest/frag_unittest.vcproj
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/frag_unittest/frag_unittest.vcproj
rename to third_party/tcmalloc/vendor/vsprojects/frag_unittest/frag_unittest.vcproj
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj b/third_party/tcmalloc/vendor/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj
rename to third_party/tcmalloc/vendor/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj b/third_party/tcmalloc/vendor/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj
rename to third_party/tcmalloc/vendor/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/malloc_extension_test/malloc_extension_test.vcproj b/third_party/tcmalloc/vendor/vsprojects/malloc_extension_test/malloc_extension_test.vcproj
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/malloc_extension_test/malloc_extension_test.vcproj
rename to third_party/tcmalloc/vendor/vsprojects/malloc_extension_test/malloc_extension_test.vcproj
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/markidle_unittest/markidle_unittest.vcproj b/third_party/tcmalloc/vendor/vsprojects/markidle_unittest/markidle_unittest.vcproj
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/markidle_unittest/markidle_unittest.vcproj
rename to third_party/tcmalloc/vendor/vsprojects/markidle_unittest/markidle_unittest.vcproj
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/nm-pdb/nm-pdb.vcproj b/third_party/tcmalloc/vendor/vsprojects/nm-pdb/nm-pdb.vcproj
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/nm-pdb/nm-pdb.vcproj
rename to third_party/tcmalloc/vendor/vsprojects/nm-pdb/nm-pdb.vcproj
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/packed-cache_test/packed-cache_test.vcproj b/third_party/tcmalloc/vendor/vsprojects/packed-cache_test/packed-cache_test.vcproj
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/packed-cache_test/packed-cache_test.vcproj
rename to third_party/tcmalloc/vendor/vsprojects/packed-cache_test/packed-cache_test.vcproj
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/page_heap_test/page_heap_test.vcproj b/third_party/tcmalloc/vendor/vsprojects/page_heap_test/page_heap_test.vcproj
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/page_heap_test/page_heap_test.vcproj
rename to third_party/tcmalloc/vendor/vsprojects/page_heap_test/page_heap_test.vcproj
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/pagemap_unittest/pagemap_unittest.vcproj b/third_party/tcmalloc/vendor/vsprojects/pagemap_unittest/pagemap_unittest.vcproj
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/pagemap_unittest/pagemap_unittest.vcproj
rename to third_party/tcmalloc/vendor/vsprojects/pagemap_unittest/pagemap_unittest.vcproj
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/realloc_unittest/realloc_unittest.vcproj b/third_party/tcmalloc/vendor/vsprojects/realloc_unittest/realloc_unittest.vcproj
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/realloc_unittest/realloc_unittest.vcproj
rename to third_party/tcmalloc/vendor/vsprojects/realloc_unittest/realloc_unittest.vcproj
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/sampler_test/sampler_test.vcproj b/third_party/tcmalloc/vendor/vsprojects/sampler_test/sampler_test.vcproj
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/sampler_test/sampler_test.vcproj
rename to third_party/tcmalloc/vendor/vsprojects/sampler_test/sampler_test.vcproj
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/stack_trace_table_test/stack_trace_table_test.vcproj b/third_party/tcmalloc/vendor/vsprojects/stack_trace_table_test/stack_trace_table_test.vcproj
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/stack_trace_table_test/stack_trace_table_test.vcproj
rename to third_party/tcmalloc/vendor/vsprojects/stack_trace_table_test/stack_trace_table_test.vcproj
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj b/third_party/tcmalloc/vendor/vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj
rename to third_party/tcmalloc/vendor/vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcproj b/third_party/tcmalloc/vendor/vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcproj
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcproj
rename to third_party/tcmalloc/vendor/vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcproj
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcproj b/third_party/tcmalloc/vendor/vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcproj
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcproj
rename to third_party/tcmalloc/vendor/vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcproj
diff --git a/third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/tmu-static/tmu-static.vcproj b/third_party/tcmalloc/vendor/vsprojects/tmu-static/tmu-static.vcproj
similarity index 100%
rename from third_party/tcmalloc/gperftools-2.0/vendor/vsprojects/tmu-static/tmu-static.vcproj
rename to third_party/tcmalloc/vendor/vsprojects/tmu-static/tmu-static.vcproj
diff --git a/tools/binary_size/libsupersize/html_report.py b/tools/binary_size/libsupersize/html_report.py
index 6f088b6..abb3f6d 100644
--- a/tools/binary_size/libsupersize/html_report.py
+++ b/tools/binary_size/libsupersize/html_report.py
@@ -61,6 +61,18 @@
 # graphing lib.
 _BIG_BUCKET_LIMIT = 3000
 
+_TEMPLATE_FILES = [
+  'index.html',
+  'favicon.ico',
+  'options.css',
+  'infocard.css',
+  'shared.js',
+  'state.js',
+  'infocard-ui.js',
+  'tree-ui.js',
+  'tree-worker.js',
+]
+
 
 def _GetOrMakeChildNode(node, node_type, name):
   child = node[_NODE_CHILDREN_KEY].get(name)
@@ -333,14 +345,8 @@
     KeyError: thrown if a variable tag does not have a corresponding kwarg.
   """
   _MakeDirIfDoesNotExist(dest_dir)
-  shutil.copy(os.path.join(template_src, 'index.html'), dest_dir)
-  shutil.copy(os.path.join(template_src, 'options.css'), dest_dir)
-  shutil.copy(os.path.join(template_src, 'infocard.css'), dest_dir)
-  shutil.copy(os.path.join(template_src, 'shared.js'), dest_dir)
-  shutil.copy(os.path.join(template_src, 'state.js'), dest_dir)
-  shutil.copy(os.path.join(template_src, 'infocard-ui.js'), dest_dir)
-  shutil.copy(os.path.join(template_src, 'tree-ui.js'), dest_dir)
-  shutil.copy(os.path.join(template_src, 'tree-worker.js'), dest_dir)
+  for path in _TEMPLATE_FILES:
+    shutil.copy(os.path.join(template_src, path), dest_dir)
 
 
 def AddArguments(parser):
diff --git a/tools/binary_size/libsupersize/template_tree_view/favicon.ico b/tools/binary_size/libsupersize/template_tree_view/favicon.ico
new file mode 100644
index 0000000..32e97ee
--- /dev/null
+++ b/tools/binary_size/libsupersize/template_tree_view/favicon.ico
Binary files differ
diff --git a/tools/binary_size/libsupersize/template_tree_view/index.html b/tools/binary_size/libsupersize/template_tree_view/index.html
index 815717be..88d0000 100644
--- a/tools/binary_size/libsupersize/template_tree_view/index.html
+++ b/tools/binary_size/libsupersize/template_tree_view/index.html
@@ -197,6 +197,7 @@
     </style>
     <link rel="preload" href="tree-worker.js" as="worker">
     <link rel="stylesheet" href="options.css">
+    <link rel="icon" href="favicon.ico" sizes="16x16 32x32 256x256" type="image/x-icon">
     <script defer src="shared.js"></script>
     <script defer src="state.js"></script>
     <script defer src="infocard-ui.js"></script>
diff --git a/tools/determinism/compare_build_artifacts.py b/tools/determinism/compare_build_artifacts.py
index 62dae00..6a82825 100755
--- a/tools/determinism/compare_build_artifacts.py
+++ b/tools/determinism/compare_build_artifacts.py
@@ -164,7 +164,7 @@
   return diff_binary(first_filepath, second_filepath, file_len)
 
 
-def get_deps(build_dir, target):
+def get_deps(ninja_path, build_dir, target):
   """Returns list of object files needed to build target."""
   NODE_PATTERN = re.compile(r'label="([a-zA-Z0-9_\\/.-]+)"')
   CHECK_EXTS = ('.o', '.obj')
@@ -181,7 +181,7 @@
       shutil.move(build_dir, fixed_build_dir)
 
   try:
-    out = subprocess.check_output(['ninja', '-C', fixed_build_dir,
+    out = subprocess.check_output([ninja_path, '-C', fixed_build_dir,
                                    '-t', 'graph', target])
   except subprocess.CalledProcessError as e:
     print >> sys.stderr, 'error to get graph for %s: %s' % (target, e)
@@ -207,12 +207,12 @@
   return files
 
 
-def compare_deps(first_dir, second_dir, targets):
+def compare_deps(first_dir, second_dir, ninja_path, targets):
   """Print difference of dependent files."""
   diffs = set()
   for target in targets:
-    first_deps = get_deps(first_dir, target)
-    second_deps = get_deps(second_dir, target)
+    first_deps = get_deps(ninja_path, first_dir, target)
+    second_deps = get_deps(ninja_path, second_dir, target)
     print 'Checking %s difference: (%s deps)' % (target, len(first_deps))
     if set(first_deps) != set(second_deps):
       # Since we do not thiks this case occur, we do not do anything special
@@ -231,7 +231,7 @@
   return list(diffs)
 
 
-def compare_build_artifacts(first_dir, second_dir, target_platform,
+def compare_build_artifacts(first_dir, second_dir, ninja_path, target_platform,
                             json_output, recursive=False):
   """Compares the artifacts from two distinct builds."""
   if not os.path.isdir(first_dir):
@@ -300,7 +300,8 @@
 
   all_diffs = expected_diffs + unexpected_diffs
   diffs_to_investigate = sorted(set(all_diffs).difference(missing_files))
-  deps_diff = compare_deps(first_dir, second_dir, diffs_to_investigate)
+  deps_diff = compare_deps(first_dir, second_dir,
+                           ninja_path, diffs_to_investigate)
 
   if json_output:
     try:
@@ -326,6 +327,8 @@
   parser.add_option('-r', '--recursive', action='store_true', default=False,
                     help='Indicates if the comparison should be recursive.')
   parser.add_option('--json-output', help='JSON file to output differences')
+  parser.add_option('--ninja-path', help='path to ninja command.',
+                    default='ninja')
   target = {
       'darwin': 'mac', 'linux2': 'linux', 'win32': 'win'
   }.get(sys.platform, sys.platform)
@@ -342,6 +345,7 @@
 
   return compare_build_artifacts(os.path.abspath(options.first_build_dir),
                                  os.path.abspath(options.second_build_dir),
+                                 options.ninja_path,
                                  options.target_platform,
                                  options.json_output,
                                  options.recursive)
diff --git a/tools/licenses.py b/tools/licenses.py
index fce5266..3862aa0a 100755
--- a/tools/licenses.py
+++ b/tools/licenses.py
@@ -94,7 +94,6 @@
 
     # Mock test data.
     os.path.join('tools', 'binary_size', 'libsupersize', 'testdata'),
-    os.path.join('tools', 'binary_size', 'libsupersize', 'third_party', 'gvr-android-sdk'),
 
     # Overrides some WebRTC files, same license. Skip this one.
     os.path.join('third_party', 'webrtc_overrides'),
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index e00ff86f..c770f9e 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -27206,6 +27206,11 @@
   <int value="2" label="Area with references loaded"/>
 </enum>
 
+<enum name="LockedFullscreenState">
+  <int value="0" label="Exited"/>
+  <int value="1" label="Entered"/>
+</enum>
+
 <enum name="LockScreenActionAvailability">
   <int value="0" label="Available"/>
   <int value="1" label="Not available - no action handler app"/>
@@ -27897,6 +27902,7 @@
   <int value="-1022165708" label="BreakingNewsPush:disabled"/>
   <int value="-1020450980" label="gesture-deletion"/>
   <int value="-1019967332" label="VrBrowsing:enabled"/>
+  <int value="-1016669222" label="CloudPrinterHandler:enabled"/>
   <int value="-1016202433" label="disable-add-to-shelf"/>
   <int value="-1015006759" label="ImportantSitesInCBD:disabled"/>
   <int value="-1014649471" label="committed-interstitials"/>
@@ -28746,6 +28752,7 @@
   <int value="841343322" label="disable-new-korean-ime"/>
   <int value="841779535" label="password-export:enabled"/>
   <int value="842432903" label="CaptureThumbnailOnNavigatingAway:enabled"/>
+  <int value="842789526" label="CloudPrinterHandler:disabled"/>
   <int value="843896452" label="UserActivationV2:enabled"/>
   <int value="846951416" label="CopylessPaste:enabled"/>
   <int value="848324390" label="enable-lock-screen-apps"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 5c5d771..db627e1 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -8361,6 +8361,13 @@
   <summary>Count of resources attempted Stale Revalidation.</summary>
 </histogram>
 
+<histogram name="Blink.ResourceFetcher.StaleWhileRevalidateDuration" units="ms"
+    expires_after="M71">
+  <owner>dtapuska@chromium.org</owner>
+  <owner>kenjibaheux@google.com</owner>
+  <summary>Duration of completed stale revalidation attempts.</summary>
+</histogram>
+
 <histogram base="true" name="Blink.ResourceLoadScheduler.DecodedBytes"
     units="bytes">
 <!-- Name completed by histogram_suffixes name="ResourceLoadScheduler.FrameType" -->
@@ -28603,6 +28610,16 @@
   </summary>
 </histogram>
 
+<histogram name="Extensions.LockedFullscreenStateRequest"
+    enum="LockedFullscreenState" expires_after="2019-07-01">
+  <owner>isandrk@chromium.org</owner>
+  <owner>jhastings@chromium.org</owner>
+  <summary>
+    Records requests to enter or exit locked fullscreen mode through extension
+    APIs. Used only on Chrome OS.
+  </summary>
+</histogram>
+
 <histogram base="true" name="Extensions.LongInjectionTaskTime" units="ms">
   <owner>ksakamoto@chromium.org</owner>
   <summary>
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index 56b5d57f..617f99c 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -188,7 +188,7 @@
 # to generate the correct json for each tester
 NEW_PERF_RECIPE_MIGRATED_TESTERS = {
   'testers' : {
-    'Android Nexus5X Perf': {
+    'android-nexus5x-perf': {
       'tests': [
         {
           'isolate': 'performance_test_suite',
@@ -363,7 +363,7 @@
         'gpu': '8086:1616'
       },
     },
-    'Win 10 Perf': {
+    'win-10-perf': {
       'tests': [
         {
           'isolate': 'performance_test_suite',
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc
index 7eab9252..4930402 100644
--- a/ui/accessibility/platform/ax_platform_node_win.cc
+++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -6128,7 +6128,7 @@
   base::char16 new_ch = hypertext_.hypertext[new_char_index];
   if (old_ch != new_ch)
     return false;
-  if (old_ch == new_ch && new_ch != kEmbeddedCharacter)
+  if (new_ch != kEmbeddedCharacter)
     return true;
 
   // If it's an embedded character, they're only identical if the child id
@@ -6157,6 +6157,17 @@
   return old_child_id == new_child_id;
 }
 
+// Return true if the index represents a text character.
+bool AXPlatformNodeWin::IsText(const base::string16& text,
+                               size_t index,
+                               bool is_indexed_from_end) {
+  size_t text_len = text.size();
+  if (index == text_len)
+    return false;
+  auto ch = text[is_indexed_from_end ? text_len - index - 1 : index];
+  return ch != kEmbeddedCharacter;
+}
+
 void AXPlatformNodeWin::ComputeHypertextRemovedAndInserted(int* start,
                                                            int* old_len,
                                                            int* new_len) {
@@ -6173,18 +6184,44 @@
   const base::string16& old_text = old_hypertext_.hypertext;
   const base::string16& new_text = hypertext_.hypertext;
 
+  // TODO(accessibility) Plumb through which part of text changed so we don't
+  // have to guess what changed based on character differences. This can be
+  // wrong in some cases as follows:
+  // -- EDITABLE --
+  // If editable: when part of the text node changes, assume only that part
+  // changed, and not the entire thing. For example, if "car" changes to
+  // "cat", assume only 1 letter changed. This code compares common characters
+  // to guess what has changed.
+  // -- NOT EDITABLE --
+  // When part of the text changes, assume the entire node's text changed. For
+  // example, if "car" changes to "cat" then assume all 3 letters changed. Note,
+  // it is possible (though rare) that CharacterData methods are used to remove,
+  // insert, replace or append a substring.
+  bool allow_partial_text_node_changes =
+      GetData().HasState(ax::mojom::State::kEditable);
+  size_t prefix_index = 0;
   size_t common_prefix = 0;
-  while (common_prefix < old_text.size() && common_prefix < new_text.size() &&
-         IsSameHypertextCharacter(common_prefix, common_prefix)) {
-    ++common_prefix;
+  while (prefix_index < old_text.size() && prefix_index < new_text.size() &&
+         IsSameHypertextCharacter(prefix_index, prefix_index)) {
+    ++prefix_index;
+    if (allow_partial_text_node_changes ||
+        (!IsText(old_text, prefix_index) && !IsText(new_text, prefix_index))) {
+      common_prefix = prefix_index;
+    }
   }
 
+  size_t suffix_index = 0;
   size_t common_suffix = 0;
-  while (common_prefix + common_suffix < old_text.size() &&
-         common_prefix + common_suffix < new_text.size() &&
-         IsSameHypertextCharacter(old_text.size() - common_suffix - 1,
-                                  new_text.size() - common_suffix - 1)) {
-    ++common_suffix;
+  while (common_prefix + suffix_index < old_text.size() &&
+         common_prefix + suffix_index < new_text.size() &&
+         IsSameHypertextCharacter(old_text.size() - suffix_index - 1,
+                                  new_text.size() - suffix_index - 1)) {
+    ++suffix_index;
+    if (allow_partial_text_node_changes ||
+        (!IsText(old_text, suffix_index, true) &&
+         !IsText(new_text, suffix_index, true))) {
+      common_suffix = suffix_index;
+    }
   }
 
   *start = (int)common_prefix;
diff --git a/ui/accessibility/platform/ax_platform_node_win.h b/ui/accessibility/platform/ax_platform_node_win.h
index 50d010f..80069406 100644
--- a/ui/accessibility/platform/ax_platform_node_win.h
+++ b/ui/accessibility/platform/ax_platform_node_win.h
@@ -999,6 +999,11 @@
                     LONG start_offset,
                     TextBoundaryDirection direction);
 
+  // Return true if the index represents a text character.
+  bool IsText(const base::string16& text,
+              size_t index,
+              bool is_indexed_from_end = false);
+
   // Many MSAA methods take a var_id parameter indicating that the operation
   // should be performed on a particular child ID, rather than this object.
   // This method tries to figure out the target object from |var_id| and
diff --git a/ui/events/gestures/blink/web_gesture_curve_impl.cc b/ui/events/gestures/blink/web_gesture_curve_impl.cc
index 314863f8..0ea17b68 100644
--- a/ui/events/gestures/blink/web_gesture_curve_impl.cc
+++ b/ui/events/gestures/blink/web_gesture_curve_impl.cc
@@ -37,7 +37,7 @@
                                                 base::TimeTicks());
   }
 
-#if defined(CHROMECAST_BUILD)
+#if !defined(OS_ANDROID) && defined(CHROMECAST_BUILD)
   auto scroller = std::make_unique<Scroller>(Scroller::Config());
   scroller->Fling(0, 0, initial_velocity.x(), initial_velocity.y(), INT_MIN,
                   INT_MAX, INT_MIN, INT_MAX, base::TimeTicks());
diff --git a/ui/file_manager/file_manager/common/js/files_app_entry_types.js b/ui/file_manager/file_manager/common/js/files_app_entry_types.js
index fa0b5f2..3bc171e 100644
--- a/ui/file_manager/file_manager/common/js/files_app_entry_types.js
+++ b/ui/file_manager/file_manager/common/js/files_app_entry_types.js
@@ -283,6 +283,58 @@
   createReader() {
     return new StaticReader(this.children_);
   }
+
+  /**
+   * @param {!Entry|!FakeEntry|!FilesAppEntry} entry that should be removed as
+   * child of this EntryList.
+   * This method is specific to EntryList instance.
+   * @return {boolean} if entry was removed.
+   */
+  removeEntry(entry) {
+    const entryIndex = this.children.indexOf(entry);
+    if (entryIndex !== -1) {
+      this.children.splice(entryIndex, 1);
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * @param {!VolumeInfo} volumeInfo that's desired to be removed.
+   * This method is specific to EntryList instance.
+   * @return {number} index of entry on this EntryList or -1 if not found.
+   */
+  findIndexByVolumeInfo(volumeInfo) {
+    return this.children.findIndex(
+        childEntry => childEntry.volumeInfo === volumeInfo);
+  }
+
+  /**
+   * Removes the first volume with the given type.
+   * @param {!VolumeManagerCommon.VolumeType} volumeType desired type.
+   * This method is specific to EntryList instance.
+   * @return {boolean} if entry was removed.
+   */
+  removeByVolumeType(volumeType) {
+    const childIndex = this.children.findIndex(
+        childEntry => childEntry.volumeInfo &&
+            childEntry.volumeInfo.volumeType === volumeType);
+    if (childIndex !== -1) {
+      this.children.splice(childIndex, 1);
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * @param {Entry|FakeEntry|FilesAppEntry} entry that should be checked as
+   * child of this EntryList.
+   * This method is specific to EntryList instance.
+   * @return {boolean} if entry was removed.
+   */
+  containEntry(entry) {
+    return !!this.children.find(childEntry => childEntry === entry);
+  }
 }
 
 /**
diff --git a/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.html b/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.html
index fe96bde5..88378be 100644
--- a/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.html
+++ b/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.html
@@ -8,6 +8,7 @@
   <script src="../../common/js/unittest_util.js"></script>
 
   <script src="files_app_entry_types.js"></script>
+  <script src="volume_manager_common.js"></script>
   <script src="files_app_entry_types_unittest.js"></script>
   </body>
 </html>
diff --git a/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.js b/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.js
index 637085a..751761a6 100644
--- a/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.js
+++ b/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.js
@@ -75,8 +75,63 @@
   assertEquals(childEntry, entryList.children[0]);
 }
 
+/** Tests methods to remove entries. */
+function testEntryListRemoveEntry() {
+  const entryList = new EntryList('My Files');
+
+  const fakeRootEntry = createFakeDisplayRoot();
+  const fakeVolumeInfo = {
+    displayRoot: fakeRootEntry,
+    label: 'Fake Filesystem',
+  };
+  const childEntry = new VolumeEntry(fakeVolumeInfo);
+  entryList.addEntry(childEntry);
+  assertTrue(entryList.removeEntry(childEntry));
+  assertEquals(0, entryList.children.length);
+}
+
+/** Tests methods findIndexByVolumeInfo, removeByVolumeType and containEntry. */
+function testEntryFindIndex() {
+  const entryList = new EntryList('My Files');
+
+  const fakeRootEntry = createFakeDisplayRoot();
+  const downloadsVolumeInfo = {
+    displayRoot: fakeRootEntry,
+    label: 'Fake Filesystem',
+    volumeType: VolumeManagerCommon.VolumeType.DOWNLOADS,
+  };
+  const downloads = new VolumeEntry(downloadsVolumeInfo);
+
+  const crostiniRootEntry = createFakeDisplayRoot();
+  const crostiniVolumeInfo = {
+    displayRoot: crostiniRootEntry,
+    label: 'Fake Filesystem',
+    volumeType: VolumeManagerCommon.VolumeType.CROSTINI,
+  };
+  const crostini = new VolumeEntry(crostiniVolumeInfo);
+
+  entryList.addEntry(downloads);
+  // Test containEntry.
+  assertTrue(entryList.containEntry(downloads));
+  assertFalse(entryList.containEntry(crostini));
+  entryList.addEntry(crostini);
+  assertTrue(entryList.containEntry(crostini));
+
+  // Test findIndexByVolumeInfo.
+  assertEquals(0, entryList.findIndexByVolumeInfo(downloadsVolumeInfo));
+  assertEquals(1, entryList.findIndexByVolumeInfo(crostiniVolumeInfo));
+
+  // Test removeByVolumeType.
+  assertTrue(
+      entryList.removeByVolumeType(VolumeManagerCommon.VolumeType.CROSTINI));
+  assertEquals(1, entryList.children.length);
+  // Now crostini volume doesn't exist anymore, so should return False.
+  assertFalse(
+      entryList.removeByVolumeType(VolumeManagerCommon.VolumeType.CROSTINI));
+}
+
 /** Tests method EntryList.getMetadata. */
-function testEntryListAddVolume(testReportCallback) {
+function testEntryListGetMetadata(testReportCallback) {
   const entryList = new EntryList('My Files');
 
   let modificationTime = null;
diff --git a/ui/file_manager/file_manager/foreground/js/navigation_list_model.js b/ui/file_manager/file_manager/foreground/js/navigation_list_model.js
index 0f799fd0..d436bc4f5 100644
--- a/ui/file_manager/file_manager/foreground/js/navigation_list_model.js
+++ b/ui/file_manager/file_manager/foreground/js/navigation_list_model.js
@@ -556,11 +556,11 @@
       getSingleVolume(VolumeManagerCommon.VolumeType.DOWNLOADS);
   if (downloadsVolume) {
     // Only add volume if MyFiles doesn't have it yet.
-    if (!myFilesEntry.children.find(
-            childEntry =>
-                childEntry.volumeInfo === downloadsVolume.volumeInfo)) {
+    if (myFilesEntry.findIndexByVolumeInfo(downloadsVolume.volumeInfo) === -1) {
       myFilesEntry.addEntry(new VolumeEntry(downloadsVolume.volumeInfo));
     }
+  } else {
+    myFilesEntry.removeByVolumeType(VolumeManagerCommon.VolumeType.DOWNLOADS);
   }
 
   // Add Android to My Files.
@@ -568,10 +568,12 @@
       getSingleVolume(VolumeManagerCommon.VolumeType.ANDROID_FILES);
   if (androidVolume) {
     // Only add volume if MyFiles doesn't have it yet.
-    if (!myFilesEntry.children.find(
-            childEntry => childEntry.volumeInfo === androidVolume.volumeInfo)) {
+    if (myFilesEntry.findIndexByVolumeInfo(androidVolume.volumeInfo) === -1) {
       myFilesEntry.addEntry(new VolumeEntry(androidVolume.volumeInfo));
     }
+  } else {
+    myFilesEntry.removeByVolumeType(
+        VolumeManagerCommon.VolumeType.ANDROID_FILES);
   }
 
   // Add Linux to My Files.
@@ -579,25 +581,22 @@
       getSingleVolume(VolumeManagerCommon.VolumeType.CROSTINI);
   if (crostiniVolume) {
     // Crostini is mounted so add it if MyFiles doesn't have it yet.
-    if (!myFilesEntry.children.find(
-            childEntry =>
-                childEntry.volumeInfo === crostiniVolume.volumeInfo)) {
-      myFilesEntry.addEntry(new crostiniVolume.volumeInfo);
+    if (myFilesEntry.findIndexByVolumeInfo(crostiniVolume.volumeInfo) === -1) {
+      myFilesEntry.addEntry(new VolumeEntry(crostiniVolume.volumeInfo));
     }
     // Remove linuxFilesItem_ if exists on EntryList.
+    if (this.linuxFilesItem_)
+      myFilesEntry.removeEntry(this.linuxFilesItem_.entry);
+  } else {
+    myFilesEntry.removeByVolumeType(VolumeManagerCommon.VolumeType.CROSTINI);
     if (this.linuxFilesItem_) {
-      const fakeCrostiniIndex =
-          myFilesEntry.children.indexOf(this.linuxFilesItem_.entry);
-      if (fakeCrostiniIndex != -1) {
-        myFilesEntry.children.splice(fakeCrostiniIndex, 1);
+      const fakeEntry = this.linuxFilesItem_.entry;
+      // Here it's just a fake item, only add if MyFiles doesn't have it yet.
+      if (!myFilesEntry.containEntry(fakeEntry)) {
+        fakeEntry.navigationModel = this.linuxFilesItem_;
+        myFilesEntry.addEntry(fakeEntry);
       }
     }
-  } else if (this.linuxFilesItem_) {
-    // Here it's just a fake item, only add if MyFiles doesn't have it yet.
-    if (!myFilesEntry.children.find(
-            childEntry => childEntry === this.linuxFilesItem_.entry)) {
-      myFilesEntry.addEntry(this.linuxFilesItem_.entry);
-    }
   }
 
   // Join MEDIA_VIEW, MTP, ARCHIVE and REMOVABLE. These types belong to same
diff --git a/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js b/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js
index e4593f0a..49786a6 100644
--- a/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js
@@ -195,6 +195,9 @@
   volumeManager.volumeInfoList.push(
       MockVolumeManagerWrapper.createMockVolumeInfo(
           VolumeManagerCommon.VolumeType.PROVIDED, 'provided:prov2'));
+  volumeManager.volumeInfoList.push(
+      MockVolumeManagerWrapper.createMockVolumeInfo(
+          VolumeManagerCommon.VolumeType.ANDROID_FILES, 'android_files:droid'));
 
   // Navigation items built above:
   //  1.  fake-entry://recent
@@ -202,6 +205,7 @@
   //  3.  /root/shortcut2
   //  4.  My-Files
   //        -> Downloads
+  //        -> Play Files
   //        -> Linux Files
   //  5.  removable:hoge
   //  6.  archive:a-zip
diff --git a/ui/file_manager/integration_tests/file_manager/context_menu.js b/ui/file_manager/integration_tests/file_manager/context_menu.js
index f9719d1e..aba40b4 100644
--- a/ui/file_manager/integration_tests/file_manager/context_menu.js
+++ b/ui/file_manager/integration_tests/file_manager/context_menu.js
@@ -9,9 +9,6 @@
  * The names passed to the tests are file names to select. They are generated
  * from COMPLEX_DRIVE_ENTRY_SET (see setupAndWaitUntilReady).
  *
- * TODO(sashab): Update selector paths to use the [full-path-for-testing]
- * selector rather than nth-child.
- *
  * TODO(sashab): Generate the entries used in these tests at runtime, by
  * creating entries with pre-set combinations of permissions and ensuring the
  * outcome is always as expected.
@@ -611,8 +608,7 @@
 testcase.checkCopyEnabledForReadWriteFolderInTree = function() {
   checkContextMenuForDriveFolderInTree(
       'copy',
-      '#directory-tree .tree-item:nth-child(1) .tree-item:nth-child(1) ' +
-          '.tree-item:nth-child(1)',
+      '#directory-tree [full-path-for-testing="/root/photos"]:not([hidden])',
       true);
 };
 
@@ -623,8 +619,8 @@
 testcase.checkCopyEnabledForReadOnlyFolderInTree = function() {
   checkContextMenuForDriveFolderInTree(
       'copy',
-      '#directory-tree .tree-item:nth-child(1) .tree-item:nth-child(1) ' +
-          '.tree-item:nth-child(2)',
+      '#directory-tree [full-path-for-testing="/root/Read-Only Folder"]' +
+          ':not([hidden])',
       true);
 };
 
@@ -635,8 +631,7 @@
 testcase.checkCutEnabledForReadWriteFolderInTree = function() {
   checkContextMenuForDriveFolderInTree(
       'cut',
-      '#directory-tree .tree-item:nth-child(1) .tree-item:nth-child(1) ' +
-          '.tree-item:nth-child(1)',
+      '#directory-tree [full-path-for-testing="/root/photos"]:not([hidden])',
       true);
 };
 
@@ -647,8 +642,8 @@
 testcase.checkCutDisabledForReadOnlyFolderInTree = function() {
   checkContextMenuForDriveFolderInTree(
       'cut',
-      '#directory-tree .tree-item:nth-child(1) .tree-item:nth-child(1) ' +
-          '.tree-item:nth-child(2)',
+      '#directory-tree [full-path-for-testing="/root/Read-Only Folder"]' +
+          ':not([hidden])',
       false);
 };
 
@@ -661,8 +656,7 @@
   copyEntryToClipboard('hello.txt', () => {
     checkContextMenuForDriveFolderInTree(
         'paste-into-folder',
-        '#directory-tree .tree-item:nth-child(1) .tree-item:nth-child(1) ' +
-            '.tree-item:nth-child(1)',
+        '#directory-tree [full-path-for-testing="/root/photos"]:not([hidden])',
         true);
   });
 };
@@ -676,8 +670,8 @@
   copyEntryToClipboard('hello.txt', () => {
     checkContextMenuForDriveFolderInTree(
         'paste-into-folder',
-        '#directory-tree .tree-item:nth-child(1) .tree-item:nth-child(1) ' +
-            '.tree-item:nth-child(3)',
+        '#directory-tree [full-path-for-testing="/root/Read-Only Folder"]' +
+            ':not([hidden])',
         false);
   });
 };
diff --git a/ui/file_manager/integration_tests/file_manager/create_new_folder.js b/ui/file_manager/integration_tests/file_manager/create_new_folder.js
index e94f74cc..186abb20 100644
--- a/ui/file_manager/integration_tests/file_manager/create_new_folder.js
+++ b/ui/file_manager/integration_tests/file_manager/create_new_folder.js
@@ -9,15 +9,9 @@
  * When we are not in guest mode, we fill Google Drive with the basic entry set
  * which causes an extra tree-item to be added.
  */
-var TREEITEM_DRIVE;
-var TREEITEM_DOWNLOADS;
-if (!chrome.extension.inIncognitoContext) {
-  TREEITEM_DRIVE = '#directory-tree > div:nth-child(1) ';
-  TREEITEM_DOWNLOADS = '#directory-tree > div:nth-child(2) ';
-} else {
-  // In guest mode Google Drive is not mounted so the folder indices differ.
-  TREEITEM_DOWNLOADS = '#directory-tree > div:nth-child(1) ';
-}
+var TREEITEM_DRIVE = '#directory-tree [entry-label="My Drive"] ';
+var TREEITEM_DOWNLOADS =
+    '#directory-tree [volume-type-for-testing="downloads"] ';
 var EXPAND_ICON = '> .tree-row > .expand-icon';
 var EXPANDED_SUBTREE = '> .tree-children[expanded]';
 
diff --git a/ui/file_manager/integration_tests/file_manager/folder_shortcuts.js b/ui/file_manager/integration_tests/file_manager/folder_shortcuts.js
index d0071c3a..c3f675c 100644
--- a/ui/file_manager/integration_tests/file_manager/folder_shortcuts.js
+++ b/ui/file_manager/integration_tests/file_manager/folder_shortcuts.js
@@ -7,13 +7,13 @@
 /**
  * Constants for selectors.
  */
-var TREEITEM_DRIVE = '#directory-tree > div:nth-child(1) > .tree-children ' +
-    '> div:nth-child(1) ';
-var TREEITEM_A = TREEITEM_DRIVE + '> .tree-children > div:nth-child(1) ';
-var TREEITEM_B = TREEITEM_A + '> .tree-children > div:nth-child(1) ';
-var TREEITEM_C = TREEITEM_B + '> .tree-children > div:nth-child(1) ';
-var TREEITEM_D = TREEITEM_DRIVE + '> .tree-children > div:nth-child(2) ';
-var TREEITEM_E = TREEITEM_D + '> .tree-children > div:nth-child(1) ';
+
+var TREEITEM_DRIVE = '#directory-tree [entry-label="My Drive"] ';
+var TREEITEM_A = TREEITEM_DRIVE + ' [entry-label="A"] ';
+var TREEITEM_B = TREEITEM_A + '[entry-label="B"] ';
+var TREEITEM_C = TREEITEM_B + '[entry-label="C"] ';
+var TREEITEM_D = TREEITEM_DRIVE + '[entry-label="D"] ';
+var TREEITEM_E = TREEITEM_D + '[entry-label="E"] ';
 var EXPAND_ICON = '> .tree-row > .expand-icon';
 var ITEM_ICON = '> .tree-row > .item-icon';
 var EXPANDED_SUBTREE = '> .tree-children[expanded]';
@@ -43,7 +43,7 @@
       ENTRIES.directoryA.getExpectedRow(), ENTRIES.directoryD.getExpectedRow()
     ],
     name: 'Drive',
-    navItem: '#tree-item-autogen-id-5',
+    navItem: '.tree-item[entry-label="My Drive"]',
     treeItem: TREEITEM_DRIVE
   },
   A: {
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index 7d594e26..d8f800cf 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -136,6 +136,7 @@
     "controls/menu/menu_runner_handler.h",
     "controls/menu/menu_runner_impl.h",
     "controls/menu/menu_runner_impl_adapter.h",
+    "controls/menu/menu_runner_impl_cocoa.h",
     "controls/menu/menu_runner_impl_interface.h",
     "controls/menu/menu_scroll_view_container.h",
     "controls/menu/menu_separator.h",
@@ -334,6 +335,7 @@
     "controls/menu/menu_runner.cc",
     "controls/menu/menu_runner_impl.cc",
     "controls/menu/menu_runner_impl_adapter.cc",
+    "controls/menu/menu_runner_impl_cocoa.mm",
     "controls/menu/menu_scroll_view_container.cc",
     "controls/menu/menu_separator.cc",
     "controls/menu/native_menu_win.cc",
diff --git a/ui/views/controls/menu/menu_runner_cocoa_unittest.mm b/ui/views/controls/menu/menu_runner_cocoa_unittest.mm
index e5b22651..ae0c8baf 100644
--- a/ui/views/controls/menu/menu_runner_cocoa_unittest.mm
+++ b/ui/views/controls/menu/menu_runner_cocoa_unittest.mm
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#import "ui/views/controls/menu/menu_runner_impl_cocoa.h"
+
 #import <Cocoa/Cocoa.h>
 
 #include "base/macros.h"
@@ -72,9 +74,16 @@
   DISALLOW_COPY_AND_ASSIGN(TestModel);
 };
 
+enum class MenuType { NATIVE, VIEWS };
+
+std::string MenuTypeToString(::testing::TestParamInfo<MenuType> info) {
+  return info.param == MenuType::VIEWS ? "VIEWS_MenuItemView" : "NATIVE_NSMenu";
+}
+
 }  // namespace
 
-class MenuRunnerCocoaTest : public ViewsTestBase {
+class MenuRunnerCocoaTest : public ViewsTestBase,
+                            public ::testing::WithParamInterface<MenuType> {
  public:
   enum {
     kWindowHeight = 200,
@@ -99,7 +108,10 @@
 
     base::Closure on_close = base::Bind(&MenuRunnerCocoaTest::MenuCloseCallback,
                                         base::Unretained(this));
-    runner_ = new internal::MenuRunnerImplAdapter(menu_.get(), on_close);
+    if (GetParam() == MenuType::NATIVE)
+      runner_ = new internal::MenuRunnerImplCocoa(menu_.get(), on_close);
+    else
+      runner_ = new internal::MenuRunnerImplAdapter(menu_.get(), on_close);
     EXPECT_FALSE(runner_->IsRunning());
   }
 
@@ -113,13 +125,21 @@
     ViewsTestBase::TearDown();
   }
 
+  int IsAsync() const { return GetParam() == MenuType::VIEWS; }
+
   // Runs the menu after registering |callback| as the menu open callback.
   void RunMenu(base::OnceClosure callback) {
-    // Cancelling an async menu under MenuControllerCocoa::OpenMenuImpl()
-    // (which invokes WillShowMenu()) will cause a UAF when that same function
-    // tries to show the menu. So post a task instead.
-    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
-                                                  std::move(callback));
+    if (IsAsync()) {
+      // Cancelling an async menu under MenuControllerCocoa::OpenMenuImpl()
+      // (which invokes WillShowMenu()) will cause a UAF when that same function
+      // tries to show the menu. So post a task instead.
+      base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                    std::move(callback));
+    } else {
+      menu_->set_menu_open_callback(
+          base::BindOnce(&MenuRunnerCocoaTest::RunMenuWrapperCallback,
+                         base::Unretained(this), std::move(callback)));
+    }
 
     runner_->RunMenuAt(parent_, nullptr, gfx::Rect(), MENU_ANCHOR_TOPLEFT,
                        MenuRunner::CONTEXT_MENU);
@@ -129,6 +149,8 @@
   // Runs then cancels a combobox menu and captures the frame of the anchoring
   // view.
   void RunMenuAt(const gfx::Rect& anchor) {
+    last_anchor_frame_ = NSZeroRect;
+
     // Should be one child (the compositor layer) before showing, and it should
     // go up by one (the anchor view) while the menu is shown.
     EXPECT_EQ(1u, [[parent_->GetNativeView() subviews] count]);
@@ -136,8 +158,12 @@
     base::OnceClosure callback =
         base::BindOnce(&MenuRunnerCocoaTest::ComboboxRunMenuAtCallback,
                        base::Unretained(this));
-    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
-                                                  std::move(callback));
+    if (IsAsync()) {
+      base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                    std::move(callback));
+    } else {
+      menu_->set_menu_open_callback(std::move(callback));
+    }
 
     runner_->RunMenuAt(parent_, nullptr, anchor, MENU_ANCHOR_TOPLEFT,
                        MenuRunner::COMBOBOX);
@@ -149,8 +175,15 @@
 
   void MenuCancelCallback() {
     runner_->Cancel();
-    // Async menus report their cancellation immediately.
-    EXPECT_FALSE(runner_->IsRunning());
+    if (IsAsync()) {
+      // Async menus report their cancellation immediately.
+      EXPECT_FALSE(runner_->IsRunning());
+    } else {
+      // For a synchronous menu, MenuRunner::IsRunning() should return true
+      // immediately after MenuRunner::Cancel() since the menu message loop has
+      // not yet terminated. It has only been marked for termination.
+      EXPECT_TRUE(runner_->IsRunning());
+    }
   }
 
   void MenuDeleteCallback() {
@@ -162,7 +195,20 @@
     QuitAsyncRunLoop();
   }
 
+  NSMenu* GetNativeNSMenu() {
+    if (GetParam() == MenuType::VIEWS)
+      return nil;
+
+    internal::MenuRunnerImplCocoa* cocoa_runner =
+        static_cast<internal::MenuRunnerImplCocoa*>(runner_);
+    return [cocoa_runner->menu_controller_ menu];
+  }
+
   void ModelDeleteThenSelectItemCallback() {
+    // AppKit may retain a reference to the NSMenu.
+    base::scoped_nsobject<NSMenu> native_menu(GetNativeNSMenu(),
+                                              base::scoped_policy::RETAIN);
+
     // A View showing a menu typically owns a MenuRunner unique_ptr, which will
     // will be destroyed (releasing the MenuRunnerImpl) alongside the MenuModel.
     runner_->Release();
@@ -174,7 +220,17 @@
     // doesn't bother views menus (see MenuRunnerImpl::empty_delegate_) but
     // Cocoa menu items are refcounted and have access to a raw weak pointer in
     // the MenuController.
-    QuitAsyncRunLoop();
+    if (GetParam() == MenuType::VIEWS) {
+      QuitAsyncRunLoop();
+      return;
+    }
+
+    EXPECT_TRUE(native_menu.get());
+
+    // Simulate clicking the item using its accelerator.
+    NSEvent* accelerator = cocoa_test_event_utils::KeyEventWithKeyCode(
+        'e', 'e', NSKeyDown, NSCommandKeyMask);
+    [native_menu performKeyEquivalent:accelerator];
   }
 
   void MenuCancelAndDeleteCallback() {
@@ -187,6 +243,7 @@
   std::unique_ptr<TestModel> menu_;
   internal::MenuRunnerImplInterface* runner_ = nullptr;
   views::Widget* parent_ = nullptr;
+  NSRect last_anchor_frame_ = NSZeroRect;
   int menu_close_count_ = 0;
 
  private:
@@ -198,13 +255,21 @@
   void ComboboxRunMenuAtCallback() {
     NSArray* subviews = [parent_->GetNativeView() subviews];
     // An anchor view should only be added for Native menus.
-    EXPECT_EQ(1u, [subviews count]);
+    if (GetParam() == MenuType::NATIVE) {
+      ASSERT_EQ(2u, [subviews count]);
+      last_anchor_frame_ = [[subviews objectAtIndex:1] frame];
+    } else {
+      EXPECT_EQ(1u, [subviews count]);
+    }
     runner_->Cancel();
   }
 
   // Run a nested run loop so that async and sync menus can be tested the
   // same way.
   void MaybeRunAsync() {
+    if (!IsAsync())
+      return;
+
     base::RunLoop run_loop;
     quit_closure_ = run_loop.QuitClosure();
     base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
@@ -216,6 +281,10 @@
   }
 
   void QuitAsyncRunLoop() {
+    if (!IsAsync()) {
+      EXPECT_TRUE(quit_closure_.is_null());
+      return;
+    }
     ASSERT_FALSE(quit_closure_.is_null());
     quit_closure_.Run();
     quit_closure_.Reset();
@@ -231,17 +300,23 @@
   DISALLOW_COPY_AND_ASSIGN(MenuRunnerCocoaTest);
 };
 
-TEST_F(MenuRunnerCocoaTest, RunMenuAndCancel) {
+TEST_P(MenuRunnerCocoaTest, RunMenuAndCancel) {
+  base::TimeTicks min_time = ui::EventTimeForNow();
+
   RunMenu(base::BindOnce(&MenuRunnerCocoaTest::MenuCancelCallback,
                          base::Unretained(this)));
 
   EXPECT_EQ(1, menu_close_count_);
   EXPECT_FALSE(runner_->IsRunning());
 
-  // MenuItemView's MenuRunnerImpl gets the closing time from
-  // MenuControllerCocoa:: closing_event_time(). This is is reset on show, but
-  // only updated when an event closes the menu -- not a cancellation.
-  EXPECT_EQ(runner_->GetClosingEventTime(), base::TimeTicks());
+  if (GetParam() == MenuType::VIEWS) {
+    // MenuItemView's MenuRunnerImpl gets the closing time from
+    // MenuControllerCocoa:: closing_event_time(). This is is reset on show, but
+    // only updated when an event closes the menu -- not a cancellation.
+    EXPECT_EQ(runner_->GetClosingEventTime(), base::TimeTicks());
+  } else {
+    EXPECT_GE(runner_->GetClosingEventTime(), min_time);
+  }
   EXPECT_LE(runner_->GetClosingEventTime(), ui::EventTimeForNow());
 
   // Cancel again.
@@ -250,7 +325,7 @@
   EXPECT_EQ(1, menu_close_count_);
 }
 
-TEST_F(MenuRunnerCocoaTest, RunMenuAndDelete) {
+TEST_P(MenuRunnerCocoaTest, RunMenuAndDelete) {
   RunMenu(base::BindOnce(&MenuRunnerCocoaTest::MenuDeleteCallback,
                          base::Unretained(this)));
   // Note the close callback is NOT invoked for deleted menus.
@@ -259,7 +334,7 @@
 
 // Tests a potential lifetime issue using the Cocoa MenuController, which has a
 // weak reference to the model.
-TEST_F(MenuRunnerCocoaTest, RunMenuAndDeleteThenSelectItem) {
+TEST_P(MenuRunnerCocoaTest, RunMenuAndDeleteThenSelectItem) {
   RunMenu(
       base::BindOnce(&MenuRunnerCocoaTest::ModelDeleteThenSelectItemCallback,
                      base::Unretained(this)));
@@ -268,14 +343,20 @@
 
 // Ensure a menu can be safely released immediately after a call to Cancel() in
 // the same run loop iteration.
-TEST_F(MenuRunnerCocoaTest, DestroyAfterCanceling) {
+TEST_P(MenuRunnerCocoaTest, DestroyAfterCanceling) {
   RunMenu(base::BindOnce(&MenuRunnerCocoaTest::MenuCancelAndDeleteCallback,
                          base::Unretained(this)));
 
-  EXPECT_EQ(1, menu_close_count_);
+  if (IsAsync()) {
+    EXPECT_EQ(1, menu_close_count_);
+  } else {
+    // For a synchronous menu, the deletion happens before the cancel can be
+    // processed, so the close callback will not be invoked.
+    EXPECT_EQ(0, menu_close_count_);
+  }
 }
 
-TEST_F(MenuRunnerCocoaTest, RunMenuTwice) {
+TEST_P(MenuRunnerCocoaTest, RunMenuTwice) {
   for (int i = 0; i < 2; ++i) {
     RunMenu(base::BindOnce(&MenuRunnerCocoaTest::MenuCancelCallback,
                            base::Unretained(this)));
@@ -284,18 +365,71 @@
   }
 }
 
-TEST_F(MenuRunnerCocoaTest, CancelWithoutRunning) {
+TEST_P(MenuRunnerCocoaTest, CancelWithoutRunning) {
   runner_->Cancel();
   EXPECT_FALSE(runner_->IsRunning());
   EXPECT_EQ(base::TimeTicks(), runner_->GetClosingEventTime());
   EXPECT_EQ(0, menu_close_count_);
 }
 
-TEST_F(MenuRunnerCocoaTest, DeleteWithoutRunning) {
+TEST_P(MenuRunnerCocoaTest, DeleteWithoutRunning) {
   runner_->Release();
   runner_ = NULL;
   EXPECT_EQ(0, menu_close_count_);
 }
 
+// Tests anchoring of the menus used for toolkit-views Comboboxes.
+TEST_P(MenuRunnerCocoaTest, ComboboxAnchoring) {
+  // Combobox at 20,10 in the Widget.
+  const gfx::Rect combobox_rect(20, 10, 80, 50);
+
+  // Menu anchor rects are always in screen coordinates. The window is frameless
+  // so offset by the bounds.
+  gfx::Rect anchor_rect = combobox_rect;
+  anchor_rect.Offset(kWindowOffset, kWindowOffset);
+  RunMenuAt(anchor_rect);
+
+  if (GetParam() != MenuType::NATIVE) {
+    // Combobox anchoring is only implemented for native menus.
+    EXPECT_NSEQ(NSZeroRect, last_anchor_frame_);
+    return;
+  }
+
+  // Nothing is checked, so the anchor view should have no height, to ensure the
+  // menu goes below the anchor rect. There should also be no x-offset since the
+  // there is no need to line-up text.
+  EXPECT_NSEQ(
+      NSMakeRect(combobox_rect.x(), kWindowHeight - combobox_rect.bottom(),
+                 combobox_rect.width(), 0),
+      last_anchor_frame_);
+
+  menu_->set_checked_command(kTestCommandId);
+  RunMenuAt(anchor_rect);
+
+  // Native constant used by MenuRunnerImplCocoa.
+  const CGFloat kNativeCheckmarkWidth = 18;
+
+  // There is now a checked item, so the anchor should be vertically centered
+  // inside the combobox, and offset by the width of the checkmark column.
+  EXPECT_EQ(combobox_rect.x() - kNativeCheckmarkWidth,
+            last_anchor_frame_.origin.x);
+  EXPECT_EQ(kWindowHeight - combobox_rect.CenterPoint().y(),
+            NSMidY(last_anchor_frame_));
+  EXPECT_EQ(combobox_rect.width(), NSWidth(last_anchor_frame_));
+  EXPECT_NE(0, NSHeight(last_anchor_frame_));
+
+  // In RTL, Cocoa messes up the positioning unless the anchor rectangle is
+  // offset to the right of the view. The offset for the checkmark is also
+  // skipped, to give a better match to native behavior.
+  base::i18n::SetICUDefaultLocale("he");
+  RunMenuAt(anchor_rect);
+  EXPECT_EQ(combobox_rect.right(), last_anchor_frame_.origin.x);
+}
+
+INSTANTIATE_TEST_CASE_P(,
+                        MenuRunnerCocoaTest,
+                        ::testing::Values(MenuType::NATIVE, MenuType::VIEWS),
+                        &MenuTypeToString);
+
 }  // namespace test
 }  // namespace views
diff --git a/ui/views/controls/menu/menu_runner_impl.cc b/ui/views/controls/menu/menu_runner_impl.cc
index aa1faf6..1c7b5c4 100644
--- a/ui/views/controls/menu/menu_runner_impl.cc
+++ b/ui/views/controls/menu/menu_runner_impl.cc
@@ -24,12 +24,14 @@
 namespace views {
 namespace internal {
 
+#if !defined(OS_MACOSX)
 MenuRunnerImplInterface* MenuRunnerImplInterface::Create(
     ui::MenuModel* menu_model,
     int32_t run_types,
     const base::Closure& on_menu_closed_callback) {
   return new MenuRunnerImplAdapter(menu_model, on_menu_closed_callback);
 }
+#endif
 
 MenuRunnerImpl::MenuRunnerImpl(MenuItemView* menu)
     : menu_(menu),
diff --git a/ui/views/controls/menu/menu_runner_impl_cocoa.h b/ui/views/controls/menu/menu_runner_impl_cocoa.h
new file mode 100644
index 0000000..599000d
--- /dev/null
+++ b/ui/views/controls/menu/menu_runner_impl_cocoa.h
@@ -0,0 +1,66 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_CONTROLS_MENU_MENU_RUNNER_IMPL_COCOA_H_
+#define UI_VIEWS_CONTROLS_MENU_MENU_RUNNER_IMPL_COCOA_H_
+
+#include <stdint.h>
+
+#include "base/callback.h"
+#import "base/mac/scoped_nsobject.h"
+#include "base/macros.h"
+#include "base/time/time.h"
+#include "ui/views/controls/menu/menu_runner_impl_interface.h"
+
+@class MenuControllerCocoa;
+
+namespace views {
+namespace test {
+class MenuRunnerCocoaTest;
+}
+namespace internal {
+
+// A menu runner implementation that uses NSMenu to show a context menu.
+class VIEWS_EXPORT MenuRunnerImplCocoa : public MenuRunnerImplInterface {
+ public:
+  MenuRunnerImplCocoa(ui::MenuModel* menu,
+                      const base::Closure& on_menu_closed_callback);
+
+  bool IsRunning() const override;
+  void Release() override;
+  void RunMenuAt(Widget* parent,
+                 MenuButton* button,
+                 const gfx::Rect& bounds,
+                 MenuAnchorPosition anchor,
+                 int32_t run_types) override;
+  void Cancel() override;
+  base::TimeTicks GetClosingEventTime() const override;
+
+ private:
+  friend class views::test::MenuRunnerCocoaTest;
+
+  ~MenuRunnerImplCocoa() override;
+
+  // The Cocoa menu controller that this instance is bridging.
+  base::scoped_nsobject<MenuControllerCocoa> menu_controller_;
+
+  // Are we in run waiting for it to return?
+  bool running_;
+
+  // Set if |running_| and Release() has been invoked.
+  bool delete_after_run_;
+
+  // The timestamp of the event which closed the menu - or 0.
+  base::TimeTicks closing_event_time_;
+
+  // Invoked before RunMenuAt() returns, except upon a Release().
+  base::Closure on_menu_closed_callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(MenuRunnerImplCocoa);
+};
+
+}  // namespace internal
+}  // namespace views
+
+#endif  // UI_VIEWS_CONTROLS_MENU_MENU_RUNNER_IMPL_COCOA_H_
diff --git a/ui/views/controls/menu/menu_runner_impl_cocoa.mm b/ui/views/controls/menu/menu_runner_impl_cocoa.mm
new file mode 100644
index 0000000..f0ea471
--- /dev/null
+++ b/ui/views/controls/menu/menu_runner_impl_cocoa.mm
@@ -0,0 +1,224 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ui/views/controls/menu/menu_runner_impl_cocoa.h"
+
+#include "base/mac/sdk_forward_declarations.h"
+#import "base/message_loop/message_pump_mac.h"
+#import "ui/base/cocoa/cocoa_base_utils.h"
+#import "ui/base/cocoa/menu_controller.h"
+#include "ui/base/models/menu_model.h"
+#include "ui/events/base_event_utils.h"
+#include "ui/events/event_utils.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/mac/coordinate_conversion.h"
+#include "ui/views/controls/menu/menu_runner_impl_adapter.h"
+#include "ui/views/widget/widget.h"
+
+namespace views {
+namespace internal {
+namespace {
+
+const CGFloat kNativeCheckmarkWidth = 18;
+const CGFloat kNativeMenuItemHeight = 18;
+
+// Returns the first item in |menu_controller|'s menu that will be checked.
+NSMenuItem* FirstCheckedItem(MenuControllerCocoa* menu_controller) {
+  for (NSMenuItem* item in [[menu_controller menu] itemArray]) {
+    if ([menu_controller model]->IsItemCheckedAt([item tag]))
+      return item;
+  }
+  return nil;
+}
+
+// Places a temporary, hidden NSView at |screen_bounds| within |window|. Used
+// with -[NSMenu popUpMenuPositioningItem:atLocation:inView:] to position the
+// menu for a combobox. The caller must remove the returned NSView from its
+// superview when the menu is closed.
+base::scoped_nsobject<NSView> CreateMenuAnchorView(
+    NSWindow* window,
+    const gfx::Rect& screen_bounds,
+    NSMenuItem* checked_item,
+    CGFloat actual_menu_width,
+    MenuAnchorPosition position) {
+  NSRect rect = gfx::ScreenRectToNSRect(screen_bounds);
+  rect = [window convertRectFromScreen:rect];
+  rect = [[window contentView] convertRect:rect fromView:nil];
+
+  // If there's no checked item (e.g. Combobox::STYLE_ACTION), NSMenu will
+  // anchor at the top left of the frame. Action buttons should anchor below.
+  if (!checked_item) {
+    rect.size.height = 0;
+    if (base::i18n::IsRTL())
+      rect.origin.x += rect.size.width;
+  } else {
+    // To ensure a consistent anchoring that's vertically centered in the
+    // bounds, fix the height to be the same as a menu item.
+    rect.origin.y = NSMidY(rect) - kNativeMenuItemHeight / 2;
+    rect.size.height = kNativeMenuItemHeight;
+    if (base::i18n::IsRTL()) {
+      // The Views menu controller flips the MenuAnchorPosition value from left
+      // to right in RTL. NSMenu does this automatically: the menu opens to the
+      // left of the anchor, but AppKit doesn't account for the anchor width.
+      // So the width needs to be added to anchor at the right of the view.
+      // Note the checkmark width is not also added - it doesn't quite line up
+      // the text. A Yosemite NSComboBox doesn't line up in RTL either: just
+      // adding the width is a good match for the native behavior.
+      rect.origin.x += rect.size.width;
+    } else {
+      rect.origin.x -= kNativeCheckmarkWidth;
+    }
+  }
+
+  // When the actual menu width is larger than the anchor, right alignment
+  // should be respected.
+  if (actual_menu_width > rect.size.width &&
+      position == views::MENU_ANCHOR_TOPRIGHT && !base::i18n::IsRTL()) {
+    int width_diff = actual_menu_width - rect.size.width;
+    rect.origin.x -= width_diff;
+  }
+  // A plain NSView will anchor below rather than "over", so use an NSButton.
+  base::scoped_nsobject<NSView> anchor_view(
+      [[NSButton alloc] initWithFrame:rect]);
+  [anchor_view setHidden:YES];
+  [[window contentView] addSubview:anchor_view];
+  return anchor_view;
+}
+
+// Returns an appropriate event (with a location) suitable for showing a context
+// menu. Uses [NSApp currentEvent] if it's a non-nil mouse click event,
+// otherwise creates an autoreleased dummy event located at |anchor|.
+NSEvent* EventForPositioningContextMenu(const gfx::Rect& anchor,
+                                        NSWindow* window) {
+  NSEvent* event = [NSApp currentEvent];
+  switch ([event type]) {
+    case NSLeftMouseDown:
+    case NSLeftMouseUp:
+    case NSRightMouseDown:
+    case NSRightMouseUp:
+    case NSOtherMouseDown:
+    case NSOtherMouseUp:
+      return event;
+    default:
+      break;
+  }
+  NSPoint location_in_window = ui::ConvertPointFromScreenToWindow(
+      window, gfx::ScreenPointToNSPoint(anchor.CenterPoint()));
+  return [NSEvent mouseEventWithType:NSRightMouseDown
+                            location:location_in_window
+                       modifierFlags:0
+                           timestamp:0
+                        windowNumber:[window windowNumber]
+                             context:nil
+                         eventNumber:0
+                          clickCount:1
+                            pressure:0];
+}
+
+}  // namespace
+
+// static
+MenuRunnerImplInterface* MenuRunnerImplInterface::Create(
+    ui::MenuModel* menu_model,
+    int32_t run_types,
+    const base::Closure& on_menu_closed_callback) {
+  if ((run_types & MenuRunner::CONTEXT_MENU) &&
+      !(run_types & MenuRunner::IS_NESTED)) {
+    return new MenuRunnerImplCocoa(menu_model, on_menu_closed_callback);
+  }
+  return new MenuRunnerImplAdapter(menu_model, on_menu_closed_callback);
+}
+
+MenuRunnerImplCocoa::MenuRunnerImplCocoa(
+    ui::MenuModel* menu,
+    const base::Closure& on_menu_closed_callback)
+    : running_(false),
+      delete_after_run_(false),
+      closing_event_time_(base::TimeTicks()),
+      on_menu_closed_callback_(on_menu_closed_callback) {
+  menu_controller_.reset([[MenuControllerCocoa alloc] initWithModel:menu
+                                             useWithPopUpButtonCell:NO]);
+  [menu_controller_ setPostItemSelectedAsTask:YES];
+}
+
+bool MenuRunnerImplCocoa::IsRunning() const {
+  return running_;
+}
+
+void MenuRunnerImplCocoa::Release() {
+  if (IsRunning()) {
+    if (delete_after_run_)
+      return;  // We already canceled.
+
+    delete_after_run_ = true;
+
+    // Reset |menu_controller_| to ensure it clears itself as a delegate to
+    // prevent NSMenu attempting to access the weak pointer to the ui::MenuModel
+    // it holds (which is not owned by |this|). Toolkit-views menus use
+    // MenuRunnerImpl::empty_delegate_ to handle this case.
+    menu_controller_.reset();
+  } else {
+    delete this;
+  }
+}
+
+void MenuRunnerImplCocoa::RunMenuAt(Widget* parent,
+                                    MenuButton* button,
+                                    const gfx::Rect& bounds,
+                                    MenuAnchorPosition anchor,
+                                    int32_t run_types) {
+  DCHECK(!IsRunning());
+  DCHECK(parent);
+  closing_event_time_ = base::TimeTicks();
+  running_ = true;
+
+  // Ensure the UI can update while the menu is fading out.
+  base::ScopedPumpMessagesInPrivateModes pump_private;
+
+  NSWindow* window = parent->GetNativeWindow();
+  if (run_types & MenuRunner::CONTEXT_MENU) {
+    [NSMenu popUpContextMenu:[menu_controller_ menu]
+                   withEvent:EventForPositioningContextMenu(bounds, window)
+                     forView:parent->GetNativeView()];
+  } else if (run_types & MenuRunner::COMBOBOX) {
+    NSMenuItem* checked_item = FirstCheckedItem(menu_controller_);
+    NSMenu* menu = [menu_controller_ menu];
+    base::scoped_nsobject<NSView> anchor_view(CreateMenuAnchorView(
+        window, bounds, checked_item, menu.size.width, anchor));
+    [menu setMinimumWidth:bounds.width() + kNativeCheckmarkWidth];
+    [menu popUpMenuPositioningItem:checked_item
+                        atLocation:NSZeroPoint
+                            inView:anchor_view];
+
+    [anchor_view removeFromSuperview];
+  } else {
+    NOTREACHED();
+  }
+
+  closing_event_time_ = ui::EventTimeForNow();
+  running_ = false;
+
+  if (delete_after_run_) {
+    delete this;
+    return;
+  }
+
+  // Don't invoke the callback if Release() was called, since that usually means
+  // the owning instance is being destroyed.
+  if (!on_menu_closed_callback_.is_null())
+    on_menu_closed_callback_.Run();
+}
+
+void MenuRunnerImplCocoa::Cancel() {
+  [menu_controller_ cancel];
+}
+
+base::TimeTicks MenuRunnerImplCocoa::GetClosingEventTime() const {
+  return closing_event_time_;
+}
+
+MenuRunnerImplCocoa::~MenuRunnerImplCocoa() {}
+
+}  // namespace internal
+}  // namespace views
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc
index 7872753..5cd8c61f 100644
--- a/ui/views/controls/textfield/textfield.cc
+++ b/ui/views/controls/textfield/textfield.cc
@@ -1168,6 +1168,15 @@
 void Textfield::ShowContextMenuForView(View* source,
                                        const gfx::Point& point,
                                        ui::MenuSourceType source_type) {
+#if defined(OS_MACOSX)
+  // On Mac, the context menu contains a look up item which displays the
+  // selected text. As such, the menu needs to be updated if the selection has
+  // changed. Be careful to reset the MenuRunner first so it doesn't reference
+  // the old model.
+  context_menu_runner_.reset();
+  context_menu_contents_.reset();
+#endif
+
   UpdateContextMenu();
   context_menu_runner_->RunMenuAt(GetWidget(), NULL,
                                   gfx::Rect(point, gfx::Size()),
@@ -2198,15 +2207,6 @@
   if (touch_selection_controller_)
     touch_selection_controller_->SelectionChanged();
 
-#if defined(OS_MACOSX)
-  // On Mac, the context menu contains a look up item which displays the
-  // selected text. As such, the menu needs to be updated if the selection has
-  // changed. Be careful to reset the MenuRunner first so it doesn't reference
-  // the old model.
-  context_menu_runner_.reset();
-  context_menu_contents_.reset();
-#endif
-
   // Screen reader users don't expect notifications about unfocused textfields.
   if (HasFocus())
     NotifyAccessibilityEvent(ax::mojom::Event::kTextSelectionChanged, true);
diff --git a/ui/views/controls/textfield/textfield_unittest.cc b/ui/views/controls/textfield/textfield_unittest.cc
index 0bdc2d66..6ccde82 100644
--- a/ui/views/controls/textfield/textfield_unittest.cc
+++ b/ui/views/controls/textfield/textfield_unittest.cc
@@ -698,14 +698,6 @@
         textfield_->GetSelectedRange().length() == text.length();
 
     int menu_index = 0;
-#if defined(OS_MACOSX)
-    // On Mac, the Look Up item should appear at the top of the menu if the
-    // textfield has a selection.
-    if (textfield_has_selection) {
-      EXPECT_TRUE(menu->IsEnabledAt(menu_index++ /* LOOK UP */));
-      EXPECT_TRUE(menu->IsEnabledAt(menu_index++ /* Separator */));
-    }
-#endif
     if (ui::IsEmojiPanelSupported()) {
       EXPECT_TRUE(menu->IsEnabledAt(menu_index++ /* EMOJI */));
       EXPECT_TRUE(menu->IsEnabledAt(menu_index++ /* Separator */));
@@ -3550,6 +3542,11 @@
   EXPECT_EQ(context_menu->GetLabelAt(0),
             l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_LOOK_UP, kTextOne));
 
+#if !defined(OS_MACOSX)
+  // Mac context menus don't behave this way: it's not possible to update the
+  // text while the menu is still "open", but also the selection can't change
+  // while the menu is open (because the user can't interact with the rest of
+  // the app).
   const base::string16 kTextTwo = ASCIIToUTF16("rail");
   textfield_->SetText(kTextTwo);
   textfield_->SelectAll(false);
@@ -3559,6 +3556,7 @@
   EXPECT_GT(context_menu->GetItemCount(), 0);
   EXPECT_EQ(context_menu->GetLabelAt(0),
             l10n_util::GetStringFUTF16(IDS_CONTENT_CONTEXT_LOOK_UP, kTextTwo));
+#endif
 }
 
 // Tests to see if the look up item is hidden for password fields.
diff --git a/ui/views/mus/remote_view/BUILD.gn b/ui/views/mus/remote_view/BUILD.gn
index a523299..8b33332 100644
--- a/ui/views/mus/remote_view/BUILD.gn
+++ b/ui/views/mus/remote_view/BUILD.gn
@@ -8,7 +8,7 @@
     "remote_view_host.h",
   ]
 
-  deps = [
+  public_deps = [
     "//base",
     "//ui/aura",
     "//ui/views",
diff --git a/webrunner/BUILD.gn b/webrunner/BUILD.gn
index fa80954..1077f33 100644
--- a/webrunner/BUILD.gn
+++ b/webrunner/BUILD.gn
@@ -13,6 +13,17 @@
   defines = [ "WEBRUNNER_IMPLEMENTATION" ]
 }
 
+# Uber-target, used by buildbots and :gn_all for discovery of all buildable
+# webrunner code.
+group("webrunner") {
+  testonly = true
+  deps = [
+    ":runner_pkg",
+    ":service_pkg",
+    ":service_unittests",
+  ]
+}
+
 fuchsia_package("runner_pkg") {
   binary = ":runner_exe"
   package_name_override = "web_runner"
@@ -42,16 +53,6 @@
   ]
 }
 
-# Uber-target, used by buildbots and :gn_all for discovery of all buildable
-# webrunner code.
-group("webrunner") {
-  testonly = true
-  deps = [
-    ":service_pkg",
-    ":service_unittests",
-  ]
-}
-
 fuchsia_package("service_pkg") {
   binary = ":service_exe"
   package_name_override = "chromium"
diff --git a/webrunner/app/component_controller_impl.cc b/webrunner/app/component_controller_impl.cc
index c4e0efc..d7403559 100644
--- a/webrunner/app/component_controller_impl.cc
+++ b/webrunner/app/component_controller_impl.cc
@@ -17,18 +17,28 @@
 
 namespace webrunner {
 
-ComponentControllerImpl::ComponentControllerImpl(
+// static
+std::unique_ptr<ComponentControllerImpl>
+ComponentControllerImpl::CreateForRequest(
     WebContentRunner* runner,
     fuchsia::sys::Package package,
     fuchsia::sys::StartupInfo startup_info,
-    ::fidl::InterfaceRequest<fuchsia::sys::ComponentController>
-        controller_request)
+    fidl::InterfaceRequest<fuchsia::sys::ComponentController>
+        controller_request) {
+  std::unique_ptr<ComponentControllerImpl> result{
+      new ComponentControllerImpl(runner)};
+  if (!result->BindToRequest(std::move(package), std::move(startup_info),
+                             std::move(controller_request))) {
+    return nullptr;
+  }
+  return result;
+}
+
+ComponentControllerImpl::ComponentControllerImpl(WebContentRunner* runner)
     : runner_(runner),
       controller_binding_(this),
       frame_observer_binding_(this) {
   DCHECK(runner);
-  BindToRequest(std::move(package), std::move(startup_info),
-                std::move(controller_request));
 }
 
 ComponentControllerImpl::~ComponentControllerImpl() {
@@ -37,10 +47,10 @@
   }
 }
 
-void ComponentControllerImpl::BindToRequest(
+bool ComponentControllerImpl::BindToRequest(
     fuchsia::sys::Package package,
     fuchsia::sys::StartupInfo startup_info,
-    ::fidl::InterfaceRequest<fuchsia::sys::ComponentController>
+    fidl::InterfaceRequest<fuchsia::sys::ComponentController>
         controller_request) {
   DCHECK(!service_directory_);
   DCHECK(!view_provider_binding_);
@@ -48,10 +58,7 @@
   url_ = GURL(*package.resolved_url);
   if (!url_.is_valid()) {
     LOG(ERROR) << "Rejected invalid URL: " << url_;
-
-    // By now |this| has been destroyed by WebContentRunner, so return
-    // immediately.
-    return;
+    return false;
   }
 
   if (controller_request.is_valid()) {
@@ -65,12 +72,18 @@
   frame_->GetNavigationController(navigation_controller_.NewRequest());
   navigation_controller_->LoadUrl(url_.spec(), nullptr);
 
-  // Publish a ViewProvider service.
+  // Create ServiceDirectory for the component and publish ViewProvider
+  // interface. ViewProvider will be used by the caller to create a view for the
+  // Frame. Note that these two operations must be done on the same/
+  // AsyncDispatcher in order to ensure that ServiceDirectory doesn't process
+  // incoming service requests before the service is published.
   service_directory_ = std::make_unique<base::fuchsia::ServiceDirectory>(
       std::move(startup_info.launch_info.directory_request));
   view_provider_binding_ = std::make_unique<
       base::fuchsia::ScopedServiceBinding<fuchsia::ui::views_v1::ViewProvider>>(
       service_directory_.get(), this);
+
+  return true;
 }
 
 void ComponentControllerImpl::Kill() {
@@ -91,13 +104,13 @@
     OnNavigationStateChangedCallback callback) {}
 
 void ComponentControllerImpl::CreateView(
-    ::fidl::InterfaceRequest<fuchsia::ui::views_v1_token::ViewOwner> view_owner,
-    ::fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> services) {
+    fidl::InterfaceRequest<fuchsia::ui::views_v1_token::ViewOwner> view_owner,
+    fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> services) {
   DCHECK(frame_);
-  DCHECK(!view_bound_);
+  DCHECK(!view_is_bound_);
 
   frame_->CreateView(std::move(view_owner), std::move(services));
-  view_bound_ = true;
+  view_is_bound_ = true;
 }
 
 }  // namespace webrunner
diff --git a/webrunner/app/component_controller_impl.h b/webrunner/app/component_controller_impl.h
index 488df9fd..d628cc1 100644
--- a/webrunner/app/component_controller_impl.h
+++ b/webrunner/app/component_controller_impl.h
@@ -29,13 +29,17 @@
                                 public chromium::web::FrameObserver,
                                 public fuchsia::ui::views_v1::ViewProvider {
  public:
-  ComponentControllerImpl(
+  ~ComponentControllerImpl() override;
+
+  // |runner| must outlive the returned object (normally it owns all
+  // ComponentControllerImpl). It's used by this class to get web::Context
+  // interface.
+  static std::unique_ptr<ComponentControllerImpl> CreateForRequest(
       WebContentRunner* runner,
       fuchsia::sys::Package package,
       fuchsia::sys::StartupInfo startup_info,
-      ::fidl::InterfaceRequest<fuchsia::sys::ComponentController>
+      fidl::InterfaceRequest<fuchsia::sys::ComponentController>
           controller_request);
-  ~ComponentControllerImpl() override;
 
   // fuchsia::sys::ComponentController implementation.
   void Kill() override;
@@ -49,28 +53,29 @@
 
   // fuchsia::ui::views_v1::ViewProvider implementation.
   void CreateView(
-      ::fidl::InterfaceRequest<::fuchsia::ui::views_v1_token::ViewOwner>
+      fidl::InterfaceRequest<::fuchsia::ui::views_v1_token::ViewOwner>
           view_owner,
-      ::fidl::InterfaceRequest<::fuchsia::sys::ServiceProvider> services)
+      fidl::InterfaceRequest<::fuchsia::sys::ServiceProvider> services)
       override;
 
  private:
   friend class WebContentRunner;
 
-  // Binds |this| to a Runner::StartComponent() call.
-  void BindToRequest(fuchsia::sys::Package package,
+  ComponentControllerImpl(WebContentRunner* runner);
+
+  // Binds |this| to a Runner::StartComponent() call. Returns false on failure
+  // (e.g. when the URL in |startup_info| is invalid).
+  bool BindToRequest(fuchsia::sys::Package package,
                      fuchsia::sys::StartupInfo startup_info,
-                     ::fidl::InterfaceRequest<fuchsia::sys::ComponentController>
+                     fidl::InterfaceRequest<fuchsia::sys::ComponentController>
                          controller_request);
 
   GURL url_;
   WebContentRunner* runner_ = nullptr;
 
-  // WebContextService client objects.
   chromium::web::FramePtr frame_;
   chromium::web::NavigationControllerPtr navigation_controller_;
 
-  // Bindings for services passed in to WebContextService.
   fidl::Binding<fuchsia::sys::ComponentController> controller_binding_;
   fidl::Binding<chromium::web::FrameObserver> frame_observer_binding_;
 
@@ -83,7 +88,7 @@
   std::vector<WaitCallback> termination_wait_callbacks_;
 
   bool did_terminate_abnormally_ = false;
-  bool view_bound_ = false;
+  bool view_is_bound_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(ComponentControllerImpl);
 };
diff --git a/webrunner/app/main.cc b/webrunner/app/main.cc
index 6cfeee9..7825180 100644
--- a/webrunner/app/main.cc
+++ b/webrunner/app/main.cc
@@ -42,8 +42,7 @@
 
   auto web_context = CreateContext();
   base::RunLoop run_loop;
-  webrunner::WebContentRunner runner(std::move(web_context),
-                                     run_loop.QuitClosure());
+  webrunner::WebContentRunner runner(std::move(web_context));
 
   base::fuchsia::ServiceDirectory* directory =
       base::fuchsia::ServiceDirectory::GetDefault();
diff --git a/webrunner/app/web_content_runner.cc b/webrunner/app/web_content_runner.cc
index 96c5042..03eee1ad 100644
--- a/webrunner/app/web_content_runner.cc
+++ b/webrunner/app/web_content_runner.cc
@@ -16,11 +16,9 @@
 
 namespace webrunner {
 
-WebContentRunner::WebContentRunner(chromium::web::ContextPtr context,
-                                   base::OnceClosure on_all_closed)
-    : context_(std::move(context)), on_all_closed_(std::move(on_all_closed)) {
+WebContentRunner::WebContentRunner(chromium::web::ContextPtr context)
+    : context_(std::move(context)) {
   DCHECK(context_);
-  DCHECK(on_all_closed_);
 }
 
 WebContentRunner::~WebContentRunner() = default;
@@ -28,12 +26,9 @@
 void WebContentRunner::StartComponent(
     fuchsia::sys::Package package,
     fuchsia::sys::StartupInfo startup_info,
-    ::fidl::InterfaceRequest<fuchsia::sys::ComponentController>
+    fidl::InterfaceRequest<fuchsia::sys::ComponentController>
         controller_request) {
-  DCHECK(on_all_closed_)
-      << "StartComponent() called after Runner was deactivated.";
-
-  auto controller = std::make_unique<ComponentControllerImpl>(
+  auto controller = ComponentControllerImpl::CreateForRequest(
       this, std::move(package), std::move(startup_info),
       std::move(controller_request));
   controller->BindToRequest(std::move(package), std::move(startup_info),
@@ -42,11 +37,7 @@
 }
 
 void WebContentRunner::DestroyComponent(ComponentControllerImpl* component) {
-  DCHECK(on_all_closed_);
   controllers_.erase(controllers_.find(component));
-  if (controllers_.empty()) {
-    std::move(on_all_closed_).Run();
-  }
 }
 
 }  // namespace webrunner
diff --git a/webrunner/app/web_content_runner.h b/webrunner/app/web_content_runner.h
index bb58e00d..e5a46ae 100644
--- a/webrunner/app/web_content_runner.h
+++ b/webrunner/app/web_content_runner.h
@@ -22,12 +22,9 @@
 // inside a View.
 class WebContentRunner : public fuchsia::sys::Runner {
  public:
-  // |context|: The web Context used to creates Frames.
-  // |on_all_closed|: A closure which is invoked when the last connected Frame
-  //    disconnects, signaling to the parent that the Context can be safely
-  //    destroyed.
-  WebContentRunner(chromium::web::ContextPtr context,
-                   base::OnceClosure on_all_closed);
+  // |content|: Context (e.g. persisted profile storage) under which all web
+  //   content launched through this Runner instance will be run.
+  explicit WebContentRunner(chromium::web::ContextPtr context);
   ~WebContentRunner() override;
 
   chromium::web::Context* context() { return context_.get(); }
@@ -37,17 +34,15 @@
   void DestroyComponent(ComponentControllerImpl* component);
 
   // fuchsia::sys::Runner implementation.
-  void StartComponent(
-      fuchsia::sys::Package package,
-      fuchsia::sys::StartupInfo startup_info,
-      ::fidl::InterfaceRequest<fuchsia::sys::ComponentController>
-          controller_request) override;
+  void StartComponent(fuchsia::sys::Package package,
+                      fuchsia::sys::StartupInfo startup_info,
+                      fidl::InterfaceRequest<fuchsia::sys::ComponentController>
+                          controller_request) override;
 
  private:
   chromium::web::ContextPtr context_;
   std::set<std::unique_ptr<ComponentControllerImpl>, base::UniquePtrComparator>
       controllers_;
-  base::OnceClosure on_all_closed_;
 
   DISALLOW_COPY_AND_ASSIGN(WebContentRunner);
 };