diff --git a/AUTHORS b/AUTHORS
index b27da88..16cb4dd 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -274,6 +274,7 @@
 Frédéric Jacob <frederic.jacob.78@gmail.com>
 Frédéric Wang <fred.wang@free.fr>
 Fu Junwei <junwei.fu@intel.com>
+Gabor Rapcsanyi <g.rapcsanyi@samsung.com>
 Gaetano Mendola <mendola@gmail.com>
 Gajendra N <gajendra.n@samsung.com>
 Gajendra Singh <wxjg68@motorola.com>
@@ -911,6 +912,7 @@
 Vivek Galatage <vivek.vg@samsung.com>
 Volker Sorge <volker.sorge@gmail.com>
 Waihung Fu <fufranci@amazon.com>
+Wanming Lin <wanming.lin@intel.com>
 WenSheng He <wensheng.he@samsung.com>
 Wesley Lancel <wesleylancel@gmail.com>
 Wesley Wigham <t-weswig@microsoft.com>
diff --git a/BUILD.gn b/BUILD.gn
index 3eb2034..b072baf 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -984,6 +984,7 @@
       "//device/usb/public/mojom:mojom_js_data_deps",
       "//device/vr/public/mojom:mojom_js_data_deps",
       "//media/capture/mojom:image_capture_js_data_deps",
+      "//media/midi:mojo_js_data_deps",
       "//mojo/public/interfaces/bindings/tests:test_data_deps",
       "//mojo/public/mojom/base:base_js_data_deps",
       "//services/shape_detection/public/mojom:mojom_js_data_deps",
diff --git a/DEPS b/DEPS
index 36df7b1..235488e0 100644
--- a/DEPS
+++ b/DEPS
@@ -115,11 +115,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '1f9c73766d63bd649da4bf02f237612b77078195',
+  'skia_revision': 'f6206f91b3c13de83865bfda464e147c5e39fd6e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '16d19c1895693cd8fe589b7bc860481de73f8990',
+  'v8_revision': '1962a66fe3c2d93454f7ceaea7c34b60c2892b1f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -127,7 +127,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '4a9f9b08b691aebbb421d2b33e5c7fbadfaffe1f',
+  'angle_revision': '70fd9b5d381e08710771ff44d8a129128f83f4b2',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -147,7 +147,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
-  'boringssl_revision': '0f5ecd3a854546d943104e1f7421e489b7f4d5aa',
+  'boringssl_revision': '4cce955d1487b5bd2b3c03ead986558649cdaadf',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling google-toolbox-for-mac
   # and whatever else without interference from each other.
@@ -239,7 +239,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': 'ff9562f7927b614f16449f3c757c57c70543eb37',
+  'dawn_revision': '08aa58f8d6ed07966cc388ed7bde26976be09a07',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -662,7 +662,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '86cdce6fb00ded79d666c191a21c6520be29f449',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'f15e4e6c0c9dba759e1a3fc6e90549aea595c58b',
       'condition': 'checkout_linux',
   },
 
@@ -1019,7 +1019,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '745aaf284105c855e03a36df6074bddbe27a8cd3',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '61804c04b375eefcd341751fd7f3369ab46d41d1',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78',
@@ -1213,7 +1213,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@d484f4385ce6f23623a1a9a65eb18f682bfaa809',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@b94aa37fe30c0052ede44e30ed3b94530fe44bf6',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/ash/login/login_screen_controller.cc b/ash/login/login_screen_controller.cc
index 0d64986..7733074 100644
--- a/ash/login/login_screen_controller.cc
+++ b/ash/login/login_screen_controller.cc
@@ -529,6 +529,13 @@
       ->SetAddUserButtonEnabled(enable);
 }
 
+void LoginScreenController::SetShutdownButtonEnabled(bool enable) {
+  Shelf::ForWindow(Shell::Get()->GetPrimaryRootWindow())
+      ->shelf_widget()
+      ->login_shelf_view()
+      ->SetShutdownButtonEnabled(enable);
+}
+
 void LoginScreenController::LaunchKioskApp(const std::string& app_id) {
   login_screen_client_->LaunchKioskApp(app_id);
 }
diff --git a/ash/login/login_screen_controller.h b/ash/login/login_screen_controller.h
index b09d83b4..07af915 100644
--- a/ash/login/login_screen_controller.h
+++ b/ash/login/login_screen_controller.h
@@ -154,6 +154,7 @@
   void ShowKioskAppError(const std::string& message) override;
   void NotifyOobeDialogState(mojom::OobeDialogState state) override;
   void SetAddUserButtonEnabled(bool enable) override;
+  void SetShutdownButtonEnabled(bool enable) override;
   void SetAllowLoginAsGuest(bool allow_guest) override;
   void SetShowGuestButtonInOobe(bool show) override;
   void FocusLoginShelf(bool reverse) override;
diff --git a/ash/public/interfaces/login_screen.mojom b/ash/public/interfaces/login_screen.mojom
index f5e0973..ee8df7d 100644
--- a/ash/public/interfaces/login_screen.mojom
+++ b/ash/public/interfaces/login_screen.mojom
@@ -208,6 +208,9 @@
   // Sets whether users can be added from the login screen.
   SetAddUserButtonEnabled(bool enable);
 
+  // Sets whether shutdown button is enabled in the login screen.
+  SetShutdownButtonEnabled(bool enable);
+
   // Sets if the guest button on the login shelf can be shown. Even if set to
   // true the button may still not be visible.
   SetAllowLoginAsGuest(bool allow_guest);
diff --git a/ash/shelf/login_shelf_view.cc b/ash/shelf/login_shelf_view.cc
index f7c1ea7..d10c55e 100644
--- a/ash/shelf/login_shelf_view.cc
+++ b/ash/shelf/login_shelf_view.cc
@@ -514,6 +514,10 @@
   GetViewByID(kAddUser)->SetEnabled(enable_add_user);
 }
 
+void LoginShelfView::SetShutdownButtonEnabled(bool enable_shutdown_button) {
+  GetViewByID(kShutdown)->SetEnabled(enable_shutdown_button);
+}
+
 void LoginShelfView::OnLockScreenNoteStateChanged(
     mojom::TrayActionState state) {
   UpdateUi();
diff --git a/ash/shelf/login_shelf_view.h b/ash/shelf/login_shelf_view.h
index 75f6a09d..1dd6e459 100644
--- a/ash/shelf/login_shelf_view.h
+++ b/ash/shelf/login_shelf_view.h
@@ -85,6 +85,9 @@
   // Sets whether users can be added from the login screen.
   void SetAddUserButtonEnabled(bool enable_add_user);
 
+  // Sets whether shutdown button is enabled in the login screen.
+  void SetShutdownButtonEnabled(bool enable_shutdown_button);
+
   // views::View:
   const char* GetClassName() const override;
   void OnFocus() override;
diff --git a/ash/shelf/login_shelf_view_unittest.cc b/ash/shelf/login_shelf_view_unittest.cc
index ba2374f..71b269b 100644
--- a/ash/shelf/login_shelf_view_unittest.cc
+++ b/ash/shelf/login_shelf_view_unittest.cc
@@ -498,5 +498,26 @@
   EXPECT_TRUE(IsButtonEnabled(LoginShelfView::kAddUser));
 }
 
+TEST_F(LoginShelfViewTest, ShouldUpdateUiAfterShutdownButtonStatusChange) {
+  login_shelf_view_->SetAllowLoginAsGuest(true /*allow_guest*/);
+  NotifySessionStateChanged(SessionState::LOGIN_PRIMARY);
+  EXPECT_TRUE(ShowsShelfButtons({LoginShelfView::kShutdown,
+                                 LoginShelfView::kBrowseAsGuest,
+                                 LoginShelfView::kAddUser}));
+  EXPECT_TRUE(IsButtonEnabled(LoginShelfView::kShutdown));
+
+  login_shelf_view_->SetShutdownButtonEnabled(false /*enable_shutdown_button*/);
+  EXPECT_TRUE(ShowsShelfButtons({LoginShelfView::kShutdown,
+                                 LoginShelfView::kBrowseAsGuest,
+                                 LoginShelfView::kAddUser}));
+  EXPECT_FALSE(IsButtonEnabled(LoginShelfView::kShutdown));
+
+  login_shelf_view_->SetShutdownButtonEnabled(true /*enable_shutdown_button*/);
+  EXPECT_TRUE(ShowsShelfButtons({LoginShelfView::kShutdown,
+                                 LoginShelfView::kBrowseAsGuest,
+                                 LoginShelfView::kAddUser}));
+  EXPECT_TRUE(IsButtonEnabled(LoginShelfView::kShutdown));
+}
+
 }  // namespace
 }  // namespace ash
diff --git a/base/android/proguard/OWNERS b/base/android/proguard/OWNERS
new file mode 100644
index 0000000..48c6ddc
--- /dev/null
+++ b/base/android/proguard/OWNERS
@@ -0,0 +1 @@
+smaier@chromium.org
diff --git a/base/json/json_perftest.cc b/base/json/json_perftest.cc
index 309913ca..fc05bdc 100644
--- a/base/json/json_perftest.cc
+++ b/base/json/json_perftest.cc
@@ -7,7 +7,6 @@
 #include "base/memory/ptr_util.h"
 #include "base/time/time.h"
 #include "base/values.h"
-#include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/perf/perf_test.h"
 
@@ -74,13 +73,7 @@
   }
 };
 
-// Times out on Android (crbug.com/906686).
-#if defined(OS_ANDROID)
-#define MAYBE_StressTest DISABLED_StressTest
-#else
-#define MAYBE_StressTest StressTest
-#endif
-TEST_F(JSONPerfTest, MAYBE_StressTest) {
+TEST_F(JSONPerfTest, StressTest) {
   for (int i = 0; i < 4; ++i) {
     for (int j = 0; j < 12; ++j) {
       TestWriteAndRead(i + 1, j + 1);
diff --git a/base/mac/sdk_forward_declarations.h b/base/mac/sdk_forward_declarations.h
index f2019b7..6a4cd64 100644
--- a/base/mac/sdk_forward_declarations.h
+++ b/base/mac/sdk_forward_declarations.h
@@ -357,10 +357,6 @@
 @end
 
 BASE_EXPORT extern NSAppearanceName const NSAppearanceNameDarkAqua;
-BASE_EXPORT extern NSAppearanceName const
-    NSAppearanceNameAccessibilityHighContrastDarkAqua;
-BASE_EXPORT extern NSAppearanceName const
-    NSAppearanceNameAccessibilityHighContrastAqua;
 
 #endif
 
diff --git a/base/mac/sdk_forward_declarations.mm b/base/mac/sdk_forward_declarations.mm
index a463c27..1235e51a 100644
--- a/base/mac/sdk_forward_declarations.mm
+++ b/base/mac/sdk_forward_declarations.mm
@@ -22,8 +22,4 @@
 #if !defined(MAC_OS_X_VERSION_10_14) || \
     MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_14
 NSString* const NSAppearanceNameDarkAqua = @"NSAppearanceNameDarkAqua";
-NSString* const NSAppearanceNameAccessibilityHighContrastDarkAqua =
-    @"NSAppearanceNameAccessibilityHighContrastDarkAqua";
-NSString* const NSAppearanceNameAccessibilityHighContrastAqua =
-    @"NSAppearanceNameAccessibilityHighContrastAqua";
 #endif
diff --git a/base/message_loop/message_pump_perftest.cc b/base/message_loop/message_pump_perftest.cc
index eb09aad..9bbb2d4 100644
--- a/base/message_loop/message_pump_perftest.cc
+++ b/base/message_loop/message_pump_perftest.cc
@@ -83,9 +83,6 @@
 
   void ScheduleWork(MessageLoop::Type target_type, int num_scheduling_threads) {
 #if defined(OS_ANDROID)
-    // Test randomly times out on Android (crbug.com/906686).
-    return;
-
     if (target_type == MessageLoop::TYPE_JAVA) {
       java_thread_.reset(new android::JavaHandlerThread("target"));
       java_thread_->Start();
diff --git a/base/observer_list_perftest.cc b/base/observer_list_perftest.cc
index 6fe9c7b..2e0e5e88 100644
--- a/base/observer_list_perftest.cc
+++ b/base/observer_list_perftest.cc
@@ -10,7 +10,6 @@
 #include "base/observer_list.h"
 #include "base/strings/stringprintf.h"
 #include "base/time/time.h"
-#include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/perf/perf_test.h"
 
@@ -62,12 +61,7 @@
 TYPED_TEST_CASE(ObserverListPerfTest, ObserverTypes);
 
 // Performance test for base::ObserverList and Checked Observers.
-// Times out on Android (crbug.com/906686).
-#if defined(OS_ANDROID)
-TYPED_TEST(ObserverListPerfTest, DISABLED_NotifyPerformance) {
-#else
 TYPED_TEST(ObserverListPerfTest, NotifyPerformance) {
-#endif
   constexpr int kMaxObservers = 128;
 #if DCHECK_IS_ON()
   // The test takes about 100x longer in debug builds, mostly due to sequence
diff --git a/base/test/scoped_task_environment.cc b/base/test/scoped_task_environment.cc
index 49e91a3..2bc5607 100644
--- a/base/test/scoped_task_environment.cc
+++ b/base/test/scoped_task_environment.cc
@@ -297,7 +297,8 @@
     ExecutionMode execution_control_mode,
     NowSource now_source,
     NotATraitTag)
-    : execution_control_mode_(execution_control_mode),
+    : main_thread_type_(main_thread_type),
+      execution_control_mode_(execution_control_mode),
       mock_time_domain_(MockTimeDomain::Create(main_thread_type, now_source)),
       sequence_manager_(
           CreateSequenceManagerForMainThreadType(main_thread_type)),
@@ -314,6 +315,7 @@
       task_tracker_(new TestTaskTracker()) {
   CHECK(now_source == NowSource::REAL_TIME || mock_time_domain_)
       << "NowSource must be REAL_TIME unless we're using mock time";
+  CHECK(!base::ThreadTaskRunnerHandle::IsSet());
   CHECK(!TaskScheduler::GetInstance())
       << "Someone has already initialized TaskScheduler. If nothing in your "
          "test does so, then a test that ran earlier may have initialized one, "
@@ -385,14 +387,24 @@
   // on their main thread.
   ScopedAllowBaseSyncPrimitivesForTesting allow_waits_to_destroy_task_tracker;
   TaskScheduler::SetInstance(nullptr);
+  task_queue_ = nullptr;
+  NotifyDestructionObserversAndReleaseSequenceManager();
+}
+
+void ScopedTaskEnvironment::
+    NotifyDestructionObserversAndReleaseSequenceManager() {
+  // A derived classes may call this method early.
+  if (!sequence_manager_)
+    return;
 
   LifetimeObserver* observer = environment_lifetime_observer.Get().Get();
   if (observer)
     observer->OnScopedTaskEnvironmentDestroyed();
 
-  task_queue_ = nullptr;
   if (mock_time_domain_)
     sequence_manager_->UnregisterTimeDomain(mock_time_domain_.get());
+
+  sequence_manager_.reset();
 }
 
 scoped_refptr<sequence_manager::TaskQueue>
diff --git a/base/test/scoped_task_environment.h b/base/test/scoped_task_environment.h
index 8695da1..68816bdd 100644
--- a/base/test/scoped_task_environment.h
+++ b/base/test/scoped_task_environment.h
@@ -134,7 +134,7 @@
 
   // Waits until no undelayed TaskScheduler tasks remain. Then, unregisters the
   // TaskScheduler and the (Thread|Sequenced)TaskRunnerHandle.
-  ~ScopedTaskEnvironment();
+  virtual ~ScopedTaskEnvironment();
 
   class LifetimeObserver {
    public:
@@ -200,6 +200,16 @@
   // TaskRunner.
   TimeDelta NextMainThreadPendingTaskDelay() const;
 
+ protected:
+  MainThreadType main_thread_type() const { return main_thread_type_; }
+
+  ExecutionMode execution_control_mode() const {
+    return execution_control_mode_;
+  }
+
+  // Derived classes may need to control when the sequence manager goes away.
+  void NotifyDestructionObserversAndReleaseSequenceManager();
+
  private:
   class MockTimeDomain;
   class TestTaskTracker;
@@ -221,10 +231,11 @@
 
   scoped_refptr<sequence_manager::TaskQueue> CreateDefaultTaskQueue();
 
+  const MainThreadType main_thread_type_;
   const ExecutionMode execution_control_mode_;
 
   const std::unique_ptr<MockTimeDomain> mock_time_domain_;
-  const std::unique_ptr<sequence_manager::SequenceManager> sequence_manager_;
+  std::unique_ptr<sequence_manager::SequenceManager> sequence_manager_;
 
   scoped_refptr<sequence_manager::TaskQueue> task_queue_;
 
diff --git a/build/android/gyp/dexsplitter.py b/build/android/gyp/dexsplitter.py
index 02b047c7..a0761581 100755
--- a/build/android/gyp/dexsplitter.py
+++ b/build/android/gyp/dexsplitter.py
@@ -110,7 +110,7 @@
       with build_utils.AtomicOutput(dest) as f:
         if curr_location.endswith('.zip'):
           if dest.endswith('.zip'):
-            shutil.move(curr_location, f.name)
+            shutil.copy(curr_location, f.name)
           else:
             with zipfile.ZipFile(curr_location, 'r') as z:
               namelist = z.namelist()
diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py
index 2c1b6ff..2a8be71 100755
--- a/build/android/gyp/write_build_config.py
+++ b/build/android/gyp/write_build_config.py
@@ -366,9 +366,6 @@
 List of native libraries for the secondary ABI to be embedded in this APK.
 Empty if only a single ABI is supported.
 
-* `native['secondary_abi_java_libraries_list']`
-The same list as `native['second_abi_libraries']` as a Java source string.
-
 * `native['uncompress_shared_libraries']`
 A boolean indicating whether native libraries are stored uncompressed in the
 APK.
@@ -1408,14 +1405,11 @@
       java_libraries_list = _CreateJavaLibrariesList(library_paths)
 
     secondary_abi_library_paths = []
-    secondary_abi_java_libraries_list = None
     secondary_abi_runtime_deps_files = build_utils.ParseGnList(
         options.secondary_abi_shared_libraries_runtime_deps or '[]')
     if secondary_abi_runtime_deps_files:
       secondary_abi_library_paths = _ExtractSharedLibsFromRuntimeDeps(
           secondary_abi_runtime_deps_files)
-      secondary_abi_java_libraries_list = _CreateJavaLibrariesList(
-          secondary_abi_library_paths)
     for gn_list in options.secondary_native_libs:
       secondary_abi_library_paths.extend(build_utils.ParseGnList(gn_list))
 
@@ -1428,7 +1422,6 @@
       'libraries': library_paths,
       'secondary_abi_libraries': secondary_abi_library_paths,
       'java_libraries_list': java_libraries_list,
-      'secondary_abi_java_libraries_list': secondary_abi_java_libraries_list,
       'uncompress_shared_libraries': options.uncompress_shared_libraries,
       'extra_shared_libraries': extra_shared_libraries,
     }
diff --git a/build/android/gyp/write_ordered_libraries.py b/build/android/gyp/write_ordered_libraries.py
index 92c82bb..61da64c 100755
--- a/build/android/gyp/write_ordered_libraries.py
+++ b/build/android/gyp/write_ordered_libraries.py
@@ -109,8 +109,8 @@
       only_if_changed=True)
 
   if options.depfile:
-    build_utils.WriteDepfile(options.depfile, options.output, libraries,
-                             add_pydeps=False)
+    build_utils.WriteDepfile(
+        options.depfile, options.output, lib_paths, add_pydeps=False)
 
 
 if __name__ == '__main__':
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index 9b1c6c9..f70eb63 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -2404,11 +2404,7 @@
           _native_lib_placeholders != []) {
         args += [ "--android-abi=$android_app_abi" ]
       }
-      if (defined(invoker.secondary_abi_native_libs_filearg) ||
-          (defined(invoker.secondary_abi_loadable_modules) &&
-           invoker.secondary_abi_loadable_modules != []) ||
-          _secondary_native_lib_placeholders != []) {
-        assert(defined(android_app_secondary_abi))
+      if (defined(android_app_secondary_abi)) {
         args += [ "--secondary-android-abi=$android_app_secondary_abi" ]
       }
       if (invoker.native_libs != []) {
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index 18460a4..f15adde13 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -2665,7 +2665,9 @@
       create_apk("$_create_apk_target") {
         forward_variables_from(invoker,
                                [
+                                 "native_lib_placeholders",
                                  "public_deps",
+                                 "secondary_native_lib_placeholders",
                                  "shared_resources",
                                  "write_asset_list",
                                  "uncompress_dex",
@@ -2715,20 +2717,9 @@
               _extra_native_libs_even_when_incremental
         }
         deps += _all_native_libs_deps
-
-        if (_secondary_abi_native_libs_deps != []) {
-          deps += _secondary_abi_native_libs_deps
-          secondary_abi_native_libs_filearg =
-              "@FileArg($_rebased_build_config:native:secondary_abi_libraries)"
-        }
-
-        # Placeholders necessary for some older devices.
-        # http://crbug.com/395038
-        forward_variables_from(invoker,
-                               [
-                                 "native_lib_placeholders",
-                                 "secondary_native_lib_placeholders",
-                               ])
+        deps += _secondary_abi_native_libs_deps
+        secondary_abi_native_libs_filearg =
+            "@FileArg($_rebased_build_config:native:secondary_abi_libraries)"
 
         uncompress_shared_libraries = _uncompress_shared_libraries
       }
@@ -3941,7 +3932,7 @@
         output = _unsplit_dex_zip
       }
 
-      _dexsplitter_target = "${_unsplit_dex_target}__dexspliter"
+      _dexsplitter_target = "${_unsplit_dex_target}__dexsplitter"
       dexsplitter(_dexsplitter_target) {
         input_dex_zip = _unsplit_dex_zip
         proguard_mapping = _proguard_mapping_path
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java
index 65065d7..9dc7e14 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java
@@ -30,8 +30,7 @@
 
     /** Returns true if all conditions are satisfied to start Autofill Assistant. */
     public static boolean isConfigured(@Nullable Bundle intentExtras) {
-        return getBooleanParameter(intentExtras, PARAMETER_ENABLED)
-                && AutofillAssistantPreferencesUtil.canShowAutofillAssistant();
+        return getBooleanParameter(intentExtras, PARAMETER_ENABLED);
     }
 
     /** Starts Autofill Assistant on the given {@code activity}. */
@@ -48,15 +47,14 @@
         final AbstractAutofillAssistantUiController targetController = controller == null
                 ? new AutofillAssistantUiController(activity, parameters)
                 : controller;
-        if (!AutofillAssistantPreferencesUtil.getSkipInitScreenPreference()) {
+        if (AutofillAssistantPreferencesUtil.getShowOnboarding()) {
             FirstRunScreen.show(activity, (result) -> {
                 if (result) initiateAutofillAssistant(activity, parameters, targetController);
             });
             return;
         }
 
-        if (AutofillAssistantPreferencesUtil.isAutofillAssistantSwitchOn()
-                && AutofillAssistantPreferencesUtil.getSkipInitScreenPreference()) {
+        if (AutofillAssistantPreferencesUtil.isAutofillAssistantSwitchOn()) {
             initiateAutofillAssistant(activity, parameters, targetController);
         }
         // We don't have consent to start Autofill Assistant and cannot show initial screen.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPreferencesUtil.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPreferencesUtil.java
index 4742f2c..ece6690 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPreferencesUtil.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPreferencesUtil.java
@@ -12,9 +12,11 @@
     // Avoid instatiation by accident.
     private AutofillAssistantPreferencesUtil() {}
 
-    /**
-     * Peference keeping track of whether the initial screen should be skipped on startup.
-     */
+    /** Peference keeping track of whether the onboarding has been accepted. */
+    private static final String AUTOFILL_ASSISTANT_ONBOARDING_ACCEPTED =
+            "AUTOFILL_ASSISTANT_ONBOARDING_ACCEPTED";
+
+    /** LEGACY preference for when the `do not show again' checkbox still existed. */
     private static final String AUTOFILL_ASSISTANT_SKIP_INIT_SCREEN =
             "AUTOFILL_ASSISTANT_SKIP_INIT_SCREEN";
 
@@ -24,37 +26,35 @@
                 AutofillAssistantPreferences.PREF_AUTOFILL_ASSISTANT_SWITCH, true);
     }
 
-    /** Gets whether skip initial screen preference. */
-    static boolean getSkipInitScreenPreference() {
+    /** Checks whether the Autofill Assistant onboarding has been accepted. */
+    static boolean isAutofillOnboardingAccepted() {
         return ContextUtils.getAppSharedPreferences().getBoolean(
-                AUTOFILL_ASSISTANT_SKIP_INIT_SCREEN, false);
+                       AUTOFILL_ASSISTANT_ONBOARDING_ACCEPTED, false)
+                ||
+                /* Legacy treatment: users of earlier versions should not have to see the onboarding
+                again if they checked the `do not show again' checkbox*/
+                ContextUtils.getAppSharedPreferences().getBoolean(
+                        AUTOFILL_ASSISTANT_SKIP_INIT_SCREEN, false);
     }
 
-    /**
-     * Returns true if the switch for AutofillAssistant is turned on or the init screen can
-     * be shown. The later is important if the switched is turned off, but we can ask again
-     * to enable AutofillAssistant.
-     */
-    static boolean canShowAutofillAssistant() {
-        return isAutofillAssistantSwitchOn() || !getSkipInitScreenPreference();
+    /** Checks whether the Autofill Assistant onboarding screen should be shown. */
+    static boolean getShowOnboarding() {
+        return !isAutofillAssistantSwitchOn() || !isAutofillOnboardingAccepted();
     }
 
     /**
      * Sets preferences from the initial screen.
      *
-     * @param accept Flag indicates whether this service is accepted.
-     * @param dontShowAgain Flag indicates whether initial screen should be shown again next time.
+     * @param accept Flag indicating whether the ToS have been accepted.
      */
     static void setInitialPreferences(boolean accept) {
         ContextUtils.getAppSharedPreferences()
                 .edit()
                 .putBoolean(AutofillAssistantPreferences.PREF_AUTOFILL_ASSISTANT_SWITCH, accept)
                 .apply();
-        if (accept) {
-            ContextUtils.getAppSharedPreferences()
-                    .edit()
-                    .putBoolean(AUTOFILL_ASSISTANT_SKIP_INIT_SCREEN, true)
-                    .apply();
-        }
+        ContextUtils.getAppSharedPreferences()
+                .edit()
+                .putBoolean(AUTOFILL_ASSISTANT_ONBOARDING_ACCEPTED, accept)
+                .apply();
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
index 03b97c3..60391d9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
@@ -414,6 +414,11 @@
         AccountManagerFacade.get().invalidateAuthToken(accessToken);
     }
 
+    @CalledByNative
+    private void expandBottomSheet() {
+        mUiDelegateHolder.performUiOperation(AutofillAssistantUiDelegate::expandBottomSheet);
+    }
+
     /** Choose an account to authenticate as for making RPCs to the backend. */
     private void chooseAccountAsync(@Nullable String accountFromParameter, Bundle extras) {
         AccountManagerFacade.get().tryGetGoogleAccounts(accounts -> {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java
index 6edf33b..8c395c6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java
@@ -420,6 +420,7 @@
             // Make sure the Autofill Assistant is visible.
             show();
             mBottomBarAnimations.showCarousel();
+            expandBottomSheet();
         }
     }
 
@@ -865,4 +866,8 @@
         }
         params.setBehavior(null);
     }
+
+    public void expandBottomSheet() {
+        mBottomBarBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
index e6cdee0..6078f2f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -1198,7 +1198,7 @@
      *         purposes only.
      */
     @VisibleForTesting
-    CustomTabIntentDataProvider getIntentDataProvider() {
+    public CustomTabIntentDataProvider getIntentDataProvider() {
         return mIntentDataProvider;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
index f3f96502..e1a75fa 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
@@ -132,25 +132,28 @@
             "android.support.customtabs.extra.SEND_TO_EXTERNAL_HANDLER";
 
     /** Key for the intent extra used to define an array list of module managed hosts. */
-    /* package */ static final String EXTRA_MODULE_MANAGED_HOST_LIST =
+    @VisibleForTesting
+    public static final String EXTRA_MODULE_MANAGED_HOST_LIST =
             "org.chromium.chrome.browser.customtabs.EXTRA_MODULE_MANAGED_HOST_LIST";
 
     /** Extra that defines the module managed URLs regex. */
-    /* package */ static final String EXTRA_MODULE_MANAGED_URLS_REGEX =
+    @VisibleForTesting
+    public static final String EXTRA_MODULE_MANAGED_URLS_REGEX =
             "org.chromium.chrome.browser.customtabs.EXTRA_MODULE_MANAGED_URLS_REGEX";
 
     /** The APK package to load the module from. */
     @VisibleForTesting
-    /* package */ static final String EXTRA_MODULE_PACKAGE_NAME =
+    public static final String EXTRA_MODULE_PACKAGE_NAME =
             "org.chromium.chrome.browser.customtabs.EXTRA_MODULE_PACKAGE_NAME";
 
     /** The class name of the module entry point. */
     @VisibleForTesting
-    /* package */ static final String EXTRA_MODULE_CLASS_NAME =
+    public static final String EXTRA_MODULE_CLASS_NAME =
             "org.chromium.chrome.browser.customtabs.EXTRA_MODULE_CLASS_NAME";
 
     /** Extra that indicates whether to hide the CCT header on module managed URLs. */
-    /* package */ static final String EXTRA_HIDE_CCT_HEADER_ON_MODULE_MANAGED_URLS =
+    @VisibleForTesting
+    public static final String EXTRA_HIDE_CCT_HEADER_ON_MODULE_MANAGED_URLS =
             "org.chromium.chrome.browser.customtabs.EXTRA_HIDE_CCT_HEADER_ON_MODULE_MANAGED_URLS";
 
     private static final int MAX_CUSTOM_MENU_ITEMS = 5;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java
index 249e8bc..486aa1f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java
@@ -148,7 +148,8 @@
      *
      * @return whether or not module loading starts.
      */
-    private void loadModule() {
+    @VisibleForTesting
+    /* package */ void loadModule() {
         ComponentName componentName = mIntentDataProvider.getModuleComponentName();
 
         ModuleLoader moduleLoader = mConnection.getModuleLoader(componentName);
@@ -313,12 +314,11 @@
         }
     }
 
-    private boolean isModuleLoaded() {
+    /* package */ boolean isModuleLoaded() {
         return mModuleEntryPoint != null;
     }
 
-    @VisibleForTesting
-    public boolean isModuleLoading() {
+    /* package */ boolean isModuleLoading() {
         return mModuleCallback != null;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java
index b7560361..f6fc919 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java
@@ -161,11 +161,9 @@
         }
 
         // This checks whether Autofill Assistant is enabled.
-        // Unconditionally remove the Autofill Assistant preference entry. This is an intermediate
-        // step before completely removing that preference.
-        // TODO(crbug.com/806868): Show the preference when autofill assistant has explicitly been
-        // accepted in the first run screen.
-        getPreferenceScreen().removePreference(findPreference(PREF_AUTOFILL_ASSISTANT));
+        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.AUTOFILL_ASSISTANT)) {
+            getPreferenceScreen().removePreference(findPreference(PREF_AUTOFILL_ASSISTANT));
+        }
     }
 
     /**
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index 54558e2..0aff8c74 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -4005,10 +4005,10 @@
       </message>
       <!-- Autofill Assistant preferences -->
       <message name="IDS_PREFS_AUTOFILL_ASSISTANT_TITLE" desc="Title for the Autofill Assistant preferences screen. [CHAR-LIMIT=32]">
-        Autofill Assistant
+        Google Assistant for Chrome
       </message>
       <message name="IDS_PREFS_AUTOFILL_ASSISTANT_SWITCH" desc="Title for the switch toggling whether Autofill Assistant is enabled. [CHAR-LIMIT=32]">
-        Automate
+        Assistant Triggered Checkout
       </message>
       <message name="IDS_AUTOFILL_ASSISTANT_GOOGLE_TERMS_DESCRIPTION" desc="Message linking to the Google terms and conditions for Fast Checkout.">
         By continuing you agree to the Google terms and conditions for Fast Checkout. <ph name="BEGIN_LINK">&lt;link&gt;</ph>Read more<ph name="END_LINK">&lt;/link&gt;</ph>
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index 501d60d..27ef4b7 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -1956,12 +1956,14 @@
   "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistenceIntegrationTest.java",
   "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicyTest.java",
   "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java",
-  "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsDynamicModuleLoaderTest.java",
-  "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsDynamicModuleNavigationTest.java",
-  "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsDynamicModuleTestUtils.java",
   "javatests/src/org/chromium/chrome/browser/customtabs/DetachedResourceRequestTest.java",
   "javatests/src/org/chromium/chrome/browser/customtabs/RequestThrottlerTest.java",
   "javatests/src/org/chromium/chrome/browser/customtabs/TrustedCdnPublisherUrlTest.java",
+  "javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleLoaderTest.java",
+  "javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleNavigationTest.java",
+  "javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModulePostMessageTest.java",
+  "javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleTestUtils.java",
+  "javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleUITest.java",
   "javatests/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutTest.java",
   "javatests/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutTestRule.java",
   "javatests/src/org/chromium/chrome/browser/display_cutout/WebappDisplayCutoutTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
index 320aadd..5e1b1ce7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -8,7 +8,6 @@
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.not;
-import static org.junit.Assert.fail;
 
 import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE;
 import static org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule.LONG_TIMEOUT_MS;
@@ -38,11 +37,9 @@
 import android.support.customtabs.CustomTabsService;
 import android.support.customtabs.CustomTabsSession;
 import android.support.customtabs.CustomTabsSessionToken;
-import android.support.customtabs.PostMessageBackend;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
 import android.support.test.filters.SmallTest;
-import android.support.test.uiautomator.UiDevice;
 import android.support.v7.content.res.AppCompatResources;
 import android.text.TextUtils;
 import android.view.Menu;
@@ -78,7 +75,6 @@
 import org.chromium.base.test.util.Restriction;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.AppHooksModule;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
@@ -90,7 +86,6 @@
 import org.chromium.chrome.browser.browserservices.BrowserSessionContentUtils;
 import org.chromium.chrome.browser.browserservices.Origin;
 import org.chromium.chrome.browser.browserservices.OriginVerifier;
-import org.chromium.chrome.browser.customtabs.dynamicmodule.DynamicModuleCoordinator;
 import org.chromium.chrome.browser.dependency_injection.ModuleFactoryOverrides;
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 import org.chromium.chrome.browser.firstrun.FirstRunStatus;
@@ -117,27 +112,22 @@
 import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.chrome.test.util.browser.LocationSettingsTestUtil;
-import org.chromium.chrome.test.util.browser.TabTitleObserver;
 import org.chromium.chrome.test.util.browser.contextmenu.ContextMenuUtils;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.WebContentsObserver;
-import org.chromium.content_public.browser.test.util.ClickUtils;
 import org.chromium.content_public.browser.test.util.Criteria;
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
 import org.chromium.content_public.browser.test.util.DOMUtils;
 import org.chromium.content_public.browser.test.util.JavaScriptUtils;
 import org.chromium.content_public.browser.test.util.WebContentsUtils;
 import org.chromium.net.test.EmbeddedTestServer;
-import org.chromium.net.test.ServerCertificate;
 import org.chromium.net.test.util.TestWebServer;
-import org.chromium.ui.base.PageTransition;
 import org.chromium.ui.mojom.WindowOpenDisposition;
 import org.chromium.ui.test.util.UiRestriction;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
@@ -153,7 +143,6 @@
     public CustomTabActivityTestRule mCustomTabActivityTestRule = new CustomTabActivityTestRule();
 
     private static final int TIMEOUT_PAGE_LOAD_SECONDS = 10;
-    public static final int TITLE_UPDATE_TIMEOUT_MS = 3000;
     private static final int MAX_MENU_CUSTOM_ITEMS = 5;
     private static final int NUM_CHROME_MENU_ITEMS = 5;
     private static final String TEST_PAGE = "/chrome/test/data/android/google.html";
@@ -203,7 +192,6 @@
             + "        }"
             + "   </script>"
             + "</body></html>";
-    private static final Uri FAKE_ORIGIN_URI = Uri.parse("android-app://com.google.test");
 
     private static int sIdToIncrement = 1;
 
@@ -228,9 +216,6 @@
         PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX);
         LibraryLoader.getInstance().ensureInitialized(LibraryProcessType.PROCESS_BROWSER);
         mWebServer = TestWebServer.start();
-
-        ModuleFactoryOverrides.setOverride(AppHooksModule.Factory.class,
-                CustomTabsDynamicModuleTestUtils.AppHooksModuleForTest::new);
     }
 
     @After
@@ -1123,476 +1108,6 @@
         }
     }
 
-    private void runAndWaitForActivityStopped(Runnable runnable)
-            throws TimeoutException, InterruptedException {
-        CallbackHelper cctHiddenCallback = new CallbackHelper();
-        ActivityStateListener listener = (activity, newState) -> {
-            if (activity == mCustomTabActivityTestRule.getActivity()
-                    && (newState == ActivityState.STOPPED || newState == ActivityState.DESTROYED)) {
-                cctHiddenCallback.notifyCalled();
-            }
-        };
-        ApplicationStatus.registerStateListenerForAllActivities(listener);
-
-        runnable.run();
-        cctHiddenCallback.waitForCallback("Hide cct", 0);
-        ApplicationStatus.unregisterActivityStateListener(listener);
-    }
-
-    /**
-     This test executes the following workflow assuming dynamic module has been loaded succesfully:
-      - moduleManagedUrl1 -> nav1.1 -> nav1.2 -> modulemanagedUrl2 -> nav2.1 -> nav2.2
-      - User hits the "close button", therefore goes back to modulemanagedUrl2
-      - User hits the Android back button, going returning to nav1.2
-      - User hits the "close button" again, going return to moduleManagedUrl1
-      - User hits the Android back button thereby closes CCT.
-     */
-    @Test
-    @SmallTest
-    @EnableFeatures(ChromeFeatureList.CCT_MODULE)
-    public void testCloseButtonBehaviourWithDynamicModule()
-            throws InterruptedException, ExecutionException, TimeoutException {
-        setupHttpsTestServerAndPages();
-        String relativeUrl1 = "/chrome/test/data/android/about.html";
-        String moduleManagedUrl1 = mTestServer.getURL(relativeUrl1);
-        String relativeUrl2 = "/chrome/test/data/android/simple.html";
-        String moduleManagedUrl2 = mTestServer.getURL(relativeUrl2);
-
-        Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(
-                moduleManagedUrl1, "^(" + relativeUrl1 + "|" + relativeUrl2 + ")$");
-
-        // Open CCT with moduleManagedUrl1 and navigate
-        // moduleManagedUrl1 -> nav1.1 - nav1.2 -> modulemanagedUrl2 -> nav2.1 -> nav2.2
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-        CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
-
-        mCustomTabActivityTestRule.loadUrlInTab(mTestPage, PageTransition.LINK,
-                cctActivity.getActivityTab());
-        mCustomTabActivityTestRule.loadUrlInTab(mTestPage2, PageTransition.LINK,
-                cctActivity.getActivityTab());
-        mCustomTabActivityTestRule.loadUrlInTab(moduleManagedUrl2, PageTransition.TYPED,
-                cctActivity.getActivityTab());
-        mCustomTabActivityTestRule.loadUrlInTab(mTestPage, PageTransition.LINK,
-                cctActivity.getActivityTab());
-        mCustomTabActivityTestRule.loadUrlInTab(mTestPage2, PageTransition.LINK,
-                cctActivity.getActivityTab());
-
-        // click the close button and wait while tab page loaded
-        ClickUtils.clickButton(cctActivity.findViewById(R.id.close_button));
-        ChromeTabUtils.waitForTabPageLoaded(cctActivity.getActivityTab(), (String) null);
-
-        // close button returns back to moduleManagedUrl2
-        Assert.assertEquals(moduleManagedUrl2, cctActivity.getActivityTab().getUrl());
-
-        // press the back button and wait while tab page loaded
-        UiDevice mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
-        mDevice.pressBack();
-        ChromeTabUtils.waitForTabPageLoaded(cctActivity.getActivityTab(), (String) null);
-
-        // the back button returns to nav1.2
-        Assert.assertEquals(mTestPage2, cctActivity.getActivityTab().getUrl());
-
-        // click the close button and wait while tab page loaded
-        ClickUtils.clickButton(cctActivity.findViewById(R.id.close_button));
-        ChromeTabUtils.waitForTabPageLoaded(cctActivity.getActivityTab(), (String) null);
-
-        // close button returns back to moduleManagedUrl1
-        Assert.assertEquals(moduleManagedUrl1, cctActivity.getActivityTab().getUrl());
-
-        // press back button and while cct is hidden
-        runAndWaitForActivityStopped(mDevice::pressBack);
-    }
-
-    /**
-     This test executes the following workflow assuming dynamic module has not been loaded:
-     - moduleManagedUrl1 -> nav1.1 - nav1.2 -> modulemanagedUrl2 -> nav2.1 -> nav2.2
-     - User hits the close button, thereby closes CCT
-     */
-    @Test
-    @SmallTest
-    public void testCloseButtonBehaviourWithoutDynamicModule()
-            throws InterruptedException, ExecutionException, TimeoutException {
-        setupHttpsTestServerAndPages();
-        String moduleManagedUrl1 = mTestServer.getURL(
-                "/chrome/test/data/android/about.html");
-        String moduleManagedUrl2 = mTestServer.getURL(
-                "/chrome/test/data/android/simple.html");
-
-        // Open CCT with moduleManagedUrl1 and navigate
-        // moduleManagedUrl1 -> nav1.1 - nav1.2 -> modulemanagedUrl2 -> nav2.1 -> nav2.2
-
-        Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(
-                InstrumentationRegistry.getTargetContext(), moduleManagedUrl1);
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-        CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
-
-        mCustomTabActivityTestRule.loadUrlInTab(mTestPage, PageTransition.LINK,
-                cctActivity.getActivityTab());
-        mCustomTabActivityTestRule.loadUrlInTab(mTestPage2, PageTransition.LINK,
-                cctActivity.getActivityTab());
-        mCustomTabActivityTestRule.loadUrlInTab(moduleManagedUrl2, PageTransition.LINK,
-                cctActivity.getActivityTab());
-        mCustomTabActivityTestRule.loadUrlInTab(mTestPage, PageTransition.LINK,
-                cctActivity.getActivityTab());
-        mCustomTabActivityTestRule.loadUrlInTab(mTestPage2, PageTransition.LINK,
-                cctActivity.getActivityTab());
-
-        // click close button and wait while cct is hidden
-        runAndWaitForActivityStopped(() ->
-                ClickUtils.clickButton(cctActivity.findViewById(R.id.close_button)));
-    }
-
-    /**
-     This test executes the following workflow assuming dynamic module loading fails:
-     - moduleManagedUrl1 -> nav1.1 - nav1.2
-     - User hits the close button, thereby closes CCT
-     */
-    @Test
-    @SmallTest
-    public void testCloseButtonBehaviourDynamicModuleLoadFails()
-            throws InterruptedException, ExecutionException, TimeoutException {
-        setupHttpsTestServerAndPages();
-        String relativeUrl = "/chrome/test/data/android/about.html";
-        String moduleManagedUrl = mTestServer.getURL(relativeUrl);
-
-        // Open CCT with moduleManagedUrl1 and navigate
-        // moduleManagedUrl1 -> nav1.1 - nav1.2
-
-        // Make an intent with nonexistent class name so module loading fails.
-        ComponentName componentName =
-                new ComponentName(CustomTabsDynamicModuleTestUtils.FAKE_MODULE_PACKAGE_NAME,
-                        "ClassName");
-        Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(
-                componentName, moduleManagedUrl, "^(" + relativeUrl + ")$");
-
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-        CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
-
-        // Wait until ModuleLoader tries to load a module.
-        CriteriaHelper.pollUiThread(new Criteria() {
-            @Override
-            public boolean isSatisfied() {
-                return !cctActivity.getComponent()
-                        .resolveDynamicModuleCoordinator().isModuleLoading();
-            }
-        });
-
-        mCustomTabActivityTestRule.loadUrlInTab(mTestPage, PageTransition.LINK,
-                cctActivity.getActivityTab());
-        mCustomTabActivityTestRule.loadUrlInTab(mTestPage2, PageTransition.LINK,
-                cctActivity.getActivityTab());
-
-        // click close button and wait while cct is hidden
-        runAndWaitForActivityStopped(() ->
-                ClickUtils.clickButton(cctActivity.findViewById(R.id.close_button)));
-    }
-
-    @Test
-    @SmallTest
-    @EnableFeatures(ChromeFeatureList.CCT_MODULE)
-    public void testSetTopBarContentView() throws Exception {
-        setupHttpsTestServerAndPages();
-        String moduleManagedUrl = mTestServer.getURL("/chrome/test/data/android/about.html");
-        Intent intent =
-                CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(moduleManagedUrl, null);
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-        waitForModuleLoading();
-
-        ThreadUtils.runOnUiThread(() -> {
-            CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
-            View anyView = new View(cctActivity);
-            cctActivity.getComponent().resolveDynamicModuleCoordinator()
-                    .setTopBarContentView(anyView);
-            ViewGroup topBar = cctActivity.findViewById(R.id.topbar);
-            Assert.assertNotNull(topBar);
-            Assert.assertThat(anyView.getParent(), equalTo(topBar));
-            Assert.assertEquals(View.GONE, anyView.getVisibility());
-        });
-    }
-
-    @Test
-    @SmallTest
-    @EnableFeatures(ChromeFeatureList.CCT_MODULE)
-    public void testSetTopBarContentView_secondCallIsNoOp() throws Exception {
-        setupHttpsTestServerAndPages();
-        String moduleManagedUrl = mTestServer.getURL("/chrome/test/data/android/about.html");
-        Intent intent =
-                CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(moduleManagedUrl, null);
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-        waitForModuleLoading();
-        DynamicModuleCoordinator coordinator =
-                getActivity().getComponent().resolveDynamicModuleCoordinator();
-        ThreadUtils.runOnUiThread(() -> {
-            CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
-            View anyView = new View(cctActivity);
-            coordinator.setTopBarContentView(anyView);
-            // Second call will not crash.
-            coordinator.setTopBarContentView(anyView);
-        });
-    }
-
-    @Test
-    @SmallTest
-    @EnableFeatures(ChromeFeatureList.CCT_MODULE)
-    public void testSetTopBarContentView_moduleNotProvided_noTopBar() throws Exception {
-        Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(
-                InstrumentationRegistry.getTargetContext(),
-                "https://www.google.com/search?q=london");
-        intent.putExtra(
-                CustomTabIntentDataProvider.EXTRA_MODULE_MANAGED_HOST_LIST, "www.google.com");
-        intent.putExtra(CustomTabIntentDataProvider.EXTRA_MODULE_MANAGED_URLS_REGEX, "/search.*");
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-        waitForModuleLoading();
-
-        ThreadUtils.runOnUiThread(() -> {
-            CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
-            View anyView = new View(cctActivity);
-            ViewGroup topBar = cctActivity.findViewById(R.id.topbar);
-            Assert.assertNull(topBar);
-        });
-    }
-
-    @Test
-    @SmallTest
-    @DisableFeatures(ChromeFeatureList.CCT_MODULE)
-    public void testSetTopBarContentView_featureDisabled_noTopBar() throws Exception {
-        setupHttpsTestServerAndPages();
-        String relativeUrl = "/chrome/test/data/android/about.html";
-        String moduleManagedUrl = mTestServer.getURL(relativeUrl);
-        Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(
-                moduleManagedUrl, "^(" + relativeUrl + ")$");
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-        waitForModuleLoading();
-
-        ThreadUtils.runOnUiThread(() -> {
-            CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
-            View anyView = new View(cctActivity);
-            ViewGroup topBar = cctActivity.findViewById(R.id.topbar);
-            Assert.assertNull(topBar);
-        });
-    }
-
-    @Test
-    @SmallTest
-    @EnableFeatures(ChromeFeatureList.CCT_MODULE)
-    public void testSetTopBarContentView_moduleLoadingFailed_noTopBar() throws Exception {
-        // Make an intent with nonexistent class name so module loading fail
-        Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(
-                InstrumentationRegistry.getTargetContext(),
-                "https://www.google.com/search?q=london");
-        intent.putExtra(CustomTabIntentDataProvider.EXTRA_MODULE_PACKAGE_NAME,
-                CustomTabsDynamicModuleTestUtils.FAKE_MODULE_PACKAGE_NAME);
-        intent.putExtra(CustomTabIntentDataProvider.EXTRA_MODULE_CLASS_NAME, "ClassName");
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-        waitForModuleLoading();
-
-        ThreadUtils.runOnUiThread(() -> {
-            CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
-            View anyView = new View(cctActivity);
-            cctActivity.getComponent().resolveDynamicModuleCoordinator()
-                    .setTopBarContentView(anyView);
-            ViewGroup topBar = cctActivity.findViewById(R.id.topbar);
-            Assert.assertNull(topBar);
-        });
-    }
-
-    @Test
-    @SmallTest
-    @EnableFeatures(ChromeFeatureList.CCT_MODULE)
-    public void testSetTopBarContentView_withModuleAndManagedUrls_topBarVisible() throws Exception {
-        setupHttpsTestServerAndPages();
-        String relativeUrl = "/chrome/test/data/android/about.html";
-        String moduleManagedUrl = mTestServer.getURL(relativeUrl);
-        Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(
-                moduleManagedUrl, "^(" + relativeUrl + ")$");
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-        waitForModuleLoading();
-
-        ThreadUtils.runOnUiThread(() -> {
-            CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
-            View anyView = new View(cctActivity);
-            cctActivity.getComponent().resolveDynamicModuleCoordinator()
-                    .setTopBarContentView(anyView);
-            ViewGroup topBar = cctActivity.findViewById(R.id.topbar);
-            Assert.assertNotNull(topBar);
-            Assert.assertThat(anyView.getParent(), equalTo(topBar));
-            Assert.assertEquals(View.VISIBLE, anyView.getVisibility());
-        });
-    }
-
-    @Test
-    @SmallTest
-    @EnableFeatures({ChromeFeatureList.CCT_MODULE, ChromeFeatureList.CCT_MODULE_CUSTOM_HEADER})
-    public void testSetTopBarContentView_moduleNotProvided_cctHeaderVisible() throws Exception {
-        Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(
-                InstrumentationRegistry.getTargetContext(),
-                "https://www.google.com/search?q=london");
-        intent.putExtra(
-                CustomTabIntentDataProvider.EXTRA_MODULE_MANAGED_HOST_LIST, "www.google.com");
-        intent.putExtra(CustomTabIntentDataProvider.EXTRA_MODULE_MANAGED_URLS_REGEX, "/search.*");
-        intent.putExtra(
-                CustomTabIntentDataProvider.EXTRA_HIDE_CCT_HEADER_ON_MODULE_MANAGED_URLS, true);
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-        waitForModuleLoading();
-
-        ThreadUtils.runOnUiThread(() -> {
-            CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
-            View toolbarView = cctActivity.findViewById(R.id.toolbar);
-            Assert.assertTrue(
-                    "A custom tab toolbar is never shown", toolbarView instanceof CustomTabToolbar);
-            CustomTabToolbar toolbar = (CustomTabToolbar) toolbarView;
-            Assert.assertEquals(View.VISIBLE, toolbar.getVisibility());
-        });
-    }
-
-    @Test
-    @SmallTest
-    @DisableFeatures(ChromeFeatureList.CCT_MODULE_CUSTOM_HEADER)
-    public void testSetTopBarContentView_featureDisabled_cctHeaderVisible() throws Exception {
-        setupHttpsTestServerAndPages();
-        String relativeUrl = "/chrome/test/data/android/about.html";
-        String moduleManagedUrl = mTestServer.getURL(relativeUrl);
-        Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(
-                moduleManagedUrl, "^(" + relativeUrl + ")$");
-        intent.putExtra(
-                CustomTabIntentDataProvider.EXTRA_HIDE_CCT_HEADER_ON_MODULE_MANAGED_URLS, true);
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-        waitForModuleLoading();
-
-        ThreadUtils.runOnUiThread(() -> {
-            CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
-            cctActivity.getComponent().resolveDynamicModuleCoordinator()
-                    .setTopBarContentView(new View(cctActivity));
-            View toolbarView = cctActivity.findViewById(R.id.toolbar);
-            Assert.assertTrue(
-                    "A custom tab toolbar is never shown", toolbarView instanceof CustomTabToolbar);
-            CustomTabToolbar toolbar = (CustomTabToolbar) toolbarView;
-            Assert.assertEquals(View.VISIBLE, toolbar.getVisibility());
-        });
-    }
-
-    @Test
-    @SmallTest
-    @EnableFeatures({ChromeFeatureList.CCT_MODULE, ChromeFeatureList.CCT_MODULE_CUSTOM_HEADER})
-    public void testSetTopBarContentView_notModuleManagedHost_cctHeaderVisible() throws Exception {
-        setupHttpsTestServerAndPages();
-        String relativeUrl = "/chrome/test/data/android/about.html";
-        String moduleManagedUrl = mTestServer.getURL(relativeUrl);
-        Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(
-                moduleManagedUrl, "^(" + relativeUrl + ")$");
-        intent.putExtra(
-                CustomTabIntentDataProvider.EXTRA_HIDE_CCT_HEADER_ON_MODULE_MANAGED_URLS, true);
-        intent.putExtra(
-                CustomTabIntentDataProvider.EXTRA_MODULE_MANAGED_HOST_LIST, "www.google.com");
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-        waitForModuleLoading();
-        ThreadUtils.runOnUiThread(() -> {
-            CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
-            cctActivity.getComponent().resolveDynamicModuleCoordinator()
-                    .setTopBarContentView(new View(cctActivity));
-            View toolbarView = cctActivity.findViewById(R.id.toolbar);
-            Assert.assertTrue(
-                    "A custom tab toolbar is never shown", toolbarView instanceof CustomTabToolbar);
-            CustomTabToolbar toolbar = (CustomTabToolbar) toolbarView;
-            Assert.assertEquals(View.VISIBLE, toolbar.getVisibility());
-        });
-    }
-
-    @Test
-    @SmallTest
-    @EnableFeatures({ChromeFeatureList.CCT_MODULE, ChromeFeatureList.CCT_MODULE_CUSTOM_HEADER})
-    public void testSetTopBarContentView_withModuleAndExtras_cctHeaderHidden() throws Exception {
-        setupHttpsTestServerAndPages();
-        String relativeUrl = "/chrome/test/data/android/about.html";
-        String moduleManagedUrl = mTestServer.getURL(relativeUrl);
-        Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(
-                moduleManagedUrl, "^(" + relativeUrl + ")$");
-        intent.putExtra(
-                CustomTabIntentDataProvider.EXTRA_HIDE_CCT_HEADER_ON_MODULE_MANAGED_URLS, true);
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-        waitForModuleLoading();
-
-        ThreadUtils.runOnUiThread(() -> {
-            CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
-            cctActivity.getComponent().resolveDynamicModuleCoordinator()
-                    .setTopBarContentView(new View(cctActivity));
-            ViewGroup toolbarContainerView = cctActivity.findViewById(R.id.toolbar_container);
-            for (int index = 0; index < toolbarContainerView.getChildCount(); index++) {
-                View childView = toolbarContainerView.getChildAt(index);
-                if (childView.getId() != R.id.topbar) {
-                    Assert.assertEquals(View.GONE, childView.getVisibility());
-                }
-            }
-        });
-    }
-
-    @Test
-    @SmallTest
-    @DisableFeatures(ChromeFeatureList.CCT_MODULE_CUSTOM_HEADER)
-    public void testSetTopBarHeight_featureDisabled_heightNotChanged() throws Exception {
-        setupHttpsTestServerAndPages();
-        String relativeUrl = "/chrome/test/data/android/about.html";
-        String moduleManagedUrl = mTestServer.getURL(relativeUrl);
-        Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(
-                moduleManagedUrl, "^(" + relativeUrl + ")$");
-        intent.putExtra(
-                CustomTabIntentDataProvider.EXTRA_HIDE_CCT_HEADER_ON_MODULE_MANAGED_URLS, true);
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-
-        ThreadUtils.runOnUiThread(() -> {
-            CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
-            int defaultHeight = cctActivity.getFullscreenManager().getTopControlsHeight();
-            Assert.assertEquals(
-                    defaultHeight, cctActivity.getFullscreenManager().getTopControlsHeight());
-        });
-    }
-
-    @Test
-    @SmallTest
-    @EnableFeatures({ChromeFeatureList.CCT_MODULE, ChromeFeatureList.CCT_MODULE_CUSTOM_HEADER})
-    public void testSetTopBarHeight_cctHeaderNotHidden_heightNotChanged() throws Exception {
-        setupHttpsTestServerAndPages();
-        String relativeUrl = "/chrome/test/data/android/about.html";
-        String moduleManagedUrl = mTestServer.getURL(relativeUrl);
-        Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(
-                moduleManagedUrl, "^(" + relativeUrl + ")$");
-        intent.putExtra(
-                CustomTabIntentDataProvider.EXTRA_HIDE_CCT_HEADER_ON_MODULE_MANAGED_URLS, false);
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-
-        ThreadUtils.runOnUiThread(() -> {
-            CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
-            int defaultHeight = cctActivity.getFullscreenManager().getTopControlsHeight();
-            int newHeight = defaultHeight + 10;
-            cctActivity.getComponent().resolveDynamicModuleCoordinator().setTopBarHeight(newHeight);
-            Assert.assertEquals(
-                    defaultHeight, cctActivity.getFullscreenManager().getTopControlsHeight());
-        });
-    }
-
-    @Test
-    @SmallTest
-    @EnableFeatures({ChromeFeatureList.CCT_MODULE, ChromeFeatureList.CCT_MODULE_CUSTOM_HEADER})
-    public void testSetTopBarHeight_withModuleAndExtras_heightUpdated() throws Exception {
-        setupHttpsTestServerAndPages();
-        String relativeUrl = "/chrome/test/data/android/about.html";
-        String moduleManagedUrl = mTestServer.getURL(relativeUrl);
-        Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(
-                moduleManagedUrl, "^(" + relativeUrl + ")$");
-        intent.putExtra(
-                CustomTabIntentDataProvider.EXTRA_HIDE_CCT_HEADER_ON_MODULE_MANAGED_URLS, true);
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-
-        ThreadUtils.runOnUiThread(() -> {
-            CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
-            int defaultHeight = cctActivity.getFullscreenManager().getTopControlsHeight();
-            int newHeight = defaultHeight + 10;
-            cctActivity.getComponent().resolveDynamicModuleCoordinator().setTopBarHeight(newHeight);
-            Assert.assertEquals(
-                    newHeight, cctActivity.getFullscreenManager().getTopControlsHeight());
-        });
-    }
-
     @Test
     @SmallTest
     @Feature({"UiCatalogue"})
@@ -1867,7 +1382,6 @@
 
     /**
      * Tests that TITLE_ONLY state works as expected with a title getting set during prerendering.
-
      */
     @Test
     @SmallTest
@@ -1878,7 +1392,6 @@
 
     /**
      * Tests that TITLE_ONLY state works as expected with a title getting set delayed after load.
-
      */
     @Test
     @SmallTest
@@ -2273,156 +1786,6 @@
     }
 
     /**
-     * Tests the sent postMessage requests not only return success, but is also received by page.
-     */
-    @Test
-    @SmallTest
-    @EnableFeatures(ChromeFeatureList.CCT_MODULE_POST_MESSAGE)
-    public void testPostMessageFromDynamicModuleReceivedInPage() throws Exception {
-        final String url =
-                mWebServer.setResponse("/test.html", TITLE_FROM_POSTMESSAGE_TO_CHANNEL, null);
-
-        Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(url, null);
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-
-        ChromeTabUtils.waitForTabPageLoaded(getActivity().getActivityTab(), url);
-        DynamicModuleCoordinator coordinator =
-                getActivity().getComponent().resolveDynamicModuleCoordinator();
-        coordinator.maybeInitialiseDynamicModulePostMessageHandler(new PostMessageBackend() {
-            @Override
-            public boolean onPostMessage(String message, Bundle extras) {
-                return true;
-            }
-
-            @Override
-            public boolean onNotifyMessageChannelReady(Bundle extras) {
-                // Now attempt to post a message.
-                Assert.assertEquals(coordinator.postMessage("New title"),
-                        CustomTabsService.RESULT_SUCCESS);
-                return true;
-            }
-
-            @Override
-            public void onDisconnectChannel(Context appContext) {}
-        });
-
-        Assert.assertTrue(coordinator.requestPostMessageChannel(FAKE_ORIGIN_URI));
-        // The callback registered above will post a message once the requested channel is ready.
-        waitForTitle("New title");
-    }
-
-    /**
-     * Tests the postMessage requests sent from the page is received on the client side.
-     */
-    @Test
-    @SmallTest
-    @EnableFeatures({ChromeFeatureList.CCT_MODULE, ChromeFeatureList.CCT_MODULE_POST_MESSAGE})
-    public void testPostMessageReceivedFromPageByDynamicModule() throws Exception {
-        final CallbackHelper messageChannelHelper = new CallbackHelper();
-        final CallbackHelper onPostMessageHelper = new CallbackHelper();
-        final String url = mWebServer.setResponse("/test.html", MESSAGE_FROM_PAGE_TO_CHANNEL, null);
-
-        Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(url, null);
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-
-        ChromeTabUtils.waitForTabPageLoaded(getActivity().getActivityTab(), url);
-
-        DynamicModuleCoordinator coordinator =
-                getActivity().getComponent().resolveDynamicModuleCoordinator();
-
-        coordinator.maybeInitialiseDynamicModulePostMessageHandler(new PostMessageBackend() {
-            @Override
-            public boolean onPostMessage(String message, Bundle extras) {
-                onPostMessageHelper.notifyCalled();
-                return true;
-            }
-
-            @Override
-            public boolean onNotifyMessageChannelReady(Bundle extras) {
-                messageChannelHelper.notifyCalled();
-                return true;
-            }
-
-            @Override
-                public void onDisconnectChannel(Context appContext) {}
-        });
-
-        Assert.assertTrue(coordinator.requestPostMessageChannel(FAKE_ORIGIN_URI));
-        messageChannelHelper.waitForCallback();
-        onPostMessageHelper.waitForCallback();
-    }
-
-    /**
-     * Tests the postMessage requests sent from the page is received on the client side.
-     */
-    @Test
-    @SmallTest
-    @EnableFeatures(ChromeFeatureList.CCT_MODULE_POST_MESSAGE)
-    public void testPostMessageFromDynamicModuleDisallowedBeforeModuleLoaded() throws Exception {
-        final CallbackHelper messageChannelHelper = new CallbackHelper();
-        final CallbackHelper onPostMessageHelper = new CallbackHelper();
-        final String url = mWebServer.setResponse("/test.html", MESSAGE_FROM_PAGE_TO_CHANNEL, null);
-
-        Context context = InstrumentationRegistry.getTargetContext();
-        Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, url);
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-
-        ChromeTabUtils.waitForTabPageLoaded(getActivity().getActivityTab(), url);
-
-        // If feature disabled dynamic module is not instantiated
-        DynamicModuleCoordinator coordinator =
-                getActivity().getComponent().resolveDynamicModuleCoordinator();
-
-        // We shouldn't be able to open a channel or post messages yet.
-        Assert.assertFalse(coordinator
-                .requestPostMessageChannel(FAKE_ORIGIN_URI));
-        Assert.assertTrue(coordinator.postMessage("Message")
-                == CustomTabsService.RESULT_FAILURE_DISALLOWED);
-
-        // Now fake initialisation of the dynamic module.
-        coordinator.maybeInitialiseDynamicModulePostMessageHandler(
-                new PostMessageBackend() {
-                    @Override
-                    public boolean onPostMessage(String message, Bundle extras) {
-                        onPostMessageHelper.notifyCalled();
-                        return true;
-                    }
-
-                    @Override
-                    public boolean onNotifyMessageChannelReady(Bundle extras) {
-                        messageChannelHelper.notifyCalled();
-                        return true;
-                    }
-
-                    @Override
-                    public void onDisconnectChannel(Context appContext) {}
-                });
-
-        // We can now request a postMessage channel.
-        Assert.assertTrue(coordinator
-                .requestPostMessageChannel(FAKE_ORIGIN_URI));
-    }
-
-    @Test
-    @SmallTest
-    @EnableFeatures(ChromeFeatureList.CCT_MODULE)
-    @DisableFeatures(ChromeFeatureList.CCT_MODULE_POST_MESSAGE)
-    public void testPostMessageFromDynamicModuleDisallowedWhenFeatureDisabled() throws Exception {
-        final String url = mWebServer.setResponse("/test.html", MESSAGE_FROM_PAGE_TO_CHANNEL, null);
-
-        Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(url, null);
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-
-        ChromeTabUtils.waitForTabPageLoaded(getActivity().getActivityTab(), url);
-        DynamicModuleCoordinator coordinator = getActivity().getComponent()
-                .resolveDynamicModuleCoordinator();
-        // We shouldn't be able to open a channel or post messages yet.
-        Assert.assertFalse(coordinator.requestPostMessageChannel(FAKE_ORIGIN_URI));
-        Assert.assertEquals(coordinator.postMessage("Message"),
-                CustomTabsService.RESULT_FAILURE_DISALLOWED);
-    }
-
-    /**
      * Tests that when we use a pre-created renderer, the page loaded is the
      * only one in the navigation history.
      */
@@ -3383,36 +2746,7 @@
     }
 
     private void waitForTitle(String newTitle) throws InterruptedException {
-        Tab currentTab = mCustomTabActivityTestRule.getActivity().getActivityTab();
-        TabTitleObserver titleObserver = new TabTitleObserver(currentTab, newTitle);
-        try {
-            titleObserver.waitForTitleUpdate(TITLE_UPDATE_TIMEOUT_MS);
-        } catch (TimeoutException e) {
-            fail("Tab title didn't update in time");
-        }
-    }
-
-    private void waitForModuleLoading() {
-        CriteriaHelper.pollUiThread(new Criteria() {
-            @Override
-            public boolean isSatisfied() {
-                if (!getActivity().getIntentDataProvider().isDynamicModuleEnabled()) return true;
-
-                DynamicModuleCoordinator module =
-                        mCustomTabActivityTestRule.getActivity().getComponent()
-                                .resolveDynamicModuleCoordinator();
-                return module != null && !module.isModuleLoading();
-            }
-        });
-    }
-
-    private void setupHttpsTestServerAndPages() throws InterruptedException {
-        mTestServer.stopAndDestroyServer();
-        // Module managed hosts only work with HTTPS.
-        mTestServer = EmbeddedTestServer.createAndStartHTTPSServer(
-                InstrumentationRegistry.getInstrumentation().getContext(),
-                ServerCertificate.CERT_OK);
-        mTestPage = mTestServer.getURL(TEST_PAGE);
-        mTestPage2 = mTestServer.getURL(TEST_PAGE_2);
+        Tab currentTab = getActivity().getActivityTab();
+        ChromeTabUtils.waitForTitle(currentTab, newTitle);
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsDynamicModuleLoaderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleLoaderTest.java
similarity index 91%
rename from chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsDynamicModuleLoaderTest.java
rename to chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleLoaderTest.java
index fcd83ead..65870ac 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsDynamicModuleLoaderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleLoaderTest.java
@@ -2,12 +2,13 @@
 // 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.customtabs;
+package org.chromium.chrome.browser.customtabs.dynamicmodule;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 
-import static org.chromium.chrome.browser.customtabs.CustomTabsDynamicModuleTestUtils.FAKE_MODULE_COMPONENT_NAME;
+import static org.chromium.chrome.browser.customtabs.dynamicmodule
+        .CustomTabsDynamicModuleTestUtils.FAKE_MODULE_COMPONENT_NAME;
 
 import android.support.test.filters.SmallTest;
 
@@ -21,8 +22,6 @@
 import org.chromium.base.library_loader.LibraryProcessType;
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.chrome.browser.ChromeFeatureList;
-import org.chromium.chrome.browser.customtabs.dynamicmodule.ModuleEntryPoint;
-import org.chromium.chrome.browser.customtabs.dynamicmodule.ModuleLoader;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.Features;
 
@@ -34,7 +33,6 @@
  * Tests for {@link ModuleLoader}.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@SmallTest
 public class CustomTabsDynamicModuleLoaderTest {
     @Before
     public void setUp() throws Exception {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsDynamicModuleNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleNavigationTest.java
similarity index 60%
rename from chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsDynamicModuleNavigationTest.java
rename to chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleNavigationTest.java
index e63784ab..c107433 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsDynamicModuleNavigationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleNavigationTest.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.browser.customtabs;
+package org.chromium.chrome.browser.customtabs.dynamicmodule;
 
 import android.content.Context;
 import android.content.Intent;
@@ -22,6 +22,10 @@
 import org.chromium.base.library_loader.LibraryProcessType;
 import org.chromium.chrome.browser.AppHooksModule;
 import org.chromium.chrome.browser.ChromeFeatureList;
+import org.chromium.chrome.browser.customtabs.CustomTabActivity;
+import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
+import org.chromium.chrome.browser.customtabs.dynamicmodule.CustomTabsDynamicModuleTestUtils.FakeCCTActivityDelegate;
+import org.chromium.chrome.browser.customtabs.dynamicmodule.CustomTabsDynamicModuleTestUtils.IntentBuilder;
 import org.chromium.chrome.browser.dependency_injection.ModuleFactoryOverrides;
 import org.chromium.chrome.browser.firstrun.FirstRunStatus;
 import org.chromium.chrome.test.util.browser.Features;
@@ -31,14 +35,12 @@
 import java.util.concurrent.TimeoutException;
 
 /**
- *
+ * Instrumentation tests for the CustomTabsDynamicModuleNavigationObserver.
  */
 @RunWith(Parameterized.class)
-@SmallTest
 public class CustomTabsDynamicModuleNavigationTest {
     @Rule
-    public CustomTabActivityTestRule mCustomTabActivityTestRule =
-            new CustomTabActivityTestRule();
+    public CustomTabActivityTestRule mActivityRule = new CustomTabActivityTestRule();
 
     /**
      * Test against different module versions i.e. before and after API was introduced.
@@ -54,30 +56,29 @@
     private String mTestPage;
     private String mTestPage2;
     private String mTestPage3;
-    private EmbeddedTestServer mTestServer;
+    private EmbeddedTestServer mServer;
 
     @Before
     public void setUp() throws Exception {
         ThreadUtils.runOnUiThreadBlocking(() -> FirstRunStatus.setFirstRunFlowComplete(true));
-
         LibraryLoader.getInstance().ensureInitialized(LibraryProcessType.PROCESS_BROWSER);
 
         ModuleFactoryOverrides.setOverride(AppHooksModule.Factory.class,
                 CustomTabsDynamicModuleTestUtils.AppHooksModuleForTest::new);
 
-        Context appContext = InstrumentationRegistry.getInstrumentation()
-                .getTargetContext()
+        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext()
                 .getApplicationContext();
 
-        mTestServer = EmbeddedTestServer.createAndStartServer(appContext);
-        mTestPage = mTestServer.getURL("/chrome/test/data/android/google.html");
-        mTestPage2 = mTestServer.getURL("/chrome/test/data/android/simple.html");
-        mTestPage3 = mTestServer.getURL("/chrome/test/data/android/about.html");
+        mServer = EmbeddedTestServer.createAndStartServer(appContext);
+        mTestPage = mServer.getURL("/chrome/test/data/android/google.html");
+        mTestPage2 = mServer.getURL("/chrome/test/data/android/simple.html");
+        mTestPage3 = mServer.getURL("/chrome/test/data/android/about.html");
     }
 
     @After
     public void tearDown() {
         ModuleFactoryOverrides.clearOverrides();
+        ThreadUtils.runOnUiThreadBlocking(() -> FirstRunStatus.setFirstRunFlowComplete(true));
     }
 
     @Test
@@ -86,25 +87,29 @@
     public void testModuleNavigationNotification()
             throws TimeoutException, InterruptedException {
         CustomTabsDynamicModuleTestUtils.setModuleVersion(moduleVersion);
-        Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(
-                mTestPage, null);
+        Intent intent = new IntentBuilder(mTestPage).build();
 
-        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
-        CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
+        mActivityRule.startCustomTabActivityWithIntent(intent);
 
-        mCustomTabActivityTestRule.loadUrlInTab(mTestPage2, PageTransition.LINK,
-                cctActivity.getActivityTab());
-        mCustomTabActivityTestRule.loadUrlInTab(mTestPage3, PageTransition.LINK,
-                cctActivity.getActivityTab());
+        mActivityRule.loadUrlInTab(mTestPage2, PageTransition.LINK,
+                getActivity().getActivityTab());
+        mActivityRule.loadUrlInTab(mTestPage3, PageTransition.LINK,
+                getActivity().getActivityTab());
 
-        CustomTabsDynamicModuleTestUtils.FakeCCTActivityDelegate activityDelegate =
-                (CustomTabsDynamicModuleTestUtils.FakeCCTActivityDelegate)
-                        cctActivity.getComponent()
-                                .resolveDynamicModuleCoordinator().getActivityDelegateForTesting();
+        FakeCCTActivityDelegate activityDelegate =
+                (FakeCCTActivityDelegate) getModuleCoordinator().getActivityDelegateForTesting();
 
         activityDelegate.waitForNavigationEvent(CustomTabsCallback.NAVIGATION_STARTED,
                 0, 3);
         activityDelegate.waitForNavigationEvent(CustomTabsCallback.NAVIGATION_FINISHED,
                 0, 3);
     }
+
+    private CustomTabActivity getActivity() {
+        return mActivityRule.getActivity();
+    }
+
+    private DynamicModuleCoordinator getModuleCoordinator() {
+        return getActivity().getComponent().resolveDynamicModuleCoordinator();
+    }
 }
\ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModulePostMessageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModulePostMessageTest.java
new file mode 100644
index 0000000..3e75871
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModulePostMessageTest.java
@@ -0,0 +1,252 @@
+// 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.customtabs.dynamicmodule;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.customtabs.CustomTabsService;
+import android.support.customtabs.PostMessageBackend;
+import android.support.test.filters.SmallTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.library_loader.LibraryLoader;
+import org.chromium.base.library_loader.LibraryProcessType;
+import org.chromium.base.test.util.CallbackHelper;
+import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.chrome.browser.AppHooksModule;
+import org.chromium.chrome.browser.ChromeFeatureList;
+import org.chromium.chrome.browser.ChromeSwitches;
+import org.chromium.chrome.browser.customtabs.CustomTabActivity;
+import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
+import org.chromium.chrome.browser.customtabs.dynamicmodule.CustomTabsDynamicModuleTestUtils.IntentBuilder;
+import org.chromium.chrome.browser.dependency_injection.ModuleFactoryOverrides;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.util.ChromeTabUtils;
+import org.chromium.chrome.test.util.browser.Features;
+import org.chromium.net.test.util.TestWebServer;
+
+/**
+ * Instrumentation tests for the CCT Dynamic Module post message API.
+ */
+@RunWith(ChromeJUnit4ClassRunner.class)
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+public class CustomTabsDynamicModulePostMessageTest {
+    @Rule
+    public CustomTabActivityTestRule mActivityRule = new CustomTabActivityTestRule();
+
+    private TestWebServer mServer;
+
+    private static final String JS_MESSAGE = "from_js";
+    private static final String TITLE_FROM_POSTMESSAGE_TO_CHANNEL =
+            "<!DOCTYPE html><html><body>"
+                    + "    <script>"
+                    + "        var received = '';"
+                    + "        onmessage = function (e) {"
+                    + "            var myport = e.ports[0];"
+                    + "            myport.onmessage = function (f) {"
+                    + "                received += f.data;"
+                    + "                document.title = received;"
+                    + "            }"
+                    + "        }"
+                    + "   </script>"
+                    + "</body></html>";
+
+    private static final String MESSAGE_FROM_PAGE_TO_CHANNEL =
+            "<!DOCTYPE html><html><body>"
+                    + "    <script>"
+                    + "        onmessage = function (e) {"
+                    + "            if (e.ports != null && e.ports.length > 0) {"
+                    + "               e.ports[0].postMessage(\"" + JS_MESSAGE + "\");"
+                    + "            }"
+                    + "        }"
+                    + "   </script>"
+                    + "</body></html>";
+
+    private static final Uri FAKE_ORIGIN_URI = Uri.parse("android-app://com.google.test");
+
+
+    @Before
+    public void setUp() throws Exception {
+        LibraryLoader.getInstance().ensureInitialized(LibraryProcessType.PROCESS_BROWSER);
+        mServer = TestWebServer.start();
+        ModuleFactoryOverrides.setOverride(AppHooksModule.Factory.class,
+                CustomTabsDynamicModuleTestUtils.AppHooksModuleForTest::new);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mServer.shutdown();
+        ModuleFactoryOverrides.clearOverrides();
+    }
+
+    /**
+     * Tests the sent postMessage requests not only return success, but is also received by page.
+     */
+    @Test
+    @SmallTest
+    @Features.EnableFeatures(ChromeFeatureList.CCT_MODULE_POST_MESSAGE)
+    public void testPostMessageFromDynamicModuleReceivedInPage() throws Exception {
+        final String url =
+                mServer.setResponse("/test.html", TITLE_FROM_POSTMESSAGE_TO_CHANNEL, null);
+
+        Intent intent = new IntentBuilder(url).build();
+        mActivityRule.startCustomTabActivityWithIntent(intent);
+
+        ChromeTabUtils.waitForTabPageLoaded(getActivity().getActivityTab(), url);
+        DynamicModuleCoordinator coordinator = getModuleCoordinator();
+        coordinator.maybeInitialiseDynamicModulePostMessageHandler(new PostMessageBackend() {
+            @Override
+            public boolean onPostMessage(String message, Bundle extras) {
+                return true;
+            }
+
+            @Override
+            public boolean onNotifyMessageChannelReady(Bundle extras) {
+                // Now attempt to post a message.
+                assertEquals(coordinator.postMessage("New title"),
+                        CustomTabsService.RESULT_SUCCESS);
+                return true;
+            }
+
+            @Override
+            public void onDisconnectChannel(Context appContext) {}
+        });
+
+        assertTrue(coordinator.requestPostMessageChannel(FAKE_ORIGIN_URI));
+        // The callback registered above will post a message once the requested channel is ready.
+        ChromeTabUtils.waitForTitle(getActivity().getActivityTab(), "New title");
+    }
+
+    /**
+     * Tests the postMessage requests sent from the page is received on the client side.
+     */
+    @Test
+    @SmallTest
+    @Features.EnableFeatures(
+            {ChromeFeatureList.CCT_MODULE, ChromeFeatureList.CCT_MODULE_POST_MESSAGE})
+    public void testPostMessageReceivedFromPageByDynamicModule() throws Exception {
+        final CallbackHelper messageChannelHelper = new CallbackHelper();
+        final CallbackHelper onPostMessageHelper = new CallbackHelper();
+        final String url = mServer.setResponse("/test.html", MESSAGE_FROM_PAGE_TO_CHANNEL, null);
+
+        Intent intent = new IntentBuilder(url).build();
+        mActivityRule.startCustomTabActivityWithIntent(intent);
+
+        ChromeTabUtils.waitForTabPageLoaded(getActivity().getActivityTab(), url);
+
+        DynamicModuleCoordinator coordinator = getModuleCoordinator();
+
+        coordinator.maybeInitialiseDynamicModulePostMessageHandler(new PostMessageBackend() {
+            @Override
+            public boolean onPostMessage(String message, Bundle extras) {
+                onPostMessageHelper.notifyCalled();
+                return true;
+            }
+
+            @Override
+            public boolean onNotifyMessageChannelReady(Bundle extras) {
+                messageChannelHelper.notifyCalled();
+                return true;
+            }
+
+            @Override
+            public void onDisconnectChannel(Context appContext) {}
+        });
+
+        assertTrue(coordinator.requestPostMessageChannel(FAKE_ORIGIN_URI));
+        messageChannelHelper.waitForCallback();
+        onPostMessageHelper.waitForCallback();
+    }
+
+    /**
+     * Tests the postMessage requests sent from the page is received on the client side.
+     */
+    @Test
+    @SmallTest
+    @Features.EnableFeatures(ChromeFeatureList.CCT_MODULE_POST_MESSAGE)
+    @Features.DisableFeatures(ChromeFeatureList.CCT_MODULE)
+    public void testPostMessageFromDynamicModuleDisallowedBeforeModuleLoaded() throws Exception {
+        final CallbackHelper messageChannelHelper = new CallbackHelper();
+        final CallbackHelper onPostMessageHelper = new CallbackHelper();
+        final String url = mServer.setResponse("/test.html", MESSAGE_FROM_PAGE_TO_CHANNEL, null);
+
+        Intent intent = new IntentBuilder(url).build();
+        mActivityRule.startCustomTabActivityWithIntent(intent);
+
+        ChromeTabUtils.waitForTabPageLoaded(getActivity().getActivityTab(), url);
+
+        // Dynamic module is not instantiated because CCT_MODULE feature is disabled,
+        // resolve it manually. Module loading is started in onFinishNativeInitialization()
+        // onFinishNativeInitialization() call happens before therefore if we instantiate
+        // DynamicModuleCoordinator now, the module will not be loaded.
+        DynamicModuleCoordinator coordinator = getModuleCoordinator();
+        assertFalse(coordinator.isModuleLoading() || coordinator.isModuleLoaded());
+
+        // We shouldn't be able to open a channel or post messages yet.
+        assertFalse(coordinator.requestPostMessageChannel(FAKE_ORIGIN_URI));
+        assertEquals(coordinator.postMessage("Message"),
+                CustomTabsService.RESULT_FAILURE_DISALLOWED);
+
+        // Now fake initialisation of the dynamic module.
+        coordinator.maybeInitialiseDynamicModulePostMessageHandler(
+                new PostMessageBackend() {
+                    @Override
+                    public boolean onPostMessage(String message, Bundle extras) {
+                        onPostMessageHelper.notifyCalled();
+                        return true;
+                    }
+
+                    @Override
+                    public boolean onNotifyMessageChannelReady(Bundle extras) {
+                        messageChannelHelper.notifyCalled();
+                        return true;
+                    }
+
+                    @Override
+                    public void onDisconnectChannel(Context appContext) {}
+                });
+
+        // We can now request a postMessage channel.
+        assertTrue(coordinator.requestPostMessageChannel(FAKE_ORIGIN_URI));
+    }
+
+    @Test
+    @SmallTest
+    @Features.EnableFeatures(ChromeFeatureList.CCT_MODULE)
+    @Features.DisableFeatures(ChromeFeatureList.CCT_MODULE_POST_MESSAGE)
+    public void testPostMessageFromDynamicModuleDisallowedWhenFeatureDisabled() throws Exception {
+        final String url = mServer.setResponse("/test.html", MESSAGE_FROM_PAGE_TO_CHANNEL, null);
+
+        Intent intent = new IntentBuilder(url).build();
+        mActivityRule.startCustomTabActivityWithIntent(intent);
+
+        ChromeTabUtils.waitForTabPageLoaded(getActivity().getActivityTab(), url);
+        DynamicModuleCoordinator coordinator = getModuleCoordinator();
+
+        // We shouldn't be able to open a channel or post messages yet.
+        assertFalse(coordinator.requestPostMessageChannel(FAKE_ORIGIN_URI));
+        assertEquals(coordinator.postMessage("Message"),
+                CustomTabsService.RESULT_FAILURE_DISALLOWED);
+    }
+
+    private CustomTabActivity getActivity() {
+        return mActivityRule.getActivity();
+    }
+
+    private DynamicModuleCoordinator getModuleCoordinator() {
+        return getActivity().getComponent().resolveDynamicModuleCoordinator();
+    }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsDynamicModuleTestUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleTestUtils.java
similarity index 71%
rename from chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsDynamicModuleTestUtils.java
rename to chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleTestUtils.java
index 01bc3e8..3d1559d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsDynamicModuleTestUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleTestUtils.java
@@ -2,37 +2,31 @@
 // 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.customtabs;
-
-import static org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider.EXTRA_MODULE_CLASS_NAME;
-import static org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider.EXTRA_MODULE_MANAGED_HOST_LIST;
-import static org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider.EXTRA_MODULE_PACKAGE_NAME;
-import static org.chromium.chrome.browser.customtabs.dynamicmodule.DynamicModuleNavigationEventObserver.PENDING_URL_KEY;
-import static org.chromium.chrome.browser.customtabs.dynamicmodule.DynamicModuleNavigationEventObserver.URL_KEY;
+package org.chromium.chrome.browser.customtabs.dynamicmodule;
 
 import android.content.ComponentName;
 import android.content.Intent;
-import android.net.Uri;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
 import android.support.customtabs.CustomTabsCallback;
 import android.support.test.InstrumentationRegistry;
 
+import static org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider.EXTRA_HIDE_CCT_HEADER_ON_MODULE_MANAGED_URLS;
+import static org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider.EXTRA_MODULE_CLASS_NAME;
+import static org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider.EXTRA_MODULE_MANAGED_HOST_LIST;
+import static org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider.EXTRA_MODULE_MANAGED_URLS_REGEX;
+import static org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider.EXTRA_MODULE_PACKAGE_NAME;
+import static org.chromium.chrome.browser.customtabs.dynamicmodule.DynamicModuleNavigationEventObserver.PENDING_URL_KEY;
+import static org.chromium.chrome.browser.customtabs.dynamicmodule.DynamicModuleNavigationEventObserver.URL_KEY;
+
 import org.junit.Assert;
 
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.chrome.browser.AppHooksModule;
-import org.chromium.chrome.browser.customtabs.dynamicmodule.BaseActivityDelegate;
-import org.chromium.chrome.browser.customtabs.dynamicmodule.BaseModuleEntryPoint;
-import org.chromium.chrome.browser.customtabs.dynamicmodule.IActivityDelegate;
-import org.chromium.chrome.browser.customtabs.dynamicmodule.IActivityHost;
-import org.chromium.chrome.browser.customtabs.dynamicmodule.IModuleHost;
-import org.chromium.chrome.browser.customtabs.dynamicmodule.IObjectWrapper;
-import org.chromium.chrome.browser.document.ChromeLauncherActivity;
+import org.chromium.chrome.browser.customtabs.CustomTabsTestUtils;
 import org.chromium.chrome.browser.externalauth.ExternalAuthUtils;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.concurrent.TimeoutException;
 
 /**
@@ -193,32 +187,60 @@
     }
 
     /**
-     * Creates the simplest intent that is sufficient to let {@link ChromeLauncherActivity} launch
-     * the {@link CustomTabActivity} with fake dynamic module.
+     * Class to build an {@link Intent} to start a CCT with a dynamic module.
      *
-     * @see #makeDynamicModuleIntent(ComponentName, String, String)
+     * By default the intent contains extras to load {@link FakeCCTDynamicModule}.
      */
-    public static Intent makeDynamicModuleIntent(String url, @Nullable String managedUrlsRegex) {
-        return makeDynamicModuleIntent(FAKE_MODULE_COMPONENT_NAME, url, managedUrlsRegex);
-    }
+    /* package */ static class IntentBuilder {
+        private final Intent mIntent;
 
-    /**
-     * Creates the simplest intent that is sufficient to let {@link ChromeLauncherActivity} launch
-     * the {@link CustomTabActivity} with dynamic module.
-     */
-    public static Intent makeDynamicModuleIntent(
-            ComponentName componentName, String url, @Nullable String managedUrlsRegex) {
-        Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(
-                InstrumentationRegistry.getTargetContext(), url);
-        intent.putExtra(EXTRA_MODULE_PACKAGE_NAME, componentName.getPackageName());
-        intent.putExtra(EXTRA_MODULE_CLASS_NAME, componentName.getClassName());
-
-        if (managedUrlsRegex != null) {
-            intent.putStringArrayListExtra(EXTRA_MODULE_MANAGED_HOST_LIST,
-                    new ArrayList<>(Arrays.asList(Uri.parse(url).getHost())));
-            intent.putExtra(CustomTabIntentDataProvider.EXTRA_MODULE_MANAGED_URLS_REGEX,
-                    managedUrlsRegex);
+        public Intent build() {
+            return mIntent;
         }
-        return intent;
+
+        IntentBuilder(String url) {
+            mIntent = CustomTabsTestUtils.createMinimalCustomTabIntent(
+                    InstrumentationRegistry.getTargetContext(), url);
+            setModuleComponentName(FAKE_MODULE_COMPONENT_NAME);
+        }
+
+        IntentBuilder setModuleFailToLoadComponentName() {
+            setModulePackageName(FAKE_MODULE_PACKAGE_NAME);
+            setModuleClassName("ClassName");
+            return this;
+        }
+
+        IntentBuilder setModuleComponentName(ComponentName componentName) {
+            setModulePackageName(componentName.getPackageName());
+            setModuleClassName(componentName.getClassName());
+            return this;
+        }
+
+        IntentBuilder setModulePackageName(@Nullable String packageName) {
+            if (packageName == null) mIntent.removeExtra(EXTRA_MODULE_PACKAGE_NAME);
+            mIntent.putExtra(EXTRA_MODULE_PACKAGE_NAME, packageName);
+            return this;
+        }
+
+        IntentBuilder setModuleClassName(@Nullable String className) {
+            if (className == null) mIntent.removeExtra(EXTRA_MODULE_CLASS_NAME);
+            mIntent.putExtra(EXTRA_MODULE_CLASS_NAME, className);
+            return this;
+        }
+
+        IntentBuilder setModuleManagedUrlRegex(String urlRegex) {
+            mIntent.putExtra(EXTRA_MODULE_MANAGED_URLS_REGEX, urlRegex);
+            return this;
+        }
+
+        IntentBuilder setModuleHostList(ArrayList<String> moduleHostList) {
+            mIntent.putStringArrayListExtra(EXTRA_MODULE_MANAGED_HOST_LIST, moduleHostList);
+            return this;
+        }
+
+        IntentBuilder setHideCCTHeader(boolean isEnabled) {
+            mIntent.putExtra(EXTRA_HIDE_CCT_HEADER_ON_MODULE_MANAGED_URLS, isEnabled);
+            return this;
+        }
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleUITest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleUITest.java
new file mode 100644
index 0000000..e0bac5f
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/dynamicmodule/CustomTabsDynamicModuleUITest.java
@@ -0,0 +1,524 @@
+// 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.customtabs.dynamicmodule;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import static org.chromium.base.ThreadUtils.runOnUiThread;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.uiautomator.UiDevice;
+import android.view.View;
+import android.view.ViewGroup;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.ActivityState;
+import org.chromium.base.ApplicationStatus;
+import org.chromium.base.library_loader.LibraryLoader;
+import org.chromium.base.library_loader.LibraryProcessType;
+import org.chromium.base.test.util.CallbackHelper;
+import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.AppHooksModule;
+import org.chromium.chrome.browser.ChromeFeatureList;
+import org.chromium.chrome.browser.ChromeSwitches;
+import org.chromium.chrome.browser.customtabs.CustomTabActivity;
+import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
+import org.chromium.chrome.browser.customtabs.CustomTabsTestUtils;
+import org.chromium.chrome.browser.customtabs.dynamicmodule.CustomTabsDynamicModuleTestUtils.IntentBuilder;
+import org.chromium.chrome.browser.dependency_injection.ModuleFactoryOverrides;
+import org.chromium.chrome.browser.toolbar.top.CustomTabToolbar;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.util.ChromeTabUtils;
+import org.chromium.chrome.test.util.browser.Features;
+import org.chromium.content_public.browser.test.util.ClickUtils;
+import org.chromium.content_public.browser.test.util.Criteria;
+import org.chromium.content_public.browser.test.util.CriteriaHelper;
+import org.chromium.net.test.EmbeddedTestServer;
+import org.chromium.net.test.ServerCertificate;
+import org.chromium.ui.base.PageTransition;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Instrumentation tests for UI elements of {@link CustomTabActivity}
+ * controlled by a dynamic module.
+ */
+@RunWith(ChromeJUnit4ClassRunner.class)
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+public class CustomTabsDynamicModuleUITest {
+    @Rule
+    public CustomTabActivityTestRule mActivityRule = new CustomTabActivityTestRule();
+
+    private static final String TEST_PAGE = "/chrome/test/data/android/google.html";
+    private static final String TEST_PAGE_2 = "/chrome/test/data/android/test.html";
+    private static final String MODULE_MANAGED_PAGE = "/chrome/test/data/android/about.html";
+    private static final String MODULE_MANAGED_PAGE_2 = "/chrome/test/data/android/simple.html";
+
+    private EmbeddedTestServer mTestServer;
+
+    private String mTestPage;
+    private String mTestPage2;
+    private String mModuleManagedPage;
+    private String mModuleManagedPage2;
+
+    @Before
+    public void setUp() throws Exception {
+        LibraryLoader.getInstance().ensureInitialized(LibraryProcessType.PROCESS_BROWSER);
+
+        ModuleFactoryOverrides.setOverride(AppHooksModule.Factory.class,
+                CustomTabsDynamicModuleTestUtils.AppHooksModuleForTest::new);
+
+        // Module managed hosts only work with HTTPS.
+        mTestServer = EmbeddedTestServer.createAndStartHTTPSServer(
+                InstrumentationRegistry.getInstrumentation().getContext(),
+                ServerCertificate.CERT_OK);
+
+        mTestPage = mTestServer.getURL(TEST_PAGE);
+        mTestPage2 = mTestServer.getURL(TEST_PAGE_2);
+        mModuleManagedPage = mTestServer.getURL(MODULE_MANAGED_PAGE);
+        mModuleManagedPage2 = mTestServer.getURL(MODULE_MANAGED_PAGE_2);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        ModuleFactoryOverrides.clearOverrides();
+    }
+
+    /**
+     * When module is not provided, i.e. module component name is not specified in the intent,
+     * {@link DynamicModuleCoordinator} is not instantiated, therefore it should not be possible
+     * to update UI elements of CCT.
+     */
+    @Test
+    @SmallTest
+    @Features.EnableFeatures(ChromeFeatureList.CCT_MODULE)
+    public void testModuleNotProvided() throws InterruptedException {
+        Intent intent = new IntentBuilder(mModuleManagedPage)
+                .setModulePackageName(null).setModuleClassName(null)
+                .setModuleHostList(getServerHostsList())
+                .setModuleManagedUrlRegex(getModuleManagedRegex())
+                .build();
+
+        mActivityRule.startCustomTabActivityWithIntent(intent);
+        waitForModuleLoading();
+
+        assertFalse(getActivity().getIntentDataProvider().isDynamicModuleEnabled());
+        assertNoTopBar();
+        assertCCTHeaderIsVisible();
+    }
+
+    /**
+     * When feature {@link ChromeFeatureList.CCT_MODULE} is disabled,
+     * {@link DynamicModuleCoordinator} is not instantiated, therefore it should not be possible
+     * to update UI elements of CCT.
+     */
+    @Test
+    @SmallTest
+    @Features.DisableFeatures(ChromeFeatureList.CCT_MODULE)
+    public void testFeatureIsDisabled() throws InterruptedException {
+        Intent intent = new IntentBuilder(mModuleManagedPage)
+                .setModuleHostList(getServerHostsList())
+                .setModuleManagedUrlRegex(getModuleManagedRegex())
+                .build();
+
+        mActivityRule.startCustomTabActivityWithIntent(intent);
+        waitForModuleLoading();
+
+        assertFalse(getActivity().getIntentDataProvider().isDynamicModuleEnabled());
+        assertNoTopBar();
+        assertCCTHeaderIsVisible();
+    }
+
+    /**
+     This test executes the following workflow assuming dynamic module has been loaded succesfully:
+     - moduleManagedUrl1 -> nav1.1 -> nav1.2 -> modulemanagedUrl2 -> nav2.1 -> nav2.2
+     - User hits the "close button", therefore goes back to modulemanagedUrl2
+     - User hits the Android back button, going returning to nav1.2
+     - User hits the "close button" again, going return to moduleManagedUrl1
+     - User hits the Android back button thereby closes CCT.
+     */
+    @Test
+    @SmallTest
+    @Features.EnableFeatures(ChromeFeatureList.CCT_MODULE)
+    public void testCloseButtonBehaviourWithDynamicModule()
+            throws InterruptedException, ExecutionException, TimeoutException {
+
+        Intent intent = new IntentBuilder(mModuleManagedPage)
+                .setModuleHostList(getServerHostsList())
+                .setModuleManagedUrlRegex(getModuleManagedRegex())
+                .build();
+
+        // Open CCT with moduleManagedUrl1 and navigate
+        // moduleManagedUrl1 -> nav1.1 - nav1.2 -> modulemanagedUrl2 -> nav2.1 -> nav2.2
+        mActivityRule.startCustomTabActivityWithIntent(intent);
+        CustomTabActivity cctActivity = mActivityRule.getActivity();
+
+        mActivityRule.loadUrlInTab(mTestPage, PageTransition.LINK,
+                cctActivity.getActivityTab());
+        mActivityRule.loadUrlInTab(mTestPage2, PageTransition.LINK,
+                cctActivity.getActivityTab());
+        mActivityRule.loadUrlInTab(mModuleManagedPage2, PageTransition.TYPED,
+                cctActivity.getActivityTab());
+        mActivityRule.loadUrlInTab(mTestPage, PageTransition.LINK,
+                cctActivity.getActivityTab());
+        mActivityRule.loadUrlInTab(mTestPage2, PageTransition.LINK,
+                cctActivity.getActivityTab());
+
+        // click the close button and wait while tab page loaded
+        ClickUtils.clickButton(cctActivity.findViewById(R.id.close_button));
+        ChromeTabUtils.waitForTabPageLoaded(cctActivity.getActivityTab(), null);
+
+        // close button returns back to moduleManagedUrl2
+        assertEquals(mModuleManagedPage2, cctActivity.getActivityTab().getUrl());
+
+        // press the back button and wait while tab page loaded
+        UiDevice mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+        mDevice.pressBack();
+        ChromeTabUtils.waitForTabPageLoaded(cctActivity.getActivityTab(), null);
+
+        // the back button returns to nav1.2
+        assertEquals(mTestPage2, cctActivity.getActivityTab().getUrl());
+
+        // click the close button and wait while tab page loaded
+        ClickUtils.clickButton(cctActivity.findViewById(R.id.close_button));
+        ChromeTabUtils.waitForTabPageLoaded(cctActivity.getActivityTab(), null);
+
+        // close button returns back to moduleManagedUrl1
+        assertEquals(mModuleManagedPage, cctActivity.getActivityTab().getUrl());
+
+        // press back button and while cct is hidden
+        runAndWaitForActivityStopped(mDevice::pressBack);
+    }
+
+    /**
+     This test executes the following workflow assuming dynamic module has not been loaded:
+     - moduleManagedUrl1 -> nav1.1 - nav1.2 -> modulemanagedUrl2 -> nav2.1 -> nav2.2
+     - User hits the close button, thereby closes CCT
+     */
+    @Test
+    @SmallTest
+    public void testCloseButtonBehaviourWithoutDynamicModule()
+            throws InterruptedException, ExecutionException, TimeoutException {
+        // Open CCT with moduleManagedUrl1 and navigate
+        // moduleManagedUrl1 -> nav1.1 - nav1.2 -> modulemanagedUrl2 -> nav2.1 -> nav2.2
+
+        Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(
+                InstrumentationRegistry.getTargetContext(), mModuleManagedPage);
+        mActivityRule.startCustomTabActivityWithIntent(intent);
+        CustomTabActivity cctActivity = mActivityRule.getActivity();
+
+        mActivityRule.loadUrlInTab(mTestPage, PageTransition.LINK,
+                cctActivity.getActivityTab());
+        mActivityRule.loadUrlInTab(mTestPage2, PageTransition.LINK,
+                cctActivity.getActivityTab());
+        mActivityRule.loadUrlInTab(mModuleManagedPage2, PageTransition.LINK,
+                cctActivity.getActivityTab());
+        mActivityRule.loadUrlInTab(mTestPage, PageTransition.LINK,
+                cctActivity.getActivityTab());
+        mActivityRule.loadUrlInTab(mTestPage2, PageTransition.LINK,
+                cctActivity.getActivityTab());
+
+        // click close button and wait while cct is hidden
+        runAndWaitForActivityStopped(() ->
+                ClickUtils.clickButton(cctActivity.findViewById(R.id.close_button)));
+    }
+
+    /**
+     This test executes the following workflow assuming dynamic module loading fails:
+     - moduleManagedUrl1 -> nav1.1 - nav1.2
+     - User hits the close button, thereby closes CCT
+     */
+    @Test
+    @SmallTest
+    public void testCloseButtonBehaviourDynamicModuleLoadFails()
+            throws InterruptedException, ExecutionException, TimeoutException {
+        // Open CCT with moduleManagedUrl1 and navigate
+        // moduleManagedUrl1 -> nav1.1 - nav1.2
+        Intent intent = new IntentBuilder(mModuleManagedPage)
+                .setModuleFailToLoadComponentName()
+                .setModuleHostList(getServerHostsList())
+                .setModuleManagedUrlRegex(getModuleManagedRegex()).build();
+
+        mActivityRule.startCustomTabActivityWithIntent(intent);
+        CustomTabActivity cctActivity = mActivityRule.getActivity();
+
+        waitForModuleLoading();
+
+        mActivityRule.loadUrlInTab(mTestPage, PageTransition.LINK,
+                cctActivity.getActivityTab());
+        mActivityRule.loadUrlInTab(mTestPage2, PageTransition.LINK,
+                cctActivity.getActivityTab());
+
+        // click close button and wait while cct is hidden
+        runAndWaitForActivityStopped(() ->
+                ClickUtils.clickButton(cctActivity.findViewById(R.id.close_button)));
+    }
+
+    @Test
+    @SmallTest
+    @Features.EnableFeatures(ChromeFeatureList.CCT_MODULE)
+    public void testSetTopBarContentView() throws Exception {
+        Intent intent = new IntentBuilder(mModuleManagedPage)
+                .build();
+
+        mActivityRule.startCustomTabActivityWithIntent(intent);
+        waitForModuleLoading();
+
+        runOnUiThread(() -> {
+            CustomTabActivity cctActivity = getActivity();
+            View anyView = new View(cctActivity);
+            getModuleCoordinator().setTopBarContentView(anyView);
+            ViewGroup topBar = cctActivity.findViewById(R.id.topbar);
+            Assert.assertNotNull(topBar);
+            Assert.assertThat(anyView.getParent(), equalTo(topBar));
+            assertEquals(View.GONE, anyView.getVisibility());
+        });
+    }
+
+    @Test
+    @SmallTest
+    @Features.EnableFeatures(ChromeFeatureList.CCT_MODULE)
+    public void testSetTopBarContentView_secondCallIsNoOp() throws Exception {
+        Intent intent = new IntentBuilder(mModuleManagedPage)
+                .setModuleHostList(getServerHostsList())
+                .setModuleManagedUrlRegex(getModuleManagedRegex())
+                .build();
+
+        mActivityRule.startCustomTabActivityWithIntent(intent);
+        waitForModuleLoading();
+
+        DynamicModuleCoordinator coordinator = getModuleCoordinator();
+        runOnUiThread(() -> {
+            View anyView = new View(getActivity());
+            coordinator.setTopBarContentView(anyView);
+            // Second call will not crash.
+            coordinator.setTopBarContentView(anyView);
+        });
+    }
+
+    @Test
+    @SmallTest
+    @Features.EnableFeatures(ChromeFeatureList.CCT_MODULE)
+    public void testSetTopBarContentView_moduleLoadingFailed_noTopBar() throws Exception {
+        Intent intent = new IntentBuilder(mTestPage).setModuleFailToLoadComponentName().build();
+
+        mActivityRule.startCustomTabActivityWithIntent(intent);
+        waitForModuleLoading();
+
+        runOnUiThread(() -> {
+            View anyView = new View(getActivity());
+            getModuleCoordinator().setTopBarContentView(anyView);
+        });
+
+        assertNoTopBar();
+    }
+
+    @Test
+    @SmallTest
+    @Features.EnableFeatures(ChromeFeatureList.CCT_MODULE)
+    public void testSetTopBarContentView_withModuleAndManagedUrls_topBarVisible() throws Exception {
+        Intent intent = new IntentBuilder(mModuleManagedPage)
+                .setModuleHostList(getServerHostsList())
+                .setModuleManagedUrlRegex(getModuleManagedRegex())
+                .build();
+        mActivityRule.startCustomTabActivityWithIntent(intent);
+        waitForModuleLoading();
+
+        runOnUiThread(() -> {
+            CustomTabActivity cctActivity = getActivity();
+            View anyView = new View(cctActivity);
+            getModuleCoordinator().setTopBarContentView(anyView);
+            ViewGroup topBar = cctActivity.findViewById(R.id.topbar);
+            Assert.assertNotNull(topBar);
+            Assert.assertThat(anyView.getParent(), equalTo(topBar));
+            assertEquals(View.VISIBLE, anyView.getVisibility());
+        });
+    }
+
+    @Test
+    @SmallTest
+    @Features.EnableFeatures({
+            ChromeFeatureList.CCT_MODULE, ChromeFeatureList.CCT_MODULE_CUSTOM_HEADER})
+    public void testSetTopBarContentView_notModuleManagedHost_cctHeaderVisible() throws Exception {
+        Intent intent = new IntentBuilder(mModuleManagedPage)
+                .setModuleHostList(new ArrayList<>(Arrays.asList("www.google.com")))
+                .setModuleManagedUrlRegex(getModuleManagedRegex())
+                .setHideCCTHeader(true)
+                .build();
+
+        mActivityRule.startCustomTabActivityWithIntent(intent);
+        waitForModuleLoading();
+
+        runOnUiThread(() -> getModuleCoordinator().setTopBarContentView(new View(getActivity())));
+        assertCCTHeaderIsVisible();
+    }
+
+    @Test
+    @SmallTest
+    @Features.EnableFeatures({
+            ChromeFeatureList.CCT_MODULE, ChromeFeatureList.CCT_MODULE_CUSTOM_HEADER})
+    public void testSetTopBarContentView_withModuleAndExtras_cctHeaderHidden() throws Exception {
+        Intent intent = new IntentBuilder(mModuleManagedPage)
+                .setModuleHostList(getServerHostsList())
+                .setModuleManagedUrlRegex(getModuleManagedRegex())
+                .setHideCCTHeader(true)
+                .build();
+
+        mActivityRule.startCustomTabActivityWithIntent(intent);
+        waitForModuleLoading();
+
+        CustomTabActivity cctActivity = getActivity();
+        runOnUiThread(() -> {
+            getModuleCoordinator().setTopBarContentView(new View(cctActivity));
+            ViewGroup toolbarContainerView = cctActivity.findViewById(R.id.toolbar_container);
+            for (int index = 0; index < toolbarContainerView.getChildCount(); index++) {
+                View childView = toolbarContainerView.getChildAt(index);
+                if (childView.getId() != R.id.topbar) {
+                    assertEquals(View.GONE, childView.getVisibility());
+                }
+            }
+        });
+    }
+
+    @Test
+    @SmallTest
+    @Features.DisableFeatures(ChromeFeatureList.CCT_MODULE_CUSTOM_HEADER)
+    public void testSetTopBarHeight_featureDisabled_heightNotChanged() throws Exception {
+        Intent intent = new IntentBuilder(mModuleManagedPage)
+                .setModuleHostList(getServerHostsList())
+                .setModuleManagedUrlRegex(getModuleManagedRegex())
+                .setHideCCTHeader(true)
+                .build();
+        mActivityRule.startCustomTabActivityWithIntent(intent);
+
+        runOnUiThread(() -> {
+            CustomTabActivity cctActivity = getActivity();
+            int defaultHeight = cctActivity.getFullscreenManager().getTopControlsHeight();
+            int newHeight = defaultHeight + 10;
+            getModuleCoordinator().setTopBarHeight(newHeight);
+            assertEquals(
+                    defaultHeight, cctActivity.getFullscreenManager().getTopControlsHeight());
+        });
+    }
+
+    @Test
+    @SmallTest
+    @Features.EnableFeatures({
+            ChromeFeatureList.CCT_MODULE, ChromeFeatureList.CCT_MODULE_CUSTOM_HEADER})
+    public void testSetTopBarHeight_cctHeaderNotHidden_heightNotChanged() throws Exception {
+        Intent intent = new IntentBuilder(mModuleManagedPage)
+                .setModuleHostList(getServerHostsList())
+                .setModuleManagedUrlRegex(getModuleManagedRegex())
+                .setHideCCTHeader(false)
+                .build();
+        mActivityRule.startCustomTabActivityWithIntent(intent);
+
+        runOnUiThread(() -> {
+            CustomTabActivity cctActivity = getActivity();
+            int defaultHeight = cctActivity.getFullscreenManager().getTopControlsHeight();
+            int newHeight = defaultHeight + 10;
+            getModuleCoordinator().setTopBarHeight(newHeight);
+            assertEquals(defaultHeight, cctActivity.getFullscreenManager().getTopControlsHeight());
+        });
+    }
+
+    @Test
+    @SmallTest
+    @Features.EnableFeatures({
+            ChromeFeatureList.CCT_MODULE, ChromeFeatureList.CCT_MODULE_CUSTOM_HEADER})
+    public void testSetTopBarHeight_withModuleAndExtras_heightUpdated() throws Exception {
+        Intent intent = new IntentBuilder(mModuleManagedPage)
+                .setModuleHostList(getServerHostsList())
+                .setModuleManagedUrlRegex(getModuleManagedRegex())
+                .setHideCCTHeader(true)
+                .build();
+        mActivityRule.startCustomTabActivityWithIntent(intent);
+
+        runOnUiThread(() -> {
+            CustomTabActivity cctActivity = getActivity();
+            int defaultHeight = cctActivity.getFullscreenManager().getTopControlsHeight();
+            int newHeight = defaultHeight + 10;
+            cctActivity.getComponent().resolveDynamicModuleCoordinator().setTopBarHeight(newHeight);
+            assertEquals(newHeight, cctActivity.getFullscreenManager().getTopControlsHeight());
+        });
+    }
+
+    private void assertNoTopBar() {
+        runOnUiThread(() -> {
+            ViewGroup topBar = getActivity().findViewById(R.id.topbar);
+            Assert.assertNull(topBar);
+        });
+    }
+
+    private void assertCCTHeaderIsVisible() {
+        runOnUiThread(() -> {
+            View toolbarView = getActivity().findViewById(R.id.toolbar);
+            Assert.assertTrue("A custom tab toolbar is never shown",
+                    toolbarView instanceof CustomTabToolbar);
+            CustomTabToolbar toolbar = (CustomTabToolbar) toolbarView;
+            assertEquals(View.VISIBLE, toolbar.getVisibility());
+        });
+    }
+
+    private String getModuleManagedRegex() {
+        return "^(" + MODULE_MANAGED_PAGE + "|" + MODULE_MANAGED_PAGE_2 + ")$";
+    }
+
+    private ArrayList<String> getServerHostsList() {
+        return new ArrayList<>(new ArrayList<>(
+                Arrays.asList(Uri.parse(mModuleManagedPage).getHost())));
+    }
+
+    private void runAndWaitForActivityStopped(Runnable runnable)
+            throws TimeoutException, InterruptedException {
+        CallbackHelper cctHiddenCallback = new CallbackHelper();
+        ApplicationStatus.ActivityStateListener listener = (activity, newState) -> {
+            if (activity == getActivity() &&
+                    (newState == ActivityState.STOPPED || newState == ActivityState.DESTROYED)) {
+                cctHiddenCallback.notifyCalled();
+            }
+        };
+        ApplicationStatus.registerStateListenerForAllActivities(listener);
+
+        runnable.run();
+        cctHiddenCallback.waitForCallback("Hide cct", 0);
+        ApplicationStatus.unregisterActivityStateListener(listener);
+    }
+
+    private void waitForModuleLoading() {
+        CriteriaHelper.pollUiThread(new Criteria() {
+            @Override
+            public boolean isSatisfied() {
+                if (!getActivity().getIntentDataProvider().isDynamicModuleEnabled()) return true;
+
+                DynamicModuleCoordinator module = getModuleCoordinator();
+                return module != null && !module.isModuleLoading();
+            }
+        });
+    }
+
+    private CustomTabActivity getActivity() {
+        return mActivityRule.getActivity();
+    }
+
+    private DynamicModuleCoordinator getModuleCoordinator() {
+        return getActivity().getComponent().resolveDynamicModuleCoordinator();
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/autofill_assistant/AutofillAssistantPreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/autofill_assistant/AutofillAssistantPreferencesTest.java
index ff1959d..642f581 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/autofill_assistant/AutofillAssistantPreferencesTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/autofill_assistant/AutofillAssistantPreferencesTest.java
@@ -9,6 +9,7 @@
 import android.support.test.filters.SmallTest;
 
 import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
 import static org.hamcrest.Matchers.nullValue;
 
 import org.junit.Assert;
@@ -124,9 +125,7 @@
     }
 
     /**
-     * The "Autofill Assistant" preference entry is currently completely disabled.
-     *
-     * Ensure that the entry is not shown when the AUTOFILL_ASSISTANT feature is on.
+     * Ensure that the "Autofill Assistant" setting is shown when the feature is enabled.
      */
     @Test
     @SmallTest
@@ -141,7 +140,7 @@
             public void run() {
                 MainPreferences mainPrefs = (MainPreferences) preferences.getFragmentForTest();
                 Assert.assertThat(mainPrefs.findPreference(MainPreferences.PREF_AUTOFILL_ASSISTANT),
-                        is(nullValue()));
+                        is(not(nullValue())));
             }
         });
     }
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index 1d10f5a..3fb625599 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-73.0.3637.0_rc-r1.afdo.bz2
\ No newline at end of file
+chromeos-chrome-amd64-73.0.3640.0_rc-r1.afdo.bz2
\ No newline at end of file
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 24a9252..6bb0c820 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -3411,6 +3411,12 @@
     <message name="IDS_SETTINGS_ACCOUNT_MANAGER_SUBMENU_LABEL" desc="Label of Account Manager submenu in Settings page.">
       Google Accounts
     </message>
+    <message name="IDS_SETTINGS_ACCOUNT_MANAGER_SIGNED_OUT_ACCOUNT_PLACEHOLDER" desc="Placeholder text for the full name of a signed out account in Account Manager.">
+      Sign in again
+    </message>
+    <message name="IDS_SETTINGS_ACCOUNT_MANAGER_REAUTHENTICATION_LABEL" desc="Label of the re-authentication button on Account Manager Settings page.">
+      Sign in
+    </message>
     <message name="IDS_SETTINGS_ACCOUNT_MANAGER_REMOVE_ACCOUNT_LABEL" desc="Label of the Remove account button in Account Manager.">
       Remove account from this device
     </message>
@@ -3576,9 +3582,6 @@
   <message name="IDS_SETTINGS_SYNC" desc="Name of the sync service.">
     Sync
   </message>
-  <message name="IDS_SETTINGS_SYNC_UNIFIED_CONSENT" desc="Name of the sync service when unified consent is enabled.">
-    Sync and personalization
-  </message>
   <message name="IDS_SETTINGS_NON_PERSONALIZED_SERVICES_SECTION_LABEL" desc="Title for a section that shows options for various Google services">
     Other Google services
   </message>
@@ -3588,6 +3591,9 @@
   <message name="IDS_SETTINGS_SYNC_PAGE_TITLE" desc="Name of the settings page which manages syncing data between multiple browser instances with the same Google profile.">
     Advanced sync settings
   </message>
+  <message name="IDS_SETTINGS_SYNC_ADVANCED_PAGE_TITLE" desc="Name of the settings page which manages data used by sync.">
+    Manage sync
+  </message>
   <message name="IDS_SETTINGS_SYNC_LOADING" desc="The message shown when waiting for the sync backend to start up.">
     Please wait...
   </message>
@@ -3654,6 +3660,9 @@
   <message name="IDS_SETTINGS_MANAGE_SYNCED_DATA_TITLE" desc="Title for the link to manage Chrome Sync data via Google Dashboard.">
     Manage synced data on Google Dashboard
   </message>
+   <message name="IDS_SETTINGS_MANAGE_SYNCED_DATA_TITLE_UNIFIED_CONSENT" desc="Title for the link to manage Chrome Sync data via Google Dashboard when unified consent is enabled.">
+    Data from Chrome sync
+  </message>
   <message name="IDS_SETTINGS_EXISTING_PASSPHRASE_TITLE" desc="Title for the section where the user enters the passphrase.">
     Encryption options
   </message>
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_ACCOUNT_MANAGER_REAUTHENTICATION_LABEL.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_ACCOUNT_MANAGER_REAUTHENTICATION_LABEL.png.sha1
new file mode 100644
index 0000000..f79b2ea
--- /dev/null
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_ACCOUNT_MANAGER_REAUTHENTICATION_LABEL.png.sha1
@@ -0,0 +1 @@
+fb5e2c3af13e72d5d544e5c96473cbe23c1bab10
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_ACCOUNT_MANAGER_SIGNED_OUT_ACCOUNT_PLACEHOLDER.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_ACCOUNT_MANAGER_SIGNED_OUT_ACCOUNT_PLACEHOLDER.png.sha1
new file mode 100644
index 0000000..f79b2ea
--- /dev/null
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_ACCOUNT_MANAGER_SIGNED_OUT_ACCOUNT_PLACEHOLDER.png.sha1
@@ -0,0 +1 @@
+fb5e2c3af13e72d5d544e5c96473cbe23c1bab10
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 9e11f82..40d7b8f 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -3275,6 +3275,7 @@
       "//chrome/chrome_watcher:client",
       "//chrome/common:metrics_constants_util_win",
       "//chrome/common:version_header",
+      "//chrome/credential_provider/gaiacp:common",
       "//chrome/install_static:install_static_util",
       "//chrome/notification_helper:constants",
       "//chrome/services/util_win/public/mojom",
@@ -3828,6 +3829,8 @@
       "signin/dice_tab_helper.h",
       "signin/process_dice_header_delegate_impl.cc",
       "signin/process_dice_header_delegate_impl.h",
+      "signin/signin_util_win.cc",
+      "signin/signin_util_win.h",
     ]
   }
 
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.cc b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
index 567abb6..47baa74 100644
--- a/chrome/browser/android/autofill_assistant/ui_controller_android.cc
+++ b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
@@ -460,6 +460,11 @@
       base::android::ToJavaFloatArray(env, flattened));
 }
 
+void UiControllerAndroid::ExpandBottomSheet() {
+  Java_AutofillAssistantUiController_expandBottomSheet(
+      AttachCurrentThread(), java_autofill_assistant_ui_controller_);
+}
+
 std::string UiControllerAndroid::GetDebugContext() const {
   return ui_delegate_->GetDebugContext();
 }
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.h b/chrome/browser/android/autofill_assistant/ui_controller_android.h
index 6ff5186..df1d850 100644
--- a/chrome/browser/android/autofill_assistant/ui_controller_android.h
+++ b/chrome/browser/android/autofill_assistant/ui_controller_android.h
@@ -66,6 +66,7 @@
   void UpdateTouchableArea(bool enabled,
                            const std::vector<RectF>& areas) override;
   std::string GetDebugContext() const override;
+  void ExpandBottomSheet() override;
 
   // Overrides Client:
   std::string GetApiKey() override;
diff --git a/chrome/browser/apps/platform_apps/api/BUILD.gn b/chrome/browser/apps/platform_apps/api/BUILD.gn
index 98ecbe8..6eb9a85 100644
--- a/chrome/browser/apps/platform_apps/api/BUILD.gn
+++ b/chrome/browser/apps/platform_apps/api/BUILD.gn
@@ -26,6 +26,8 @@
   sources = [
     "browser/browser_api.cc",
     "browser/browser_api.h",
+    "browser_context_keyed_service_factories.cc",
+    "browser_context_keyed_service_factories.h",
     "media_galleries/blob_data_source_factory.cc",
     "media_galleries/blob_data_source_factory.h",
     "media_galleries/media_galleries_api.cc",
@@ -59,6 +61,8 @@
 
   if (is_chromeos) {
     sources += [
+      "arc_apps_private/arc_apps_private_api.cc",
+      "arc_apps_private/arc_apps_private_api.h",
       "webstore_widget_private/app_installer.cc",
       "webstore_widget_private/app_installer.h",
       "webstore_widget_private/webstore_widget_private_api.cc",
diff --git a/chrome/browser/chromeos/extensions/arc_apps_private_api.cc b/chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_api.cc
similarity index 78%
rename from chrome/browser/chromeos/extensions/arc_apps_private_api.cc
rename to chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_api.cc
index cc3e18b..f6f0e98 100644
--- a/chrome/browser/chromeos/extensions/arc_apps_private_api.cc
+++ b/chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_api.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/extensions/arc_apps_private_api.h"
+#include "chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_api.h"
 
 #include <string>
 #include <vector>
@@ -11,41 +11,45 @@
 #include "base/no_destructor.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
-#include "chrome/common/extensions/api/arc_apps_private.h"
+#include "chrome/common/apps/platform_apps/api/arc_apps_private.h"
 #include "ui/events/event_constants.h"
 
-namespace extensions {
+namespace chrome_apps {
+namespace api {
 
 // static
-BrowserContextKeyedAPIFactory<ArcAppsPrivateAPI>*
+extensions::BrowserContextKeyedAPIFactory<ArcAppsPrivateAPI>*
 ArcAppsPrivateAPI::GetFactoryInstance() {
-  static base::NoDestructor<BrowserContextKeyedAPIFactory<ArcAppsPrivateAPI>>
+  static base::NoDestructor<
+      extensions::BrowserContextKeyedAPIFactory<ArcAppsPrivateAPI>>
       instance;
   return instance.get();
 }
 
 ArcAppsPrivateAPI::ArcAppsPrivateAPI(content::BrowserContext* context)
     : context_(context), scoped_prefs_observer_(this) {
-  EventRouter::Get(context_)->RegisterObserver(
+  extensions::EventRouter::Get(context_)->RegisterObserver(
       this, api::arc_apps_private::OnInstalled::kEventName);
 }
 
 ArcAppsPrivateAPI::~ArcAppsPrivateAPI() = default;
 
 void ArcAppsPrivateAPI::Shutdown() {
-  EventRouter::Get(context_)->UnregisterObserver(this);
+  extensions::EventRouter::Get(context_)->UnregisterObserver(this);
   scoped_prefs_observer_.RemoveAll();
 }
 
-void ArcAppsPrivateAPI::OnListenerAdded(const EventListenerInfo& details) {
+void ArcAppsPrivateAPI::OnListenerAdded(
+    const extensions::EventListenerInfo& details) {
   DCHECK_EQ(details.event_name, api::arc_apps_private::OnInstalled::kEventName);
   auto* prefs = ArcAppListPrefs::Get(Profile::FromBrowserContext(context_));
   if (prefs && !scoped_prefs_observer_.IsObserving(prefs))
     scoped_prefs_observer_.Add(prefs);
 }
 
-void ArcAppsPrivateAPI::OnListenerRemoved(const EventListenerInfo& details) {
-  if (!EventRouter::Get(context_)->HasEventListener(
+void ArcAppsPrivateAPI::OnListenerRemoved(
+    const extensions::EventListenerInfo& details) {
+  if (!extensions::EventRouter::Get(context_)->HasEventListener(
           api::arc_apps_private::OnInstalled::kEventName)) {
     scoped_prefs_observer_.RemoveAll();
   }
@@ -58,11 +62,11 @@
     return;
   api::arc_apps_private::AppInfo app_info_result;
   app_info_result.package_name = app_info.package_name;
-  auto event = std::make_unique<Event>(
-      events::ARC_APPS_PRIVATE_ON_INSTALLED,
+  auto event = std::make_unique<extensions::Event>(
+      extensions::events::ARC_APPS_PRIVATE_ON_INSTALLED,
       api::arc_apps_private::OnInstalled::kEventName,
       api::arc_apps_private::OnInstalled::Create(app_info_result), context_);
-  EventRouter::Get(context_)->BroadcastEvent(std::move(event));
+  extensions::EventRouter::Get(context_)->BroadcastEvent(std::move(event));
 }
 
 ArcAppsPrivateGetLaunchableAppsFunction::
@@ -116,4 +120,5 @@
   return RespondNow(NoArguments());
 }
 
-}  // namespace extensions
+}  // namespace api
+}  // namespace chrome_apps
diff --git a/chrome/browser/chromeos/extensions/arc_apps_private_api.h b/chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_api.h
similarity index 66%
rename from chrome/browser/chromeos/extensions/arc_apps_private_api.h
rename to chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_api.h
index d4bb602e..c0724af 100644
--- a/chrome/browser/chromeos/extensions/arc_apps_private_api.h
+++ b/chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_api.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_ARC_APPS_PRIVATE_API_H_
-#define CHROME_BROWSER_CHROMEOS_EXTENSIONS_ARC_APPS_PRIVATE_API_H_
+#ifndef CHROME_BROWSER_APPS_PLATFORM_APPS_API_ARC_APPS_PRIVATE_ARC_APPS_PRIVATE_API_H_
+#define CHROME_BROWSER_APPS_PLATFORM_APPS_API_ARC_APPS_PRIVATE_ARC_APPS_PRIVATE_API_H_
 
 #include "base/macros.h"
 #include "base/scoped_observer.h"
@@ -13,34 +13,36 @@
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_function.h"
 
-namespace extensions {
+namespace chrome_apps {
+namespace api {
 
-class ArcAppsPrivateAPI : public BrowserContextKeyedAPI,
-                          public EventRouter::Observer,
+class ArcAppsPrivateAPI : public extensions::BrowserContextKeyedAPI,
+                          public extensions::EventRouter::Observer,
                           public ArcAppListPrefs::Observer {
  public:
-  static BrowserContextKeyedAPIFactory<ArcAppsPrivateAPI>* GetFactoryInstance();
+  static extensions::BrowserContextKeyedAPIFactory<ArcAppsPrivateAPI>*
+  GetFactoryInstance();
 
   explicit ArcAppsPrivateAPI(content::BrowserContext* context);
   ~ArcAppsPrivateAPI() override;
 
-  // BrowserContextKeyedAPI:
+  // extensions::BrowserContextKeyedAPI:
   void Shutdown() override;
 
-  // EventRouter::Observer:
-  void OnListenerAdded(const EventListenerInfo& details) override;
-  void OnListenerRemoved(const EventListenerInfo& details) override;
+  // extensions::EventRouter::Observer:
+  void OnListenerAdded(const extensions::EventListenerInfo& details) override;
+  void OnListenerRemoved(const extensions::EventListenerInfo& details) override;
 
   // ArcAppListPrefs::Observer:
   void OnAppRegistered(const std::string& app_id,
                        const ArcAppListPrefs::AppInfo& app_info) override;
 
  private:
-  friend class BrowserContextKeyedAPIFactory<ArcAppsPrivateAPI>;
+  friend class extensions::BrowserContextKeyedAPIFactory<ArcAppsPrivateAPI>;
 
   static const char* service_name() { return "ArcAppsPrivateAPI"; }
 
-  // BrowserContextKeyedAPI:
+  // extensions::BrowserContextKeyedAPI:
   static const bool kServiceIsNULLWhileTesting = true;
 
   content::BrowserContext* const context_;
@@ -50,16 +52,6 @@
   DISALLOW_COPY_AND_ASSIGN(ArcAppsPrivateAPI);
 };
 
-template <>
-struct BrowserContextFactoryDependencies<ArcAppsPrivateAPI> {
-  static void DeclareFactoryDependencies(
-      BrowserContextKeyedAPIFactory<ArcAppsPrivateAPI>* factory) {
-    factory->DependsOn(
-        ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
-    factory->DependsOn(ArcAppListPrefsFactory::GetInstance());
-  }
-};
-
 class ArcAppsPrivateGetLaunchableAppsFunction
     : public UIThreadExtensionFunction {
  public:
@@ -95,6 +87,19 @@
   DISALLOW_COPY_AND_ASSIGN(ArcAppsPrivateLaunchAppFunction);
 };
 
-}  // namespace extensions
+}  // namespace api
+}  // namespace chrome_apps
 
-#endif  // CHROME_BROWSER_CHROMEOS_EXTENSIONS_ARC_APPS_PRIVATE_API_H_
\ No newline at end of file
+template <>
+struct extensions::BrowserContextFactoryDependencies<
+    chrome_apps::api::ArcAppsPrivateAPI> {
+  static void DeclareFactoryDependencies(
+      extensions::BrowserContextKeyedAPIFactory<
+          chrome_apps::api::ArcAppsPrivateAPI>* factory) {
+    factory->DependsOn(
+        ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
+    factory->DependsOn(ArcAppListPrefsFactory::GetInstance());
+  }
+};
+
+#endif  // CHROME_BROWSER_APPS_PLATFORM_APPS_API_ARC_APPS_PRIVATE_ARC_APPS_PRIVATE_API_H_
diff --git a/chrome/browser/chromeos/extensions/arc_apps_private_apitest.cc b/chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_apitest.cc
similarity index 99%
rename from chrome/browser/chromeos/extensions/arc_apps_private_apitest.cc
rename to chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_apitest.cc
index 407d889..41a475b 100644
--- a/chrome/browser/chromeos/extensions/arc_apps_private_apitest.cc
+++ b/chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_apitest.cc
@@ -131,4 +131,4 @@
   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
   ASSERT_EQ(1u, app_instance->launch_requests().size());
   EXPECT_TRUE(app_instance->launch_requests()[0]->IsForApp(launchable_app));
-}
\ No newline at end of file
+}
diff --git a/chrome/browser/apps/platform_apps/api/browser_context_keyed_service_factories.cc b/chrome/browser/apps/platform_apps/api/browser_context_keyed_service_factories.cc
new file mode 100644
index 0000000..1854f1e
--- /dev/null
+++ b/chrome/browser/apps/platform_apps/api/browser_context_keyed_service_factories.cc
@@ -0,0 +1,21 @@
+// 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/apps/platform_apps/api/browser_context_keyed_service_factories.h"
+
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_api.h"
+#endif
+
+namespace chrome_apps {
+namespace api {
+
+void EnsureAPIBrowserContextKeyedServiceFactoriesBuilt() {
+#if defined(OS_CHROMEOS)
+  ArcAppsPrivateAPI::GetFactoryInstance();
+#endif
+}
+
+}  // namespace api
+}  // namespace chrome_apps
diff --git a/chrome/browser/apps/platform_apps/api/browser_context_keyed_service_factories.h b/chrome/browser/apps/platform_apps/api/browser_context_keyed_service_factories.h
new file mode 100644
index 0000000..d345c09
--- /dev/null
+++ b/chrome/browser/apps/platform_apps/api/browser_context_keyed_service_factories.h
@@ -0,0 +1,18 @@
+// 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_APPS_PLATFORM_APPS_API_BROWSER_CONTEXT_KEYED_SERVICE_FACTORIES_H_
+#define CHROME_BROWSER_APPS_PLATFORM_APPS_API_BROWSER_CONTEXT_KEYED_SERVICE_FACTORIES_H_
+
+namespace chrome_apps {
+namespace api {
+
+// Ensures the existence of any BrowserContextKeyedServiceFactory provided by
+// the Chrome Apps API code.
+void EnsureAPIBrowserContextKeyedServiceFactoriesBuilt();
+
+}  // namespace api
+}  // namespace chrome_apps
+
+#endif  // CHROME_BROWSER_APPS_PLATFORM_APPS_API_BROWSER_CONTEXT_KEYED_SERVICE_FACTORIES_H_
diff --git a/chrome/browser/browsing_data/browsing_data_appcache_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_appcache_helper_unittest.cc
index 5c91a8b..033b7b3 100644
--- a/chrome/browser/browsing_data/browsing_data_appcache_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_appcache_helper_unittest.cc
@@ -10,7 +10,6 @@
 #include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/stl_util.h"
-#include "base/test/scoped_task_environment.h"
 #include "build/build_config.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/test_browser_thread_bundle.h"
@@ -44,19 +43,18 @@
 class CannedBrowsingDataAppCacheHelperTest : public testing::Test {
  public:
   CannedBrowsingDataAppCacheHelperTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI),
-        thread_bundle_(content::TestBrowserThreadBundle::REAL_IO_THREAD) {}
+      : thread_bundle_(base::test::ScopedTaskEnvironment::MainThreadType::UI,
+                       base::test::ScopedTaskEnvironment::ExecutionMode::ASYNC,
+                       content::TestBrowserThreadBundle::REAL_IO_THREAD) {}
 
   void TearDown() override {
     // Make sure we run all pending tasks on IO thread before testing
     // profile is destructed.
     content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
-    scoped_task_environment_.RunUntilIdle();
+    thread_bundle_.RunUntilIdle();
   }
 
  protected:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
   content::TestBrowserThreadBundle thread_bundle_;
   TestingProfile profile_;
 };
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 1ca0e4d..f9d1518 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -1899,8 +1899,6 @@
     "virtual_machines/virtual_machines_util.h",
 
     # Extension API implementations.
-    "extensions/arc_apps_private_api.cc",
-    "extensions/arc_apps_private_api.h",
     "extensions/autotest_private/autotest_private_api.cc",
     "extensions/autotest_private/autotest_private_api.h",
     "extensions/backdrop_wallpaper_handlers/backdrop_wallpaper_handlers.cc",
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc
index 146ea49..295d8704 100644
--- a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc
+++ b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc
@@ -25,7 +25,6 @@
 #include "components/arc/common/accessibility_helper.mojom.h"
 #include "components/exo/shell_surface.h"
 #include "components/exo/shell_surface_util.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/aura/window.h"
 #include "ui/display/display.h"
@@ -177,7 +176,6 @@
       arc_notification_surface_manager_;
 
  private:
-  content::TestBrowserThreadBundle thread_bundle_;
   std::unique_ptr<TestingProfile> testing_profile_;
   std::unique_ptr<ArcBridgeService> bridge_service_;
   std::unique_ptr<TestArcAccessibilityHelperBridge>
diff --git a/chrome/browser/chromeos/arc/input_method_manager/input_connection_impl.cc b/chrome/browser/chromeos/arc/input_method_manager/input_connection_impl.cc
index 1142470c..ce72993c 100644
--- a/chrome/browser/chromeos/arc/input_method_manager/input_connection_impl.cc
+++ b/chrome/browser/chromeos/arc/input_method_manager/input_connection_impl.cc
@@ -86,7 +86,7 @@
   gfx::Range text_range, selection_range;
   base::string16 text;
   client->GetTextRange(&text_range);
-  client->GetSelectionRange(&selection_range);
+  client->GetEditableSelectionRange(&selection_range);
   client->GetTextFromRange(text_range, &text);
 
   return mojom::TextInputStatePtr(
@@ -147,7 +147,7 @@
 
   ui::TextInputClient* client = GetTextInputClient();
   gfx::Range selection_range, composition_range;
-  client->GetSelectionRange(&selection_range);
+  client->GetEditableSelectionRange(&selection_range);
   client->GetCompositionTextRange(&composition_range);
 
   std::string error;
@@ -183,7 +183,7 @@
 
   ui::TextInputClient* client = GetTextInputClient();
   gfx::Range selection_range;
-  client->GetSelectionRange(&selection_range);
+  client->GetEditableSelectionRange(&selection_range);
   if (text.empty() &&
       selection_range.start() == static_cast<uint32_t>(selection_start) &&
       selection_range.end() == static_cast<uint32_t>(selection_end)) {
@@ -214,7 +214,7 @@
   ui::TextInputClient* client = GetTextInputClient();
 
   gfx::Range selection_range;
-  client->GetSelectionRange(&selection_range);
+  client->GetEditableSelectionRange(&selection_range);
   if (new_selection_range == selection_range) {
     // This SetSelection call is no-op.
     // Return the current state immediately.
@@ -222,7 +222,7 @@
   }
 
   StartStateUpdateTimer();
-  client->SetSelectionRange(new_selection_range);
+  client->SetEditableSelectionRange(new_selection_range);
 }
 
 void InputConnectionImpl::StartStateUpdateTimer() {
diff --git a/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc b/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc
index 2589c0b9..abb6520 100644
--- a/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc
+++ b/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc
@@ -8,7 +8,6 @@
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
 #include "chrome/browser/chromeos/crostini/crostini_util.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
@@ -132,9 +131,9 @@
   }
 
   CrostiniManagerTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI),
-        test_browser_thread_bundle_(
+      : test_browser_thread_bundle_(
+            base::test::ScopedTaskEnvironment::MainThreadType::UI,
+            base::test::ScopedTaskEnvironment::ExecutionMode::ASYNC,
             content::TestBrowserThreadBundle::REAL_IO_THREAD) {
     chromeos::DBusThreadManager::Initialize();
     fake_cicerone_client_ = static_cast<chromeos::FakeCiceroneClient*>(
@@ -173,7 +172,6 @@
   bool create_container_fails_callback_called_ = false;
 
  private:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
   content::TestBrowserThreadBundle test_browser_thread_bundle_;
   DISALLOW_COPY_AND_ASSIGN(CrostiniManagerTest);
 };
diff --git a/chrome/browser/chromeos/crostini/crostini_share_path_unittest.cc b/chrome/browser/chromeos/crostini/crostini_share_path_unittest.cc
index 0001a67..db3d4d65 100644
--- a/chrome/browser/chromeos/crostini/crostini_share_path_unittest.cc
+++ b/chrome/browser/chromeos/crostini/crostini_share_path_unittest.cc
@@ -8,7 +8,6 @@
 #include "base/files/file_util.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
 #include "chrome/browser/chromeos/crostini/crostini_manager.h"
 #include "chrome/browser/chromeos/crostini/crostini_pref_names.h"
 #include "chrome/browser/chromeos/crostini/crostini_util.h"
@@ -118,9 +117,9 @@
   }
 
   CrostiniSharePathTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI),
-        test_browser_thread_bundle_(
+      : test_browser_thread_bundle_(
+            base::test::ScopedTaskEnvironment::MainThreadType::UI,
+            base::test::ScopedTaskEnvironment::ExecutionMode::ASYNC,
             content::TestBrowserThreadBundle::REAL_IO_THREAD) {
     chromeos::DBusThreadManager::Initialize();
     fake_concierge_client_ = static_cast<chromeos::FakeConciergeClient*>(
@@ -192,7 +191,6 @@
   chromeos::FakeChromeUserManager user_manager;
 
  private:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
   content::TestBrowserThreadBundle test_browser_thread_bundle_;
   DISALLOW_COPY_AND_ASSIGN(CrostiniSharePathTest);
 };
diff --git a/chrome/browser/chromeos/input_method/textinput_test_helper.cc b/chrome/browser/chromeos/input_method/textinput_test_helper.cc
index cae24c7..b2cfba3 100644
--- a/chrome/browser/chromeos/input_method/textinput_test_helper.cc
+++ b/chrome/browser/chromeos/input_method/textinput_test_helper.cc
@@ -97,7 +97,7 @@
     if (!GetTextInputClient()->GetTextRange(&text_range) ||
         !GetTextInputClient()->GetTextFromRange(text_range,
                                                 &surrounding_text_) ||
-        !GetTextInputClient()->GetSelectionRange(&selection_range_))
+        !GetTextInputClient()->GetEditableSelectionRange(&selection_range_))
       return;
   }
   if (waiting_type_ == WAIT_ON_CARET_BOUNDS_CHANGED)
diff --git a/chrome/browser/chromeos/oauth2_token_service_delegate_unittest.cc b/chrome/browser/chromeos/oauth2_token_service_delegate_unittest.cc
index 035efd74..e471070 100644
--- a/chrome/browser/chromeos/oauth2_token_service_delegate_unittest.cc
+++ b/chrome/browser/chromeos/oauth2_token_service_delegate_unittest.cc
@@ -13,7 +13,6 @@
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/stl_util.h"
-#include "base/test/scoped_task_environment.h"
 #include "chromeos/account_manager/account_manager.h"
 #include "components/signin/core/browser/account_info.h"
 #include "components/signin/core/browser/account_tracker_service.h"
@@ -110,9 +109,7 @@
 
 class CrOSOAuthDelegateTest : public testing::Test {
  public:
-  CrOSOAuthDelegateTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+  CrOSOAuthDelegateTest() {}
   ~CrOSOAuthDelegateTest() override = default;
 
  protected:
@@ -128,7 +125,7 @@
     account_manager_.Initialize(tmp_dir_.GetPath(),
                                 client_->GetURLLoaderFactory(),
                                 immediate_callback_runner_);
-    scoped_task_environment_.RunUntilIdle();
+    thread_bundle_.RunUntilIdle();
 
     account_tracker_service_.Initialize(&pref_service_, base::FilePath());
 
@@ -170,9 +167,6 @@
         GetValidTokenResponse("token", 3600));
   }
 
-  // Check base/test/scoped_task_environment.h. This must be the first member /
-  // declared before any member that cares about tasks.
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
   // Needed because
   // |content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver| in
   // |ChromeOSOAuth2TokenServiceDelegate|'s constructor CHECKs that we are
@@ -292,11 +286,11 @@
       AccountManager::AccountKey{account1.gaia, ACCOUNT_TYPE_GAIA}, "token1");
   account_manager_.UpsertToken(
       AccountManager::AccountKey{account2.gaia, ACCOUNT_TYPE_GAIA}, "token2");
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
 
   AccountManager account_manager;
   // AccountManager will not be fully initialized until
-  // |scoped_task_environment_.RunUntilIdle()| is called.
+  // |thread_bundle_.RunUntilIdle()| is called.
   account_manager.Initialize(tmp_dir_.GetPath(), client_->GetURLLoaderFactory(),
                              immediate_callback_runner_);
 
@@ -307,7 +301,7 @@
   TokenServiceObserver observer;
   delegate->AddObserver(&observer);
   // Wait until AccountManager is fully initialized.
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
 
   // Tests
 
@@ -417,9 +411,9 @@
       delegate_->CreateAccessTokenFetcher(account_info_.account_id,
                                           delegate_->GetURLLoaderFactory(),
                                           &access_token_consumer));
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   fetcher->Start("client_id", "client_secret", scopes);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(0, access_token_consumer.num_access_token_fetch_success_);
   EXPECT_EQ(1, access_token_consumer.num_access_token_fetch_failure_);
   // Expect a positive backoff time.
@@ -431,7 +425,7 @@
       account_info_.account_id, delegate_->GetURLLoaderFactory(),
       &access_token_consumer));
   fetcher->Start("client_id", "client_secret", scopes);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(1, access_token_consumer.num_access_token_fetch_success_);
   EXPECT_EQ(1, access_token_consumer.num_access_token_fetch_failure_);
 }
@@ -454,9 +448,9 @@
       delegate_->CreateAccessTokenFetcher(account_info_.account_id,
                                           delegate_->GetURLLoaderFactory(),
                                           &access_token_consumer));
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   fetcher->Start("client_id", "client_secret", scopes);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(0, access_token_consumer.num_access_token_fetch_success_);
   EXPECT_EQ(1, access_token_consumer.num_access_token_fetch_failure_);
   // Expect a positive backoff time.
@@ -469,7 +463,7 @@
       account_info_.account_id, delegate_->GetURLLoaderFactory(),
       &access_token_consumer));
   fetcher->Start("client_id", "client_secret", scopes);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(1, access_token_consumer.num_access_token_fetch_success_);
   EXPECT_EQ(1, access_token_consumer.num_access_token_fetch_failure_);
 }
diff --git a/chrome/browser/chromeos/policy/app_install_event_logger_unittest.cc b/chrome/browser/chromeos/policy/app_install_event_logger_unittest.cc
index 3717ae03..11cdc8f5 100644
--- a/chrome/browser/chromeos/policy/app_install_event_logger_unittest.cc
+++ b/chrome/browser/chromeos/policy/app_install_event_logger_unittest.cc
@@ -7,7 +7,6 @@
 #include <stdint.h>
 
 #include "base/json/json_writer.h"
-#include "base/test/scoped_task_environment.h"
 #include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/prefs/browser_prefs.h"
@@ -98,7 +97,7 @@
 class AppInstallEventLoggerTest : public testing::Test {
  protected:
   AppInstallEventLoggerTest()
-      : scoped_task_environment_(
+      : browser_thread_bundle_(
             base::test::ScopedTaskEnvironment::MainThreadType::UI,
             base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED) {}
 
@@ -126,7 +125,7 @@
 
   void TearDown() override {
     logger_.reset();
-    scoped_task_environment_.RunUntilIdle();
+    browser_thread_bundle_.RunUntilIdle();
     chromeos::NetworkHandler::Shutdown();
     chromeos::DBusThreadManager::Shutdown();
     chromeos::disks::DiskMountManager::Shutdown();
@@ -163,7 +162,6 @@
     event_.set_event_type(em::AppInstallReportLogEvent::SUCCESS);
   }
 
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
   content::TestBrowserThreadBundle browser_thread_bundle_;
   TestingProfile profile_;
   TestingPrefServiceSimple pref_service_;
@@ -256,7 +254,7 @@
   EXPECT_CALL(*disk_mount_manager_, disks());
   EXPECT_CALL(delegate_,
               Add(std::set<std::string>{kPackageName}, MatchProto(event_)));
-  scoped_task_environment_.RunUntilIdle();
+  browser_thread_bundle_.RunUntilIdle();
 }
 
 // Adds an event without a timestamp, requesting that disk space information be
@@ -288,7 +286,7 @@
   EXPECT_CALL(delegate_, Add(std::set<std::string>{kPackageName},
                              MatchEventExceptTimestamp(event_)))
       .WillOnce(SaveTimestamp<1>(&timestamp));
-  scoped_task_environment_.RunUntilIdle();
+  browser_thread_bundle_.RunUntilIdle();
 
   EXPECT_LE(before, timestamp);
   EXPECT_GE(after, timestamp);
@@ -347,7 +345,7 @@
   EXPECT_CALL(delegate_, Add(std::set<std::string>{kPackageName, kPackageName3},
                              MatchEventExceptTimestamp(event_)));
   EXPECT_CALL(*disk_mount_manager_, disks());
-  scoped_task_environment_.RunUntilIdle();
+  browser_thread_bundle_.RunUntilIdle();
   Mock::VerifyAndClearExpectations(&delegate_);
 
   // To avoid extra logging.
diff --git a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
index 67fc487..582e986 100644
--- a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
@@ -1062,6 +1062,26 @@
     }
   }
 
+  if (policy.has_device_gpo_cache_lifetime()) {
+    const em::DeviceGpoCacheLifetimeProto& container(
+        policy.device_gpo_cache_lifetime());
+    if (container.has_lifetime_hours()) {
+      policies->Set(key::kDeviceGpoCacheLifetime, POLICY_LEVEL_MANDATORY,
+                    POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
+                    DecodeIntegerValue(container.lifetime_hours()), nullptr);
+    }
+  }
+
+  if (policy.has_device_auth_data_cache_lifetime()) {
+    const em::DeviceAuthDataCacheLifetimeProto& container(
+        policy.device_auth_data_cache_lifetime());
+    if (container.has_lifetime_hours()) {
+      policies->Set(key::kDeviceAuthDataCacheLifetime, POLICY_LEVEL_MANDATORY,
+                    POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
+                    DecodeIntegerValue(container.lifetime_hours()), nullptr);
+    }
+  }
+
   if (policy.has_device_unaffiliated_crostini_allowed()) {
     const em::DeviceUnaffiliatedCrostiniAllowedProto& container(
         policy.device_unaffiliated_crostini_allowed());
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/adapter_unittest.cc b/chrome/browser/chromeos/power/auto_screen_brightness/adapter_unittest.cc
index d9d3f39..24b50fe 100644
--- a/chrome/browser/chromeos/power/auto_screen_brightness/adapter_unittest.cc
+++ b/chrome/browser/chromeos/power/auto_screen_brightness/adapter_unittest.cc
@@ -118,9 +118,8 @@
 class AdapterTest : public testing::Test {
  public:
   AdapterTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
-        thread_bundle_(content::TestBrowserThreadBundle::PLAIN_MAINLOOP) {
+      : thread_bundle_(
+            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {
     chromeos::DBusThreadManager::GetSetterForTesting()->SetPowerManagerClient(
         std::make_unique<chromeos::FakePowerManagerClient>());
     power_manager::SetBacklightBrightnessRequest request;
@@ -128,7 +127,7 @@
     chromeos::DBusThreadManager::Get()
         ->GetPowerManagerClient()
         ->SetScreenBrightness(request);
-    scoped_task_environment_.RunUntilIdle();
+    thread_bundle_.RunUntilIdle();
 
     chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(
         &test_observer_);
@@ -187,8 +186,7 @@
         profile_.get(), &fake_als_reader_, &fake_brightness_monitor_,
         &fake_modeller_, nullptr /* metrics_reporter */,
         chromeos::DBusThreadManager::Get()->GetPowerManagerClient());
-    adapter_->SetTickClockForTesting(
-        scoped_task_environment_.GetMockTickClock());
+    adapter_->SetTickClockForTesting(thread_bundle_.GetMockTickClock());
   }
 
   void Init(AlsReader::AlsInitStatus als_reader_status,
@@ -201,11 +199,10 @@
     fake_brightness_monitor_.set_status(brightness_monitor_status);
     fake_modeller_.InitModellerWithCurves(global_curve, personal_curve);
     SetUpAdapter(params, brightness_set_by_policy);
-    scoped_task_environment_.RunUntilIdle();
+    thread_bundle_.RunUntilIdle();
   }
 
  protected:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
   content::TestBrowserThreadBundle thread_bundle_;
 
   TestObserver test_observer_;
@@ -286,7 +283,7 @@
 
   fake_als_reader_.set_als_init_status(AlsReader::AlsInitStatus::kSuccess);
   fake_als_reader_.ReportReaderInitialized();
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(adapter_->GetStatusForTesting(), Adapter::Status::kSuccess);
   EXPECT_TRUE(adapter_->GetGlobalCurveForTesting());
   EXPECT_EQ(*adapter_->GetGlobalCurveForTesting(), *global_curve_);
@@ -316,7 +313,7 @@
 
   fake_brightness_monitor_.set_status(BrightnessMonitor::Status::kSuccess);
   fake_brightness_monitor_.ReportBrightnessMonitorInitialized();
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(adapter_->GetStatusForTesting(), Adapter::Status::kSuccess);
   EXPECT_TRUE(adapter_->GetGlobalCurveForTesting());
   EXPECT_EQ(*adapter_->GetGlobalCurveForTesting(), *global_curve_);
@@ -328,7 +325,7 @@
   fake_als_reader_.set_als_init_status(AlsReader::AlsInitStatus::kSuccess);
   fake_brightness_monitor_.set_status(BrightnessMonitor::Status::kSuccess);
   SetUpAdapter(default_params_);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(adapter_->GetStatusForTesting(), Adapter::Status::kInitializing);
 
   fake_modeller_.InitModellerWithCurves(base::nullopt, base::nullopt);
@@ -343,7 +340,7 @@
   fake_als_reader_.set_als_init_status(AlsReader::AlsInitStatus::kSuccess);
   fake_brightness_monitor_.set_status(BrightnessMonitor::Status::kSuccess);
   SetUpAdapter(default_params_);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(adapter_->GetStatusForTesting(), Adapter::Status::kInitializing);
 
   fake_modeller_.InitModellerWithCurves(global_curve_, personal_curve_);
@@ -367,38 +364,38 @@
 
   // Forward by 1sec because in real implementation, |first_als_time_| is zero
   // if there's no ALS reading received.
-  scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+  thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(1));
 
   // Brightness is changed after the 1st ALS reading comes in.
   fake_als_reader_.ReportAmbientLightUpdate(10);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(test_observer_.num_changes(), 1);
 
   // Another ALS value is received in 3 sec, but no brightness update is done.
-  scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(3));
+  thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(3));
   fake_als_reader_.ReportAmbientLightUpdate(20);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(test_observer_.num_changes(), 1);
 
   // |params.min_time_between_brightness_changes| has elapsed since we've made
   // the change, but there's no new ALS value, hence no brightness change is
   // triggered.
-  scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(10));
+  thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(10));
   EXPECT_EQ(test_observer_.num_changes(), 1);
 
   // A new ALS value triggers a brightness change.
   fake_als_reader_.ReportAmbientLightUpdate(40);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(test_observer_.num_changes(), 2);
 
   // Adapter is disabled after a user manual adjustment.
   fake_brightness_monitor_.ReportUserBrightnessChangeRequested();
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(adapter_->GetStatusForTesting(), Adapter::Status::kDisabled);
 
   // Another user manual adjustment came in.
   fake_brightness_monitor_.ReportUserBrightnessChangeRequested();
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(adapter_->GetStatusForTesting(), Adapter::Status::kDisabled);
 
 }
@@ -415,12 +412,12 @@
 
   // Adapter is disabled after a user manual adjustment.
   fake_brightness_monitor_.ReportUserBrightnessChangeRequested();
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(adapter_->GetStatusForTesting(), Adapter::Status::kDisabled);
 
   // Another user manual adjustment came in.
   fake_brightness_monitor_.ReportUserBrightnessChangeRequested();
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(adapter_->GetStatusForTesting(), Adapter::Status::kDisabled);
 }
 
@@ -435,12 +432,12 @@
   EXPECT_TRUE(adapter_->GetPersonalCurveForTesting());
   EXPECT_EQ(*adapter_->GetPersonalCurveForTesting(), *personal_curve_);
 
-  scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+  thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(1));
 
   // Brightness is changed after the 1st ALS value, and the thresholds are
   // changed.
   fake_als_reader_.ReportAmbientLightUpdate(20);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(test_observer_.num_changes(), 1);
   EXPECT_DOUBLE_EQ(adapter_->GetAverageAmbientForTesting(), 20);
   EXPECT_DOUBLE_EQ(adapter_->GetBrighteningThresholdForTesting(), 22);
@@ -448,7 +445,7 @@
 
   // A 2nd ALS comes in, but average ambient is within the thresholds, hence
   // brightness isn't changed and thresholds aren't updated.
-  scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(20));
+  thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(20));
   fake_als_reader_.ReportAmbientLightUpdate(21);
   EXPECT_EQ(1, test_observer_.num_changes());
   EXPECT_DOUBLE_EQ(adapter_->GetAverageAmbientForTesting(), (20 + 21) / 2.0);
@@ -466,7 +463,7 @@
   // A 4th ALS makes average value below the darkening threshold, hence
   // brightness is changed. Thresholds are also changed.
   fake_als_reader_.ReportAmbientLightUpdate(7);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
 
   EXPECT_EQ(test_observer_.num_changes(), 2);
   const double expected_average_ambient = (20 + 21 + 15 + 7) / 4.0;
@@ -480,12 +477,12 @@
   // Next check |ambient_light_values_| has capacity
   // |Adapter::kNumberAmbientValuesToTrack|.
   fake_als_reader_.ReportAmbientLightUpdate(8);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_DOUBLE_EQ(adapter_->GetAverageAmbientForTesting(),
                    (20 + 21 + 15 + 7 + 8) / 5.0);
 
   fake_als_reader_.ReportAmbientLightUpdate(9);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
 
   EXPECT_DOUBLE_EQ(adapter_->GetAverageAmbientForTesting(),
                    (21 + 15 + 7 + 8 + 9) / 5.0);
@@ -505,25 +502,25 @@
   EXPECT_TRUE(adapter_->GetPersonalCurveForTesting());
   EXPECT_EQ(*adapter_->GetPersonalCurveForTesting(), *personal_curve_);
 
-  scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+  thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(1));
 
   // Brightness is changed after the 1st ALS reading comes in.
   fake_als_reader_.ReportAmbientLightUpdate(10);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(test_observer_.num_changes(), 1);
 
   // Another ALS value is received in 1 sec, brightness is changed because it
   // exceeds immediate transition threshold.
-  scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+  thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(1));
   fake_als_reader_.ReportAmbientLightUpdate(17);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(test_observer_.num_changes(), 2);
 
   // Another ALS value is received in 2 sec, brightness is changed because it
   // exceeds immediate transition threshold.
-  scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(2));
+  thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(2));
   fake_als_reader_.ReportAmbientLightUpdate(1);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(test_observer_.num_changes(), 3);
 }
 
@@ -536,20 +533,20 @@
 
   EXPECT_EQ(adapter_->GetStatusForTesting(), Adapter::Status::kSuccess);
 
-  scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+  thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(1));
 
   // 1st ALS reading doesn't trigger a brightness change.
   fake_als_reader_.ReportAmbientLightUpdate(10);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(test_observer_.num_changes(), 0);
 
-  scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(5));
+  thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(5));
   EXPECT_EQ(test_observer_.num_changes(), 0);
 
   // 2nd ALS comes in so that we have |kAmbientLightShortHorizonSeconds| of
   // data, hence brightness is changed.
   fake_als_reader_.ReportAmbientLightUpdate(20);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(test_observer_.num_changes(), 1);
 }
 
@@ -565,17 +562,17 @@
 
   // ALS comes in but no brightness change is triggered because there is no
   // personal curve.
-  scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+  thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(1));
   fake_als_reader_.ReportAmbientLightUpdate(10);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(test_observer_.num_changes(), 0);
 
   // Personal curve is received.
-  scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+  thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(1));
   fake_modeller_.ReportModelTrained(*personal_curve_);
   EXPECT_EQ(test_observer_.num_changes(), 0);
   fake_als_reader_.ReportAmbientLightUpdate(20);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(test_observer_.num_changes(), 1);
   EXPECT_EQ(test_observer_.GetCause(),
             power_manager::BacklightBrightnessChange_Cause_MODEL);
@@ -598,9 +595,9 @@
 
   EXPECT_EQ(adapter_->GetStatusForTesting(), Adapter::Status::kSuccess);
 
-  scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+  thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(1));
   fake_als_reader_.ReportAmbientLightUpdate(10);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(test_observer_.num_changes(), 1);
   EXPECT_DOUBLE_EQ(adapter_->GetAverageAmbientForTesting(), 10);
 
@@ -610,10 +607,10 @@
                    expected_brightness_percent1);
 
   // A new personal curve is received but adapter still uses the global curve.
-  scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(20));
+  thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(20));
   fake_modeller_.ReportModelTrained(*personal_curve_);
   fake_als_reader_.ReportAmbientLightUpdate(20);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(test_observer_.num_changes(), 2);
   EXPECT_EQ(test_observer_.GetCause(),
             power_manager::BacklightBrightnessChange_Cause_MODEL);
@@ -634,9 +631,9 @@
 
   EXPECT_EQ(adapter_->GetStatusForTesting(), Adapter::Status::kSuccess);
 
-  scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+  thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(1));
   fake_als_reader_.ReportAmbientLightUpdate(10);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(test_observer_.num_changes(), 0);
 }
 
@@ -653,11 +650,11 @@
   EXPECT_TRUE(adapter_->GetGlobalCurveForTesting());
   EXPECT_TRUE(adapter_->GetPersonalCurveForTesting());
 
-  scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+  thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(1));
 
   // Brightness not changed after the 1st ALS reading comes in.
   fake_als_reader_.ReportAmbientLightUpdate(10);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(test_observer_.num_changes(), 0);
 }
 
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/modeller_impl_unittest.cc b/chrome/browser/chromeos/power/auto_screen_brightness/modeller_impl_unittest.cc
index d71dea1..87a40ab 100644
--- a/chrome/browser/chromeos/power/auto_screen_brightness/modeller_impl_unittest.cc
+++ b/chrome/browser/chromeos/power/auto_screen_brightness/modeller_impl_unittest.cc
@@ -175,9 +175,8 @@
 class ModellerImplTest : public testing::Test {
  public:
   ModellerImplTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
-        thread_bundle_(content::TestBrowserThreadBundle::PLAIN_MAINLOOP) {
+      : thread_bundle_(
+            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {
     CHECK(temp_dir_.CreateUniqueTempDir());
     TestingProfile::Builder profile_builder;
     profile_builder.SetProfileName("testuser@gmail.com");
@@ -197,7 +196,7 @@
         std::make_unique<FakeTrainer>(is_trainer_configured,
                                       is_personal_curve_valid),
         base::SequencedTaskRunnerHandle::Get(),
-        scoped_task_environment_.GetMockTickClock());
+        thread_bundle_.GetMockTickClock());
 
     test_observer_ = std::make_unique<TestObserver>();
     modeller_->AddObserver(test_observer_.get());
@@ -210,7 +209,7 @@
     fake_als_reader_.set_als_init_status(als_reader_status);
     fake_brightness_monitor_.set_status(brightness_monitor_status);
     SetUpModeller(is_trainer_configured, is_personal_curve_valid);
-    scoped_task_environment_.RunUntilIdle();
+    thread_bundle_.RunUntilIdle();
   }
 
  protected:
@@ -227,7 +226,6 @@
         << " to " << curve_path;
   }
 
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
   content::TestBrowserThreadBundle thread_bundle_;
   base::HistogramTester histogram_tester_;
 
@@ -277,7 +275,7 @@
 
   fake_als_reader_.set_als_init_status(AlsReader::AlsInitStatus::kDisabled);
   fake_als_reader_.ReportReaderInitialized();
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
 
   test_observer_->CheckStatus(true /* is_model_initialized */,
                               base::nullopt /* global_curve */,
@@ -295,7 +293,7 @@
 
   fake_als_reader_.set_als_init_status(AlsReader::AlsInitStatus::kSuccess);
   fake_als_reader_.ReportReaderInitialized();
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
 
   test_observer_->CheckStatus(true /* is_model_initialized */,
                               modeller_->GetGlobalCurveForTesting(),
@@ -330,7 +328,7 @@
 
   fake_brightness_monitor_.set_status(BrightnessMonitor::Status::kSuccess);
   fake_brightness_monitor_.ReportBrightnessMonitorInitialized();
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
 
   test_observer_->CheckStatus(true /* is_model_initialized */,
                               modeller_->GetGlobalCurveForTesting(),
@@ -354,7 +352,7 @@
 
   WriteCurveToFile(curve);
 
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
 
   Init(AlsReader::AlsInitStatus::kSuccess, BrightnessMonitor::Status::kSuccess);
 
@@ -374,7 +372,7 @@
 
   WriteCurveToFile(curve);
 
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
 
   Init(AlsReader::AlsInitStatus::kSuccess, BrightnessMonitor::Status::kSuccess,
        true /* is_trainer_configured */, false /* is_personal_curve_valid */);
@@ -429,10 +427,8 @@
   for (size_t i = 0; i < modeller_->GetMaxTrainingDataPointsForTesting() - 1;
        ++i) {
     EXPECT_EQ(i, modeller_->NumberTrainingDataPointsForTesting());
-    scoped_task_environment_.FastForwardBy(
-        base::TimeDelta::FromMilliseconds(1));
-    const base::TimeTicks now =
-        scoped_task_environment_.GetMockTickClock()->NowTicks();
+    thread_bundle_.FastForwardBy(base::TimeDelta::FromMilliseconds(1));
+    const base::TimeTicks now = thread_bundle_.GetMockTickClock()->NowTicks();
     const int lux = i * 20;
     fake_als_reader_.ReportAmbientLightUpdate(lux);
     const double brightness_old = 10.0 + i;
@@ -448,16 +444,15 @@
             modeller_->NumberTrainingDataPointsForTesting());
 
   // Add one more data point to trigger the training early.
-  scoped_task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(1));
-  const base::TimeTicks now =
-      scoped_task_environment_.GetMockTickClock()->NowTicks();
+  thread_bundle_.FastForwardBy(base::TimeDelta::FromMilliseconds(1));
+  const base::TimeTicks now = thread_bundle_.GetMockTickClock()->NowTicks();
   const double brightness_old = 85;
   const double brightness_new = 95;
   modeller_->OnUserBrightnessChanged(brightness_old, brightness_new);
   expected_data.push_back({brightness_old, brightness_new,
                            ConvertToLog(modeller_->AverageAmbientForTesting()),
                            now});
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
 
   EXPECT_EQ(0u, modeller_->NumberTrainingDataPointsForTesting());
 
@@ -482,10 +477,8 @@
   std::vector<TrainingDataPoint> expected_data;
   for (size_t i = 0; i < 10; ++i) {
     EXPECT_EQ(i, modeller_->NumberTrainingDataPointsForTesting());
-    scoped_task_environment_.FastForwardBy(
-        base::TimeDelta::FromMilliseconds(1));
-    const base::TimeTicks now =
-        scoped_task_environment_.GetMockTickClock()->NowTicks();
+    thread_bundle_.FastForwardBy(base::TimeDelta::FromMilliseconds(1));
+    const base::TimeTicks now = thread_bundle_.GetMockTickClock()->NowTicks();
     const int lux = i * 20;
     fake_als_reader_.ReportAmbientLightUpdate(lux);
     const double brightness_old = 10.0 + i;
@@ -498,30 +491,24 @@
 
   EXPECT_EQ(modeller_->NumberTrainingDataPointsForTesting(), 10u);
 
-  scoped_task_environment_.FastForwardBy(
-      modeller_->GetTrainingDelayForTesting() / 2);
+  thread_bundle_.FastForwardBy(modeller_->GetTrainingDelayForTesting() / 2);
   // A user activity is received, timer should be reset.
   const ui::MouseEvent mouse_event(ui::ET_MOUSE_EXITED, gfx::Point(0, 0),
                                    gfx::Point(0, 0), base::TimeTicks(), 0, 0);
   modeller_->OnUserActivity(&mouse_event);
 
-  scoped_task_environment_.FastForwardBy(
-      modeller_->GetTrainingDelayForTesting() / 3);
+  thread_bundle_.FastForwardBy(modeller_->GetTrainingDelayForTesting() / 3);
   EXPECT_EQ(modeller_->NumberTrainingDataPointsForTesting(), 10u);
 
   // Another user event is received.
   modeller_->OnUserActivity(&mouse_event);
 
   // After |training_delay_|/2, no training has started.
-  scoped_task_environment_.FastForwardBy(
-      modeller_->GetTrainingDelayForTesting() / 2);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.FastForwardBy(modeller_->GetTrainingDelayForTesting() / 2);
   EXPECT_EQ(modeller_->NumberTrainingDataPointsForTesting(), 10u);
 
   // After another |training_delay_|/2, training is scheduled.
-  scoped_task_environment_.FastForwardBy(
-      modeller_->GetTrainingDelayForTesting() / 2);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.FastForwardBy(modeller_->GetTrainingDelayForTesting() / 2);
 
   EXPECT_EQ(0u, modeller_->NumberTrainingDataPointsForTesting());
   const base::Optional<MonotoneCubicSpline>& result_curve =
@@ -598,7 +585,7 @@
   modeller_->OnUserActivity(&mouse_event);
 
   modeller_->OnUserBrightnessChanged(10, 20);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_EQ(0u, modeller_->NumberTrainingDataPointsForTesting());
   EXPECT_TRUE(test_observer_->trained_curve_received());
 }
diff --git a/chrome/browser/chromeos/system_logs/single_debug_daemon_log_source_unittest.cc b/chrome/browser/chromeos/system_logs/single_debug_daemon_log_source_unittest.cc
index 3a884e6..e377101b 100644
--- a/chrome/browser/chromeos/system_logs/single_debug_daemon_log_source_unittest.cc
+++ b/chrome/browser/chromeos/system_logs/single_debug_daemon_log_source_unittest.cc
@@ -10,7 +10,6 @@
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_debug_daemon_client.h"
 #include "content/public/test/test_browser_thread_bundle.h"
@@ -22,10 +21,7 @@
 
 class SingleDebugDaemonLogSourceTest : public ::testing::Test {
  public:
-  SingleDebugDaemonLogSourceTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI),
-        num_callback_calls_(0) {}
+  SingleDebugDaemonLogSourceTest() : num_callback_calls_(0) {}
 
   void SetUp() override {
     // Since no debug daemon will be available during a unit test, use
@@ -57,11 +53,7 @@
     response_ = *response;
   }
 
-  // For running scheduled tasks.
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-
-  // Creates the necessary browser threads. Defined after
-  // |scoped_task_environment_| in order to use the MessageLoop it created.
+  // Creates the necessary browser threads.
   content::TestBrowserThreadBundle browser_thread_bundle_;
 
   // Used to verify that OnFetchComplete was called the correct number of times.
diff --git a/chrome/browser/chromeos/system_logs/single_log_file_log_source_unittest.cc b/chrome/browser/chromeos/system_logs/single_log_file_log_source_unittest.cc
index 1d2eb893..60c1a44 100644
--- a/chrome/browser/chromeos/system_logs/single_log_file_log_source_unittest.cc
+++ b/chrome/browser/chromeos/system_logs/single_log_file_log_source_unittest.cc
@@ -14,7 +14,6 @@
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/strings/string_split.h"
-#include "base/test/scoped_task_environment.h"
 #include "base/time/time.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -23,10 +22,7 @@
 
 class SingleLogFileLogSourceTest : public ::testing::Test {
  public:
-  SingleLogFileLogSourceTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI),
-        num_callback_calls_(0) {
+  SingleLogFileLogSourceTest() : num_callback_calls_(0) {
     InitializeTestLogDir();
   }
 
@@ -93,7 +89,7 @@
   void FetchFromSource() {
     source_->Fetch(base::Bind(&SingleLogFileLogSourceTest::OnFileRead,
                               base::Unretained(this)));
-    scoped_task_environment_.RunUntilIdle();
+    browser_thread_bundle_.RunUntilIdle();
   }
 
   // Callback for fetching logs from |source_|. Overwrites the previous stored
@@ -116,11 +112,7 @@
   const base::FilePath& log_file_path() const { return log_file_path_; }
 
  private:
-  // For running scheduled tasks.
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-
-  // Creates the necessary browser threads. Defined after
-  // |scoped_task_environment_| in order to use the MessageLoop it created.
+  // Creates the necessary browser threads.
   content::TestBrowserThreadBundle browser_thread_bundle_;
 
   // Unit under test.
diff --git a/chrome/browser/extensions/api/image_writer_private/operation_unittest.cc b/chrome/browser/extensions/api/image_writer_private/operation_unittest.cc
index 2d3d0c3..4f9e77a41 100644
--- a/chrome/browser/extensions/api/image_writer_private/operation_unittest.cc
+++ b/chrome/browser/extensions/api/image_writer_private/operation_unittest.cc
@@ -119,7 +119,7 @@
 
     // Cancel() will ensure we Shutdown() FakeImageWriterClient.
     operation_->Cancel();
-    scoped_task_environment_.RunUntilIdle();
+    thread_bundle_.RunUntilIdle();
 
     ImageWriterUnitTestBase::TearDown();
   }
diff --git a/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos_unittest.cc b/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos_unittest.cc
index bbbea6d..91fd7c8 100644
--- a/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos_unittest.cc
+++ b/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos_unittest.cc
@@ -6,7 +6,6 @@
 
 #include "base/bind.h"
 #include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
 #include "chrome/browser/extensions/api/image_writer_private/removable_storage_provider.h"
 #include "chromeos/disks/mock_disk_mount_manager.h"
 #include "content/public/test/test_browser_thread_bundle.h"
@@ -35,9 +34,7 @@
 
 class RemovableStorageProviderChromeOsUnitTest : public testing::Test {
  public:
-  RemovableStorageProviderChromeOsUnitTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+  RemovableStorageProviderChromeOsUnitTest() {}
   void SetUp() override {
     disk_mount_manager_mock_ = new MockDiskMountManager();
     DiskMountManager::InitializeForTesting(disk_mount_manager_mock_);
@@ -107,12 +104,9 @@
     EXPECT_EQ(capacity, device->capacity);
   }
 
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  content::TestBrowserThreadBundle thread_bundle_;
   MockDiskMountManager* disk_mount_manager_mock_;
   scoped_refptr<StorageDeviceList> devices_;
-
- private:
-  content::TestBrowserThreadBundle thread_bundle_;
 };
 
 }  // namespace
@@ -131,7 +125,7 @@
       base::Bind(&RemovableStorageProviderChromeOsUnitTest::DevicesCallback,
                  base::Unretained(this)));
 
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
 
   ASSERT_EQ(2U, devices_->data.size());
 
@@ -152,7 +146,7 @@
       base::Bind(&RemovableStorageProviderChromeOsUnitTest::DevicesCallback,
                  base::Unretained(this)));
 
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
 
   ASSERT_EQ(2U, devices_->data.size());
 
diff --git a/chrome/browser/extensions/api/image_writer_private/test_utils.cc b/chrome/browser/extensions/api/image_writer_private/test_utils.cc
index f6d4020..6415a69c 100644
--- a/chrome/browser/extensions/api/image_writer_private/test_utils.cc
+++ b/chrome/browser/extensions/api/image_writer_private/test_utils.cc
@@ -315,9 +315,9 @@
 }
 
 ImageWriterUnitTestBase::ImageWriterUnitTestBase()
-    : scoped_task_environment_(
-          base::test::ScopedTaskEnvironment::MainThreadType::UI),
-      thread_bundle_(content::TestBrowserThreadBundle::REAL_IO_THREAD) {}
+    : thread_bundle_(base::test::ScopedTaskEnvironment::MainThreadType::UI,
+                     base::test::ScopedTaskEnvironment::ExecutionMode::ASYNC,
+                     content::TestBrowserThreadBundle::REAL_IO_THREAD) {}
 ImageWriterUnitTestBase::~ImageWriterUnitTestBase() {
 }
 
diff --git a/chrome/browser/extensions/api/image_writer_private/test_utils.h b/chrome/browser/extensions/api/image_writer_private/test_utils.h
index aa039798..ab9f77a 100644
--- a/chrome/browser/extensions/api/image_writer_private/test_utils.h
+++ b/chrome/browser/extensions/api/image_writer_private/test_utils.h
@@ -204,9 +204,6 @@
 
   ImageWriterTestUtils test_utils_;
 
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-
- private:
   content::TestBrowserThreadBundle thread_bundle_;
 };
 
diff --git a/chrome/browser/extensions/browser_context_keyed_service_factories.cc b/chrome/browser/extensions/browser_context_keyed_service_factories.cc
index b72a34e..966d4347 100644
--- a/chrome/browser/extensions/browser_context_keyed_service_factories.cc
+++ b/chrome/browser/extensions/browser_context_keyed_service_factories.cc
@@ -50,7 +50,6 @@
 #include "ppapi/buildflags/buildflags.h"
 
 #if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/extensions/arc_apps_private_api.h"
 #include "chrome/browser/chromeos/extensions/file_manager/event_router_factory.h"
 #include "chrome/browser/chromeos/extensions/input_method_api.h"
 #include "chrome/browser/chromeos/extensions/media_player_api.h"
@@ -72,9 +71,6 @@
 void EnsureBrowserContextKeyedServiceFactoriesBuilt() {
   extensions::ActivityLog::GetFactoryInstance();
   extensions::ActivityLogAPI::GetFactoryInstance();
-#if defined(OS_CHROMEOS)
-  extensions::ArcAppsPrivateAPI::GetFactoryInstance();
-#endif
   extensions::AutofillPrivateEventRouterFactory::GetInstance();
   extensions::BluetoothLowEnergyAPI::GetFactoryInstance();
   extensions::BookmarksAPI::GetFactoryInstance();
diff --git a/chrome/browser/extensions/external_registry_loader_win_unittest.cc b/chrome/browser/extensions/external_registry_loader_win_unittest.cc
index 6c11456..40143e6a 100644
--- a/chrome/browser/extensions/external_registry_loader_win_unittest.cc
+++ b/chrome/browser/extensions/external_registry_loader_win_unittest.cc
@@ -8,7 +8,6 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
 #include "base/values.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/common/value_builder.h"
@@ -67,16 +66,13 @@
 
 class ExternalRegistryLoaderUnittest : public testing::Test {
  public:
-  ExternalRegistryLoaderUnittest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+  ExternalRegistryLoaderUnittest() {}
   ~ExternalRegistryLoaderUnittest() override {}
 
  protected:
-  void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
+  void RunUntilIdle() { thread_bundle_.RunUntilIdle(); }
 
  private:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
   content::TestBrowserThreadBundle thread_bundle_;
 
   DISALLOW_COPY_AND_ASSIGN(ExternalRegistryLoaderUnittest);
diff --git a/chrome/browser/extensions/window_open_apitest.cc b/chrome/browser/extensions/window_open_apitest.cc
index 1a4a8bc1..fbb1df01 100644
--- a/chrome/browser/extensions/window_open_apitest.cc
+++ b/chrome/browser/extensions/window_open_apitest.cc
@@ -461,13 +461,17 @@
                                       "updateWindowToLockedFullscreen"))
       << message_;
 
-  // IDC_EXIT is not enabled in locked fullscreen.
+  // IDC_EXIT should always be disabled in locked fullscreen.
   EXPECT_FALSE(browser()->command_controller()->IsCommandEnabled(IDC_EXIT));
 
+  // Some other disabled commands.
+  EXPECT_FALSE(browser()->command_controller()->IsCommandEnabled(IDC_FIND));
+  EXPECT_FALSE(
+      browser()->command_controller()->IsCommandEnabled(IDC_ZOOM_PLUS));
+
   // Verify some whitelisted commands.
   EXPECT_TRUE(browser()->command_controller()->IsCommandEnabled(IDC_COPY));
-  EXPECT_TRUE(browser()->command_controller()->IsCommandEnabled(IDC_FIND));
-  EXPECT_TRUE(browser()->command_controller()->IsCommandEnabled(IDC_ZOOM_PLUS));
+  EXPECT_TRUE(browser()->command_controller()->IsCommandEnabled(IDC_PASTE));
 }
 
 IN_PROC_BROWSER_TEST_F(WindowOpenApiTest,
diff --git a/chrome/browser/favicon/content_favicon_driver_browsertest.cc b/chrome/browser/favicon/content_favicon_driver_browsertest.cc
index efc0766..07f3dbb 100644
--- a/chrome/browser/favicon/content_favicon_driver_browsertest.cc
+++ b/chrome/browser/favicon/content_favicon_driver_browsertest.cc
@@ -713,7 +713,7 @@
 
   // Observe the message for a blocked favicon.
   content::ConsoleObserverDelegate console_observer(web_contents(),
-                                                    "*insecure*");
+                                                    "*icon.png*");
   web_contents()->SetDelegate(&console_observer);
 
   // Observe if the favicon URL is requested.
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index daf3cd79..f653fcee 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -1319,11 +1319,6 @@
     "expiry_milestone": 75
   },
   {
-    "name": "enable-improved-language-settings",
-    // "owners": [ "your-team" ],
-    "expiry_milestone": 76
-  },
-  {
     "name": "enable-improved-geolanguage-data",
     "owners": [ "frechette", "chrome-language@google.com" ],
     "expiry_milestone": 76
diff --git a/chrome/browser/google/google_search_domain_mixing_metrics_emitter_unittest.cc b/chrome/browser/google/google_search_domain_mixing_metrics_emitter_unittest.cc
index 322fbc9..4674699 100644
--- a/chrome/browser/google/google_search_domain_mixing_metrics_emitter_unittest.cc
+++ b/chrome/browser/google/google_search_domain_mixing_metrics_emitter_unittest.cc
@@ -6,7 +6,6 @@
 
 #include "base/files/scoped_temp_dir.h"
 #include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_task_environment.h"
 #include "base/test/simple_test_clock.h"
 #include "base/timer/mock_timer.h"
 #include "components/history/core/browser/history_service.h"
@@ -20,9 +19,8 @@
 class GoogleSearchDomainMixingMetricsEmitterTest : public testing::Test {
  public:
   GoogleSearchDomainMixingMetricsEmitterTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
-        thread_bundle_(content::TestBrowserThreadBundle::PLAIN_MAINLOOP) {}
+      : thread_bundle_(
+            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {}
 
   void SetUp() override {
     GoogleSearchDomainMixingMetricsEmitter::RegisterProfilePrefs(
@@ -44,7 +42,7 @@
     emitter_->SetTimerForTesting(std::move(timer));
 
     emitter_->SetUIThreadTaskRunnerForTesting(
-        scoped_task_environment_.GetMainThreadTaskRunner());
+        thread_bundle_.GetMainThreadTaskRunner());
   }
 
   // Sets up test history such that domain mixing metrics for the day starting
@@ -79,7 +77,6 @@
   }
 
  protected:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
   content::TestBrowserThreadBundle thread_bundle_;
   TestingPrefServiceSimple prefs_;
   base::ScopedTempDir history_dir_;
@@ -107,7 +104,7 @@
   // The next metric calculation should be scheduled at 4am on the next day,
   // i.e. 16 hours from |now|.
   EXPECT_EQ(base::TimeDelta::FromHours(16),
-            scoped_task_environment_.NextMainThreadPendingTaskDelay());
+            thread_bundle_.NextMainThreadPendingTaskDelay());
 }
 
 TEST_F(GoogleSearchDomainMixingMetricsEmitterTest, Waits10SecondsAfterStart) {
@@ -121,7 +118,7 @@
   emitter_->Start();
 
   EXPECT_EQ(base::TimeDelta::FromSeconds(10),
-            scoped_task_environment_.NextMainThreadPendingTaskDelay());
+            thread_bundle_.NextMainThreadPendingTaskDelay());
 }
 
 TEST_F(GoogleSearchDomainMixingMetricsEmitterTest, WaitsUntilNeeded) {
@@ -136,7 +133,7 @@
   emitter_->Start();
 
   EXPECT_EQ(base::TimeDelta::FromHours(23),
-            scoped_task_environment_.NextMainThreadPendingTaskDelay());
+            thread_bundle_.NextMainThreadPendingTaskDelay());
 }
 
 TEST_F(GoogleSearchDomainMixingMetricsEmitterTest, EmitsMetricsOnStart) {
@@ -156,7 +153,7 @@
   emitter_->Start();
 
   base::HistogramTester tester;
-  scoped_task_environment_.FastForwardUntilNoTasksRemain();
+  thread_bundle_.FastForwardUntilNoTasksRemain();
   BlockUntilHistoryProcessesPendingRequests(history_service_.get());
   VerifyHistograms(tester);
 }
@@ -178,7 +175,7 @@
   emitter_->Start();
 
   // Wait for the first run to be done.
-  scoped_task_environment_.FastForwardUntilNoTasksRemain();
+  thread_bundle_.FastForwardUntilNoTasksRemain();
   BlockUntilHistoryProcessesPendingRequests(history_service_.get());
 
   // last_metrics_time is expected to have been incremented.
@@ -199,7 +196,7 @@
   timer_->Fire();
 
   base::HistogramTester tester;
-  scoped_task_environment_.FastForwardUntilNoTasksRemain();
+  thread_bundle_.FastForwardUntilNoTasksRemain();
   BlockUntilHistoryProcessesPendingRequests(history_service_.get());
   VerifyHistograms(tester);
 
diff --git a/chrome/browser/history/history_browsertest.cc b/chrome/browser/history/history_browsertest.cc
index c57a386..633fd850 100644
--- a/chrome/browser/history/history_browsertest.cc
+++ b/chrome/browser/history/history_browsertest.cc
@@ -25,6 +25,7 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/history/core/browser/history_db_task.h"
 #include "components/history/core/browser/history_service.h"
+#include "components/history/core/common/pref_names.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/render_frame_host.h"
diff --git a/chrome/browser/history/history_service_factory.cc b/chrome/browser/history/history_service_factory.cc
index ed1fd9b..3ef673e 100644
--- a/chrome/browser/history/history_service_factory.cc
+++ b/chrome/browser/history/history_service_factory.cc
@@ -14,6 +14,7 @@
 #include "components/history/content/browser/history_database_helper.h"
 #include "components/history/core/browser/history_database_params.h"
 #include "components/history/core/browser/history_service.h"
+#include "components/history/core/common/pref_names.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/keyed_service/core/service_access_type.h"
 #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/media/router/discovery/discovery_network_monitor_metric_observer_unittest.cc b/chrome/browser/media/router/discovery/discovery_network_monitor_metric_observer_unittest.cc
index 34b47d1..23ace4c 100644
--- a/chrome/browser/media/router/discovery/discovery_network_monitor_metric_observer_unittest.cc
+++ b/chrome/browser/media/router/discovery/discovery_network_monitor_metric_observer_unittest.cc
@@ -61,13 +61,12 @@
 class DiscoveryNetworkMonitorMetricObserverTest : public ::testing::Test {
  public:
   DiscoveryNetworkMonitorMetricObserverTest()
-      : scoped_task_environment_(
+      : thread_bundle_(
             base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
-        thread_bundle_(content::TestBrowserThreadBundle::PLAIN_MAINLOOP),
-        start_ticks_(scoped_task_environment_.NowTicks()),
+        start_ticks_(thread_bundle_.NowTicks()),
         metrics_(std::make_unique<MockMetrics>()),
         mock_metrics_(metrics_.get()),
-        metric_observer_(scoped_task_environment_.GetMockTickClock(),
+        metric_observer_(thread_bundle_.GetMockTickClock(),
                          std::move(metrics_)) {
     SetConnectionType(network::mojom::ConnectionType::CONNECTION_NONE);
   }
@@ -78,7 +77,6 @@
         connection_type);
   }
 
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
   content::TestBrowserThreadBundle thread_bundle_;
   base::TimeDelta time_advance_ = base::TimeDelta::FromMilliseconds(10);
   const base::TimeTicks start_ticks_;
@@ -166,8 +164,7 @@
   metric_observer_.OnNetworksChanged(
       DiscoveryNetworkMonitor::kNetworkIdDisconnected);
 
-  scoped_task_environment_.FastForwardUntilNoTasksRemain();
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.FastForwardUntilNoTasksRemain();
 }
 
 TEST_F(DiscoveryNetworkMonitorMetricObserverTest,
@@ -191,8 +188,7 @@
       RecordConnectionType(DiscoveryNetworkMonitorConnectionType::kEthernet));
   metric_observer_.OnNetworksChanged("network2");
 
-  scoped_task_environment_.FastForwardUntilNoTasksRemain();
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.FastForwardUntilNoTasksRemain();
 }
 
 TEST_F(DiscoveryNetworkMonitorMetricObserverTest,
@@ -209,8 +205,7 @@
       RecordConnectionType(DiscoveryNetworkMonitorConnectionType::kEthernet));
   metric_observer_.OnNetworksChanged("network2");
 
-  scoped_task_environment_.FastForwardUntilNoTasksRemain();
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.FastForwardUntilNoTasksRemain();
 }
 
 TEST_F(DiscoveryNetworkMonitorMetricObserverTest,
@@ -222,12 +217,12 @@
   SetConnectionType(network::mojom::ConnectionType::CONNECTION_ETHERNET);
   metric_observer_.OnNetworksChanged("network1");
 
-  scoped_task_environment_.FastForwardBy(time_advance_);
+  thread_bundle_.FastForwardBy(time_advance_);
   SetConnectionType(network::mojom::ConnectionType::CONNECTION_NONE);
   metric_observer_.OnNetworksChanged(
       DiscoveryNetworkMonitor::kNetworkIdDisconnected);
 
-  scoped_task_environment_.FastForwardBy(time_advance_);
+  thread_bundle_.FastForwardBy(time_advance_);
   SetConnectionType(network::mojom::ConnectionType::CONNECTION_ETHERNET);
   EXPECT_CALL(*mock_metrics_,
               RecordTimeBetweenNetworkChangeEvents(
@@ -237,8 +232,7 @@
       RecordConnectionType(DiscoveryNetworkMonitorConnectionType::kEthernet));
   metric_observer_.OnNetworksChanged("network2");
 
-  scoped_task_environment_.FastForwardUntilNoTasksRemain();
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.FastForwardUntilNoTasksRemain();
 }
 
 TEST_F(DiscoveryNetworkMonitorMetricObserverTest,
@@ -250,12 +244,12 @@
   SetConnectionType(network::mojom::ConnectionType::CONNECTION_ETHERNET);
   metric_observer_.OnNetworksChanged("network1");
 
-  scoped_task_environment_.FastForwardBy(time_advance_);
+  thread_bundle_.FastForwardBy(time_advance_);
   SetConnectionType(network::mojom::ConnectionType::CONNECTION_NONE);
   metric_observer_.OnNetworksChanged(
       DiscoveryNetworkMonitor::kNetworkIdDisconnected);
 
-  scoped_task_environment_.FastForwardBy(time_advance_);
+  thread_bundle_.FastForwardBy(time_advance_);
   EXPECT_CALL(*mock_metrics_,
               RecordTimeBetweenNetworkChangeEvents(
                   (start_ticks_ + time_advance_) - start_ticks_));
@@ -263,8 +257,7 @@
               RecordConnectionType(
                   DiscoveryNetworkMonitorConnectionType::kDisconnected));
 
-  scoped_task_environment_.FastForwardUntilNoTasksRemain();
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.FastForwardUntilNoTasksRemain();
 }
 
 TEST_F(DiscoveryNetworkMonitorMetricObserverTest,
@@ -276,13 +269,13 @@
   SetConnectionType(network::mojom::ConnectionType::CONNECTION_ETHERNET);
   metric_observer_.OnNetworksChanged("network1");
 
-  scoped_task_environment_.FastForwardBy(time_advance_);
-  const auto disconnect_ticks = scoped_task_environment_.NowTicks();
+  thread_bundle_.FastForwardBy(time_advance_);
+  const auto disconnect_ticks = thread_bundle_.NowTicks();
   SetConnectionType(network::mojom::ConnectionType::CONNECTION_NONE);
   metric_observer_.OnNetworksChanged(
       DiscoveryNetworkMonitor::kNetworkIdDisconnected);
 
-  scoped_task_environment_.FastForwardBy(time_advance_);
+  thread_bundle_.FastForwardBy(time_advance_);
   EXPECT_CALL(*mock_metrics_,
               RecordTimeBetweenNetworkChangeEvents(
                   (start_ticks_ + time_advance_) - start_ticks_));
@@ -290,11 +283,10 @@
               RecordConnectionType(
                   DiscoveryNetworkMonitorConnectionType::kDisconnected));
 
-  scoped_task_environment_.FastForwardUntilNoTasksRemain();
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.FastForwardUntilNoTasksRemain();
 
-  scoped_task_environment_.FastForwardBy(time_advance_);
-  const auto second_ethernet_ticks = scoped_task_environment_.NowTicks();
+  thread_bundle_.FastForwardBy(time_advance_);
+  const auto second_ethernet_ticks = thread_bundle_.NowTicks();
   EXPECT_CALL(*mock_metrics_, RecordTimeBetweenNetworkChangeEvents(
                                   second_ethernet_ticks - disconnect_ticks));
   EXPECT_CALL(
diff --git a/chrome/browser/media/router/issue_manager_unittest.cc b/chrome/browser/media/router/issue_manager_unittest.cc
index 23e5fd7..87c8f74 100644
--- a/chrome/browser/media/router/issue_manager_unittest.cc
+++ b/chrome/browser/media/router/issue_manager_unittest.cc
@@ -31,14 +31,12 @@
 class IssueManagerTest : public ::testing::Test {
  protected:
   IssueManagerTest()
-      : environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
-        thread_bundle_(content::TestBrowserThreadBundle::PLAIN_MAINLOOP) {
-    manager_.set_task_runner_for_test(environment_.GetMainThreadTaskRunner());
+      : thread_bundle_(
+            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {
+    manager_.set_task_runner_for_test(thread_bundle_.GetMainThreadTaskRunner());
   }
   ~IssueManagerTest() override {}
 
-  base::test::ScopedTaskEnvironment environment_;
   content::TestBrowserThreadBundle thread_bundle_;
   IssueManager manager_;
 };
@@ -112,8 +110,8 @@
   EXPECT_CALL(observer, OnIssuesCleared()).Times(1);
   base::TimeDelta timeout = IssueManager::GetAutoDismissTimeout(issue_info1);
   EXPECT_FALSE(timeout.is_zero());
-  EXPECT_TRUE(environment_.MainThreadHasPendingTask());
-  environment_.FastForwardBy(timeout);
+  EXPECT_TRUE(thread_bundle_.MainThreadHasPendingTask());
+  thread_bundle_.FastForwardBy(timeout);
 
   EXPECT_CALL(observer, OnIssue(_)).Times(1);
   IssueInfo issue_info2 = CreateTestIssue(IssueInfo::Severity::WARNING);
@@ -122,9 +120,9 @@
   EXPECT_CALL(observer, OnIssuesCleared()).Times(1);
   timeout = IssueManager::GetAutoDismissTimeout(issue_info2);
   EXPECT_FALSE(timeout.is_zero());
-  EXPECT_TRUE(environment_.MainThreadHasPendingTask());
-  environment_.FastForwardBy(timeout);
-  EXPECT_FALSE(environment_.MainThreadHasPendingTask());
+  EXPECT_TRUE(thread_bundle_.MainThreadHasPendingTask());
+  thread_bundle_.FastForwardBy(timeout);
+  EXPECT_FALSE(thread_bundle_.MainThreadHasPendingTask());
 }
 
 TEST_F(IssueManagerTest, IssueAutoDismissNoopsIfAlreadyCleared) {
@@ -138,13 +136,13 @@
   ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&observer));
 
   EXPECT_CALL(observer, OnIssuesCleared()).Times(1);
-  EXPECT_TRUE(environment_.MainThreadHasPendingTask());
+  EXPECT_TRUE(thread_bundle_.MainThreadHasPendingTask());
   manager_.ClearIssue(issue1.id());
 
   EXPECT_CALL(observer, OnIssuesCleared()).Times(0);
   base::TimeDelta timeout = IssueManager::GetAutoDismissTimeout(issue_info1);
   EXPECT_FALSE(timeout.is_zero());
-  EXPECT_FALSE(environment_.MainThreadHasPendingTask());
+  EXPECT_FALSE(thread_bundle_.MainThreadHasPendingTask());
 }
 
 TEST_F(IssueManagerTest, BlockingIssuesDoNotGetAutoDismissed) {
@@ -160,7 +158,7 @@
 
   base::TimeDelta timeout = IssueManager::GetAutoDismissTimeout(issue_info1);
   EXPECT_TRUE(timeout.is_zero());
-  EXPECT_FALSE(environment_.MainThreadHasPendingTask());
+  EXPECT_FALSE(thread_bundle_.MainThreadHasPendingTask());
 
   // FATAL issues are always blocking.
   IssueInfo issue_info2 = CreateTestIssue(IssueInfo::Severity::FATAL);
@@ -168,7 +166,7 @@
 
   timeout = IssueManager::GetAutoDismissTimeout(issue_info2);
   EXPECT_TRUE(timeout.is_zero());
-  EXPECT_FALSE(environment_.MainThreadHasPendingTask());
+  EXPECT_FALSE(thread_bundle_.MainThreadHasPendingTask());
 }
 
 TEST_F(IssueManagerTest, ClearNonBlockingIssues) {
diff --git a/chrome/browser/media/webrtc/native_desktop_media_list_unittest.cc b/chrome/browser/media/webrtc/native_desktop_media_list_unittest.cc
index bb892a6..e54a139 100644
--- a/chrome/browser/media/webrtc/native_desktop_media_list_unittest.cc
+++ b/chrome/browser/media/webrtc/native_desktop_media_list_unittest.cc
@@ -19,7 +19,6 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/media/webrtc/desktop_media_list_observer.h"
 #include "chrome/test/views/chrome_views_test_base.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
@@ -317,8 +316,6 @@
   }
 
  protected:
-  content::TestBrowserThreadBundle test_browser_thread_bundle_;
-
   // Must be listed before |model_|, so it's destroyed last.
   MockObserver observer_;
 
diff --git a/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac_unittest.mm b/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac_unittest.mm
index 0fa1af0..14eae35 100644
--- a/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac_unittest.mm
+++ b/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac_unittest.mm
@@ -14,7 +14,6 @@
 #include "base/macros.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
-#include "base/test/scoped_task_environment.h"
 #include "chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac.h"
 #include "components/storage_monitor/image_capture_device_manager.h"
 #include "components/storage_monitor/test_storage_monitor.h"
@@ -147,11 +146,7 @@
 
 class MTPDeviceDelegateImplMacTest : public testing::Test {
  public:
-  MTPDeviceDelegateImplMacTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI),
-        camera_(NULL),
-        delegate_(NULL) {}
+  MTPDeviceDelegateImplMacTest() : camera_(NULL), delegate_(NULL) {}
 
   void SetUp() override {
     storage_monitor::TestStorageMonitor* monitor =
@@ -233,7 +228,7 @@
       base::Bind(&MTPDeviceDelegateImplMacTest::OnError,
                  base::Unretained(this),
                  &wait));
-    scoped_task_environment_.RunUntilIdle();
+    test_browser_thread_bundle_.RunUntilIdle();
     EXPECT_TRUE(wait.IsSignaled());
     *info = info_;
     return error_;
@@ -248,7 +243,7 @@
                             base::Unretained(this), &wait),
         base::Bind(&MTPDeviceDelegateImplMacTest::OnError,
                    base::Unretained(this), &wait));
-    scoped_task_environment_.RunUntilIdle();
+    test_browser_thread_bundle_.RunUntilIdle();
     wait.Wait();
     return error_;
   }
@@ -266,13 +261,12 @@
         base::Bind(&MTPDeviceDelegateImplMacTest::OnError,
                    base::Unretained(this),
                    &wait));
-    scoped_task_environment_.RunUntilIdle();
+    test_browser_thread_bundle_.RunUntilIdle();
     wait.Wait();
     return error_;
   }
 
  protected:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
   content::TestBrowserThreadBundle test_browser_thread_bundle_;
 
   base::ScopedTempDir temp_dir_;
@@ -341,7 +335,7 @@
   // Signal the delegate that no files are coming.
   delegate_->NoMoreItems();
 
-  scoped_task_environment_.RunUntilIdle();
+  test_browser_thread_bundle_.RunUntilIdle();
   wait.Wait();
 
   EXPECT_EQ(base::File::FILE_OK, error_);
diff --git a/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc b/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc
index 194e7e88..797f419f 100644
--- a/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc
+++ b/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc
@@ -18,7 +18,6 @@
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
 #include "base/values.h"
 #include "build/build_config.h"
 #include "chrome/browser/extensions/test_extension_system.h"
@@ -111,10 +110,7 @@
       DeviceIdPrefIdsMap;
 
   MediaGalleriesPreferencesTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI),
-        profile_(new TestingProfile()),
-        default_galleries_count_(0) {}
+      : profile_(new TestingProfile()), default_galleries_count_(0) {}
 
   ~MediaGalleriesPreferencesTest() override {}
 
@@ -357,8 +353,6 @@
   MediaGalleriesPrefInfoMap expected_galleries_;
 
  private:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-
   // Needed for extension service & friends to work.
   content::TestBrowserThreadBundle thread_bundle_;
 
diff --git a/chrome/browser/metrics/thread_watcher_report_hang.cc b/chrome/browser/metrics/thread_watcher_report_hang.cc
index f954106..908fccb 100644
--- a/chrome/browser/metrics/thread_watcher_report_hang.cc
+++ b/chrome/browser/metrics/thread_watcher_report_hang.cc
@@ -41,15 +41,21 @@
 #endif  // !defined(OS_ANDROID)
 
 NOINLINE void ThreadUnresponsive_UI() {
+  ReportThreadHang();
+  // Defining |inhibit_comdat| *after* calling ReportThreadHang() prevents tail
+  // call optimization from not putting this function's address on the stack.
+  // https://crbug.com/905288#c10
   volatile int inhibit_comdat = __LINE__;
   ALLOW_UNUSED_LOCAL(inhibit_comdat);
-  ReportThreadHang();
 }
 
 NOINLINE void ThreadUnresponsive_IO() {
+  ReportThreadHang();
+  // Defining |inhibit_comdat| *after* calling ReportThreadHang() prevents tail
+  // call optimization from not putting this function's address on the stack.
+  // https://crbug.com/905288#c10
   volatile int inhibit_comdat = __LINE__;
   ALLOW_UNUSED_LOCAL(inhibit_comdat);
-  ReportThreadHang();
 }
 
 NOINLINE void CrashBecauseThreadWasUnresponsive(
diff --git a/chrome/browser/notifications/notification_platform_bridge_win_unittest.cc b/chrome/browser/notifications/notification_platform_bridge_win_unittest.cc
index bd540fb5..4c1acf3 100644
--- a/chrome/browser/notifications/notification_platform_bridge_win_unittest.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_win_unittest.cc
@@ -18,7 +18,6 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
 #include "base/win/scoped_com_initializer.h"
 #include "base/win/scoped_hstring.h"
 #include "base/win/windows_version.h"
@@ -50,9 +49,8 @@
 class NotificationPlatformBridgeWinTest : public testing::Test {
  public:
   NotificationPlatformBridgeWinTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
-        thread_bundle_(content::TestBrowserThreadBundle::PLAIN_MAINLOOP) {}
+      : thread_bundle_(
+            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {}
 
   ~NotificationPlatformBridgeWinTest() override = default;
 
@@ -94,7 +92,6 @@
     return toast2;
   }
 
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
   content::TestBrowserThreadBundle thread_bundle_;
 
  private:
diff --git a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
index 2e36030..e7f1f072 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
+++ b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
@@ -189,7 +189,8 @@
             ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
                 profile(), base::BindRepeating(&BuildMockProfileSyncService)));
 
-    EXPECT_CALL(*mock_sync_service, IsFirstSetupComplete())
+    EXPECT_CALL(*mock_sync_service->GetUserSettingsMock(),
+                IsFirstSetupComplete())
         .WillRepeatedly(Return(true));
     EXPECT_CALL(*mock_sync_service, GetTransportState())
         .WillRepeatedly(Return(syncer::SyncService::TransportState::ACTIVE));
@@ -199,7 +200,8 @@
   // Make a navigation entry that will accept an annotation.
   void SetupNavigationForAnnotation() {
     ProfileSyncServiceMock* mock_sync_service = SetupBasicMockSync();
-    EXPECT_CALL(*mock_sync_service, IsUsingSecondaryPassphrase())
+    EXPECT_CALL(*mock_sync_service->GetUserSettingsMock(),
+                IsUsingSecondaryPassphrase())
         .WillRepeatedly(Return(false));
     metrics_enabled_ = true;
     NavigateAndCommit(GURL("about:blank"));
@@ -291,7 +293,8 @@
   active_types.Put(syncer::PASSWORDS);
   EXPECT_CALL(*mock_sync_service, GetActiveDataTypes())
       .WillRepeatedly(Return(active_types));
-  EXPECT_CALL(*mock_sync_service, IsUsingSecondaryPassphrase())
+  EXPECT_CALL(*mock_sync_service->GetUserSettingsMock(),
+              IsUsingSecondaryPassphrase())
       .WillRepeatedly(Return(false));
 
   ChromePasswordManagerClient* client = GetClient();
@@ -301,7 +304,8 @@
             client->GetPasswordSyncState());
 
   // Again, using a custom passphrase.
-  EXPECT_CALL(*mock_sync_service, IsUsingSecondaryPassphrase())
+  EXPECT_CALL(*mock_sync_service->GetUserSettingsMock(),
+              IsUsingSecondaryPassphrase())
       .WillRepeatedly(Return(true));
 
   EXPECT_EQ(password_manager::SYNCING_WITH_CUSTOM_PASSPHRASE,
@@ -316,7 +320,8 @@
   EXPECT_EQ(password_manager::NOT_SYNCING, client->GetPasswordSyncState());
 
   // Again, without a custom passphrase.
-  EXPECT_CALL(*mock_sync_service, IsUsingSecondaryPassphrase())
+  EXPECT_CALL(*mock_sync_service->GetUserSettingsMock(),
+              IsUsingSecondaryPassphrase())
       .WillRepeatedly(Return(false));
 
   EXPECT_EQ(password_manager::NOT_SYNCING, client->GetPasswordSyncState());
@@ -575,7 +580,8 @@
 TEST_F(ChromePasswordManagerClientTest,
        AnnotateNavigationEntryWithMetricsNoCustom) {
   ProfileSyncServiceMock* mock_sync_service = SetupBasicMockSync();
-  EXPECT_CALL(*mock_sync_service, IsUsingSecondaryPassphrase())
+  EXPECT_CALL(*mock_sync_service->GetUserSettingsMock(),
+              IsUsingSecondaryPassphrase())
       .WillRepeatedly(Return(false));
   metrics_enabled_ = true;
 
@@ -591,7 +597,8 @@
 TEST_F(ChromePasswordManagerClientTest,
        AnnotateNavigationEntryNoMetricsNoCustom) {
   ProfileSyncServiceMock* mock_sync_service = SetupBasicMockSync();
-  EXPECT_CALL(*mock_sync_service, IsUsingSecondaryPassphrase())
+  EXPECT_CALL(*mock_sync_service->GetUserSettingsMock(),
+              IsUsingSecondaryPassphrase())
       .WillRepeatedly(Return(false));
   metrics_enabled_ = false;
 
@@ -607,7 +614,8 @@
 TEST_F(ChromePasswordManagerClientTest,
        AnnotateNavigationEntryWithMetricsWithCustom) {
   ProfileSyncServiceMock* mock_sync_service = SetupBasicMockSync();
-  EXPECT_CALL(*mock_sync_service, IsUsingSecondaryPassphrase())
+  EXPECT_CALL(*mock_sync_service->GetUserSettingsMock(),
+              IsUsingSecondaryPassphrase())
       .WillRepeatedly(Return(true));
   metrics_enabled_ = true;
 
@@ -623,7 +631,8 @@
 TEST_F(ChromePasswordManagerClientTest,
        AnnotateNavigationEntryNoMetricsWithCustom) {
   ProfileSyncServiceMock* mock_sync_service = SetupBasicMockSync();
-  EXPECT_CALL(*mock_sync_service, IsUsingSecondaryPassphrase())
+  EXPECT_CALL(*mock_sync_service->GetUserSettingsMock(),
+              IsUsingSecondaryPassphrase())
       .WillRepeatedly(Return(true));
   metrics_enabled_ = false;
 
diff --git a/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc b/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc
index 0036cd8..5272869 100644
--- a/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc
+++ b/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc
@@ -16,7 +16,6 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task_runner_util.h"
-#include "base/test/scoped_task_environment.h"
 #include "base/time/time.h"
 #include "chrome/browser/password_manager/native_backend_gnome_x.h"
 #include "chrome/test/base/testing_profile.h"
@@ -355,9 +354,7 @@
     SYNCED,
   };
 
-  NativeBackendGnomeTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+  NativeBackendGnomeTest() {}
 
   void SetUp() override {
     ASSERT_TRUE(MockGnomeKeyringLoader::LoadMockGnomeKeyring());
@@ -514,7 +511,7 @@
                    target_form, &form_list),
         base::Bind(&CheckTrue));
 
-    scoped_task_environment_.RunUntilIdle();
+    test_browser_thread_bundle_.RunUntilIdle();
 
     EXPECT_EQ(1u, mock_keyring_items.size());
     if (mock_keyring_items.size() > 0)
@@ -559,7 +556,7 @@
                    m_facebook_lookup, &form_list),
         base::Bind(&CheckTrue));
 
-    scoped_task_environment_.RunUntilIdle();
+    test_browser_thread_bundle_.RunUntilIdle();
 
     EXPECT_EQ(1u, mock_keyring_items.size());
     EXPECT_EQ(1u, form_list.size());
@@ -574,7 +571,7 @@
         base::BindOnce(base::IgnoreResult(&NativeBackendGnome::AddLogin),
                        base::Unretained(&backend), m_facebook));
 
-    scoped_task_environment_.RunUntilIdle();
+    test_browser_thread_bundle_.RunUntilIdle();
 
     EXPECT_EQ(2u, mock_keyring_items.size());
 
@@ -610,7 +607,7 @@
         break;
     }
 
-    scoped_task_environment_.RunUntilIdle();
+    test_browser_thread_bundle_.RunUntilIdle();
 
     EXPECT_EQ(2u, mock_keyring_items.size());
 
@@ -621,7 +618,7 @@
                    m_facebook_lookup, &form_list),
         base::Bind(&CheckTrue));
 
-    scoped_task_environment_.RunUntilIdle();
+    test_browser_thread_bundle_.RunUntilIdle();
 
     // There should be two results -- the exact one, and the PSL-matched one.
     EXPECT_EQ(2u, form_list.size());
@@ -640,7 +637,7 @@
                    PasswordStore::FormDigest(form_facebook_), &form_list),
         base::Bind(&CheckTrue));
 
-    scoped_task_environment_.RunUntilIdle();
+    test_browser_thread_bundle_.RunUntilIdle();
 
     // There should be two results -- the exact one, and the PSL-matched one.
     EXPECT_EQ(2u, form_list.size());
@@ -714,7 +711,7 @@
         base::Bind(&CheckPasswordChangesWithResult, &expected_changes,
                    &changes));
 
-    scoped_task_environment_.RunUntilIdle();
+    test_browser_thread_bundle_.RunUntilIdle();
 
     EXPECT_EQ(1u, mock_keyring_items.size());
     if (mock_keyring_items.size() > 0)
@@ -731,18 +728,11 @@
         base::Bind(&CheckPasswordChangesWithResult, &expected_changes,
                    &changes));
 
-    scoped_task_environment_.RunUntilIdle();
+    test_browser_thread_bundle_.RunUntilIdle();
 
     EXPECT_EQ(0u, mock_keyring_items.size());
   }
 
-  // Create the ScopedTaskEnvirnment first to ensure that
-  // CreateSequencedTaskRunnerWithTraits will work correctly. Then create also
-  // TestBrowserThreadBundle so that BrowserThread::UI has an associated
-  // TaskRunner. The order is important because the bundle can detect that the
-  // MessageLoop used by the environment exists and reuse it, but not vice
-  // versa.
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
   content::TestBrowserThreadBundle test_browser_thread_bundle_;
 
   // Provide some test forms to avoid having to set them up in each test.
@@ -765,7 +755,7 @@
           PasswordStoreChangeList(
               1, PasswordStoreChange(PasswordStoreChange::ADD, form_google_))));
 
-  scoped_task_environment_.RunUntilIdle();
+  test_browser_thread_bundle_.RunUntilIdle();
 
   EXPECT_EQ(1u, mock_keyring_items.size());
   if (mock_keyring_items.size() > 0)
@@ -788,7 +778,7 @@
                  base::Unretained(&backend), &form_list),
       base::Bind(&CheckTrue));
 
-  scoped_task_environment_.RunUntilIdle();
+  test_browser_thread_bundle_.RunUntilIdle();
 
   // Quick check that we got something back.
   EXPECT_EQ(1u, form_list.size());
@@ -898,7 +888,7 @@
       base::BindOnce(base::IgnoreResult(&NativeBackendGnome::AddLogin),
                      base::Unretained(&backend), form_google_));
 
-  scoped_task_environment_.RunUntilIdle();
+  test_browser_thread_bundle_.RunUntilIdle();
 
   PasswordForm new_form_google(form_google_);
   new_form_google.times_used = 1;
@@ -918,7 +908,7 @@
                  new_form_google, &changes),
       base::Bind(&CheckPasswordChangesWithResult, &expected_changes, &changes));
 
-  scoped_task_environment_.RunUntilIdle();
+  test_browser_thread_bundle_.RunUntilIdle();
 
   EXPECT_EQ(1u, mock_keyring_items.size());
   if (mock_keyring_items.size() > 0)
@@ -934,7 +924,7 @@
       base::BindOnce(base::IgnoreResult(&NativeBackendGnome::AddLogin),
                      base::Unretained(&backend), form_google_));
 
-  scoped_task_environment_.RunUntilIdle();
+  test_browser_thread_bundle_.RunUntilIdle();
 
   EXPECT_EQ(1u, mock_keyring_items.size());
   if (mock_keyring_items.size() > 0)
@@ -949,7 +939,7 @@
                  form_google_, &changes),
       base::Bind(&CheckPasswordChangesWithResult, &expected_changes, &changes));
 
-  scoped_task_environment_.RunUntilIdle();
+  test_browser_thread_bundle_.RunUntilIdle();
 
   EXPECT_EQ(0u, mock_keyring_items.size());
 }
@@ -964,7 +954,7 @@
       base::BindOnce(base::IgnoreResult(&NativeBackendGnome::AddLogin),
                      base::Unretained(&backend), form_google_));
 
-  scoped_task_environment_.RunUntilIdle();
+  test_browser_thread_bundle_.RunUntilIdle();
 
   EXPECT_EQ(1u, mock_keyring_items.size());
   if (mock_keyring_items.size() > 0)
@@ -982,7 +972,7 @@
                  form_google_, &changes),
       base::Bind(&CheckPasswordChangesWithResult, &expected_changes, &changes));
 
-  scoped_task_environment_.RunUntilIdle();
+  test_browser_thread_bundle_.RunUntilIdle();
 
   EXPECT_EQ(0u, mock_keyring_items.size());
 }
@@ -997,7 +987,7 @@
       base::BindOnce(base::IgnoreResult(&NativeBackendGnome::AddLogin),
                      base::Unretained(&backend), form_google_));
 
-  scoped_task_environment_.RunUntilIdle();
+  test_browser_thread_bundle_.RunUntilIdle();
 
   EXPECT_EQ(1u, mock_keyring_items.size());
   if (mock_keyring_items.size() > 0)
@@ -1020,7 +1010,7 @@
                  base::Unretained(&backend), &form_list),
       base::Bind(&CheckTrue));
 
-  scoped_task_environment_.RunUntilIdle();
+  test_browser_thread_bundle_.RunUntilIdle();
 
   // Quick check that we got something back.
   EXPECT_EQ(1u, form_list.size());
@@ -1040,7 +1030,7 @@
       base::BindOnce(base::IgnoreResult(&NativeBackendGnome::AddLogin),
                      base::Unretained(&backend), form_google_));
 
-  scoped_task_environment_.RunUntilIdle();
+  test_browser_thread_bundle_.RunUntilIdle();
 
   EXPECT_EQ(1u, mock_keyring_items.size());
   if (mock_keyring_items.size() > 0)
@@ -1055,7 +1045,7 @@
       base::Bind(&CheckPasswordChangesWithResult,
                  base::Owned(new PasswordStoreChangeList), &changes));
 
-  scoped_task_environment_.RunUntilIdle();
+  test_browser_thread_bundle_.RunUntilIdle();
 
   EXPECT_EQ(1u, mock_keyring_items.size());
   if (mock_keyring_items.size() > 0)
@@ -1072,7 +1062,7 @@
       base::BindOnce(base::IgnoreResult(&NativeBackendGnome::AddLogin),
                      base::Unretained(&backend), form_google_));
 
-  scoped_task_environment_.RunUntilIdle();
+  test_browser_thread_bundle_.RunUntilIdle();
 
   EXPECT_EQ(1u, mock_keyring_items.size());
   if (mock_keyring_items.size() > 0)
@@ -1087,7 +1077,7 @@
                  form_google_, &changes),
       base::Bind(&CheckPasswordChangesWithResult, &expected_changes, &changes));
 
-  scoped_task_environment_.RunUntilIdle();
+  test_browser_thread_bundle_.RunUntilIdle();
 
   EXPECT_EQ(1u, mock_keyring_items.size());
   if (mock_keyring_items.size() > 0)
@@ -1121,7 +1111,7 @@
                  form_google_),
       base::Bind(&CheckPasswordChanges, changes));
 
-  scoped_task_environment_.RunUntilIdle();
+  test_browser_thread_bundle_.RunUntilIdle();
 
   EXPECT_EQ(1u, mock_keyring_items.size());
   if (mock_keyring_items.size() > 0)
@@ -1157,7 +1147,7 @@
                  observed_android_form, &form_list),
       base::Bind(&CheckTrue));
 
-  scoped_task_environment_.RunUntilIdle();
+  test_browser_thread_bundle_.RunUntilIdle();
 
   EXPECT_EQ(1u, form_list.size());
   EXPECT_EQ(saved_android_form, *form_list[0]);
@@ -1186,7 +1176,7 @@
       base::BindOnce(base::IgnoreResult(&NativeBackendGnome::AddLogin),
                      base::Unretained(&backend), form_facebook_));
 
-  scoped_task_environment_.RunUntilIdle();
+  test_browser_thread_bundle_.RunUntilIdle();
 
   EXPECT_EQ(2u, mock_keyring_items.size());
   for (const auto& item : mock_keyring_items)
@@ -1211,7 +1201,7 @@
           &changes),
       base::Bind(&CheckPasswordChangesWithResult, &expected_changes, &changes));
 
-  scoped_task_environment_.RunUntilIdle();
+  test_browser_thread_bundle_.RunUntilIdle();
 
   EXPECT_EQ(2u, mock_keyring_items.size());
   CheckStringAttribute(
@@ -1242,7 +1232,7 @@
       base::BindOnce(base::IgnoreResult(&NativeBackendGnome::AddLogin),
                      base::Unretained(&backend), form_google_));
 
-  scoped_task_environment_.RunUntilIdle();
+  test_browser_thread_bundle_.RunUntilIdle();
 
   // Read the raw value back. Change the |unique_string| to
   // |unique_string_replacement| so the forms become unique.
@@ -1263,7 +1253,7 @@
                  base::Unretained(&backend), &form_list),
       base::Bind(&CheckTrue));
 
-  scoped_task_environment_.RunUntilIdle();
+  test_browser_thread_bundle_.RunUntilIdle();
 
   EXPECT_EQ(1u, form_list.size());
   EXPECT_EQ(form_google_, *form_list[0]);
@@ -1294,7 +1284,7 @@
                  &form_list),
       base::Bind(&CheckTrue));
 
-  scoped_task_environment_.RunUntilIdle();
+  test_browser_thread_bundle_.RunUntilIdle();
 
   EXPECT_EQ(2u, form_list.size());
   EXPECT_THAT(form_list, UnorderedElementsAre(Pointee(form_google_),
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index e6d4a6ca..44e6a80 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -42,6 +42,7 @@
 #include "components/certificate_transparency/pref_names.h"
 #include "components/component_updater/pref_names.h"
 #include "components/content_settings/core/common/pref_names.h"
+#include "components/history/core/common/pref_names.h"
 #include "components/language/core/browser/pref_names.h"
 #include "components/metrics/metrics_pref_names.h"
 #include "components/network_time/network_time_pref_names.h"
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
index dd96c3f..c7a6be562 100644
--- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
+++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -144,6 +144,7 @@
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
 #include "apps/browser_context_keyed_service_factories.h"
+#include "chrome/browser/apps/platform_apps/api/browser_context_keyed_service_factories.h"
 #include "chrome/browser/apps/platform_apps/browser_context_keyed_service_factories.h"
 #include "chrome/browser/extensions/api/networking_private/networking_private_ui_delegate_factory_impl.h"
 #include "chrome/browser/extensions/browser_context_keyed_service_factories.h"
@@ -208,6 +209,7 @@
   extensions::ExtensionManagementFactory::GetInstance();
   chrome_extensions::EnsureBrowserContextKeyedServiceFactoriesBuilt();
   chrome_apps::EnsureBrowserContextKeyedServiceFactoriesBuilt();
+  chrome_apps::api::EnsureAPIBrowserContextKeyedServiceFactoriesBuilt();
 #endif
 
 #if BUILDFLAG(ENABLE_APP_LIST)
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index d7e2546..4a793cc 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -104,6 +104,7 @@
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/content_settings/core/common/pref_names.h"
 #include "components/gcm_driver/gcm_profile_service.h"
+#include "components/history/core/common/pref_names.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/language/core/browser/pref_names.h"
 #include "components/language/core/common/locale_util.h"
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc
index 67bee09..130de94 100644
--- a/chrome/browser/profiles/profile_manager.cc
+++ b/chrome/browser/profiles/profile_manager.cc
@@ -148,7 +148,12 @@
 
 #if defined(OS_WIN)
 #include "base/win/win_util.h"
-#endif
+
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
+#include "chrome/browser/signin/signin_util_win.h"
+#endif  // BUILDFLAG(ENABLE_DICE_SUPPORT)
+
+#endif  // defined(OS_WIN)
 
 using base::UserMetricsAction;
 using content::BrowserThread;
@@ -1368,6 +1373,10 @@
   // Generates notifications from the above, if experiment is enabled.
   ContentSuggestionsNotifierServiceFactory::GetForProfile(profile);
 #endif
+
+#if defined(OS_WIN) && BUILDFLAG(ENABLE_DICE_SUPPORT)
+  signin_util::SigninWithCredentialProviderIfPossible(profile);
+#endif
 }
 
 void ProfileManager::DoFinalInitLogging(Profile* profile) {
diff --git a/chrome/browser/profiles/profile_window.cc b/chrome/browser/profiles/profile_window.cc
index d336ad7..03f17f3 100644
--- a/chrome/browser/profiles/profile_window.cc
+++ b/chrome/browser/profiles/profile_window.cc
@@ -89,42 +89,6 @@
 }
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
-// Handles running a callback when a new Browser for the given profile
-// has been completely created.
-class BrowserAddedForProfileObserver : public BrowserListObserver {
- public:
-  BrowserAddedForProfileObserver(
-      Profile* profile,
-      ProfileManager::CreateCallback callback)
-      : profile_(profile),
-        callback_(callback) {
-    DCHECK(!callback_.is_null());
-    BrowserList::AddObserver(this);
-  }
-  ~BrowserAddedForProfileObserver() override {}
-
- private:
-  // Overridden from BrowserListObserver:
-  void OnBrowserAdded(Browser* browser) override {
-    if (browser->profile() == profile_) {
-      BrowserList::RemoveObserver(this);
-      // By the time the browser is added a tab (or multiple) are about to be
-      // added. Post the callback to the message loop so it gets executed after
-      // the tabs are created.
-      base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE, base::BindOnce(callback_, profile_,
-                                    Profile::CREATE_STATUS_INITIALIZED));
-      base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
-    }
-  }
-
-  // Profile for which the browser should be opened.
-  Profile* profile_;
-  ProfileManager::CreateCallback callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(BrowserAddedForProfileObserver);
-};
-
 // Called after a |system_profile| is available to be used by the user manager.
 // Runs |callback|, if it exists. Depending on the value of
 // |user_manager_action|, executes an action once the user manager displays or
@@ -481,4 +445,27 @@
   }
 }
 
+BrowserAddedForProfileObserver::BrowserAddedForProfileObserver(
+    Profile* profile,
+    ProfileManager::CreateCallback callback)
+    : profile_(profile), callback_(callback) {
+  DCHECK(!callback_.is_null());
+  BrowserList::AddObserver(this);
+}
+
+BrowserAddedForProfileObserver::~BrowserAddedForProfileObserver() {}
+
+void BrowserAddedForProfileObserver::OnBrowserAdded(Browser* browser) {
+  if (browser->profile() == profile_) {
+    BrowserList::RemoveObserver(this);
+    // By the time the browser is added a tab (or multiple) are about to be
+    // added. Post the callback to the message loop so it gets executed after
+    // the tabs are created.
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::BindOnce(callback_, profile_,
+                                  Profile::CREATE_STATUS_INITIALIZED));
+    base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
+  }
+}
+
 }  // namespace profiles
diff --git a/chrome/browser/profiles/profile_window.h b/chrome/browser/profiles/profile_window.h
index 54c100a..6a4d038 100644
--- a/chrome/browser/profiles/profile_window.h
+++ b/chrome/browser/profiles/profile_window.h
@@ -130,6 +130,26 @@
 void BubbleViewModeFromAvatarBubbleMode(BrowserWindow::AvatarBubbleMode mode,
                                         BubbleViewMode* bubble_view_mode);
 
+// Handles running a callback when a new Browser for the given profile
+// has been completely created.  This object deletes itself once the browser
+// is created and the callback is executed.
+class BrowserAddedForProfileObserver : public BrowserListObserver {
+ public:
+  BrowserAddedForProfileObserver(Profile* profile,
+                                 ProfileManager::CreateCallback callback);
+  ~BrowserAddedForProfileObserver() override;
+
+ private:
+  // Overridden from BrowserListObserver:
+  void OnBrowserAdded(Browser* browser) override;
+
+  // Profile for which the browser should be opened.
+  Profile* profile_;
+  ProfileManager::CreateCallback callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(BrowserAddedForProfileObserver);
+};
+
 }  // namespace profiles
 
 #endif  // CHROME_BROWSER_PROFILES_PROFILE_WINDOW_H_
diff --git a/chrome/browser/profiling_host/background_profiling_triggers_unittest.cc b/chrome/browser/profiling_host/background_profiling_triggers_unittest.cc
index 9c7e4680..333a25a 100644
--- a/chrome/browser/profiling_host/background_profiling_triggers_unittest.cc
+++ b/chrome/browser/profiling_host/background_profiling_triggers_unittest.cc
@@ -8,7 +8,6 @@
 #include <utility>
 #include <vector>
 
-#include "base/test/scoped_task_environment.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
@@ -98,9 +97,7 @@
 class BackgroundProfilingTriggersTest : public testing::Test {
  public:
   BackgroundProfilingTriggersTest()
-      : scoped_task_envrionment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI),
-        testing_profile_manager_(TestingBrowserProcess::GetGlobal()),
+      : testing_profile_manager_(TestingBrowserProcess::GetGlobal()),
         triggers_(&host_),
         is_metrics_enabled_(true) {}
 
@@ -118,8 +115,7 @@
   }
 
  protected:
-  base::test::ScopedTaskEnvironment scoped_task_envrionment_;
-  content::TestBrowserThreadBundle thread_bundle;
+  content::TestBrowserThreadBundle thread_bundle_;
   TestingProfileManager testing_profile_manager_;
 
   ProfilingProcessHost host_;
diff --git a/chrome/browser/resources/safe_browsing/download_file_types.asciipb b/chrome/browser/resources/safe_browsing/download_file_types.asciipb
index 402780a32..e0d80fa 100644
--- a/chrome/browser/resources/safe_browsing/download_file_types.asciipb
+++ b/chrome/browser/resources/safe_browsing/download_file_types.asciipb
@@ -8,7 +8,7 @@
 ##
 ## Top level settings
 ##
-version_id: 24
+version_id: 25
 sampled_ping_probability: 0.01
 max_archived_binaries_to_report: 10
 default_file_type {
@@ -1221,6 +1221,18 @@
     auto_open_hint: ALLOW_AUTO_OPEN
   }
 }
+file_types {
+  # Control Panel Item. Executable used for adding icons to Control Panel.
+  # Added in crbug.com/914400
+  extension: "cpi"
+  uma_value: 321
+  ping_setting: FULL_PING
+  platform_settings {
+    platform: PLATFORM_WINDOWS
+    danger_level: ALLOW_ON_USER_GESTURE
+    auto_open_hint: DISALLOW_AUTO_OPEN
+  }
+}
 
 # OOXML MS Office files.  These can embed executables, but they don't
 # execute automatically when opened.  These are here to produce UMA metrics.
diff --git a/chrome/browser/resources/settings/people_page/account_manager.html b/chrome/browser/resources/settings/people_page/account_manager.html
index 5d56124..0c996154 100644
--- a/chrome/browser/resources/settings/people_page/account_manager.html
+++ b/chrome/browser/resources/settings/people_page/account_manager.html
@@ -33,21 +33,39 @@
         cursor: pointer;
       }
     </style>
+
     <div class="settings-box first">$i18n{accountManagerDescription}</div>
+
     <div class="settings-box first">
       <h2>$i18n{accountListHeader}</h2>
     </div>
+
     <div id="outer" class="layout vertical nowrap">
       <template is="dom-repeat" id="account-list" items="[[accounts_]]">
         <div class="settings-box">
+
           <div class="profile-icon"
               style="background-image: [[getIconImageSet_(item.pic)]]"></div>
+
           <div class="middle two-line no-min-width">
             <div class="flex text-elide">
-              <span>[[item.fullName]]</span>
+              <!-- If account is signed in, display the full name -->
+              <template is="dom-if" if="[[item.isSignedIn]]">
+                <span>[[item.fullName]]</span>
+              </template>
+              <!-- Else, display a re-authentication message -->
+              <template is="dom-if" if="[[!item.isSignedIn]]">
+                <span style="color:red">$i18n{accountManagerSignedOutAccountName}</span>
+              </template>
+
               <div class="secondary">[[item.email]]</div>
             </div>
           </div>
+
+          <template is="dom-if" if="[[shouldShowReauthenticationButton_(item)]]">
+            <paper-button on-click="onReauthenticationTap_">$i18n{accountManagerReauthenticationLabel}</paper-button>
+          </template>
+
           <paper-icon-button-light class="icon-more-vert"
               hidden="[[item.isDeviceAccount]]">
             <button title="$i18n{moreActions}"
@@ -59,6 +77,7 @@
       <div id="add-account-button" class="settings-box" on-tap="addAccount_">
         $i18n{addAccountLabel}
       </div>
+
       <div class="clear settings-box"></div>
 
       <cr-action-menu>
diff --git a/chrome/browser/resources/settings/people_page/account_manager.js b/chrome/browser/resources/settings/people_page/account_manager.js
index e754d4c..69bae4b5 100644
--- a/chrome/browser/resources/settings/people_page/account_manager.js
+++ b/chrome/browser/resources/settings/people_page/account_manager.js
@@ -67,6 +67,29 @@
   },
 
   /**
+   * @param {!settings.Account} account
+   * @return {boolean} True if the account reauthentication button should be
+   *    shown, false otherwise.
+   * @private
+   */
+  shouldShowReauthenticationButton_: function(account) {
+    // Device account re-authentication cannot be handled in-session, primarily
+    // because the user may have changed their password (leading to an LST
+    // invalidation) and we do not have a mechanism to change the cryptohome
+    // password in-session.
+    return !account.isDeviceAccount && !account.isSignedIn;
+  },
+
+  /**
+   * @param {!Event} event
+   * @private
+   */
+  onReauthenticationTap_: function(event) {
+    this.browserProxy_.reauthenticateAccount(
+      this.$['account-list'].itemForElement(event.path[0]).email);
+  },
+
+  /**
    * @private
    */
   refreshAccounts_: function() {
diff --git a/chrome/browser/resources/settings/people_page/account_manager_browser_proxy.js b/chrome/browser/resources/settings/people_page/account_manager_browser_proxy.js
index 0c5f2e48..565e7503 100644
--- a/chrome/browser/resources/settings/people_page/account_manager_browser_proxy.js
+++ b/chrome/browser/resources/settings/people_page/account_manager_browser_proxy.js
@@ -15,6 +15,7 @@
  *   id: string,
  *   accountType: number,
  *   isDeviceAccount: boolean,
+ *   isSignedIn: boolean,
  *   fullName: string,
  *   email: string,
  *   pic: string,
@@ -37,6 +38,13 @@
     addAccount() {}
 
     /**
+     * Triggers the re-authentication flow for the account pointed to by
+     * |account_email|.
+     * @param {!string} account_email
+     */
+    reauthenticateAccount(account_email) {}
+
+    /**
      * Removes |account| from Account Manager.
      * @param {?settings.Account} account
      */
@@ -58,6 +66,11 @@
     }
 
     /** @override */
+    reauthenticateAccount(account_email) {
+      chrome.send('reauthenticateAccount', [account_email]);
+    }
+
+    /** @override */
     removeAccount(account) {
       chrome.send('removeAccount', [account]);
     }
diff --git a/chrome/browser/resources/settings/people_page/people_page.html b/chrome/browser/resources/settings/people_page/people_page.html
index 993a8d79..0d82612d 100644
--- a/chrome/browser/resources/settings/people_page/people_page.html
+++ b/chrome/browser/resources/settings/people_page/people_page.html
@@ -21,6 +21,7 @@
 <link rel="import" href="../settings_page/settings_subpage.html">
 <link rel="import" href="../settings_shared_css.html">
 <link rel="import" href="signout_dialog.html">
+<link rel="import" href="sync_controls.html">
 
 <if expr="chromeos">
 <link rel="import" href="account_manager.html">
@@ -344,6 +345,15 @@
         </settings-subpage>
       </template>
 
+      <template is="dom-if" route-path="/syncSetup/advanced">
+        <settings-subpage page-title="$i18n{syncAdvancedPageTitle}"
+            learn-more-url="$i18n{syncAndGoogleServicesLearnMoreURL}">
+          <settings-sync-controls sync-status="[[syncStatus]]"
+              sync-page="[[$$('settings-sync-page')]]">
+          </settings-sync-controls>
+        </settings-subpage>
+      </template>
+
 <if expr="chromeos">
       <template is="dom-if" route-path="/lockScreen">
         <settings-subpage
diff --git a/chrome/browser/resources/settings/people_page/sync_controls.html b/chrome/browser/resources/settings/people_page/sync_controls.html
index 83839137..d5a4063 100644
--- a/chrome/browser/resources/settings/people_page/sync_controls.html
+++ b/chrome/browser/resources/settings/people_page/sync_controls.html
@@ -8,6 +8,10 @@
 <link rel="import" href="../settings_shared_css.html">
 <link rel="import" href="../settings_vars_css.html">
 
+<if expr="not chromeos">
+<link rel="import" href="chrome://resources/cr_elements/cr_toast/cr_toast.html">
+</if>
+
 <dom-module id="settings-sync-controls">
   <template>
     <style include="settings-shared">
@@ -22,6 +26,19 @@
       .list-item > div {
         flex: 1;
       }
+
+<if expr="not chromeos">
+      #toast {
+        color: white;
+        left: 0;
+        z-index: 1;
+      }
+
+      :host-context([dir='rtl']) #toast {
+        left: auto;
+        right: 0;
+      }
+</if>
     </style>
 
     <div class="settings-box first">
@@ -169,6 +186,15 @@
       </div>
     </div>
 
+<if expr="not chromeos">
+  <cr-toast id="toast"
+      open="[[shouldShowSyncSetupToast_(syncStatus.setupInProgress)]]">
+    <div>$i18n{syncWillStart}</div>
+    <paper-button on-click="onCancelSyncClick_">
+      $i18n{cancelSync}
+    </paper-button>
+  </cr-toast>
+</if>
   </template>
   <script src="sync_controls.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/settings/people_page/sync_controls.js b/chrome/browser/resources/settings/people_page/sync_controls.js
index 61e5e7bd..82ce3cc 100644
--- a/chrome/browser/resources/settings/people_page/sync_controls.js
+++ b/chrome/browser/resources/settings/people_page/sync_controls.js
@@ -37,6 +37,21 @@
      * @type {settings.SyncPrefs|undefined}
      */
     syncPrefs: Object,
+
+    /**
+     * The current sync status, supplied by the parent.
+     * @type {settings.SyncStatus}
+     */
+    syncStatus: Object,
+
+    /**
+     * Reference to the main sync page.
+     * @type {?SettingsSyncPageElement}
+     */
+    syncPage: {
+      type: Object,
+      value: null,
+    },
   },
 
   /** @private {?settings.SyncBrowserProxy} */
@@ -58,6 +73,9 @@
   attached: function() {
     this.addWebUIListener(
         'sync-prefs-changed', this.handleSyncPrefsChanged_.bind(this));
+
+    if (settings.getCurrentRoute() == settings.routes.SYNC_ADVANCED)
+      this.browserProxy_.didNavigateToSyncPage();
   },
 
   /**
@@ -145,5 +163,20 @@
       syncAllDataTypes, autofillSynced) {
     return syncAllDataTypes || !autofillSynced;
   },
+
+  /**
+   * @private
+   * @return {boolean}
+   */
+  shouldShowSyncSetupToast_: function() {
+    return settings.getCurrentRoute() == settings.routes.SYNC_ADVANCED &&
+        this.syncStatus.setupInProgress;
+  },
+
+  /** @private */
+  onCancelSyncClick_: function() {
+    assert(this.syncPage);
+    this.syncPage.cancelSyncSetup();
+  },
 });
 })();
diff --git a/chrome/browser/resources/settings/people_page/sync_page.html b/chrome/browser/resources/settings/people_page/sync_page.html
index 172854be..071e196e 100644
--- a/chrome/browser/resources/settings/people_page/sync_page.html
+++ b/chrome/browser/resources/settings/people_page/sync_page.html
@@ -65,7 +65,7 @@
         padding-bottom: 8px;
       }
 
-      #other-sync-items > .list-item {
+      #other-sync-items > .list-item:not(.first) {
         border-top: var(--settings-separator-line);
       }
 
@@ -147,11 +147,11 @@
       </div>
     </template>
 
-    <div class="settings-box first" hidden="[[!unifiedConsentEnabled]]">
-      <h2 class="start">$i18n{sync}</h2>
-    </div>
-
     <div id="sync-section" hidden="[[syncSectionDisabled_]]">
+      <div class="settings-box first" hidden="[[!unifiedConsentEnabled]]">
+        <h2 class="start">$i18n{sync}</h2>
+      </div>
+
       <div id="[[pages_.SPINNER]]" class="settings-box first settings-box-text"
           hidden$="[[!isStatus_(pages_.SPINNER, pageStatus_)]]">
         $i18n{syncLoading}
@@ -194,10 +194,26 @@
           </div>
         </template>
 
-        <settings-sync-controls></settings-sync-controls>
+        <template is="dom-if" if="[[!unifiedConsentEnabled]]">
+          <settings-sync-controls sync-status="syncStatus">
+          </settings-sync-controls>
+        </template>
 
         <div id="other-sync-items"
             class$="[[getListFrameClass_(unifiedConsentEnabled)]]">
+
+          <template is="dom-if" if="[[unifiedConsentEnabled]]">
+            <div id="sync-advanced-row" class="list-item first"
+                on-click="onSyncAdvancedTap_" actionable>
+              <div class="start">
+                $i18n{syncAdvancedPageTitle}
+              </div>
+              <paper-icon-button-light class="subpage-arrow">
+                <button aria-label="$i18n{syncAdvancedPageTitle}"></button>
+              </paper-icon-button-light>
+            </div>
+          </template>
+
           <template is="dom-if" if="[[driveSuggestAvailable_]]">
             <settings-toggle-button
                 class$="[[getListItemClass_(unifiedConsentEnabled)]]"
@@ -313,7 +329,7 @@
 <if expr="not chromeos">
     <cr-toast id="toast" open="[[syncStatus.setupInProgress]]">
       <div>$i18n{syncWillStart}</div>
-      <paper-button on-click="onCancelSyncClick_">
+      <paper-button on-click="cancelSyncSetup">
         $i18n{cancelSync}
       </paper-button>
     </cr-toast>
diff --git a/chrome/browser/resources/settings/people_page/sync_page.js b/chrome/browser/resources/settings/people_page/sync_page.js
index 4596795..bfd3ec9 100644
--- a/chrome/browser/resources/settings/people_page/sync_page.js
+++ b/chrome/browser/resources/settings/people_page/sync_page.js
@@ -184,10 +184,18 @@
     if (settings.getCurrentRoute() == settings.routes.SYNC)
       this.onNavigateToPage_();
   },
+  /**
+   * Can be called from subpages to notify this page (=main sync page) that sync
+   * setup was cancelled.
+   */
+  cancelSyncSetup: function() {
+    this.didAbort_ = true;
+    settings.navigateTo(settings.routes.BASIC);
+  },
 
   /** @override */
   detached: function() {
-    if (settings.getCurrentRoute() == settings.routes.SYNC)
+    if (settings.routes.SYNC.contains(settings.getCurrentRoute()))
       this.onNavigateAwayFromPage_();
 
     if (this.beforeunloadCallback_) {
@@ -220,7 +228,7 @@
   currentRouteChanged: function() {
     if (settings.getCurrentRoute() == settings.routes.SYNC)
       this.onNavigateToPage_();
-    else
+    else if (!settings.routes.SYNC.contains(settings.getCurrentRoute()))
       this.onNavigateAwayFromPage_();
   },
 
@@ -441,12 +449,6 @@
     }
   },
 
-  /** @private */
-  onCancelSyncClick_: function() {
-    this.didAbort_ = true;
-    settings.navigateTo(settings.routes.BASIC);
-  },
-
   /**
    * When unified-consent enabled, the non-toggle items on the bottom of sync
    * section should be wrapped with 'list-frame' in order to be indented
@@ -507,6 +509,11 @@
     return !this.unifiedConsentEnabled && this.syncPrefs !== undefined &&
         !!this.syncPrefs.passphraseRequired;
   },
+
+  /** @private */
+  onSyncAdvancedTap_: function() {
+    settings.navigateTo(settings.routes.SYNC_ADVANCED);
+  },
 });
 
 })();
diff --git a/chrome/browser/resources/settings/route.js b/chrome/browser/resources/settings/route.js
index df4e50f..8c8168d 100644
--- a/chrome/browser/resources/settings/route.js
+++ b/chrome/browser/resources/settings/route.js
@@ -101,6 +101,7 @@
  *   STORAGE: (undefined|!settings.Route),
  *   STYLUS: (undefined|!settings.Route),
  *   SYNC: (undefined|!settings.Route),
+ *   SYNC_ADVANCED: (undefined|!settings.Route),
  *   SYSTEM: (undefined|!settings.Route),
  *   TRIGGERED_RESET_DIALOG: (undefined|!settings.Route),
  * }}
@@ -284,6 +285,7 @@
     if (pageVisibility.people !== false) {
       r.PEOPLE = r.BASIC.createSection('/people', 'people');
       r.SYNC = r.PEOPLE.createChild('/syncSetup');
+      r.SYNC_ADVANCED = r.SYNC.createChild('/syncSetup/advanced');
       // <if expr="not chromeos">
       r.MANAGE_PROFILE = r.PEOPLE.createChild('/manageProfile');
       // </if>
diff --git a/chrome/browser/signin/signin_manager_factory.cc b/chrome/browser/signin/signin_manager_factory.cc
index 7be65b6..710183b 100644
--- a/chrome/browser/signin/signin_manager_factory.cc
+++ b/chrome/browser/signin/signin_manager_factory.cc
@@ -24,10 +24,10 @@
     : BrowserContextKeyedServiceFactory(
         "SigninManager",
         BrowserContextDependencyManager::GetInstance()) {
+  DependsOn(AccountTrackerServiceFactory::GetInstance());
   DependsOn(ChromeSigninClientFactory::GetInstance());
   DependsOn(GaiaCookieManagerServiceFactory::GetInstance());
   DependsOn(ProfileOAuth2TokenServiceFactory::GetInstance());
-  DependsOn(AccountTrackerServiceFactory::GetInstance());
   DependsOn(SigninErrorControllerFactory::GetInstance());
 }
 
diff --git a/chrome/browser/signin/signin_util_win.cc b/chrome/browser/signin/signin_util_win.cc
new file mode 100644
index 0000000..17f0705
--- /dev/null
+++ b/chrome/browser/signin/signin_util_win.cc
@@ -0,0 +1,199 @@
+// 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/signin/signin_util_win.h"
+
+#include <memory>
+#include <string>
+
+#include "base/bind.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/win/registry.h"
+#include "base/win/win_util.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/first_run/first_run.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/profiles/profile_window.h"
+#include "chrome/browser/signin/about_signin_internals_factory.h"
+#include "chrome/browser/signin/account_tracker_service_factory.h"
+#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
+#include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/sync/one_click_signin_sync_starter.h"
+#include "chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h"
+#include "chrome/credential_provider/common/gcp_strings.h"
+#include "components/os_crypt/os_crypt.h"
+#include "components/prefs/pref_service.h"
+#include "components/signin/core/browser/about_signin_internals.h"
+#include "components/signin/core/browser/signin_manager.h"
+#include "components/signin/core/browser/signin_metrics.h"
+#include "components/signin/core/browser/signin_pref_names.h"
+
+namespace signin_util {
+
+namespace {
+
+std::unique_ptr<DiceTurnSyncOnHelper::Delegate>*
+GetDiceTurnSyncOnHelperDelegateForTestingStorage() {
+  static std::unique_ptr<DiceTurnSyncOnHelper::Delegate> delegate;
+  return &delegate;
+}
+
+std::string DecryptRefreshToken(const std::string& cipher_text) {
+  std::string refresh_token;
+  if (!OSCrypt::DecryptString(cipher_text, &refresh_token))
+    return std::string();
+
+  return refresh_token;
+}
+
+// Finish the process of signing in with the credential provider.  This is
+// either called directly from SigninWithCredentialProvider() is a browser
+// window for the profile is already available or is delayed until a browser
+// can first be opened.
+void FinishSigninWithCredentialProvider(const std::string& account_id,
+                                        Browser* browser,
+                                        Profile* profile,
+                                        Profile::CreateStatus status) {
+  // DiceTurnSyncOnHelper deletes itself once done.
+  if (GetDiceTurnSyncOnHelperDelegateForTestingStorage()->get()) {
+    new DiceTurnSyncOnHelper(
+        profile, signin_metrics::AccessPoint::ACCESS_POINT_MACHINE_LOGON,
+        signin_metrics::PromoAction::PROMO_ACTION_WITH_DEFAULT,
+        signin_metrics::Reason::REASON_SIGNIN_PRIMARY_ACCOUNT, account_id,
+        DiceTurnSyncOnHelper::SigninAbortedMode::KEEP_ACCOUNT,
+        std::move(*GetDiceTurnSyncOnHelperDelegateForTestingStorage()));
+  } else {
+    if (!browser)
+      browser = chrome::FindLastActiveWithProfile(profile);
+
+    new DiceTurnSyncOnHelper(
+        profile, browser,
+        signin_metrics::AccessPoint::ACCESS_POINT_MACHINE_LOGON,
+        signin_metrics::PromoAction::PROMO_ACTION_WITH_DEFAULT,
+        signin_metrics::Reason::REASON_SIGNIN_PRIMARY_ACCOUNT, account_id,
+        DiceTurnSyncOnHelper::SigninAbortedMode::KEEP_ACCOUNT);
+  }
+
+  // Mark this profile as having been signed in with the credential provider.
+  profile->GetPrefs()->SetBoolean(prefs::kSignedInWithCredentialProvider, true);
+
+  // TODO(rogerta): delete the refresh_token regkey.
+}
+
+// Start the process of signing in with the credential provider given that
+// all the required information is available.  The process depends on having
+// a browser window for the profile.  If a browser window exists the profile
+// be signed in and sync will be starting up.  If not, the profile will be
+// still be signed in but sync will be started once the browser window is
+// ready.
+void SigninWithCredentialProvider(Profile* profile,
+                                  const base::string16& gaia_id,
+                                  const base::string16& email,
+                                  const std::string& refresh_token) {
+  // For debugging purposes, record that the credentials for this profile
+  // came from a credential provider.
+  AboutSigninInternals* signin_internals =
+      AboutSigninInternalsFactory::GetInstance()->GetForProfile(profile);
+  signin_internals->OnAuthenticationResultReceived("Credential Provider");
+
+  // First seed the account tracker before adding the account to the token
+  // service.
+  AccountTrackerService* account_tracker =
+      AccountTrackerServiceFactory::GetForProfile(profile);
+  std::string account_id = account_tracker->SeedAccountInfo(
+      base::UTF16ToUTF8(gaia_id), base::UTF16ToUTF8(email));
+
+  ProfileOAuth2TokenService* token_service =
+      ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
+  token_service->UpdateCredentials(
+      account_id, refresh_token,
+      signin_metrics::SourceForRefreshTokenOperation::
+          kMachineLogon_CredentialProvider);
+
+  Browser* browser = chrome::FindLastActiveWithProfile(profile);
+  if (browser) {
+    FinishSigninWithCredentialProvider(account_id, browser, profile,
+                                       Profile::CREATE_STATUS_CREATED);
+  } else {
+    // If no active browser exists yet, this profile is in the process of
+    // being created.  Wait for the browser to be created before finishing the
+    // sign in.  This object deletes itself when done.
+    new profiles::BrowserAddedForProfileObserver(
+        profile, base::BindRepeating(&FinishSigninWithCredentialProvider,
+                                     account_id, nullptr));
+  }
+}
+
+}  // namespace
+
+void SetDiceTurnSyncOnHelperDelegateForTesting(
+    std::unique_ptr<DiceTurnSyncOnHelper::Delegate> delegate) {
+  GetDiceTurnSyncOnHelperDelegateForTestingStorage()->swap(delegate);
+}
+
+void SigninWithCredentialProviderIfPossible(Profile* profile) {
+  // Check to see if auto signin information is available.  Only applies if:
+  //
+  //  - This is first run.
+  //  - Opening the initial profile.
+  //  - Not already signed in.
+  if (!(first_run::IsChromeFirstRun() &&
+        g_browser_process->profile_manager()->GetInitialProfileDir() ==
+            profile->GetPath().BaseName() &&
+        !SigninManagerFactory::GetForProfile(profile)->IsAuthenticated())) {
+    return;
+  }
+
+  base::win::RegKey key;
+  if (key.Open(HKEY_CURRENT_USER, credential_provider::kRegHkcuAccountsPath,
+               KEY_READ) != ERROR_SUCCESS) {
+    return;
+  }
+
+  base::win::RegistryKeyIterator it(key.Handle(), L"");
+  if (!it.Valid() || it.SubkeyCount() == 0)
+    return;
+
+  base::win::RegKey key_account(key.Handle(), it.Name(), KEY_READ | KEY_WRITE);
+  if (!key_account.Valid())
+    return;
+
+  base::string16 gaia_id = it.Name();
+  base::string16 email;
+  if (key_account.ReadValue(
+          base::UTF8ToUTF16(credential_provider::kKeyEmail).c_str(), &email) !=
+      ERROR_SUCCESS) {
+    return;
+  }
+
+  // Read the encrypted refresh token.  The data is stored in binary format.
+  // No matter what happens, delete the registry entry.
+  std::string encrypted_refresh_token;
+  DWORD size = 0;
+  DWORD type;
+  if (key_account.ReadValue(
+          base::UTF8ToUTF16(credential_provider::kKeyRefreshToken).c_str(),
+          nullptr, &size, &type) != ERROR_SUCCESS) {
+    return;
+  }
+
+  encrypted_refresh_token.resize(size);
+  key_account.ReadValue(
+      base::UTF8ToUTF16(credential_provider::kKeyRefreshToken).c_str(),
+      const_cast<char*>(encrypted_refresh_token.c_str()), &size, &type);
+  if (!gaia_id.empty() && !email.empty() && type == REG_BINARY &&
+      !encrypted_refresh_token.empty()) {
+    std::string refresh_token = DecryptRefreshToken(encrypted_refresh_token);
+    if (!refresh_token.empty())
+      SigninWithCredentialProvider(profile, gaia_id, email, refresh_token);
+  }
+
+  key_account.DeleteValue(
+      base::UTF8ToUTF16(credential_provider::kKeyRefreshToken).c_str());
+}
+
+}  // namespace signin_util
diff --git a/chrome/browser/signin/signin_util_win.h b/chrome/browser/signin/signin_util_win.h
new file mode 100644
index 0000000..8e9067c3
--- /dev/null
+++ b/chrome/browser/signin/signin_util_win.h
@@ -0,0 +1,26 @@
+// 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_SIGNIN_SIGNIN_UTIL_WIN_H_
+#define CHROME_BROWSER_SIGNIN_SIGNIN_UTIL_WIN_H_
+
+#include <memory>
+
+#include "chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h"
+
+class Profile;
+
+namespace signin_util {
+
+// Attempt to sign in with a credentials from a system installed credential
+// provider if available.
+void SigninWithCredentialProviderIfPossible(Profile* profile);
+
+// Sets the DiceTurnSyncOnHelper delegate for browser tests.
+void SetDiceTurnSyncOnHelperDelegateForTesting(
+    std::unique_ptr<DiceTurnSyncOnHelper::Delegate> delegate);
+
+}  // namespace signin_util
+
+#endif  // CHROME_BROWSER_SIGNIN_SIGNIN_UTIL_WIN_H_
diff --git a/chrome/browser/signin/signin_util_win_browsertest.cc b/chrome/browser/signin/signin_util_win_browsertest.cc
new file mode 100644
index 0000000..b31ce6a
--- /dev/null
+++ b/chrome/browser/signin/signin_util_win_browsertest.cc
@@ -0,0 +1,214 @@
+// 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 <stddef.h>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/command_line.h"
+#include "base/macros.h"
+#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/test_reg_util_win.h"
+#include "build/build_config.h"
+#include "chrome/browser/first_run/first_run.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/signin/signin_util_win.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/credential_provider/common/gcp_strings.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "components/os_crypt/os_crypt.h"
+#include "components/prefs/pref_service.h"
+#include "components/signin/core/browser/signin_pref_names.h"
+
+namespace {
+
+class TestDiceTurnSyncOnHelperDelegate : public DiceTurnSyncOnHelper::Delegate {
+  ~TestDiceTurnSyncOnHelperDelegate() override {}
+
+  // DiceTurnSyncOnHelper::Delegate:
+  void ShowLoginError(const std::string& email,
+                      const std::string& error_message) override {}
+  void ShowMergeSyncDataConfirmation(
+      const std::string& previous_email,
+      const std::string& new_email,
+      DiceTurnSyncOnHelper::SigninChoiceCallback callback) override {
+    std::move(callback).Run(DiceTurnSyncOnHelper::SIGNIN_CHOICE_CONTINUE);
+  }
+  void ShowEnterpriseAccountConfirmation(
+      const std::string& email,
+      DiceTurnSyncOnHelper::SigninChoiceCallback callback) override {
+    std::move(callback).Run(DiceTurnSyncOnHelper::SIGNIN_CHOICE_CONTINUE);
+  }
+  void ShowSyncConfirmation(
+      base::OnceCallback<void(LoginUIService::SyncConfirmationUIClosedResult)>
+          callback) override {
+    std::move(callback).Run(LoginUIService::SYNC_WITH_DEFAULT_SETTINGS);
+  }
+  void ShowSyncSettings() override {}
+  void ShowSigninPageInNewProfile(Profile* new_profile,
+                                  const std::string& username) override {}
+};
+
+struct SigninUtilWinBrowserTestParams {
+  SigninUtilWinBrowserTestParams(bool is_first_run,
+                                 const base::string16& gaia_id,
+                                 const base::string16& email,
+                                 const std::string& refresh_token,
+                                 bool expect_is_started)
+      : is_first_run(is_first_run),
+        gaia_id(gaia_id),
+        email(email),
+        refresh_token(refresh_token),
+        expect_is_started(expect_is_started) {}
+
+  bool is_first_run = false;
+  base::string16 gaia_id;
+  base::string16 email;
+  std::string refresh_token;
+  bool expect_is_started = false;
+};
+
+void AssertSigninStarted(bool expect_is_started, Profile* profile) {
+  ASSERT_EQ(expect_is_started, profile->GetPrefs()->GetBoolean(
+                                   prefs::kSignedInWithCredentialProvider));
+}
+
+}  // namespace
+
+class SigninUtilWinBrowserTest
+    : public InProcessBrowserTest,
+      public testing::WithParamInterface<SigninUtilWinBrowserTestParams> {
+ protected:
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    command_line->AppendSwitch(GetParam().is_first_run
+                                   ? switches::kForceFirstRun
+                                   : switches::kNoFirstRun);
+  }
+
+  bool SetUpUserDataDirectory() override {
+    registry_override_.OverrideRegistry(HKEY_CURRENT_USER);
+
+    base::win::RegKey key;
+
+    if (!GetParam().gaia_id.empty()) {
+      EXPECT_EQ(
+          ERROR_SUCCESS,
+          key.Create(HKEY_CURRENT_USER,
+                     credential_provider::kRegHkcuAccountsPath, KEY_WRITE));
+      EXPECT_EQ(ERROR_SUCCESS,
+                key.CreateKey(GetParam().gaia_id.c_str(), KEY_WRITE));
+    }
+
+    if (!GetParam().email.empty()) {
+      EXPECT_TRUE(key.Valid());
+      EXPECT_EQ(ERROR_SUCCESS,
+                key.WriteValue(
+                    base::ASCIIToUTF16(credential_provider::kKeyEmail).c_str(),
+                    GetParam().email.c_str()));
+    }
+
+    if (!GetParam().refresh_token.empty()) {
+      EXPECT_TRUE(key.Valid());
+      std::string ciphertext;
+      EXPECT_TRUE(
+          OSCrypt::EncryptString(GetParam().refresh_token, &ciphertext));
+      EXPECT_EQ(
+          ERROR_SUCCESS,
+          key.WriteValue(
+              base::ASCIIToUTF16(credential_provider::kKeyRefreshToken).c_str(),
+              ciphertext.c_str(), ciphertext.length(), REG_BINARY));
+    }
+
+    if (GetParam().expect_is_started) {
+      signin_util::SetDiceTurnSyncOnHelperDelegateForTesting(
+          std::unique_ptr<DiceTurnSyncOnHelper::Delegate>(
+              new TestDiceTurnSyncOnHelperDelegate()));
+    }
+
+    return InProcessBrowserTest::SetUpUserDataDirectory();
+  }
+
+ private:
+  registry_util::RegistryOverrideManager registry_override_;
+};
+
+IN_PROC_BROWSER_TEST_P(SigninUtilWinBrowserTest, Run) {
+  ASSERT_EQ(GetParam().is_first_run, first_run::IsChromeFirstRun());
+
+  ProfileManager* profile_manager = g_browser_process->profile_manager();
+  ASSERT_EQ(1u, profile_manager->GetNumberOfProfiles());
+
+  Profile* profile =
+      profile_manager->GetLastUsedProfile(profile_manager->user_data_dir());
+  ASSERT_EQ(profile_manager->GetInitialProfileDir(),
+            profile->GetPath().BaseName());
+
+  Browser* browser = chrome::FindLastActiveWithProfile(profile);
+  ASSERT_NE(nullptr, browser);
+
+  AssertSigninStarted(GetParam().expect_is_started, profile);
+
+  // If a refresh token was specified and a sign in attempt was expected, make
+  // sure the refresh token was removed from the registry.
+  if (!GetParam().refresh_token.empty() && GetParam().expect_is_started) {
+    base::win::RegKey key;
+    EXPECT_EQ(ERROR_SUCCESS,
+              key.Open(HKEY_CURRENT_USER,
+                       credential_provider::kRegHkcuAccountsPath, KEY_READ));
+    EXPECT_EQ(ERROR_SUCCESS, key.OpenKey(GetParam().gaia_id.c_str(), KEY_READ));
+    EXPECT_FALSE(key.HasValue(
+        base::ASCIIToUTF16(credential_provider::kKeyRefreshToken).c_str()));
+  }
+}
+
+INSTANTIATE_TEST_CASE_P(SigninUtilWinBrowserTest1,
+                        SigninUtilWinBrowserTest,
+                        testing::Values(SigninUtilWinBrowserTestParams(
+                            /*is_first_run=*/false,
+                            /*gaia_id=*/base::string16(),
+                            /*email=*/base::string16(),
+                            /*refresh_token=*/std::string(),
+                            /*expect_is_started=*/false)));
+
+INSTANTIATE_TEST_CASE_P(SigninUtilWinBrowserTest2,
+                        SigninUtilWinBrowserTest,
+                        testing::Values(SigninUtilWinBrowserTestParams(
+                            /*is_first_run=*/true,
+                            /*gaia_id=*/base::string16(),
+                            /*email=*/base::string16(),
+                            /*refresh_token=*/std::string(),
+                            /*expect_is_started=*/false)));
+
+INSTANTIATE_TEST_CASE_P(SigninUtilWinBrowserTest3,
+                        SigninUtilWinBrowserTest,
+                        testing::Values(SigninUtilWinBrowserTestParams(
+                            /*is_first_run=*/true,
+                            /*gaia_id=*/L"gaia-123456",
+                            /*email=*/base::string16(),
+                            /*refresh_token=*/std::string(),
+                            /*expect_is_started=*/false)));
+
+INSTANTIATE_TEST_CASE_P(SigninUtilWinBrowserTest4,
+                        SigninUtilWinBrowserTest,
+                        testing::Values(SigninUtilWinBrowserTestParams(
+                            /*is_first_run=*/true,
+                            /*gaia_id=*/L"gaia-123456",
+                            /*email=*/L"foo@gmail.com",
+                            /*refresh_token=*/std::string(),
+                            /*expect_is_started=*/false)));
+
+INSTANTIATE_TEST_CASE_P(SigninUtilWinBrowserTest5,
+                        SigninUtilWinBrowserTest,
+                        testing::Values(SigninUtilWinBrowserTestParams(
+                            /*is_first_run=*/true,
+                            /*gaia_id=*/L"gaia-123456",
+                            /*email=*/L"foo@gmail.com",
+                            /*refresh_token=*/"lst-123456",
+                            /*expect_is_started=*/true)));
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc
index fa920506..cbc792bb 100644
--- a/chrome/browser/ssl/ssl_browsertest.cc
+++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -1347,52 +1347,6 @@
                                  AuthState::RAN_INSECURE_CONTENT);
 }
 
-// Checks that a console message is printed when a subresource is
-// loaded over broken HTTPS. The test will:
-// 1. Navigate to a site with broken SSL (example.test)
-// 2. Click through the interstitial
-// 3. Navigate to another site with an iframe to example.test
-// 4. Check that console message has been printed
-IN_PROC_BROWSER_TEST_P(SSLUITest, TestBrokenHTTPSConsoleMessage) {
-  ASSERT_TRUE(https_server_.Start());
-  ASSERT_TRUE(https_server_mismatched_.Start());
-
-  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
-  ASSERT_TRUE(tab);
-  content::ConsoleObserverDelegate console_observer(
-      tab,
-      "Mixed Content: The page at * attempted to load subresource at * over "
-      "broken HTTPS.");
-  tab->SetDelegate(&console_observer);
-
-  GURL url = https_server_mismatched_.GetURL("/ssl/blank_page.html");
-  GURL::Replacements replacements;
-  replacements.SetHostStr("example.test");
-  url = url.ReplaceComponents(replacements);
-  // Navigate to a page with a certificate error and click through the
-  // interstitial.
-  ui_test_utils::NavigateToURL(browser(), url);
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_COMMON_NAME_INVALID,
-                                 AuthState::SHOWING_INTERSTITIAL);
-  ProceedThroughInterstitial(tab);
-
-  net::HostPortPair pair("example.test",
-                         https_server_mismatched_.host_port_pair().port());
-  std::string replacement_path;
-  GetFilePathWithHostAndPortReplacement("/ssl/blank_page.html", pair,
-                                        &replacement_path);
-
-  ui_test_utils::NavigateToURL(browser(),
-                               https_server_.GetURL(replacement_path));
-
-  ASSERT_FALSE(IsShowingInterstitial(tab));
-
-  console_observer.Wait();
-  EXPECT_TRUE(base::MatchPattern(console_observer.message(),
-                                 "Mixed Content: The page at * attempted to "
-                                 "load subresource at * over broken HTTPS."));
-}
-
 namespace {
 
 // A WebContentsObserver that allows the user to wait for a same-document
diff --git a/chrome/browser/sync/chrome_sync_client.cc b/chrome/browser/sync/chrome_sync_client.cc
index 2aeb331..0c6f9354 100644
--- a/chrome/browser/sync/chrome_sync_client.cc
+++ b/chrome/browser/sync/chrome_sync_client.cc
@@ -58,6 +58,7 @@
 #include "components/dom_distiller/core/dom_distiller_service.h"
 #include "components/history/core/browser/history_service.h"
 #include "components/history/core/browser/sync/history_model_worker.h"
+#include "components/history/core/common/pref_names.h"
 #include "components/invalidation/impl/invalidation_switches.h"
 #include "components/invalidation/impl/profile_invalidation_provider.h"
 #include "components/password_manager/core/browser/password_store.h"
diff --git a/chrome/browser/sync/sync_error_notifier_ash_unittest.cc b/chrome/browser/sync/sync_error_notifier_ash_unittest.cc
index 0fc2816..537934ea1 100644
--- a/chrome/browser/sync/sync_error_notifier_ash_unittest.cc
+++ b/chrome/browser/sync/sync_error_notifier_ash_unittest.cc
@@ -69,7 +69,7 @@
   void SetUp() override {
     BrowserWithTestWindowTest::SetUp();
 
-    service_ = std::make_unique<browser_sync::ProfileSyncServiceMock>(
+    service_ = std::make_unique<NiceMock<browser_sync::ProfileSyncServiceMock>>(
         CreateProfileSyncServiceParamsForTest(profile()));
 
     FakeLoginUIService* login_ui_service = static_cast<FakeLoginUIService*>(
@@ -98,12 +98,11 @@
                                      bool is_signed_in,
                                      bool is_error,
                                      bool expected_notification) {
-    EXPECT_CALL(*service_, IsFirstSetupComplete())
-        .WillRepeatedly(Return(is_signed_in));
+    ON_CALL(*service_->GetUserSettingsMock(), IsFirstSetupComplete())
+        .WillByDefault(Return(is_signed_in));
 
     GoogleServiceAuthError auth_error(error_state);
-    EXPECT_CALL(*service_, GetAuthError()).WillRepeatedly(
-        ReturnRef(auth_error));
+    ON_CALL(*service_, GetAuthError()).WillByDefault(ReturnRef(auth_error));
     ASSERT_EQ(is_error,
               sync_ui_util::ShouldShowPassphraseError(service_.get()));
 
@@ -137,13 +136,12 @@
   ASSERT_FALSE(display_service_->GetNotification(kNotificationId));
 
   syncer::SyncEngine::Status status;
-  EXPECT_CALL(*service_, QueryDetailedSyncStatus(_))
-              .WillRepeatedly(Return(false));
+  ON_CALL(*service_, QueryDetailedSyncStatus(_)).WillByDefault(Return(false));
 
-  EXPECT_CALL(*service_, IsPassphraseRequired())
-              .WillRepeatedly(Return(true));
-  EXPECT_CALL(*service_, IsPassphraseRequiredForDecryption())
-              .WillRepeatedly(Return(true));
+  ON_CALL(*service_->GetUserSettingsMock(), IsPassphraseRequired())
+      .WillByDefault(Return(true));
+  ON_CALL(*service_->GetUserSettingsMock(), IsPassphraseRequiredForDecryption())
+      .WillByDefault(Return(true));
   {
     SCOPED_TRACE("Expected a notification for passphrase error");
     VerifySyncErrorNotifierResult(GoogleServiceAuthError::NONE,
@@ -162,10 +160,10 @@
   }
 
   // Check that no notification is shown if there is no error.
-  EXPECT_CALL(*service_, IsPassphraseRequired())
-              .WillRepeatedly(Return(false));
-  EXPECT_CALL(*service_, IsPassphraseRequiredForDecryption())
-              .WillRepeatedly(Return(false));
+  ON_CALL(*service_->GetUserSettingsMock(), IsPassphraseRequired())
+      .WillByDefault(Return(false));
+  ON_CALL(*service_->GetUserSettingsMock(), IsPassphraseRequiredForDecryption())
+      .WillByDefault(Return(false));
   {
     SCOPED_TRACE("Not expecting notification since no error exists");
     VerifySyncErrorNotifierResult(GoogleServiceAuthError::NONE,
@@ -174,10 +172,10 @@
   }
 
   // Check that no notification is shown if sync setup is not completed.
-  EXPECT_CALL(*service_, IsPassphraseRequired())
-              .WillRepeatedly(Return(true));
-  EXPECT_CALL(*service_, IsPassphraseRequiredForDecryption())
-              .WillRepeatedly(Return(true));
+  ON_CALL(*service_->GetUserSettingsMock(), IsPassphraseRequired())
+      .WillByDefault(Return(true));
+  ON_CALL(*service_->GetUserSettingsMock(), IsPassphraseRequiredForDecryption())
+      .WillByDefault(Return(true));
   {
     SCOPED_TRACE("Not expecting notification since sync setup is incomplete");
     VerifySyncErrorNotifierResult(
diff --git a/chrome/browser/sync/test/integration/enable_disable_test.cc b/chrome/browser/sync/test/integration/enable_disable_test.cc
index 5e65194..636a5a4a 100644
--- a/chrome/browser/sync/test/integration/enable_disable_test.cc
+++ b/chrome/browser/sync/test/integration/enable_disable_test.cc
@@ -377,8 +377,18 @@
   EXPECT_EQ(0, GetNumUpdatesDownloadedInLastCycle());
 }
 
-IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,
-                       DoesNotRedownloadAfterKeepDataWithStandaloneTransport) {
+#if defined(THREAD_SANITIZER)
+// https://crbug.com/915219
+#define MAYBE_DoesNotRedownloadAfterKeepDataWithStandaloneTransport \
+  DISABLEDDoesNotRedownloadAfterKeepDataWithStandaloneTransport
+#else
+#define MAYBE_DoesNotRedownloadAfterKeepDataWithStandaloneTransport \
+  DoesNotRedownloadAfterKeepDataWithStandaloneTransport
+#endif
+
+IN_PROC_BROWSER_TEST_F(
+    EnableDisableSingleClientTest,
+    MAYBE_DoesNotRedownloadAfterKeepDataWithStandaloneTransport) {
   base::test::ScopedFeatureList enable_standalone_transport;
   enable_standalone_transport.InitAndEnableFeature(
       switches::kSyncStandaloneTransport);
diff --git a/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc b/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc
index 31db02d6..0f79bde 100644
--- a/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc
@@ -76,8 +76,16 @@
   }
 };
 
+#if defined(THREAD_SANITIZER)
+// https://crbug.com/915219
+#define MAYBE_StopThenDisableDeletesDirectory \
+  DISABLED_StopThenDisableDeletesDirectory
+#else
+#define MAYBE_StopThenDisableDeletesDirectory StopThenDisableDeletesDirectory
+#endif
+
 IN_PROC_BROWSER_TEST_F(SingleClientDirectorySyncTest,
-                       StopThenDisableDeletesDirectory) {
+                       MAYBE_StopThenDisableDeletesDirectory) {
   // If SyncStandaloneTransport is enabled, then the sync service will
   // immediately restart (and thus recreate directory files) after StopAndClear.
   // TODO(crbug.com/856179): Rewrite this test to pass with
diff --git a/chrome/browser/sync/test/integration/single_client_sessions_sync_test.cc b/chrome/browser/sync/test/integration/single_client_sessions_sync_test.cc
index ed15dd9..7497db2 100644
--- a/chrome/browser/sync/test/integration/single_client_sessions_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_sessions_sync_test.cc
@@ -564,6 +564,54 @@
                                          /*LOCAL_DELETION=*/0));
 }
 
+// Regression test for crbug.com/915133 that verifies the browser doesn't crash
+// if the server sends corrupt data during initial merge.
+IN_PROC_BROWSER_TEST_F(SingleClientSessionsSyncTest, CorruptInitialForeignTab) {
+  // Tabs with a negative node ID should be ignored.
+  sync_pb::EntitySpecifics specifics;
+  specifics.mutable_session()->mutable_tab();
+  specifics.mutable_session()->set_tab_node_id(-1);
+
+  GetFakeServer()->InjectEntity(
+      syncer::PersistentUniqueClientEntity::CreateFromEntitySpecifics(
+          "someclienttag", specifics,
+          /*creation_time=*/0,
+          /*last_modified_time=*/0));
+
+  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
+
+  // Foreign data should be empty.
+  SyncedSessionVector sessions;
+  ASSERT_FALSE(GetSessionData(0, &sessions));
+  EXPECT_EQ(0U, sessions.size());
+}
+
+// Regression test for crbug.com/915133 that verifies the browser doesn't crash
+// if the server sends corrupt data as incremental update.
+IN_PROC_BROWSER_TEST_F(SingleClientSessionsSyncTest, CorruptForeignTabUpdate) {
+  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
+
+  // Tabs with a negative node ID should be ignored.
+  sync_pb::EntitySpecifics specifics;
+  specifics.mutable_session()->mutable_tab();
+  specifics.mutable_session()->set_tab_node_id(-1);
+
+  GetFakeServer()->InjectEntity(
+      syncer::PersistentUniqueClientEntity::CreateFromEntitySpecifics(
+          "someclienttag", specifics,
+          /*creation_time=*/0,
+          /*last_modified_time=*/0));
+
+  // Mimic a browser restart to force a reconfiguration and fetch updates.
+  GetClient(0)->StopSyncServiceWithoutClearingData();
+  ASSERT_TRUE(GetClient(0)->StartSyncService());
+
+  // Foreign data should be empty.
+  SyncedSessionVector sessions;
+  ASSERT_FALSE(GetSessionData(0, &sessions));
+  EXPECT_EQ(0U, sessions.size());
+}
+
 IN_PROC_BROWSER_TEST_F(SingleClientSessionsSyncTest, TabMovedToOtherWindow) {
   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
   ASSERT_TRUE(CheckInitialState(0));
diff --git a/chrome/browser/sync/test/integration/sync_errors_test.cc b/chrome/browser/sync/test/integration/sync_errors_test.cc
index 7b1873b..9cd9bdf 100644
--- a/chrome/browser/sync/test/integration/sync_errors_test.cc
+++ b/chrome/browser/sync/test/integration/sync_errors_test.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/sync/test/integration/updated_progress_marker_checker.h"
 #include "chrome/common/pref_names.h"
 #include "components/browser_sync/profile_sync_service.h"
+#include "components/history/core/common/pref_names.h"
 #include "components/prefs/pref_member.h"
 #include "components/prefs/pref_service.h"
 #include "components/sync/protocol/sync_protocol_error.h"
diff --git a/chrome/browser/sync/test/integration/two_client_custom_passphrase_sync_test.cc b/chrome/browser/sync/test/integration/two_client_custom_passphrase_sync_test.cc
index 745ce33..606c7f0 100644
--- a/chrome/browser/sync/test/integration/two_client_custom_passphrase_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_custom_passphrase_sync_test.cc
@@ -126,8 +126,18 @@
   EXPECT_TRUE(WaitForBookmarksToMatchVerifier());
 }
 
-IN_PROC_BROWSER_TEST_F(TwoClientCustomPassphraseSyncTest,
-                       ClientsCanSyncDataWhenScryptEncryptionEnabledInOne) {
+#if defined(THREAD_SANITIZER)
+// https://crbug.com/915219
+#define MAYBE_ClientsCanSyncDataWhenScryptEncryptionEnabledInOne \
+  DISABLED_ClientsCanSyncDataWhenScryptEncryptionEnabledInOne
+#else
+#define MAYBE_ClientsCanSyncDataWhenScryptEncryptionEnabledInOne \
+  ClientsCanSyncDataWhenScryptEncryptionEnabledInOne
+#endif
+
+IN_PROC_BROWSER_TEST_F(
+    TwoClientCustomPassphraseSyncTest,
+    MAYBE_ClientsCanSyncDataWhenScryptEncryptionEnabledInOne) {
   ScopedScryptFeatureToggler toggler(/*force_disabled=*/false,
                                      /*use_for_new_passphrases=*/false);
   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc
index 2c61e20..fa45e3c 100644
--- a/chrome/browser/ui/browser_command_controller.cc
+++ b/chrome/browser/ui/browser_command_controller.cc
@@ -1241,11 +1241,7 @@
 // Makes sure that all commands that are not whitelisted are disabled. DCHECKs
 // otherwise. Compiled only in debug mode.
 void NonWhitelistedCommandsAreDisabled(CommandUpdaterImpl* command_updater) {
-  constexpr int kWhitelistedIds[] = {
-    IDC_CUT, IDC_COPY, IDC_PASTE,
-    IDC_FIND, IDC_FIND_NEXT, IDC_FIND_PREVIOUS,
-    IDC_ZOOM_PLUS, IDC_ZOOM_NORMAL, IDC_ZOOM_MINUS,
-  };
+  constexpr int kWhitelistedIds[] = {IDC_CUT, IDC_COPY, IDC_PASTE};
 
   // Go through all the command ids, skip the whitelisted ones.
   for (int id : command_updater->GetAllIds()) {
@@ -1272,10 +1268,7 @@
     // Update the state of whitelisted commands:
     // IDC_CUT/IDC_COPY/IDC_PASTE,
     UpdateCommandsForContentRestrictionState();
-    // IDC_FIND/IDC_FIND_NEXT/IDC_FIND_PREVIOUS,
-    UpdateCommandsForFind();
-    // IDC_ZOOM_PLUS/IDC_ZOOM_NORMAL/IDC_ZOOM_MINUS.
-    UpdateCommandsForZoomState();
+    // TODO(crbug.com/904637): Re-enable Find and Zoom in locked fullscreen.
     // All other commands will be disabled (there is an early return in their
     // corresponding UpdateCommandsFor* functions).
 #if DCHECK_IS_ON()
diff --git a/chrome/browser/ui/browser_command_controller_browsertest.cc b/chrome/browser/ui/browser_command_controller_browsertest.cc
index a1e33f5..a067173 100644
--- a/chrome/browser/ui/browser_command_controller_browsertest.cc
+++ b/chrome/browser/ui/browser_command_controller_browsertest.cc
@@ -142,11 +142,7 @@
   // IDC_EXIT is not enabled in locked fullscreen.
   EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_EXIT));
 
-  constexpr int kWhitelistedIds[] = {
-    IDC_CUT, IDC_COPY, IDC_PASTE,
-    IDC_FIND, IDC_FIND_NEXT, IDC_FIND_PREVIOUS,
-    IDC_ZOOM_PLUS, IDC_ZOOM_NORMAL, IDC_ZOOM_MINUS,
-  };
+  constexpr int kWhitelistedIds[] = {IDC_CUT, IDC_COPY, IDC_PASTE};
 
   // Go through all the command ids and make sure all non-whitelisted commands
   // are disabled.
@@ -157,13 +153,8 @@
     EXPECT_FALSE(command_updater->IsCommandEnabled(id));
   }
 
-  // Verify the set of whitelisted commands. All but IDC_ZOOM_NORMAL should be
-  // enabled.
+  // Verify the set of whitelisted commands.
   for (int id : kWhitelistedIds) {
-    if (id == IDC_ZOOM_NORMAL) {
-      EXPECT_FALSE(command_updater->IsCommandEnabled(id));
-      continue;
-    }
     EXPECT_TRUE(command_updater->IsCommandEnabled(id));
   }
 
diff --git a/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc b/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
index 1980a20..742f3f3e 100644
--- a/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
+++ b/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
@@ -382,8 +382,8 @@
       web_contents, WideToUTF16(search_string), kFwd, kIgnoreCase, NULL, NULL));
 }
 
-// Verifies that span and lists are searchable.
-IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, SpanAndListsSearchable) {
+// Verifies that span are searchable.
+IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, SpanSearchable) {
   WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
   ui_test_utils::NavigateToURL(browser(), GetURL("FindRandomTests.html"));
@@ -392,11 +392,6 @@
   EXPECT_EQ(1,
             ui_test_utils::FindInPage(web_contents, ASCIIToUTF16(search_string),
                                       kFwd, kIgnoreCase, NULL, NULL));
-
-  search_string = "Google\nApple\nandroid";
-  EXPECT_EQ(1,
-            ui_test_utils::FindInPage(web_contents, ASCIIToUTF16(search_string),
-                                      kFwd, kIgnoreCase, NULL, NULL));
 }
 
 #if defined(OS_WIN)
@@ -435,6 +430,8 @@
     base::ScopedAllowBlockingForTesting allow_blocking;
     base::ReadFileToString(path, &query);
   }
+  if (query[query.length() - 1] == '\n')
+    query.pop_back();
   EXPECT_EQ(1, FindInPage16(web_contents, base::UTF8ToUTF16(query),
                             kFwd, kIgnoreCase, NULL));
 }
@@ -484,25 +481,6 @@
   ASSERT_EQ(first_rect, second_rect);
 }
 
-// Find the whole text file page and find count should be 1.
-IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, FindWholeFileContent) {
-  WebContents* web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-
-  base::FilePath path = ui_test_utils::GetTestFilePath(
-      base::FilePath().AppendASCII("find_in_page"),
-      base::FilePath().AppendASCII("find_test.txt"));
-  ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL(path));
-
-  std::string query;
-  {
-    base::ScopedAllowBlockingForTesting allow_blocking;
-    base::ReadFileToString(path, &query);
-  }
-  EXPECT_EQ(1, FindInPage16(web_contents, base::UTF8ToUTF16(query),
-                            false, false, NULL));
-}
-
 // This test loads a single-frame page and makes sure the ordinal returned makes
 // sense as we FindNext over all the items.
 IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, FindInPageOrdinal) {
diff --git a/chrome/browser/ui/passwords/password_manager_presenter_unittest.cc b/chrome/browser/ui/passwords/password_manager_presenter_unittest.cc
index 3734188..7436fea 100644
--- a/chrome/browser/ui/passwords/password_manager_presenter_unittest.cc
+++ b/chrome/browser/ui/passwords/password_manager_presenter_unittest.cc
@@ -11,7 +11,6 @@
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
 #include "build/build_config.h"
 #include "chrome/browser/password_manager/password_store_factory.h"
 #include "chrome/browser/ui/passwords/password_ui_view.h"
@@ -52,7 +51,7 @@
 
   ~PasswordManagerPresenterTest() override {
     store_->ShutdownOnUIThread();
-    scoped_task_environment_.RunUntilIdle();
+    thread_bundle_.RunUntilIdle();
   }
 
   void AddPasswordEntry(const GURL& origin,
@@ -76,15 +75,13 @@
 
   void UpdatePasswordLists() {
     mock_controller_.GetPasswordManagerPresenter()->UpdatePasswordLists();
-    scoped_task_environment_.RunUntilIdle();
+    thread_bundle_.RunUntilIdle();
   }
 
   MockPasswordUIView& GetUIController() { return mock_controller_; }
 
  private:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-  content::TestBrowserThreadBundle thread_bundle_{
-      content::TestBrowserThreadBundle::PLAIN_MAINLOOP};
+  content::TestBrowserThreadBundle thread_bundle_;
   TestingProfile profile_;
   MockPasswordUIView mock_controller_{&profile_};
   scoped_refptr<password_manager::PasswordStore> store_;
diff --git a/chrome/browser/ui/search/search_tab_helper_unittest.cc b/chrome/browser/ui/search/search_tab_helper_unittest.cc
index 24d4b95..1378146 100644
--- a/chrome/browser/ui/search/search_tab_helper_unittest.cc
+++ b/chrome/browser/ui/search/search_tab_helper_unittest.cc
@@ -93,17 +93,16 @@
   void SetHistorySync(bool sync_history) {
     browser_sync::ProfileSyncServiceMock* sync_service =
         static_cast<browser_sync::ProfileSyncServiceMock*>(
-            ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile()));
+            ProfileSyncServiceFactory::GetForProfile(profile()));
 
-    syncer::ModelTypeSet result;
+    ON_CALL(*sync_service->GetUserSettingsMock(), IsFirstSetupComplete())
+        .WillByDefault(Return(true));
+    syncer::ModelTypeSet types;
     if (sync_history) {
-      result.Put(syncer::TYPED_URLS);
-      result.Put(syncer::HISTORY_DELETE_DIRECTIVES);
-      result.Put(syncer::SESSIONS);
+      types.Put(syncer::TYPED_URLS);
     }
-    ON_CALL(*sync_service, IsFirstSetupComplete()).WillByDefault(Return(true));
-    ON_CALL(*sync_service, GetPreferredDataTypes())
-        .WillByDefault(Return(result));
+    ON_CALL(*sync_service->GetUserSettingsMock(), GetChosenDataTypes())
+        .WillByDefault(Return(types));
   }
 
   identity::IdentityTestEnvironment* identity_test_env() {
diff --git a/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc b/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc
index 5d8845c..0ff96ed 100644
--- a/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc
+++ b/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc
@@ -120,13 +120,13 @@
   return false;
 }
 
-bool RemoteTextInputClient::GetSelectionRange(gfx::Range* range) const {
+bool RemoteTextInputClient::GetEditableSelectionRange(gfx::Range* range) const {
   // TODO(moshayedi): crbug.com/631527.
   NOTIMPLEMENTED_LOG_ONCE();
   return false;
 }
 
-bool RemoteTextInputClient::SetSelectionRange(const gfx::Range& range) {
+bool RemoteTextInputClient::SetEditableSelectionRange(const gfx::Range& range) {
   // TODO(moshayedi): crbug.com/631527.
   NOTIMPLEMENTED_LOG_ONCE();
   return false;
diff --git a/chrome/browser/ui/views/ime_driver/remote_text_input_client.h b/chrome/browser/ui/views/ime_driver/remote_text_input_client.h
index 157308a..6bcd332d 100644
--- a/chrome/browser/ui/views/ime_driver/remote_text_input_client.h
+++ b/chrome/browser/ui/views/ime_driver/remote_text_input_client.h
@@ -50,8 +50,8 @@
   FocusReason GetFocusReason() const override;
   bool GetTextRange(gfx::Range* range) const override;
   bool GetCompositionTextRange(gfx::Range* range) const override;
-  bool GetSelectionRange(gfx::Range* range) const override;
-  bool SetSelectionRange(const gfx::Range& range) override;
+  bool GetEditableSelectionRange(gfx::Range* range) const override;
+  bool SetEditableSelectionRange(const gfx::Range& range) override;
   bool DeleteRange(const gfx::Range& range) override;
   bool GetTextFromRange(const gfx::Range& range,
                         base::string16* text) const override;
diff --git a/chrome/browser/ui/views/infobars/infobar_view_unittest.cc b/chrome/browser/ui/views/infobars/infobar_view_unittest.cc
index 57e7937..5e0fac3 100644
--- a/chrome/browser/ui/views/infobars/infobar_view_unittest.cc
+++ b/chrome/browser/ui/views/infobars/infobar_view_unittest.cc
@@ -8,7 +8,6 @@
 #include "chrome/browser/ui/views/infobars/infobar_container_view.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/views/chrome_views_test_base.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_web_contents_factory.h"
 
 class TestInfoBarDelegate : public infobars::InfoBarDelegate {
@@ -44,7 +43,6 @@
   }
 
  private:
-  content::TestBrowserThreadBundle thread_bundle_;
   TestingProfile profile_;
   content::TestWebContentsFactory web_contents_factory_;
   content::WebContents* web_contents_;
diff --git a/chrome/browser/ui/views/media_router/cast_dialog_no_sinks_view_unittest.cc b/chrome/browser/ui/views/media_router/cast_dialog_no_sinks_view_unittest.cc
index 587d95c..25bdb82 100644
--- a/chrome/browser/ui/views/media_router/cast_dialog_no_sinks_view_unittest.cc
+++ b/chrome/browser/ui/views/media_router/cast_dialog_no_sinks_view_unittest.cc
@@ -9,7 +9,6 @@
 #include "base/run_loop.h"
 #include "base/time/time.h"
 #include "chrome/test/views/chrome_views_test_base.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace media_router {
@@ -33,7 +32,6 @@
   }
 
  private:
-  content::TestBrowserThreadBundle test_thread_bundle_;
   std::unique_ptr<CastDialogNoSinksView> no_sinks_view_;
 
   DISALLOW_COPY_AND_ASSIGN(CastDialogNoSinksViewTest);
diff --git a/chrome/browser/ui/views/media_router/cast_dialog_view_unittest.cc b/chrome/browser/ui/views/media_router/cast_dialog_view_unittest.cc
index e06f545..820b6f5 100644
--- a/chrome/browser/ui/views/media_router/cast_dialog_view_unittest.cc
+++ b/chrome/browser/ui/views/media_router/cast_dialog_view_unittest.cc
@@ -19,7 +19,6 @@
 #include "chrome/browser/ui/views/media_router/cast_dialog_sink_button.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/test/views/chrome_views_test_base.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -141,7 +140,6 @@
     return dialog_->sources_menu_runner_for_test();
   }
 
-  content::TestBrowserThreadBundle test_thread_bundle_;
   std::unique_ptr<views::Widget> anchor_widget_;
   MockCastDialogController controller_;
   CastDialogView* dialog_ = nullptr;
diff --git a/chrome/browser/ui/views/media_router/cast_toolbar_button_unittest.cc b/chrome/browser/ui/views/media_router/cast_toolbar_button_unittest.cc
index f4562f53..5f0ed1b2 100644
--- a/chrome/browser/ui/views/media_router/cast_toolbar_button_unittest.cc
+++ b/chrome/browser/ui/views/media_router/cast_toolbar_button_unittest.cc
@@ -17,7 +17,6 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/views/chrome_views_test_base.h"
 #include "components/vector_icons/vector_icons.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/base_event_utils.h"
@@ -98,7 +97,6 @@
     return gfx::Image(button_->GetImage(views::Button::STATE_NORMAL));
   }
 
-  content::TestBrowserThreadBundle thread_bundle_;
   std::unique_ptr<BrowserWindow> window_;
   std::unique_ptr<Browser> browser_;
   std::unique_ptr<CastToolbarButton> button_;
diff --git a/chrome/browser/ui/views/media_router/cloud_services_dialog_view_unittest.cc b/chrome/browser/ui/views/media_router/cloud_services_dialog_view_unittest.cc
index fd7ba75..29255df 100644
--- a/chrome/browser/ui/views/media_router/cloud_services_dialog_view_unittest.cc
+++ b/chrome/browser/ui/views/media_router/cloud_services_dialog_view_unittest.cc
@@ -10,7 +10,6 @@
 #include "chrome/test/base/test_browser_window.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/views/chrome_views_test_base.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/views/widget/widget.h"
 
@@ -65,7 +64,6 @@
                          prefs::kMediaRouterCloudServicesPrefSet));
   }
 
-  content::TestBrowserThreadBundle thread_bundle_;
   std::unique_ptr<BrowserWindow> window_;
   std::unique_ptr<Browser> browser_;
   std::unique_ptr<views::Widget> anchor_widget_;
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc
index 53b073f..0bd716f 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc
@@ -11,7 +11,6 @@
 #include "chrome/test/views/chrome_views_test_base.h"
 #include "components/omnibox/browser/omnibox_edit_model.h"
 #include "components/omnibox/browser/test_omnibox_client.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/events/event.h"
@@ -93,8 +92,6 @@
   OmniboxResultView* result_view() { return result_view_; }
 
  private:
-  content::TestBrowserThreadBundle test_browser_thread_bundle_;
-
   std::unique_ptr<OmniboxEditModel> edit_model_;
   std::unique_ptr<TestOmniboxPopupContentsView> popup_view_;
   OmniboxResultView* result_view_;
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
index 2943ef3..8161fe4e 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
@@ -27,7 +27,6 @@
 #include "components/omnibox/browser/omnibox_edit_model.h"
 #include "components/omnibox/browser/omnibox_field_trial.h"
 #include "components/omnibox/browser/test_location_bar_model.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/metrics_proto/omnibox_event.pb.h"
 #include "ui/base/ime/input_method.h"
@@ -235,7 +234,6 @@
   }
 
  private:
-  content::TestBrowserThreadBundle thread_bundle_;
   TestingProfile profile_;
   TemplateURLServiceFactoryTestUtil util_;
   CommandUpdaterImpl command_updater_;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view_unittest.cc b/chrome/browser/ui/views/toolbar/toolbar_action_view_unittest.cc
index 76ccb01..ff27520 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_action_view_unittest.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_action_view_unittest.cc
@@ -13,7 +13,6 @@
 #include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/views/chrome_views_test_base.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_web_contents_factory.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/events/test/event_generator.h"
@@ -120,9 +119,6 @@
   views::Widget* widget() { return widget_; }
 
  private:
-  // Web contents need a UI thread and a TaskScheduler.
-  content::TestBrowserThreadBundle test_browser_thread_bundle_;
-
   // The widget managed by this test.
   views::Widget* widget_;
 
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button_views_unittest.cc b/chrome/browser/ui/views/toolbar/toolbar_button_views_unittest.cc
index f1f71e2..2b5f47e 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_button_views_unittest.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_button_views_unittest.cc
@@ -90,8 +90,6 @@
   ToolbarButtonViewsTest() {}
 
  private:
-  content::TestBrowserThreadBundle browser_thread_bundle_;
-
   DISALLOW_COPY_AND_ASSIGN(ToolbarButtonViewsTest);
 };
 
diff --git a/chrome/browser/ui/webui/about_ui_unittest.cc b/chrome/browser/ui/webui/about_ui_unittest.cc
index 73b4632..425b35c4 100644
--- a/chrome/browser/ui/webui/about_ui_unittest.cc
+++ b/chrome/browser/ui/webui/about_ui_unittest.cc
@@ -17,7 +17,6 @@
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/task/post_task.h"
-#include "base/test/scoped_task_environment.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/test/base/scoped_browser_locale.h"
@@ -65,9 +64,7 @@
 // Base class for ChromeOS offline terms tests.
 class ChromeOSTermsTest : public testing::Test {
  protected:
-  ChromeOSTermsTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+  ChromeOSTermsTest() {}
   ~ChromeOSTermsTest() override = default;
 
   void SetUp() override {
@@ -126,14 +123,13 @@
         request_url, std::move(wc_getter),
         base::BindRepeating(&TestDataReceiver::OnDataReceived,
                             base::Unretained(data_receiver)));
-    scoped_task_environment_.RunUntilIdle();
+    test_browser_thread_bundle_.RunUntilIdle();
   }
 
  private:
   base::ScopedTempDir root_dir_;
   base::FilePath arc_tos_dir_;
 
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
   content::TestBrowserThreadBundle test_browser_thread_bundle_;
 
   chromeos::system::ScopedFakeStatisticsProvider statistics_provider_;
diff --git a/chrome/browser/ui/webui/chromeos/login/supervision_transition_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/supervision_transition_screen_handler.cc
index 02abaa6..9f860e26 100644
--- a/chrome/browser/ui/webui/chromeos/login/supervision_transition_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/supervision_transition_screen_handler.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/chromeos/login/screens/supervision_transition_screen.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/ash/login_screen_client.h"
+#include "chrome/browser/ui/ash/system_tray_client.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/arc/arc_prefs.h"
 #include "components/login/localized_values_builder.h"
@@ -90,6 +91,10 @@
           &SupervisionTransitionScreenHandler::OnSupervisionTransitionFinished,
           weak_factory_.GetWeakPtr()));
 
+  // Disable system tray, shutdown button and prevent login as guest when
+  // supervision transition screen is shown.
+  SystemTrayClient::Get()->SetPrimaryTrayEnabled(false);
+  LoginScreenClient::Get()->login_screen()->SetShutdownButtonEnabled(false);
   LoginScreenClient::Get()->login_screen()->SetAllowLoginAsGuest(false);
   LoginScreenClient::Get()->login_screen()->SetShowGuestButtonInOobe(false);
 
@@ -114,6 +119,9 @@
 
 void SupervisionTransitionScreenHandler::OnSupervisionTransitionFailed() {
   LOG(ERROR) << "Supervision transition failed; resetting ARC++ data.";
+  // Prevent ARC++ data removal below from triggering the success flow (since it
+  // will reset the supervision transition pref).
+  registrar_.RemoveAll();
   arc::ArcSessionManager::Get()->RequestArcDataRemoval();
   arc::ArcSessionManager::Get()->StopAndEnableArc();
   if (screen_) {
@@ -123,6 +131,12 @@
 }
 
 void SupervisionTransitionScreenHandler::OnSupervisionTransitionFinished() {
+  // This method is called both when supervision transition succeeds (observing
+  // pref changes) and when it fails ("OK" button from error screen, see
+  // RegisterMessages()). Once this screen exits, user session will be started,
+  // so there's no need to re-enable shutdown button from login screen, only the
+  // system tray.
+  SystemTrayClient::Get()->SetPrimaryTrayEnabled(true);
   if (screen_)
     screen_->OnSupervisionTransitionFinished();
 }
diff --git a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc
index ba2d182..f03b7f73 100644
--- a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc
@@ -19,8 +19,12 @@
 #include "chromeos/account_manager/account_manager_factory.h"
 #include "components/signin/core/browser/account_tracker_service.h"
 #include "components/user_manager/user.h"
+#include "google_apis/gaia/google_service_auth_error.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "ui/base/webui/web_ui_util.h"
+#include "ui/chromeos/resources/grit/ui_chromeos_resources.h"
+#include "ui/gfx/image/image_skia.h"
 
 namespace chromeos {
 namespace settings {
@@ -51,9 +55,11 @@
 
 AccountManagerUIHandler::AccountManagerUIHandler(
     AccountManager* account_manager,
-    AccountTrackerService* account_tracker_service)
+    AccountTrackerService* account_tracker_service,
+    identity::IdentityManager* identity_manager)
     : account_manager_(account_manager),
       account_tracker_service_(account_tracker_service),
+      identity_manager_(identity_manager),
       account_mapper_util_(account_tracker_service_),
       account_manager_observer_(this),
       account_tracker_service_observer_(this),
@@ -74,6 +80,10 @@
       base::BindRepeating(&AccountManagerUIHandler::HandleAddAccount,
                           weak_factory_.GetWeakPtr()));
   web_ui()->RegisterMessageCallback(
+      "reauthenticateAccount",
+      base::BindRepeating(&AccountManagerUIHandler::HandleReauthenticateAccount,
+                          weak_factory_.GetWeakPtr()));
+  web_ui()->RegisterMessageCallback(
       "removeAccount",
       base::BindRepeating(&AccountManagerUIHandler::HandleRemoveAccount,
                           weak_factory_.GetWeakPtr()));
@@ -110,7 +120,8 @@
         account_tracker_service_->FindAccountInfoByGaiaId(account_key.id);
     DCHECK(!account_info.IsEmpty());
 
-    if (account_info.full_name.empty()) {
+    if (account_manager_->IsTokenAvailable(account_key) &&
+        account_info.full_name.empty()) {
       // Account info has not been fully fetched yet from GAIA. Ignore this
       // account.
       continue;
@@ -120,11 +131,30 @@
     account.SetString("id", account_key.id);
     account.SetInteger("accountType", account_key.account_type);
     account.SetBoolean("isDeviceAccount", false);
+
+    const std::string oauth_account_id =
+        account_mapper_util_.AccountKeyToOAuthAccountId(account_key);
+    account.SetBoolean(
+        "isSignedIn",
+        identity_manager_->HasAccountWithRefreshToken(oauth_account_id) &&
+            !identity_manager_
+                 ->HasAccountWithRefreshTokenInPersistentErrorState(
+                     oauth_account_id));
     account.SetString("fullName", account_info.full_name);
     account.SetString("email", account_info.email);
     gfx::Image icon =
         account_tracker_service_->GetAccountImage(account_info.account_id);
-    account.SetString("pic", webui::GetBitmapDataUrl(icon.AsBitmap()));
+    if (!icon.IsEmpty()) {
+      account.SetString("pic", webui::GetBitmapDataUrl(icon.AsBitmap()));
+    } else {
+      // TODO(crbug.com/914751): Badge this icon with an exclamation mark.
+      gfx::ImageSkia default_icon =
+          *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+              IDR_LOGIN_DEFAULT_USER);
+      account.SetString("pic",
+                        webui::GetBitmapDataUrl(
+                            default_icon.GetRepresentation(1.0f).GetBitmap()));
+    }
 
     if (account_mapper_util_.IsEqual(account_key, device_account_id)) {
       device_account = std::move(account);
@@ -148,6 +178,16 @@
   InlineLoginHandlerDialogChromeOS::Show();
 }
 
+void AccountManagerUIHandler::HandleReauthenticateAccount(
+    const base::ListValue* args) {
+  AllowJavascript();
+
+  std::string account_email;
+  args->GetList()[0].GetAsString(&account_email);
+
+  InlineLoginHandlerDialogChromeOS::Show(account_email);
+}
+
 void AccountManagerUIHandler::HandleRemoveAccount(const base::ListValue* args) {
   AllowJavascript();
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h
index ce57798f..f373484 100644
--- a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h
@@ -15,6 +15,7 @@
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
 #include "chromeos/account_manager/account_manager.h"
 #include "components/signin/core/browser/account_tracker_service.h"
+#include "services/identity/public/cpp/identity_manager.h"
 
 namespace chromeos {
 namespace settings {
@@ -26,7 +27,8 @@
   // Accepts non-owning pointers to |AccountManager| and
   // |AccountTrackerService|. Both of these must outlive |this| instance.
   AccountManagerUIHandler(AccountManager* account_manager,
-                          AccountTrackerService* account_tracker_service);
+                          AccountTrackerService* account_tracker_service,
+                          identity::IdentityManager* identity_manager);
   ~AccountManagerUIHandler() override;
 
   // WebUIMessageHandler implementation.
@@ -53,6 +55,9 @@
   // WebUI "addAccount" message callback.
   void HandleAddAccount(const base::ListValue* args);
 
+  // WebUI "reauthenticateAccount" message callback.
+  void HandleReauthenticateAccount(const base::ListValue* args);
+
   // WebUI "removeAccount" message callback.
   void HandleRemoveAccount(const base::ListValue* args);
 
@@ -70,6 +75,9 @@
   // A non-owning pointer to |AccountTrackerService|.
   AccountTrackerService* const account_tracker_service_;
 
+  // A non-owning pointer to |IdentityManager|.
+  identity::IdentityManager* const identity_manager_;
+
   chromeos::AccountMapperUtil account_mapper_util_;
 
   // An observer for |AccountManager|. Automatically deregisters when |this| is
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
index 5800aa2..ab254bb 100644
--- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -1579,6 +1579,10 @@
     {"accountListHeader", IDS_SETTINGS_ACCOUNT_MANAGER_LIST_HEADER},
     {"addAccountLabel", IDS_SETTINGS_ACCOUNT_MANAGER_ADD_ACCOUNT_LABEL},
     {"removeAccountLabel", IDS_SETTINGS_ACCOUNT_MANAGER_REMOVE_ACCOUNT_LABEL},
+    {"accountManagerSignedOutAccountName",
+     IDS_SETTINGS_ACCOUNT_MANAGER_SIGNED_OUT_ACCOUNT_PLACEHOLDER},
+    {"accountManagerReauthenticationLabel",
+     IDS_SETTINGS_ACCOUNT_MANAGER_REAUTHENTICATION_LABEL},
     {"configureFingerprintTitle", IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_TITLE},
     {"configureFingerprintInstructionLocateScannerStep",
      IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_LOCATE_SCANNER},
@@ -1722,8 +1726,7 @@
     {"deleteProfileWarningWithoutCounts",
      IDS_SETTINGS_SYNC_DISCONNECT_DELETE_PROFILE_WARNING_WITHOUT_COUNTS},
     {"syncDisconnectConfirm", IDS_SETTINGS_SYNC_DISCONNECT_CONFIRM},
-    {"sync", is_unified_consent_enabled ? IDS_SETTINGS_SYNC_UNIFIED_CONSENT
-                                        : IDS_SETTINGS_SYNC},
+    {"sync", IDS_SETTINGS_SYNC},
     {"nonPersonalizedServicesSectionLabel",
      IDS_SETTINGS_NON_PERSONALIZED_SERVICES_SECTION_LABEL},
     {"syncAndNonPersonalizedServices",
@@ -1731,6 +1734,7 @@
     {"syncPageTitle", is_unified_consent_enabled
                           ? IDS_SETTINGS_SYNC_SYNC_AND_NON_PERSONALIZED_SERVICES
                           : IDS_SETTINGS_SYNC_PAGE_TITLE},
+    {"syncAdvancedPageTitle", IDS_SETTINGS_SYNC_ADVANCED_PAGE_TITLE},
     {"syncLoading", IDS_SETTINGS_SYNC_LOADING},
     {"syncTimeout", IDS_SETTINGS_SYNC_TIMEOUT},
     {"syncEverythingCheckboxLabel",
@@ -1748,7 +1752,10 @@
     {"openTabsCheckboxLabel", IDS_SETTINGS_OPEN_TABS_CHECKBOX_LABEL},
     {"driveSuggestPref", IDS_DRIVE_SUGGEST_PREF},
     {"driveSuggestPrefDesc", IDS_DRIVE_SUGGEST_PREF_DESC},
-    {"manageSyncedDataTitle", IDS_SETTINGS_MANAGE_SYNCED_DATA_TITLE},
+    {"manageSyncedDataTitle",
+     unified_consent::IsUnifiedConsentFeatureEnabled()
+         ? IDS_SETTINGS_MANAGE_SYNCED_DATA_TITLE_UNIFIED_CONSENT
+         : IDS_SETTINGS_MANAGE_SYNCED_DATA_TITLE},
     {"encryptionOptionsTitle", IDS_SETTINGS_ENCRYPTION_OPTIONS},
     {"syncDataEncryptedText", IDS_SETTINGS_SYNC_DATA_ENCRYPTED_TEXT},
     {"encryptWithGoogleCredentialsLabel",
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc
index 5060ff5c..ff22b4b 100644
--- a/chrome/browser/ui/webui/settings/md_settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc
@@ -16,6 +16,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "build/build_config.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
 #include "chrome/browser/ui/webui/dark_mode_handler.h"
 #include "chrome/browser/ui/webui/metrics_handler.h"
@@ -200,8 +201,8 @@
     AddSettingsPageUIHandler(
         std::make_unique<chromeos::settings::AccountManagerUIHandler>(
             account_manager,
-            AccountTrackerServiceFactory::GetInstance()->GetForProfile(
-                profile)));
+            AccountTrackerServiceFactory::GetInstance()->GetForProfile(profile),
+            IdentityManagerFactory::GetForProfile(profile)));
   }
   AddSettingsPageUIHandler(
       std::make_unique<chromeos::settings::ChangePictureHandler>());
diff --git a/chrome/browser/ui/webui/settings/people_handler_unittest.cc b/chrome/browser/ui/webui/settings/people_handler_unittest.cc
index 91da24a..0a0631c 100644
--- a/chrome/browser/ui/webui/settings/people_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/people_handler_unittest.cc
@@ -35,7 +35,6 @@
 #include "components/prefs/pref_service.h"
 #include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "components/signin/core/browser/signin_manager.h"
-#include "components/sync/base/sync_prefs.h"
 #include "components/sync_preferences/pref_service_syncable.h"
 #include "components/unified_consent/scoped_unified_consent.h"
 #include "content/public/browser/web_contents.h"
@@ -49,7 +48,6 @@
 #include "google_apis/gaia/oauth2_token_service_delegate.h"
 #include "services/identity/public/cpp/identity_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/layout.h"
 
 using ::testing::_;
 using ::testing::Invoke;
@@ -213,10 +211,10 @@
         ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
             profile(), base::BindRepeating(&BuildMockProfileSyncService)));
     ON_CALL(*mock_pss_, GetAuthError()).WillByDefault(ReturnRef(error_));
-    ON_CALL(*mock_pss_, GetPassphraseType())
+    ON_CALL(*mock_pss_->GetUserSettingsMock(), GetPassphraseType())
         .WillByDefault(Return(syncer::PassphraseType::IMPLICIT_PASSPHRASE));
-    ON_CALL(*mock_pss_, GetExplicitPassphraseTime()).WillByDefault(
-        Return(base::Time()));
+    ON_CALL(*mock_pss_->GetUserSettingsMock(), GetExplicitPassphraseTime())
+        .WillByDefault(Return(base::Time()));
     ON_CALL(*mock_pss_, GetRegisteredDataTypes())
         .WillByDefault(Return(syncer::ModelTypeSet()));
     ON_CALL(*mock_pss_, GetSetupInProgressHandle())
@@ -250,15 +248,19 @@
   void SetDefaultExpectationsForConfigPage() {
     ON_CALL(*mock_pss_, GetDisableReasons())
         .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
+    ON_CALL(*mock_pss_->GetUserSettingsMock(), IsSyncRequested())
+        .WillByDefault(Return(true));
     ON_CALL(*mock_pss_, GetRegisteredDataTypes())
         .WillByDefault(Return(GetAllTypes()));
-    ON_CALL(*mock_pss_, GetPreferredDataTypes())
+    ON_CALL(*mock_pss_->GetUserSettingsMock(), IsSyncEverythingEnabled())
+        .WillByDefault(Return(true));
+    ON_CALL(*mock_pss_->GetUserSettingsMock(), GetChosenDataTypes())
         .WillByDefault(Return(GetAllTypes()));
     ON_CALL(*mock_pss_, GetActiveDataTypes())
         .WillByDefault(Return(GetAllTypes()));
-    ON_CALL(*mock_pss_, IsEncryptEverythingAllowed())
+    ON_CALL(*mock_pss_->GetUserSettingsMock(), IsEncryptEverythingAllowed())
         .WillByDefault(Return(true));
-    ON_CALL(*mock_pss_, IsEncryptEverythingEnabled())
+    ON_CALL(*mock_pss_->GetUserSettingsMock(), IsEncryptEverythingEnabled())
         .WillByDefault(Return(false));
   }
 
@@ -356,7 +358,8 @@
 
   ON_CALL(*mock_pss_, GetDisableReasons())
       .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN));
-  ON_CALL(*mock_pss_, IsFirstSetupComplete()).WillByDefault(Return(false));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsFirstSetupComplete())
+      .WillByDefault(Return(false));
   // Ensure that the user is not signed in before calling |HandleStartSignin()|.
   identity_test_env()->ClearPrimaryAccount();
   base::ListValue list_args;
@@ -378,7 +381,8 @@
 TEST_F(PeopleHandlerTest, ShowSyncSetupWhenNotSignedIn) {
   ON_CALL(*mock_pss_, GetDisableReasons())
       .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN));
-  ON_CALL(*mock_pss_, IsFirstSetupComplete()).WillByDefault(Return(false));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsFirstSetupComplete())
+      .WillByDefault(Return(false));
   handler_->HandleShowSetupUI(nullptr);
 
   ExpectPageStatusChanged(PeopleHandler::kDonePageStatus);
@@ -410,11 +414,14 @@
 TEST_F(PeopleHandlerTest, DisplayConfigureWithEngineDisabledAndCancel) {
   ON_CALL(*mock_pss_, GetDisableReasons())
       .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
-  ON_CALL(*mock_pss_, IsFirstSetupComplete()).WillByDefault(Return(false));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsSyncRequested())
+      .WillByDefault(Return(true));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsFirstSetupComplete())
+      .WillByDefault(Return(false));
   error_ = GoogleServiceAuthError::AuthErrorNone();
   ON_CALL(*mock_pss_, GetTransportState())
       .WillByDefault(Return(syncer::SyncService::TransportState::INITIALIZING));
-  EXPECT_CALL(*mock_pss_, RequestStart());
+  EXPECT_CALL(*mock_pss_->GetUserSettingsMock(), SetSyncRequested(true));
 
   // We're simulating a user setting up sync, which would cause the engine to
   // kick off initialization, but not download user data types. The sync
@@ -434,15 +441,18 @@
 // to showing a configuration page when sync setup completes successfully.
 TEST_F(PeopleHandlerTest,
        DisplayConfigureWithEngineDisabledAndSyncStartupCompleted) {
-  ON_CALL(*mock_pss_, IsFirstSetupComplete()).WillByDefault(Return(false));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsFirstSetupComplete())
+      .WillByDefault(Return(false));
   ON_CALL(*mock_pss_, GetDisableReasons())
       .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsSyncRequested())
+      .WillByDefault(Return(true));
   error_ = GoogleServiceAuthError::AuthErrorNone();
   // Sync engine is stopped initially, and will start up.
   ON_CALL(*mock_pss_, GetTransportState())
       .WillByDefault(Return(
           syncer::SyncService::TransportState::WAITING_FOR_START_REQUEST));
-  EXPECT_CALL(*mock_pss_, RequestStart());
+  EXPECT_CALL(*mock_pss_->GetUserSettingsMock(), SetSyncRequested(true));
   SetDefaultExpectationsForConfigPage();
 
   handler_->HandleShowSetupUI(nullptr);
@@ -477,12 +487,15 @@
        DisplayConfigureWithEngineDisabledAndCancelAfterSigninSuccess) {
   ON_CALL(*mock_pss_, GetDisableReasons())
       .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
-  ON_CALL(*mock_pss_, IsFirstSetupComplete()).WillByDefault(Return(false));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsSyncRequested())
+      .WillByDefault(Return(true));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsFirstSetupComplete())
+      .WillByDefault(Return(false));
   error_ = GoogleServiceAuthError::AuthErrorNone();
   EXPECT_CALL(*mock_pss_, GetTransportState())
       .WillOnce(Return(syncer::SyncService::TransportState::INITIALIZING))
       .WillRepeatedly(Return(syncer::SyncService::TransportState::ACTIVE));
-  EXPECT_CALL(*mock_pss_, RequestStart());
+  EXPECT_CALL(*mock_pss_->GetUserSettingsMock(), SetSyncRequested(true));
   SetDefaultExpectationsForConfigPage();
   handler_->HandleShowSetupUI(nullptr);
 
@@ -501,11 +514,14 @@
 TEST_F(PeopleHandlerTest, DisplayConfigureWithEngineDisabledAndSigninFailed) {
   ON_CALL(*mock_pss_, GetDisableReasons())
       .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
-  ON_CALL(*mock_pss_, IsFirstSetupComplete()).WillByDefault(Return(false));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsSyncRequested())
+      .WillByDefault(Return(true));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsFirstSetupComplete())
+      .WillByDefault(Return(false));
   error_ = GoogleServiceAuthError::AuthErrorNone();
   ON_CALL(*mock_pss_, GetTransportState())
       .WillByDefault(Return(syncer::SyncService::TransportState::INITIALIZING));
-  EXPECT_CALL(*mock_pss_, RequestStart());
+  EXPECT_CALL(*mock_pss_->GetUserSettingsMock(), SetSyncRequested(true));
 
   handler_->HandleShowSetupUI(nullptr);
   ExpectPageStatusChanged(PeopleHandler::kSpinnerPageStatus);
@@ -526,20 +542,24 @@
   // being set.
   ON_CALL(*mock_pss_, GetDisableReasons())
       .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_USER_CHOICE));
-  ON_CALL(*mock_pss_, IsFirstSetupComplete()).WillByDefault(Return(true));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsFirstSetupComplete())
+      .WillByDefault(Return(true));
   ON_CALL(*mock_pss_, GetTransportState())
       .WillByDefault(Return(syncer::SyncService::TransportState::DISABLED));
 
   // Attempting to open the setup UI should restart sync.
-  EXPECT_CALL(*mock_pss_, RequestStart()).WillOnce([&]() {
-    // RequestStart() clears DISABLE_REASON_USER_CHOICE, and immediately starts
-    // initialzing the engine.
-    ON_CALL(*mock_pss_, GetDisableReasons())
-        .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
-    ON_CALL(*mock_pss_, GetTransportState())
-        .WillByDefault(
-            Return(syncer::SyncService::TransportState::INITIALIZING));
-  });
+  EXPECT_CALL(*mock_pss_->GetUserSettingsMock(), SetSyncRequested(true))
+      .WillOnce([&](bool) {
+        // SetSyncRequested(true) clears DISABLE_REASON_USER_CHOICE, and
+        // immediately starts initialzing the engine.
+        ON_CALL(*mock_pss_, GetDisableReasons())
+            .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
+        ON_CALL(*mock_pss_->GetUserSettingsMock(), IsSyncRequested())
+            .WillByDefault(Return(true));
+        ON_CALL(*mock_pss_, GetTransportState())
+            .WillByDefault(
+                Return(syncer::SyncService::TransportState::INITIALIZING));
+      });
 
   handler_->HandleShowSetupUI(nullptr);
   ExpectPageStatusChanged(PeopleHandler::kSpinnerPageStatus);
@@ -552,20 +572,24 @@
   // mode.
   ON_CALL(*mock_pss_, GetDisableReasons())
       .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_USER_CHOICE));
-  ON_CALL(*mock_pss_, IsFirstSetupComplete()).WillByDefault(Return(true));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsFirstSetupComplete())
+      .WillByDefault(Return(true));
   ON_CALL(*mock_pss_, GetTransportState())
       .WillByDefault(Return(syncer::SyncService::TransportState::ACTIVE));
 
   // Attempting to open the setup UI should re-enable sync-the-feature.
-  EXPECT_CALL(*mock_pss_, RequestStart()).WillOnce([&]() {
-    // RequestStart() clears DISABLE_REASON_USER_CHOICE. Since the engine is
-    // already running, it just gets reconfigured.
-    ON_CALL(*mock_pss_, GetDisableReasons())
-        .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
-    ON_CALL(*mock_pss_, GetTransportState())
-        .WillByDefault(
-            Return(syncer::SyncService::TransportState::CONFIGURING));
-  });
+  EXPECT_CALL(*mock_pss_->GetUserSettingsMock(), SetSyncRequested(true))
+      .WillOnce([&](bool) {
+        // SetSyncRequested(true) clears DISABLE_REASON_USER_CHOICE. Since the
+        // engine is already running, it just gets reconfigured.
+        ON_CALL(*mock_pss_, GetDisableReasons())
+            .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
+        ON_CALL(*mock_pss_->GetUserSettingsMock(), IsSyncRequested())
+            .WillByDefault(Return(true));
+        ON_CALL(*mock_pss_, GetTransportState())
+            .WillByDefault(
+                Return(syncer::SyncService::TransportState::CONFIGURING));
+      });
 
   handler_->HandleShowSetupUI(nullptr);
   ExpectPageStatusChanged(PeopleHandler::kSpinnerPageStatus);
@@ -576,7 +600,8 @@
 TEST_F(PeopleHandlerTest, OnlyStartEngineWhenConfiguringSync) {
   ON_CALL(*mock_pss_, GetTransportState())
       .WillByDefault(Return(syncer::SyncService::TransportState::INITIALIZING));
-  EXPECT_CALL(*mock_pss_, RequestStart()).Times(0);
+  EXPECT_CALL(*mock_pss_->GetUserSettingsMock(), SetSyncRequested(true))
+      .Times(0);
   NotifySyncStateChanged();
 }
 
@@ -614,7 +639,8 @@
   ON_CALL(*mock_pss_, GetDisableReasons())
       .WillByDefault(
           Return(syncer::SyncService::DISABLE_REASON_UNRECOVERABLE_ERROR));
-  ON_CALL(*mock_pss_, IsFirstSetupComplete()).WillByDefault(Return(false));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsFirstSetupComplete())
+      .WillByDefault(Return(false));
   // Open the web UI.
   handler_->HandleShowSetupUI(nullptr);
 
@@ -624,7 +650,8 @@
 TEST_F(PeopleHandlerNonCrosTest, GaiaErrorInitializingSync) {
   ON_CALL(*mock_pss_, GetDisableReasons())
       .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN));
-  ON_CALL(*mock_pss_, IsFirstSetupComplete()).WillByDefault(Return(false));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsFirstSetupComplete())
+      .WillByDefault(Return(false));
   // Open the web UI.
   handler_->HandleShowSetupUI(nullptr);
 
@@ -639,11 +666,13 @@
   base::ListValue list_args;
   list_args.AppendString(kTestCallbackId);
   list_args.AppendString(args);
-  ON_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
+  ON_CALL(*mock_pss_->GetUserSettingsMock(),
+          IsPassphraseRequiredForDecryption())
       .WillByDefault(Return(false));
-  ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsPassphraseRequired())
+      .WillByDefault(Return(false));
   SetupInitializedProfileSyncService();
-  EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(true, _));
+  EXPECT_CALL(*mock_pss_->GetUserSettingsMock(), SetChosenDataTypes(true, _));
   handler_->HandleSetDatatypes(&list_args);
 
   ExpectPageStatusResponse(PeopleHandler::kConfigurePageStatus);
@@ -655,10 +684,12 @@
   base::ListValue list_args;
   list_args.AppendString(kTestCallbackId);
   list_args.AppendString(args);
-  ON_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
+  ON_CALL(*mock_pss_->GetUserSettingsMock(),
+          IsPassphraseRequiredForDecryption())
       .WillByDefault(Return(true));
-  ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(true));
-  ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsPassphraseRequired())
+      .WillByDefault(Return(true));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsUsingSecondaryPassphrase())
       .WillByDefault(Return(false));
   SetupInitializedProfileSyncService();
   SetDefaultExpectationsForConfigPage();
@@ -678,13 +709,16 @@
   list_args.AppendString(args);
   // Act as if an encryption passphrase is required the first time, then never
   // again after that.
-  EXPECT_CALL(*mock_pss_, IsPassphraseRequired()).WillOnce(Return(true));
-  ON_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
+  EXPECT_CALL(*mock_pss_->GetUserSettingsMock(), IsPassphraseRequired())
+      .WillOnce(Return(true));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(),
+          IsPassphraseRequiredForDecryption())
       .WillByDefault(Return(false));
-  ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsUsingSecondaryPassphrase())
       .WillByDefault(Return(false));
   SetupInitializedProfileSyncService();
-  EXPECT_CALL(*mock_pss_, SetDecryptionPassphrase("oldGaiaPassphrase"))
+  EXPECT_CALL(*mock_pss_->GetUserSettingsMock(),
+              SetDecryptionPassphrase("oldGaiaPassphrase"))
       .WillOnce(Return(true));
 
   handler_->HandleSetEncryption(&list_args);
@@ -699,13 +733,16 @@
   base::ListValue list_args;
   list_args.AppendString(kTestCallbackId);
   list_args.AppendString(args);
-  ON_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
+  ON_CALL(*mock_pss_->GetUserSettingsMock(),
+          IsPassphraseRequiredForDecryption())
       .WillByDefault(Return(false));
-  ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false));
-  ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsPassphraseRequired())
+      .WillByDefault(Return(false));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsUsingSecondaryPassphrase())
       .WillByDefault(Return(false));
   SetupInitializedProfileSyncService();
-  EXPECT_CALL(*mock_pss_, SetEncryptionPassphrase("custom_passphrase"));
+  EXPECT_CALL(*mock_pss_->GetUserSettingsMock(),
+              SetEncryptionPassphrase("custom_passphrase"));
 
   handler_->HandleSetEncryption(&list_args);
   ExpectPageStatusResponse(PeopleHandler::kConfigurePageStatus);
@@ -719,14 +756,17 @@
   base::ListValue list_args;
   list_args.AppendString(kTestCallbackId);
   list_args.AppendString(args);
-  ON_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
+  ON_CALL(*mock_pss_->GetUserSettingsMock(),
+          IsPassphraseRequiredForDecryption())
       .WillByDefault(Return(true));
-  ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(true));
-  ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsPassphraseRequired())
+      .WillByDefault(Return(true));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsUsingSecondaryPassphrase())
       .WillByDefault(Return(false));
   SetupInitializedProfileSyncService();
-  EXPECT_CALL(*mock_pss_, SetDecryptionPassphrase("invalid_passphrase")).
-      WillOnce(Return(false));
+  EXPECT_CALL(*mock_pss_->GetUserSettingsMock(),
+              SetDecryptionPassphrase("invalid_passphrase"))
+      .WillOnce(Return(false));
 
   SetDefaultExpectationsForConfigPage();
 
@@ -746,10 +786,12 @@
   base::ListValue list_args;
   list_args.AppendString(kTestCallbackId);
   list_args.AppendString(args);
-  ON_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
+  ON_CALL(*mock_pss_->GetUserSettingsMock(),
+          IsPassphraseRequiredForDecryption())
       .WillByDefault(Return(true));
-  ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(true));
-  ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsPassphraseRequired())
+      .WillByDefault(Return(true));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsUsingSecondaryPassphrase())
       .WillByDefault(Return(false));
   SetupInitializedProfileSyncService();
 
@@ -775,12 +817,14 @@
     base::ListValue list_args;
     list_args.AppendString(kTestCallbackId);
     list_args.AppendString(args);
-    ON_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
+    ON_CALL(*mock_pss_->GetUserSettingsMock(),
+            IsPassphraseRequiredForDecryption())
         .WillByDefault(Return(false));
-    ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false));
+    ON_CALL(*mock_pss_->GetUserSettingsMock(), IsPassphraseRequired())
+        .WillByDefault(Return(false));
     SetupInitializedProfileSyncService();
-    EXPECT_CALL(*mock_pss_,
-                OnUserChoseDatatypes(false, ModelTypeSetMatches(type_to_set)));
+    EXPECT_CALL(*mock_pss_->GetUserSettingsMock(),
+                SetChosenDataTypes(false, ModelTypeSetMatches(type_to_set)));
 
     handler_->HandleSetDatatypes(&list_args);
     ExpectPageStatusResponse(PeopleHandler::kConfigurePageStatus);
@@ -797,20 +841,23 @@
   base::ListValue list_args;
   list_args.AppendString(kTestCallbackId);
   list_args.AppendString(args);
-  ON_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
+  ON_CALL(*mock_pss_->GetUserSettingsMock(),
+          IsPassphraseRequiredForDecryption())
       .WillByDefault(Return(false));
-  ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsPassphraseRequired())
+      .WillByDefault(Return(false));
   SetupInitializedProfileSyncService();
-  EXPECT_CALL(*mock_pss_,
-              OnUserChoseDatatypes(false, ModelTypeSetMatches(GetAllTypes())));
+  EXPECT_CALL(*mock_pss_->GetUserSettingsMock(),
+              SetChosenDataTypes(false, ModelTypeSetMatches(GetAllTypes())));
   handler_->HandleSetDatatypes(&list_args);
 
   ExpectPageStatusResponse(PeopleHandler::kConfigurePageStatus);
 }
 
 TEST_F(PeopleHandlerTest, ShowSyncSetup) {
-  ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false));
-  ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsPassphraseRequired())
+      .WillByDefault(Return(false));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsUsingSecondaryPassphrase())
       .WillByDefault(Return(false));
   SetupInitializedProfileSyncService();
   // This should display the sync setup dialog (not login).
@@ -843,8 +890,11 @@
 
   ON_CALL(*mock_pss_, GetDisableReasons())
       .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
-  ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false));
-  ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsSyncRequested())
+      .WillByDefault(Return(true));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsPassphraseRequired())
+      .WillByDefault(Return(false));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsUsingSecondaryPassphrase())
       .WillByDefault(Return(false));
   ON_CALL(*mock_pss_, GetTransportState())
       .WillByDefault(Return(syncer::SyncService::TransportState::INITIALIZING));
@@ -874,8 +924,9 @@
 }
 
 TEST_F(PeopleHandlerTest, ShowSetupSyncEverything) {
-  ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false));
-  ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsPassphraseRequired())
+      .WillByDefault(Return(false));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsUsingSecondaryPassphrase())
       .WillByDefault(Return(false));
   SetupInitializedProfileSyncService();
   SetDefaultExpectationsForConfigPage();
@@ -901,13 +952,14 @@
 }
 
 TEST_F(PeopleHandlerTest, ShowSetupManuallySyncAll) {
-  ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false));
-  ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsPassphraseRequired())
+      .WillByDefault(Return(false));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsUsingSecondaryPassphrase())
       .WillByDefault(Return(false));
   SetupInitializedProfileSyncService();
-  syncer::SyncPrefs sync_prefs(profile()->GetPrefs());
-  sync_prefs.SetKeepEverythingSynced(false);
   SetDefaultExpectationsForConfigPage();
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsSyncEverythingEnabled())
+      .WillByDefault(Return(false));
   // This should display the sync setup dialog (not login).
   handler_->HandleShowSetupUI(nullptr);
 
@@ -918,16 +970,18 @@
 TEST_F(PeopleHandlerTest, ShowSetupSyncForAllTypesIndividually) {
   syncer::ModelTypeSet user_selectable_types = GetAllTypes();
   for (syncer::ModelType type : user_selectable_types) {
-    ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false));
-    ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
+    ON_CALL(*mock_pss_->GetUserSettingsMock(), IsPassphraseRequired())
+        .WillByDefault(Return(false));
+    ON_CALL(*mock_pss_->GetUserSettingsMock(), IsUsingSecondaryPassphrase())
         .WillByDefault(Return(false));
     SetupInitializedProfileSyncService();
-    syncer::SyncPrefs sync_prefs(profile()->GetPrefs());
-    sync_prefs.SetKeepEverythingSynced(false);
     SetDefaultExpectationsForConfigPage();
+    ON_CALL(*mock_pss_->GetUserSettingsMock(), IsSyncEverythingEnabled())
+        .WillByDefault(Return(false));
     syncer::ModelTypeSet types;
     types.Put(type);
-    ON_CALL(*mock_pss_, GetPreferredDataTypes()).WillByDefault(Return(types));
+    ON_CALL(*mock_pss_->GetUserSettingsMock(), GetChosenDataTypes())
+        .WillByDefault(Return(types));
 
     // This should display the sync setup dialog (not login).
     handler_->HandleShowSetupUI(nullptr);
@@ -945,8 +999,9 @@
 }
 
 TEST_F(PeopleHandlerTest, ShowSetupOldGaiaPassphraseRequired) {
-  ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(true));
-  ON_CALL(*mock_pss_, GetPassphraseType())
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsPassphraseRequired())
+      .WillByDefault(Return(true));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), GetPassphraseType())
       .WillByDefault(
           Return(syncer::PassphraseType::FROZEN_IMPLICIT_PASSPHRASE));
   SetupInitializedProfileSyncService();
@@ -961,8 +1016,9 @@
 }
 
 TEST_F(PeopleHandlerTest, ShowSetupCustomPassphraseRequired) {
-  ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(true));
-  ON_CALL(*mock_pss_, GetPassphraseType())
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsPassphraseRequired())
+      .WillByDefault(Return(true));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), GetPassphraseType())
       .WillByDefault(Return(syncer::PassphraseType::CUSTOM_PASSPHRASE));
   SetupInitializedProfileSyncService();
   SetDefaultExpectationsForConfigPage();
@@ -976,12 +1032,14 @@
 }
 
 TEST_F(PeopleHandlerTest, ShowSetupEncryptAll) {
-  ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false));
-  ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsPassphraseRequired())
+      .WillByDefault(Return(false));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsUsingSecondaryPassphrase())
       .WillByDefault(Return(false));
   SetupInitializedProfileSyncService();
   SetDefaultExpectationsForConfigPage();
-  ON_CALL(*mock_pss_, IsEncryptEverythingEnabled()).WillByDefault(Return(true));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsEncryptEverythingEnabled())
+      .WillByDefault(Return(true));
 
   // This should display the sync setup dialog (not login).
   handler_->HandleShowSetupUI(nullptr);
@@ -991,12 +1049,13 @@
 }
 
 TEST_F(PeopleHandlerTest, ShowSetupEncryptAllDisallowed) {
-  ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false));
-  ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsPassphraseRequired())
+      .WillByDefault(Return(false));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsUsingSecondaryPassphrase())
       .WillByDefault(Return(false));
   SetupInitializedProfileSyncService();
   SetDefaultExpectationsForConfigPage();
-  ON_CALL(*mock_pss_, IsEncryptEverythingAllowed())
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsEncryptEverythingAllowed())
       .WillByDefault(Return(false));
 
   // This should display the sync setup dialog (not login).
@@ -1013,13 +1072,16 @@
   base::ListValue list_args;
   list_args.AppendString(kTestCallbackId);
   list_args.AppendString(args);
-  ON_CALL(*mock_pss_, IsPassphraseRequiredForDecryption())
+  ON_CALL(*mock_pss_->GetUserSettingsMock(),
+          IsPassphraseRequiredForDecryption())
       .WillByDefault(Return(false));
-  ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false));
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsPassphraseRequired())
+      .WillByDefault(Return(false));
   SetupInitializedProfileSyncService();
-  ON_CALL(*mock_pss_, IsEncryptEverythingAllowed())
+  ON_CALL(*mock_pss_->GetUserSettingsMock(), IsEncryptEverythingAllowed())
       .WillByDefault(Return(false));
-  EXPECT_CALL(*mock_pss_, EnableEncryptEverything()).Times(0);
+  EXPECT_CALL(*mock_pss_->GetUserSettingsMock(), EnableEncryptEverything())
+      .Times(0);
   handler_->HandleSetEncryption(&list_args);
 
   ExpectPageStatusResponse(PeopleHandler::kConfigurePageStatus);
diff --git a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc
index 23e3479..f792772a 100644
--- a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc
+++ b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc
@@ -624,7 +624,9 @@
   // Set expectations.
   expected_sync_confirmation_shown_ = true;
   SetExpectationsForSyncStartupCompleted();
-  EXPECT_CALL(*GetProfileSyncServiceMock(), SetFirstSetupComplete()).Times(0);
+  EXPECT_CALL(*GetProfileSyncServiceMock()->GetUserSettingsMock(),
+              SetFirstSetupComplete())
+      .Times(0);
 
   // Signin flow.
   EXPECT_FALSE(signin_manager()->IsAuthenticated());
@@ -642,7 +644,9 @@
   expected_sync_confirmation_shown_ = true;
   expected_sync_settings_shown_ = true;
   SetExpectationsForSyncStartupCompleted();
-  EXPECT_CALL(*GetProfileSyncServiceMock(), SetFirstSetupComplete()).Times(0);
+  EXPECT_CALL(*GetProfileSyncServiceMock()->GetUserSettingsMock(),
+              SetFirstSetupComplete())
+      .Times(0);
 
   // Configure the test.
   sync_confirmation_result_ =
@@ -662,7 +666,9 @@
   // Set expectations.
   expected_sync_confirmation_shown_ = true;
   SetExpectationsForSyncStartupCompleted();
-  EXPECT_CALL(*GetProfileSyncServiceMock(), SetFirstSetupComplete()).Times(1);
+  EXPECT_CALL(*GetProfileSyncServiceMock()->GetUserSettingsMock(),
+              SetFirstSetupComplete())
+      .Times(1);
   // Configure the test.
   sync_confirmation_result_ = LoginUIService::SyncConfirmationUIClosedResult::
       SYNC_WITH_DEFAULT_SETTINGS;
@@ -684,7 +690,9 @@
   sync_confirmation_result_ = LoginUIService::SyncConfirmationUIClosedResult::
       SYNC_WITH_DEFAULT_SETTINGS;
   SetExpectationsForSyncStartupCompleted();
-  EXPECT_CALL(*GetProfileSyncServiceMock(), SetFirstSetupComplete()).Times(1);
+  EXPECT_CALL(*GetProfileSyncServiceMock()->GetUserSettingsMock(),
+              SetFirstSetupComplete())
+      .Times(1);
 
   // Signin flow.
   EXPECT_FALSE(signin_manager()->IsAuthenticated());
@@ -706,7 +714,9 @@
   sync_confirmation_result_ = LoginUIService::SyncConfirmationUIClosedResult::
       SYNC_WITH_DEFAULT_SETTINGS;
   SetExpectationsForSyncStartupCompleted();
-  EXPECT_CALL(*GetProfileSyncServiceMock(), SetFirstSetupComplete()).Times(1);
+  EXPECT_CALL(*GetProfileSyncServiceMock()->GetUserSettingsMock(),
+              SetFirstSetupComplete())
+      .Times(1);
   using Service = UnifiedConsentServiceClient::Service;
   using ServiceState = UnifiedConsentServiceClient::ServiceState;
   PrefService* pref_service = profile()->GetPrefs();
@@ -770,7 +780,9 @@
 
   // Simulate that sync startup has completed.
   expected_sync_confirmation_shown_ = true;
-  EXPECT_CALL(*GetProfileSyncServiceMock(), SetFirstSetupComplete()).Times(1);
+  EXPECT_CALL(*GetProfileSyncServiceMock()->GetUserSettingsMock(),
+              SetFirstSetupComplete())
+      .Times(1);
   sync_confirmation_result_ = LoginUIService::SyncConfirmationUIClosedResult::
       SYNC_WITH_DEFAULT_SETTINGS;
   dice_sync_starter->SyncStartupCompleted();
@@ -802,7 +814,9 @@
 
   // Simulate that sync startup has failed.
   expected_sync_confirmation_shown_ = true;
-  EXPECT_CALL(*GetProfileSyncServiceMock(), SetFirstSetupComplete()).Times(1);
+  EXPECT_CALL(*GetProfileSyncServiceMock()->GetUserSettingsMock(),
+              SetFirstSetupComplete())
+      .Times(1);
   sync_confirmation_result_ = LoginUIService::SyncConfirmationUIClosedResult::
       SYNC_WITH_DEFAULT_SETTINGS;
   dice_sync_starter->SyncStartupFailed();
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.cc b/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.cc
index 31cb50ef..a6dbae9 100644
--- a/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.cc
+++ b/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.cc
@@ -10,7 +10,9 @@
 #include "base/macros.h"
 #include "chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h"
 #include "chrome/common/webui_url_constants.h"
+#include "net/base/url_util.h"
 #include "ui/aura/window.h"
+#include "url/gurl.h"
 
 namespace chromeos {
 
@@ -21,20 +23,26 @@
 }  // namespace
 
 // static
-void InlineLoginHandlerDialogChromeOS::Show() {
+void InlineLoginHandlerDialogChromeOS::Show(const std::string& email) {
   if (dialog) {
     dialog->dialog_window()->Focus();
     return;
   }
 
+  GURL url(chrome::kChromeUIChromeSigninURL);
+  if (!email.empty()) {
+    url = net::AppendQueryParameter(url, "email", email);
+    url = net::AppendQueryParameter(url, "readOnlyEmail", "true");
+  }
+
   // Will be deleted by |SystemWebDialogDelegate::OnDialogClosed|.
-  dialog = new InlineLoginHandlerDialogChromeOS();
+  dialog = new InlineLoginHandlerDialogChromeOS(url);
   dialog->ShowSystemDialog();
 }
 
-InlineLoginHandlerDialogChromeOS::InlineLoginHandlerDialogChromeOS()
-    : SystemWebDialogDelegate(GURL(chrome::kChromeUIChromeSigninURL),
-                              base::string16() /* title */) {}
+InlineLoginHandlerDialogChromeOS::InlineLoginHandlerDialogChromeOS(
+    const GURL& url)
+    : SystemWebDialogDelegate(url, base::string16() /* title */) {}
 
 InlineLoginHandlerDialogChromeOS::~InlineLoginHandlerDialogChromeOS() {
   DCHECK_EQ(this, dialog);
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h b/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h
index 0ee3792..192f1be 100644
--- a/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h
+++ b/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h
@@ -10,6 +10,8 @@
 #include "base/macros.h"
 #include "chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h"
 
+class GURL;
+
 namespace chromeos {
 
 // Extends from |SystemWebDialogDelegate| to create an always-on-top but movable
@@ -17,10 +19,13 @@
 // passwords from password managers.
 class InlineLoginHandlerDialogChromeOS : public SystemWebDialogDelegate {
  public:
-  static void Show();
+  // Displays the dialog. |email| is an optional parameter that if provided,
+  // pre-fills the account email field in the sign-in dialog - useful for
+  // account re-authentication.
+  static void Show(const std::string& email = std::string());
 
  protected:
-  InlineLoginHandlerDialogChromeOS();
+  explicit InlineLoginHandlerDialogChromeOS(const GURL& url);
   ~InlineLoginHandlerDialogChromeOS() override;
 
   // ui::WebDialogDelegate overrides
diff --git a/chrome/browser/vr/speech_recognizer_unittest.cc b/chrome/browser/vr/speech_recognizer_unittest.cc
index 60613b1a..6a1b657 100644
--- a/chrome/browser/vr/speech_recognizer_unittest.cc
+++ b/chrome/browser/vr/speech_recognizer_unittest.cc
@@ -19,7 +19,6 @@
 #include "content/public/browser/speech_recognition_manager.h"
 #include "content/public/browser/speech_recognition_session_config.h"
 #include "content/public/browser/speech_recognition_session_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/test/test_url_loader_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -271,7 +270,6 @@
   }
 
  protected:
-  content::TestBrowserThreadBundle thread_bundle_;
   std::unique_ptr<FakeSpeechRecognitionManager>
       fake_speech_recognition_manager_;
   std::unique_ptr<MockBrowserUiInterface> ui_;
diff --git a/chrome/browser/vr/test/vr_test_suite.cc b/chrome/browser/vr/test/vr_test_suite.cc
index 6e95bee..351725a 100644
--- a/chrome/browser/vr/test/vr_test_suite.cc
+++ b/chrome/browser/vr/test/vr_test_suite.cc
@@ -8,8 +8,8 @@
 
 #include "base/files/file_util.h"
 #include "base/path_service.h"
-#include "base/test/scoped_task_environment.h"
 #include "build/build_config.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "mojo/core/embedder/embedder.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -24,9 +24,7 @@
 void VrTestSuite::Initialize() {
   base::TestSuite::Initialize();
 
-  scoped_task_environment_ =
-      std::make_unique<base::test::ScopedTaskEnvironment>(
-          base::test::ScopedTaskEnvironment::MainThreadType::UI);
+  thread_bundle_ = std::make_unique<content::TestBrowserThreadBundle>();
 
   mojo::core::Init();
 
diff --git a/chrome/browser/vr/test/vr_test_suite.h b/chrome/browser/vr/test/vr_test_suite.h
index 20662ed..e447f1c 100644
--- a/chrome/browser/vr/test/vr_test_suite.h
+++ b/chrome/browser/vr/test/vr_test_suite.h
@@ -7,11 +7,9 @@
 
 #include "base/test/test_suite.h"
 
-namespace base {
-namespace test {
-class ScopedTaskEnvironment;
-}  // namespace test
-}  // namespace base
+namespace content {
+class TestBrowserThreadBundle;
+}  // namespace content
 
 namespace vr {
 
@@ -25,7 +23,7 @@
   void Shutdown() override;
 
  private:
-  std::unique_ptr<base::test::ScopedTaskEnvironment> scoped_task_environment_;
+  std::unique_ptr<content::TestBrowserThreadBundle> thread_bundle_;
 
   DISALLOW_COPY_AND_ASSIGN(VrTestSuite);
 };
diff --git a/chrome/common/apps/platform_apps/api/_api_features.json b/chrome/common/apps/platform_apps/api/_api_features.json
index 5440309..5fc887d2 100644
--- a/chrome/common/apps/platform_apps/api/_api_features.json
+++ b/chrome/common/apps/platform_apps/api/_api_features.json
@@ -7,6 +7,10 @@
 // well as feature.h, simple_feature.h, and feature_provider.h.
 
 {
+  "arcAppsPrivate": {
+    "dependencies": ["permission:arcAppsPrivate"],
+    "contexts": ["blessed_extension"]
+  },
   "browser": {
     "dependencies": ["permission:browser"],
     "contexts": ["blessed_extension"]
diff --git a/chrome/common/apps/platform_apps/api/_permission_features.json b/chrome/common/apps/platform_apps/api/_permission_features.json
index b51ca8f5..8ed6768f 100644
--- a/chrome/common/apps/platform_apps/api/_permission_features.json
+++ b/chrome/common/apps/platform_apps/api/_permission_features.json
@@ -7,6 +7,15 @@
 // well as feature.h, simple_feature.h, and feature_provider.h.
 
 {
+  "arcAppsPrivate": {
+    "channel": "stable",
+    "extension_types": ["platform_app"],
+    "whitelist": [
+      "46578A13607D38F1DC8E280C4F499FB0A2F9565C", // http://crbug.com/819404
+      "898FB5A39687D210766B8998BA4530B99C9E6586", // http://crbug.com/819404
+      "82F30B65397BC3E4ADE627BBD857AB8A58210648"  // http://crbug.com/819404
+    ]
+  },
   "browser": {
     "channel": "stable",
     "extension_types": ["platform_app"]
diff --git a/chrome/common/apps/platform_apps/api/api_sources.gni b/chrome/common/apps/platform_apps/api/api_sources.gni
index f8550a3..2d3c68a 100644
--- a/chrome/common/apps/platform_apps/api/api_sources.gni
+++ b/chrome/common/apps/platform_apps/api/api_sources.gni
@@ -17,6 +17,10 @@
   "webstore_widget_private.idl",
 ]
 
+if (is_chromeos) {
+  chrome_apps_api_schema_files_ += [ "arc_apps_private.idl" ]
+}
+
 chrome_apps_uncompiled_schema_files_ = [ "music_manager_private.idl" ]
 
 chrome_apps_api_schema_files =
diff --git a/chrome/common/extensions/api/arc_apps_private.idl b/chrome/common/apps/platform_apps/api/arc_apps_private.idl
similarity index 90%
rename from chrome/common/extensions/api/arc_apps_private.idl
rename to chrome/common/apps/platform_apps/api/arc_apps_private.idl
index 7f32cdf..1a3dd23 100644
--- a/chrome/common/extensions/api/arc_apps_private.idl
+++ b/chrome/common/apps/platform_apps/api/arc_apps_private.idl
@@ -3,9 +3,7 @@
 // found in the LICENSE file.
 
 // Use the <code>chrome.arcAppsPrivate</code> API to manage ARC apps.
-[platforms=("chromeos"),
- implemented_in="chrome/browser/chromeos/extensions/arc_apps_private_api.h",
- nodoc]
+[platforms=("chromeos"), nodoc]
 namespace arcAppsPrivate {
 
   dictionary AppInfo {
@@ -32,4 +30,4 @@
     // Fires when a new app can be launched via $(ref:launchApp).
     static void onInstalled(AppInfo app_info);
   };
-};
\ No newline at end of file
+};
diff --git a/chrome/common/apps/platform_apps/chrome_apps_api_permissions.cc b/chrome/common/apps/platform_apps/chrome_apps_api_permissions.cc
index ba1af872..7fa3080 100644
--- a/chrome/common/apps/platform_apps/chrome_apps_api_permissions.cc
+++ b/chrome/common/apps/platform_apps/chrome_apps_api_permissions.cc
@@ -21,6 +21,7 @@
 // add the corresponding permission message rule to
 // ChromePermissionMessageProvider::GetPermissionMessages as well.
 constexpr extensions::APIPermissionInfo::InitInfo permissions_to_register[] = {
+    {extensions::APIPermission::kArcAppsPrivate, "arcAppsPrivate"},
     {extensions::APIPermission::kBrowser, "browser"},
     {extensions::APIPermission::kMusicManagerPrivate, "musicManagerPrivate",
      extensions::APIPermissionInfo::kFlagCannotBeOptional},
diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json
index cad43c6..a5c0d276 100644
--- a/chrome/common/extensions/api/_api_features.json
+++ b/chrome/common/extensions/api/_api_features.json
@@ -97,10 +97,6 @@
     "dependencies": ["permission:appview"],
     "contexts": ["blessed_extension"]
   },
-  "arcAppsPrivate": {
-    "dependencies": ["permission:arcAppsPrivate"],
-    "contexts": ["blessed_extension"]
-  },
   "autofillPrivate": [{
     "dependencies": ["permission:autofillPrivate"],
     "contexts": ["blessed_extension"]
diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json
index 4a66d88..63b2b25 100644
--- a/chrome/common/extensions/api/_permission_features.json
+++ b/chrome/common/extensions/api/_permission_features.json
@@ -47,15 +47,6 @@
       "5107DE9024C329EEA9C9A72D94C16723790C6422"   // Apps Developer Tool Dev.
     ]
   },
-  "arcAppsPrivate": {
-    "channel": "stable",
-    "extension_types": ["platform_app"],
-    "whitelist": [
-      "46578A13607D38F1DC8E280C4F499FB0A2F9565C", // http://crbug.com/819404
-      "898FB5A39687D210766B8998BA4530B99C9E6586", // http://crbug.com/819404
-      "82F30B65397BC3E4ADE627BBD857AB8A58210648"  // http://crbug.com/819404
-    ]
-  },
   "autofillPrivate": {
     "channel": "trunk",
     "extension_types": ["extension", "platform_app"],
diff --git a/chrome/common/extensions/api/api_sources.gni b/chrome/common/extensions/api/api_sources.gni
index dffbca5..0eecbabb8 100644
--- a/chrome/common/extensions/api/api_sources.gni
+++ b/chrome/common/extensions/api/api_sources.gni
@@ -85,7 +85,6 @@
 
 if (is_chromeos) {
   schema_sources_ += [
-    "arc_apps_private.idl",
     "certificate_provider.idl",
     "certificate_provider_internal.idl",
     "echo_private.json",
diff --git a/chrome/common/extensions/permissions/chrome_api_permissions.cc b/chrome/common/extensions/permissions/chrome_api_permissions.cc
index bb7e7399..6629463 100644
--- a/chrome/common/extensions/permissions/chrome_api_permissions.cc
+++ b/chrome/common/extensions/permissions/chrome_api_permissions.cc
@@ -174,7 +174,6 @@
     {APIPermission::kResourcesPrivate, "resourcesPrivate",
      APIPermissionInfo::kFlagCannotBeOptional},
     {APIPermission::kSafeBrowsingPrivate, "safeBrowsingPrivate"},
-    {APIPermission::kArcAppsPrivate, "arcAppsPrivate"},
 
     // Full url access permissions.
     {APIPermission::kDebugger, "debugger",
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 98a43ed7..e68ca34b 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -914,9 +914,6 @@
 const char kSpeechRecognitionFilterProfanities[] =
     "browser.speechinput_censor_results";
 
-// Boolean controlling whether history saving is disabled.
-const char kSavingBrowserHistoryDisabled[] = "history.saving_disabled";
-
 // Boolean controlling whether deleting browsing and download history is
 // permitted.
 const char kAllowDeletingBrowserHistory[] = "history.deleting_enabled";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index cfaf5c5..15110bb 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -290,7 +290,6 @@
 #endif  // defined(OS_CHROMEOS)
 extern const char kShowHomeButton[];
 extern const char kSpeechRecognitionFilterProfanities[];
-extern const char kSavingBrowserHistoryDisabled[];
 extern const char kAllowDeletingBrowserHistory[];
 #if !defined(OS_ANDROID)
 extern const char kMdHistoryMenuPromoShown[];
diff --git a/chrome/credential_provider/common/gcp_strings.cc b/chrome/credential_provider/common/gcp_strings.cc
index 29dab3a1..f52b9821 100644
--- a/chrome/credential_provider/common/gcp_strings.cc
+++ b/chrome/credential_provider/common/gcp_strings.cc
@@ -51,4 +51,10 @@
 
 const wchar_t kRunAsCrashpadHandlerEntryPoint[] = L"RunAsCrashpadHandler";
 
+#if defined(GOOGLE_CHROME_BUILD)
+const wchar_t kRegHkcuAccountsPath[] = L"Software\\Google\\Accounts";
+#else
+const wchar_t kRegHkcuAccountsPath[] = L"Software\\Chromium\\Accounts";
+#endif  // defined(GOOGLE_CHROME_BUILD)
+
 }  // namespace credential_provider
diff --git a/chrome/credential_provider/common/gcp_strings.h b/chrome/credential_provider/common/gcp_strings.h
index b9e3bc5..9fe6a39 100644
--- a/chrome/credential_provider/common/gcp_strings.h
+++ b/chrome/credential_provider/common/gcp_strings.h
@@ -44,11 +44,15 @@
 extern const char kGcpwSigninSwitch[];
 extern const char kEmailDomainSwitch[];
 
+// Parameter appended to sign in URL to pass domain hint to GAIA.
 extern const char kEmailDomainSigninPromoParameter[];
 
 // Crashpad related constants
 extern const wchar_t kRunAsCrashpadHandlerEntryPoint[];
 
+// HKCU account information path in the hive of the OS user.
+extern const wchar_t kRegHkcuAccountsPath[];
+
 }  // namespace credential_provider
 
 #endif  // CHROME_CREDENTIAL_PROVIDER_COMMON_GCP_STRINGS_H_
diff --git a/chrome/credential_provider/gaiacp/scoped_user_profile.cc b/chrome/credential_provider/gaiacp/scoped_user_profile.cc
index 79ff67d9..757c5d85 100644
--- a/chrome/credential_provider/gaiacp/scoped_user_profile.cc
+++ b/chrome/credential_provider/gaiacp/scoped_user_profile.cc
@@ -22,13 +22,6 @@
 
 namespace {
 
-// Registry key under HKCU to write account info into.
-#if defined(GOOGLE_CHROME_BUILD)
-const wchar_t kRegAccountsPath[] = L"Software\\Google\\Accounts";
-#else
-const wchar_t kRegAccountsPath[] = L"Software\\Chromium\\Accounts";
-#endif  // defined(GOOGLE_CHROME_BUILD)
-
 // Retry count when attempting to determine if the user's OS profile has
 // been created.  In slow envrionments, like VMs used for testing, it may
 // take some time to create the OS profile so checks are done periodically.
@@ -177,7 +170,7 @@
   {
     wchar_t key_name[128];
     swprintf_s(key_name, base::size(key_name), L"%s\\%s\\%s", sid.c_str(),
-               kRegAccountsPath, id.c_str());
+               kRegHkcuAccountsPath, id.c_str());
     LOGFN(INFO) << "HKU\\" << key_name;
 
     base::win::RegKey key;
@@ -247,7 +240,7 @@
   base::win::RegKey key;
   wchar_t key_name[128];
   swprintf_s(key_name, base::size(key_name), L"%s\\%s", sid.c_str(),
-             kRegAccountsPath);
+             kRegHkcuAccountsPath);
   LOGFN(INFO) << "HKU\\" << key_name;
 
   for (int i = 0; i < kWaitForProfileCreationRetryCount; ++i) {
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 6a4d1962..8abe571 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1170,6 +1170,9 @@
         "../browser/signin/dice_browsertest.cc",
         "../browser/unified_consent/unified_consent_browsertest.cc",
       ]
+      if (is_win) {
+        sources += [ "../browser/signin/signin_util_win_browsertest.cc" ]
+      }
     }
     if (!enable_one_click_signin) {
       sources -= [ "../browser/ui/sync/one_click_signin_links_delegate_impl_browsertest.cc" ]
@@ -1466,7 +1469,10 @@
       }
 
       if (is_chromeos) {
-        sources += [ "../browser/extensions/api/system_display/system_display_chromeos_apitest.cc" ]
+        sources += [
+          "../browser/apps/platform_apps/api/arc_apps_private/arc_apps_private_apitest.cc",
+          "../browser/extensions/api/system_display/system_display_chromeos_apitest.cc",
+        ]
       }
 
       deps += [
@@ -1651,7 +1657,6 @@
         "../browser/chromeos/drive/drive_integration_service_browsertest.cc",
         "../browser/chromeos/extensions/accessibility_features_apitest.cc",
         "../browser/chromeos/extensions/action_handlers/action_handlers_apitest.cc",
-        "../browser/chromeos/extensions/arc_apps_private_apitest.cc",
         "../browser/chromeos/extensions/autotest_private/autotest_private_apitest.cc",
         "../browser/chromeos/extensions/default_keyboard_extension_browser_test.cc",
         "../browser/chromeos/extensions/default_keyboard_extension_browser_test.h",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java
index 260845a..420c9d4 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java
@@ -33,6 +33,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
+import org.chromium.chrome.test.util.browser.TabTitleObserver;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.test.util.TestTouchUtils;
@@ -51,7 +52,7 @@
  */
 public class ChromeTabUtils {
     private static final String TAG = "cr_ChromeTabUtils";
-
+    public static final int TITLE_UPDATE_TIMEOUT_MS = 3000;
     /**
      * An observer that waits for a Tab to load a page.
      *
@@ -748,4 +749,14 @@
             observer.simulateRendererKilledForTesting(wasOomProtected);
         }
     }
+
+    public static void waitForTitle(Tab tab, String newTitle) throws InterruptedException {
+        TabTitleObserver titleObserver = new TabTitleObserver(tab, newTitle);
+        try {
+            titleObserver.waitForTitleUpdate(TITLE_UPDATE_TIMEOUT_MS);
+        } catch (TimeoutException e) {
+            Assert.fail(String.format(Locale.ENGLISH,
+                    "Tab title didn't update to %s in time.", newTitle));
+        }
+    }
 }
diff --git a/chrome/test/chromedriver/element_commands.cc b/chrome/test/chromedriver/element_commands.cc
index 4e7542ac..57043bf7 100644
--- a/chrome/test/chromedriver/element_commands.cc
+++ b/chrome/test/chromedriver/element_commands.cc
@@ -37,11 +37,14 @@
     Session* session,
     WebView* web_view,
     const std::string& element_id) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   bool is_displayed = false;
   bool is_focused = false;
   base::TimeTicks start_time = base::TimeTicks::Now();
   while (true) {
-    Status status = IsElementDisplayed(
+    status = IsElementDisplayed(
         session, web_view, element_id, true, &is_displayed);
     if (status.IsError())
       return status;
@@ -59,7 +62,7 @@
   }
 
   bool is_enabled = false;
-  Status status = IsElementEnabled(session, web_view, element_id, &is_enabled);
+  status = IsElementEnabled(session, web_view, element_id, &is_enabled);
   if (status.IsError())
     return status;
   if (!is_enabled)
@@ -297,11 +300,14 @@
                            const std::string& element_id,
                            const base::DictionaryValue& params,
                            std::unique_ptr<base::Value>* value) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   // Scrolling to element is done by webdriver::atoms::CLEAR
   bool is_displayed = false;
   base::TimeTicks start_time = base::TimeTicks::Now();
   while (true) {
-    Status status = IsElementDisplayed(
+    status = IsElementDisplayed(
       session, web_view, element_id, true, &is_displayed);
     if (status.IsError())
       return status;
@@ -326,6 +332,9 @@
                                 const std::string& element_id,
                                 const base::DictionaryValue& params,
                                 std::unique_ptr<base::Value>* value) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   const base::ListValue* key_list;
   base::ListValue key_list_local;
   if (session->w3c_compliant) {
@@ -340,7 +349,7 @@
   }
 
   bool is_input = false;
-  Status status = IsElementAttributeEqualToIgnoreCase(
+  status = IsElementAttributeEqualToIgnoreCase(
       session, web_view, element_id, "tagName", "input", &is_input);
   if (status.IsError())
     return status;
@@ -404,6 +413,9 @@
                             const std::string& element_id,
                             const base::DictionaryValue& params,
                             std::unique_ptr<base::Value>* value) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   base::ListValue args;
   args.Append(CreateElement(element_id));
   return web_view->CallFunction(
@@ -418,6 +430,9 @@
                              const std::string& element_id,
                              const base::DictionaryValue& params,
                              std::unique_ptr<base::Value>* value) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   base::ListValue args;
   args.Append(CreateElement(element_id));
   return web_view->CallFunction(
@@ -432,6 +447,9 @@
                               const std::string& element_id,
                               const base::DictionaryValue& params,
                               std::unique_ptr<base::Value>* value) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   base::ListValue args;
   args.Append(CreateElement(element_id));
   return web_view->CallFunction(
@@ -446,6 +464,9 @@
                               const std::string& element_id,
                               const base::DictionaryValue& params,
                               std::unique_ptr<base::Value>* value) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   base::ListValue args;
   args.Append(CreateElement(element_id));
 
@@ -466,6 +487,9 @@
                                 const std::string& element_id,
                                 const base::DictionaryValue& params,
                                 std::unique_ptr<base::Value>* value) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   base::ListValue args;
   args.Append(CreateElement(element_id));
   return web_view->CallFunction(
@@ -480,6 +504,9 @@
                                 const std::string& element_id,
                                 const base::DictionaryValue& params,
                                 std::unique_ptr<base::Value>* value) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   base::ListValue args;
   args.Append(CreateElement(element_id));
   return web_view->CallFunction(
@@ -494,11 +521,14 @@
                                const std::string& element_id,
                                const base::DictionaryValue& params,
                                std::unique_ptr<base::Value>* value) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   base::ListValue args;
   args.Append(CreateElement(element_id));
 
   bool is_xml = false;
-  Status status = IsDocumentTypeXml(session, web_view, &is_xml);
+  status = IsDocumentTypeXml(session, web_view, &is_xml);
   if (status.IsError())
     return status;
 
@@ -519,6 +549,9 @@
                                  const std::string& element_id,
                                  const base::DictionaryValue& params,
                                  std::unique_ptr<base::Value>* value) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   base::ListValue args;
   args.Append(CreateElement(element_id));
   return web_view->CallFunction(
@@ -533,6 +566,9 @@
                                  const std::string& element_id,
                                  const base::DictionaryValue& params,
                                  std::unique_ptr<base::Value>* value) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   base::ListValue args;
   args.Append(CreateElement(element_id));
   return web_view->CallFunction(
@@ -547,11 +583,14 @@
                              const std::string& element_id,
                              const base::DictionaryValue& params,
                              std::unique_ptr<base::Value>* value) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   base::ListValue args;
   args.Append(CreateElement(element_id));
 
   std::unique_ptr<base::Value> location;
-  Status status = web_view->CallFunction(
+  status = web_view->CallFunction(
       session->GetCurrentFrameId(),
       webdriver::atoms::asString(webdriver::atoms::GET_LOCATION), args,
       &location);
@@ -615,6 +654,9 @@
                              const std::string& element_id,
                              const base::DictionaryValue& params,
                              std::unique_ptr<base::Value>* value) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   base::ListValue args;
   args.Append(CreateElement(element_id));
   return web_view->CallFunction(
diff --git a/chrome/test/chromedriver/element_util.cc b/chrome/test/chromedriver/element_util.cc
index c144a7fe..51ea4616 100644
--- a/chrome/test/chromedriver/element_util.cc
+++ b/chrome/test/chromedriver/element_util.cc
@@ -97,11 +97,14 @@
     WebView* web_view,
     const std::string& element_id,
     const WebPoint& location) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   base::ListValue args;
   args.Append(CreateElement(element_id));
   args.Append(CreateValueFrom(location));
   std::unique_ptr<base::Value> result;
-  Status status = CallAtomsJs(
+  status = CallAtomsJs(
       frame, web_view, webdriver::atoms::IS_ELEMENT_CLICKABLE,
       args, &result);
   if (status.IsError())
@@ -131,13 +134,16 @@
     bool center,
     const std::string& clickable_element_id,
     WebPoint* location) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   WebPoint tmp_location = *location;
   base::ListValue args;
   args.Append(CreateElement(element_id));
   args.AppendBoolean(center);
   args.Append(CreateValueFrom(region));
   std::unique_ptr<base::Value> result;
-  Status status = web_view->CallFunction(
+  status = web_view->CallFunction(
       frame, webdriver::atoms::asString(webdriver::atoms::GET_LOCATION_IN_VIEW),
       args, &result);
   if (status.IsError())
@@ -184,11 +190,14 @@
     const std::string& element_id,
     const std::string& property,
     std::string* value) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   base::ListValue args;
   args.Append(CreateElement(element_id));
   args.AppendString(property);
   std::unique_ptr<base::Value> result;
-  Status status = web_view->CallFunction(
+  status = web_view->CallFunction(
       frame, webdriver::atoms::asString(webdriver::atoms::GET_EFFECTIVE_STYLE),
       args, &result);
   if (status.IsError())
@@ -249,6 +258,31 @@
     return kElementKey;
 }
 
+// example of element_id - d9cf1666-0066-4c07-bb86-03edcbab6680
+// should contain only 0-9 or a-f
+// format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+Status CheckElement(const std::string& element_id) {
+  Session* session = GetThreadLocalSession();
+  if (session && session->w3c_compliant) {
+    if (element_id.length()!=36)
+      return Status(kNoSuchElement, "Element_id length is invalid");
+
+    for (std::string::size_type i=0; i<element_id.length(); ++i) {
+      if (i==8 || i == 13 || i == 18 || i == 23) {
+        if (element_id[i] != '-')
+          return Status(kNoSuchElement, "Element_id format is invalid");
+      } else {
+        if (!(element_id[i] >='0' && element_id[i] <= '9') &&
+            !(element_id[i] >='a' && element_id[i] <= 'f'))
+          return Status(kNoSuchElement,
+                        "Element_id contains invalid letter on position: " +
+                         std::to_string(i) );
+      }
+    }
+  }
+  return Status(kOk);
+}
+
 std::unique_ptr<base::DictionaryValue> CreateElement(
     const std::string& element_id) {
   std::unique_ptr<base::DictionaryValue> element(new base::DictionaryValue());
@@ -390,6 +424,9 @@
                            const std::string& element_id,
                            const std::string& attribute_name,
                            std::unique_ptr<base::Value>* value) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   base::ListValue args;
   args.Append(CreateElement(element_id));
   args.AppendString(attribute_name);
@@ -447,6 +484,9 @@
         "  }"
         "  throw new Error('no img is found for the area');"
         "}";
+    status = CheckElement(element_id);
+    if (status.IsError())
+      return status;
     base::ListValue args;
     args.Append(CreateElement(element_id));
     std::unique_ptr<base::Value> result;
@@ -503,10 +543,13 @@
     WebView* web_view,
     const std::string& element_id,
     WebRect* rect) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   base::ListValue args;
   args.Append(CreateElement(element_id));
   std::unique_ptr<base::Value> result;
-  Status status = web_view->CallFunction(
+  status = web_view->CallFunction(
       session->GetCurrentFrameId(), kGetElementRegionScript, args, &result);
   if (status.IsError())
     return status;
@@ -522,10 +565,13 @@
     WebView* web_view,
     const std::string& element_id,
     std::string* name) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   base::ListValue args;
   args.Append(CreateElement(element_id));
   std::unique_ptr<base::Value> result;
-  Status status = web_view->CallFunction(
+  status = web_view->CallFunction(
       session->GetCurrentFrameId(),
       "function(elem) { return elem.tagName.toLowerCase(); }",
       args, &result);
@@ -541,10 +587,13 @@
     WebView* web_view,
     const std::string& element_id,
     WebSize* size) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   base::ListValue args;
   args.Append(CreateElement(element_id));
   std::unique_ptr<base::Value> result;
-  Status status = CallAtomsJs(
+  status = CallAtomsJs(
       session->GetCurrentFrameId(), web_view, webdriver::atoms::GET_SIZE,
       args, &result);
   if (status.IsError())
@@ -560,11 +609,14 @@
     const std::string& element_id,
     bool ignore_opacity,
     bool* is_displayed) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   base::ListValue args;
   args.Append(CreateElement(element_id));
   args.AppendBoolean(ignore_opacity);
   std::unique_ptr<base::Value> result;
-  Status status = CallAtomsJs(
+  status = CallAtomsJs(
       session->GetCurrentFrameId(), web_view, webdriver::atoms::IS_DISPLAYED,
       args, &result);
   if (status.IsError())
@@ -579,10 +631,13 @@
     WebView* web_view,
     const std::string& element_id,
     bool* is_enabled) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   base::ListValue args;
   args.Append(CreateElement(element_id));
   std::unique_ptr<base::Value> result;
-  Status status = CallAtomsJs(
+  status = CallAtomsJs(
       session->GetCurrentFrameId(), web_view, webdriver::atoms::IS_ENABLED,
       args, &result);
   if (status.IsError())
@@ -597,10 +652,13 @@
     WebView* web_view,
     const std::string& element_id,
     bool* is_selected) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   base::ListValue args;
   args.Append(CreateElement(element_id));
   std::unique_ptr<base::Value> result;
-  Status status = CallAtomsJs(
+  status = CallAtomsJs(
       session->GetCurrentFrameId(), web_view, webdriver::atoms::IS_SELECTED,
       args, &result);
   if (status.IsError())
@@ -615,10 +673,13 @@
     WebView* web_view,
     const std::string& element_id,
     bool* is_togglable) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   base::ListValue args;
   args.Append(CreateElement(element_id));
   std::unique_ptr<base::Value> result;
-  Status status = web_view->CallFunction(
+  status = web_view->CallFunction(
       session->GetCurrentFrameId(), kIsOptionElementToggleableScript,
       args, &result);
   if (status.IsError())
@@ -633,6 +694,9 @@
     WebView* web_view,
     const std::string& element_id,
     bool selected) {
+  Status status = CheckElement(element_id);
+  if (status.IsError())
+    return status;
   // TODO(171034): need to fix throwing error if an alert is triggered.
   base::ListValue args;
   args.Append(CreateElement(element_id));
diff --git a/chrome/test/chromedriver/element_util.h b/chrome/test/chromedriver/element_util.h
index c0e2558..ecbd0c9c 100644
--- a/chrome/test/chromedriver/element_util.h
+++ b/chrome/test/chromedriver/element_util.h
@@ -26,6 +26,8 @@
 
 std::unique_ptr<base::DictionaryValue> CreateValueFrom(const WebPoint& point);
 
+Status CheckElement(const std::string& element_id);
+
 // |root_element_id| could be null when no root element is given.
 Status FindElement(int interval_ms,
                    bool only_one,
diff --git a/chrome/test/data/find_in_page/LongFind.txt b/chrome/test/data/find_in_page/LongFind.txt
index ae97be71..e057363 100644
--- a/chrome/test/data/find_in_page/LongFind.txt
+++ b/chrome/test/data/find_in_page/LongFind.txt
@@ -1 +1 @@
-为美刺激经济献策 中国经济如期降温 世界金融机构仍看好 美贸易逆差意外增大 对华出口基本持平 巴基斯坦洪灾损失惨重 再引修大坝争议 经济学家降低预期 关注美联储举动 通胀预期升温 巴菲特缩短债券限期 破解Target:危机下零售公司的沉浮史 甲骨文CEO为赫德打抱不平 称惠普愚蠢 全球减薪排行榜 高盛CEO位居首位 危机过后仍有盈利 欧洲银行的底线何在? 亚洲洪水导致百万人陷入苦难 萧条经济已经结束? 惠普CEO涉嫌性骚扰离职 留新掌门猜想 富豪们为什么愿意从事慈善 福布斯发布富翁们的第一份工作 华尔街财务“神话”遭质疑 揭穿美国企业大骗局 华为在美遇“潜规则” 两项收购计划均遭拒 外媒:即使是中国也无法逃脱经济规律 解读危机中亚洲的节俭和西方的浪费 专家:出色的幼儿园老师年薪该为32万美金 盘点五位身价最高的年轻成功人士 石油泄露事件 BP董事会最该受谴责 福布斯盘点全球最赚钱的五家公司 离任解约金达上亿美金 这些CEO走得有点贵 全球CEO薪水排行 甲骨文拉里十年收入18.4亿美 英国石油公司更换掌门 美籍CEO达德利获任 中国经济已到政策拐点? 华尔街小题大作 欧洲不会垮掉 中国企业踊跃进军美国市场 本土企业称受到威胁 十样二手货绝对不能买 高盛与SEC和解 付出华尔街最高罚金
\ No newline at end of file
+为美刺激经济献策中国经济如期降温 世界金融机构仍看好美贸易逆差意外增大 对华出口基本持平巴基斯坦洪灾损失惨重 再引修大坝争议经济学家降低预期 关注美联储举动通胀预期升温 巴菲特缩短债券限期破解Target:危机下零售公司的沉浮史甲骨文CEO为赫德打抱不平 称惠普愚蠢全球减薪排行榜 高盛CEO位居首位危机过后仍有盈利 欧洲银行的底线何在? 亚洲洪水导致百万人陷入苦难萧条经济已经结束? 惠普CEO涉嫌性骚扰离职 留新掌门猜想富豪们为什么愿意从事慈善福布斯发布富翁们的第一份工作华尔街财务“神话”遭质疑 揭穿美国企业大骗局华为在美遇“潜规则” 两项收购计划均遭拒外媒:即使是中国也无法逃脱经济规律解读危机中亚洲的节俭和西方的浪费专家:出色的幼儿园老师年薪该为32万美金盘点五位身价最高的年轻成功人士石油泄露事件 BP董事会最该受谴责福布斯盘点全球最赚钱的五家公司离任解约金达上亿美金 这些CEO走得有点贵全球CEO薪水排行 甲骨文拉里十年收入18.4亿美英国石油公司更换掌门 美籍CEO达德利获任中国经济已到政策拐点? 华尔街小题大作 欧洲不会垮掉中国企业踊跃进军美国市场 本土企业称受到威胁十样二手货绝对不能买高盛与SEC和解 付出华尔街最高罚金
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index c9dfd97..f83d1f7 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -3983,6 +3983,16 @@
     "note": "Chrome OS device policy used by authpolicyd only, not used in Chrome"
   },
 
+  "DeviceGpoCacheLifetime": {
+    "os": ["chromeos"],
+    "note": "Chrome OS device policy used by authpolicyd only, not used in Chrome"
+  },
+
+  "DeviceAuthDataCacheLifetime": {
+    "os": ["chromeos"],
+    "note": "Chrome OS device policy used by authpolicyd only, not used in Chrome"
+  },
+
   "DeviceLoginScreenIsolateOrigins": {
     "os": ["chromeos"],
     "note": "Chrome OS device policy used by session_manager only"
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js
index 774546e..4ae446c 100644
--- a/chrome/test/data/webui/settings/cr_settings_browsertest.js
+++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -610,7 +610,7 @@
     '../test_browser_proxy.js',
     'test_sync_browser_proxy.js',
     'test_util.js',
-    'people_page_sync_controls.js',
+    'people_page_sync_controls_test.js',
   ]),
 };
 
diff --git a/chrome/test/data/webui/settings/people_page_sync_controls.js b/chrome/test/data/webui/settings/people_page_sync_controls_test.js
similarity index 67%
rename from chrome/test/data/webui/settings/people_page_sync_controls.js
rename to chrome/test/data/webui/settings/people_page_sync_controls_test.js
index 5a79974f..e778f0b 100644
--- a/chrome/test/data/webui/settings/people_page_sync_controls.js
+++ b/chrome/test/data/webui/settings/people_page_sync_controls_test.js
@@ -105,5 +105,62 @@
       }
       return browserProxy.whenCalled('setSyncDatatypes').then(verifyPrefs);
     });
+
+    if (!cr.isChromeOS) {
+      test('ToastNotShownWhenEmbedded', function() {
+        syncControls.syncStatus = {setupInProgress: false};
+        assertFalse(syncControls.$.toast.open);
+
+        syncControls.syncStatus = {setupInProgress: true};
+        assertFalse(syncControls.$.toast.open);
+      });
+    }
+  });
+
+  suite('SyncControlsSubpageTest', function() {
+    let syncControls = null;
+    let syncPage = null;
+    let browserProxy = null;
+
+    setup(function() {
+      browserProxy = new TestSyncBrowserProxy();
+      settings.SyncBrowserProxyImpl.instance_ = browserProxy;
+
+      PolymerTest.clearBody();
+      // First navigate to main sync page.
+      syncPage = document.createElement('settings-sync-page');
+      settings.navigateTo(settings.routes.SYNC);
+      document.body.appendChild(syncPage);
+
+      // Then navigate to advanced sync subpage.
+      syncControls = document.createElement('settings-sync-controls');
+      syncControls.syncPage = syncPage;
+      settings.navigateTo(settings.routes.SYNC_ADVANCED);
+      document.body.appendChild(syncControls);
+
+      Polymer.dom.flush();
+    });
+
+    teardown(function() {
+      syncControls.remove();
+      syncPage.remove();
+    });
+
+    if (!cr.isChromeOS) {
+      test('ToastShownForSyncSetup', function() {
+        syncControls.syncStatus = {setupInProgress: false};
+        assertFalse(syncControls.$.toast.open);
+
+        syncControls.syncStatus = {setupInProgress: true};
+        assertTrue(syncControls.$.toast.open);
+
+        syncControls.$.toast.querySelector('paper-button').click();
+
+        return browserProxy.whenCalled('didNavigateAwayFromSyncPage')
+            .then(abort => {
+              assertTrue(abort);
+            });
+      });
+    }
   });
 });
diff --git a/chrome/test/data/webui/settings/people_page_sync_page_test.js b/chrome/test/data/webui/settings/people_page_sync_page_test.js
index 1d56c444..16e4403 100644
--- a/chrome/test/data/webui/settings/people_page_sync_page_test.js
+++ b/chrome/test/data/webui/settings/people_page_sync_page_test.js
@@ -151,7 +151,7 @@
       assertFalse(syncSection.hidden);
       assertTrue(otherItems.classList.contains('list-frame'));
       assertEquals(
-          otherItems.querySelectorAll(':scope > .list-item').length, 3);
+          otherItems.querySelectorAll(':scope > .list-item').length, 4);
 
       // Test sync paused state.
       syncPage.syncStatus = {
@@ -471,6 +471,19 @@
       });
     });
 
+    test('SyncAdvancedRow', function() {
+      syncPage.unifiedConsentEnabled = true;
+      Polymer.dom.flush();
+
+      const syncAdvancedRow = syncPage.$$('#sync-advanced-row');
+      assertFalse(syncAdvancedRow.hidden);
+
+      syncAdvancedRow.click();
+      Polymer.dom.flush();
+
+      assertEquals(settings.routes.SYNC_ADVANCED, settings.getCurrentRoute());
+    });
+
     if (!cr.isChromeOS) {
       test('FirstTimeSetupNotification', function() {
         assertTrue(!!syncPage.$.toast);
diff --git a/chrome/test/views/chrome_views_test_base.cc b/chrome/test/views/chrome_views_test_base.cc
index bdb29a46..e378e6b 100644
--- a/chrome/test/views/chrome_views_test_base.cc
+++ b/chrome/test/views/chrome_views_test_base.cc
@@ -5,8 +5,11 @@
 #include "chrome/test/views/chrome_views_test_base.h"
 
 #include "chrome/test/views/chrome_test_views_delegate.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 
-ChromeViewsTestBase::ChromeViewsTestBase() {}
+ChromeViewsTestBase::ChromeViewsTestBase()
+    : views::ViewsTestBase(
+          std::make_unique<content::TestBrowserThreadBundle>()) {}
 
 ChromeViewsTestBase::~ChromeViewsTestBase() {}
 
diff --git a/components/arc/ime/arc_ime_service.cc b/components/arc/ime/arc_ime_service.cc
index 7181aa6c..18a58f4 100644
--- a/components/arc/ime/arc_ime_service.cc
+++ b/components/arc/ime/arc_ime_service.cc
@@ -442,7 +442,7 @@
   return true;
 }
 
-bool ArcImeService::GetSelectionRange(gfx::Range* range) const {
+bool ArcImeService::GetEditableSelectionRange(gfx::Range* range) const {
   if (!selection_range_.IsValid())
     return false;
   *range = selection_range_;
@@ -502,7 +502,7 @@
   return false;
 }
 
-bool ArcImeService::SetSelectionRange(const gfx::Range& range) {
+bool ArcImeService::SetEditableSelectionRange(const gfx::Range& range) {
   return false;
 }
 
diff --git a/components/arc/ime/arc_ime_service.h b/components/arc/ime/arc_ime_service.h
index 695df6e..23297e1 100644
--- a/components/arc/ime/arc_ime_service.h
+++ b/components/arc/ime/arc_ime_service.h
@@ -113,7 +113,7 @@
   ui::TextInputType GetTextInputType() const override;
   gfx::Rect GetCaretBounds() const override;
   bool GetTextRange(gfx::Range* range) const override;
-  bool GetSelectionRange(gfx::Range* range) const override;
+  bool GetEditableSelectionRange(gfx::Range* range) const override;
   bool GetTextFromRange(const gfx::Range& range,
                         base::string16* text) const override;
 
@@ -129,7 +129,7 @@
   bool HasCompositionText() const override;
   FocusReason GetFocusReason() const override;
   bool GetCompositionTextRange(gfx::Range* range) const override;
-  bool SetSelectionRange(const gfx::Range& range) override;
+  bool SetEditableSelectionRange(const gfx::Range& range) override;
   bool DeleteRange(const gfx::Range& range) override;
   void OnInputMethodChanged() override {}
   bool ChangeTextDirectionAndLayoutAlignment(
diff --git a/components/arc/ime/arc_ime_service_unittest.cc b/components/arc/ime/arc_ime_service_unittest.cc
index 549b372..c044f65 100644
--- a/components/arc/ime/arc_ime_service_unittest.cc
+++ b/components/arc/ime/arc_ime_service_unittest.cc
@@ -348,7 +348,7 @@
   instance_->GetTextFromRange(text_range, &temp_str);
   EXPECT_EQ(text_in_range, temp_str);
 
-  instance_->GetSelectionRange(&temp);
+  instance_->GetEditableSelectionRange(&temp);
   EXPECT_EQ(selection_range, temp);
 }
 
diff --git a/components/autofill/core/browser/autofill_profile.cc b/components/autofill/core/browser/autofill_profile.cc
index d7da676..416a8b61 100644
--- a/components/autofill/core/browser/autofill_profile.cc
+++ b/components/autofill/core/browser/autofill_profile.cc
@@ -1120,7 +1120,8 @@
             << profile.language_code() << " "
             << UTF16ToUTF8(profile.GetRawInfo(PHONE_HOME_WHOLE_NUMBER)) << " "
             << profile.GetClientValidityBitfieldValue() << " "
-            << profile.use_count() << " " << profile.use_date();
+            << profile.has_converted() << " " << profile.use_count() << " "
+            << profile.use_date();
 }
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/webdata/autofill_change.h b/components/autofill/core/browser/webdata/autofill_change.h
index 6212c60..af764ed 100644
--- a/components/autofill/core/browser/webdata/autofill_change.h
+++ b/components/autofill/core/browser/webdata/autofill_change.h
@@ -56,8 +56,9 @@
 template <typename DataType>
 class AutofillDataModelChange : public GenericAutofillChange<std::string> {
  public:
-  // The |type| input specifies the change type.  The |key| input is the key,
-  // which is expected to be the GUID identifying the |data_model|.
+  // The |type| input specifies the change type.  The |key| input is the key
+  // that identifies the |data_model|; it is the GUID of the entry for local
+  // data and server_id of the entry for server data from GPay.
   // When |type| == ADD, |data_model| should be non-NULL.
   // When |type| == UPDATE, |data_model| should be non-NULL.
   // When |type| == REMOVE, |data_model| should be NULL.
@@ -66,7 +67,8 @@
                           const DataType* data_model)
       : GenericAutofillChange<std::string>(type, key), data_model_(data_model) {
     DCHECK(type == REMOVE ? !data_model
-                          : data_model && data_model->guid() == key);
+                          : data_model && (data_model->guid() == key ||
+                                           data_model->server_id() == key));
   }
 
   ~AutofillDataModelChange() override {}
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
index a52e538..e619849 100644
--- a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
+++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
@@ -439,7 +439,7 @@
     if (cmp < 0) {
       ++result.items_removed;
       result.changes.emplace_back(AutofillDataModelChange<Item>::REMOVE,
-                                  (*old_it)->guid(), nullptr);
+                                  (*old_it)->server_id(), nullptr);
       ++old_it;
     } else if (cmp == 0) {
       ++old_it;
@@ -447,7 +447,7 @@
     } else {
       ++result.items_added;
       result.changes.emplace_back(AutofillDataModelChange<Item>::ADD,
-                                  (*new_it)->guid(), *new_it);
+                                  (*new_it)->server_id(), *new_it);
       ++new_it;
     }
   }
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc
index 2971006d6..d1ce381 100644
--- a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc
+++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc
@@ -488,13 +488,13 @@
 
   EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
   EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged(
-                              AddChange(address2.guid(), address2)));
+                              AddChange(address2.server_id(), address2)));
+  EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged(
+                              RemoveChange(address1.server_id())));
   EXPECT_CALL(*backend(),
-              NotifyOfAutofillProfileChanged(RemoveChange(address1.guid())));
+              NotifyOfCreditCardChanged(AddChange(card2.server_id(), card2)));
   EXPECT_CALL(*backend(),
-              NotifyOfCreditCardChanged(AddChange(card2.guid(), card2)));
-  EXPECT_CALL(*backend(),
-              NotifyOfCreditCardChanged(RemoveChange(card1.guid())));
+              NotifyOfCreditCardChanged(RemoveChange(card1.server_id())));
   StartSyncing({profile_specifics2, card_specifics2, customer_data_specifics});
 
   if (IsWalletMetadataOnUSS()) {
@@ -597,9 +597,9 @@
 
   EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
   EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged(
-                              RemoveChange(local_profile.guid())));
+                              RemoveChange(local_profile.server_id())));
   EXPECT_CALL(*backend(),
-              NotifyOfCreditCardChanged(RemoveChange(local_card.guid())));
+              NotifyOfCreditCardChanged(RemoveChange(local_card.server_id())));
   StartSyncing({});
 
   if (IsWalletMetadataOnUSS()) {
@@ -673,11 +673,12 @@
                                                      &customer_data_specifics);
 
   EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
+  EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged(
+                              RemoveChange(profile2.server_id())));
   EXPECT_CALL(*backend(),
-              NotifyOfAutofillProfileChanged(RemoveChange(profile2.guid())));
-  EXPECT_CALL(*backend(), NotifyOfCreditCardChanged(RemoveChange(card.guid())));
+              NotifyOfCreditCardChanged(RemoveChange(card.server_id())));
   EXPECT_CALL(*backend(),
-              NotifyOfCreditCardChanged(AddChange(card2.guid(), card2)));
+              NotifyOfCreditCardChanged(AddChange(card2.server_id(), card2)));
   StartSyncing({profile_specifics, card2_specifics, customer_data_specifics});
 
   if (IsWalletMetadataOnUSS()) {
@@ -818,9 +819,9 @@
 
   EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
   EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged(
-                              RemoveChange(local_profile.guid())));
+                              RemoveChange(local_profile.server_id())));
   EXPECT_CALL(*backend(),
-              NotifyOfCreditCardChanged(RemoveChange(local_card.guid())));
+              NotifyOfCreditCardChanged(RemoveChange(local_card.server_id())));
   // Passing in a non-null metadata change list indicates to the bridge that
   // sync is stopping because it was disabled.
   bridge()->ApplyStopSyncChanges(
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
index 796447f..3c4deea 100644
--- a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
+++ b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
@@ -410,12 +410,13 @@
     const CreditCard& card,
     WebDatabase* db) {
   DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
+  DCHECK_NE(CreditCard::LOCAL_CARD, card.record_type());
   if (!AutofillTable::FromWebDatabase(db)->UpdateServerCardMetadata(card))
     return WebDatabase::COMMIT_NOT_NEEDED;
 
   for (auto& db_observer : db_observer_list_) {
     db_observer.CreditCardChanged(
-        CreditCardChange(CreditCardChange::UPDATE, card.guid(), &card));
+        CreditCardChange(CreditCardChange::UPDATE, card.server_id(), &card));
   }
 
   return WebDatabase::COMMIT_NEEDED;
@@ -425,6 +426,7 @@
     const AutofillProfile& profile,
     WebDatabase* db) {
   DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
+  DCHECK_EQ(AutofillProfile::SERVER_PROFILE, profile.record_type());
   if (!AutofillTable::FromWebDatabase(db)->UpdateServerAddressMetadata(
           profile)) {
     return WebDatabase::COMMIT_NOT_NEEDED;
@@ -432,7 +434,7 @@
 
   for (auto& db_observer : db_observer_list_) {
     db_observer.AutofillProfileChanged(AutofillProfileChange(
-        AutofillProfileChange::UPDATE, profile.guid(), &profile));
+        AutofillProfileChange::UPDATE, profile.server_id(), &profile));
   }
 
   return WebDatabase::COMMIT_NEEDED;
diff --git a/components/autofill_assistant/browser/actions/action_delegate.h b/components/autofill_assistant/browser/actions/action_delegate.h
index 7513213..bc89eb6 100644
--- a/components/autofill_assistant/browser/actions/action_delegate.h
+++ b/components/autofill_assistant/browser/actions/action_delegate.h
@@ -67,7 +67,7 @@
       base::TimeDelta max_wait_time,
       bool allow_interrupt,
       const Selector& selector,
-      base::OnceCallback<void(bool)> callback) = 0;
+      base::OnceCallback<void(ProcessedActionStatusProto)> callback) = 0;
 
   // Click or tap the element given by |selector| on the web page.
   virtual void ClickOrTapElement(const Selector& selector,
diff --git a/components/autofill_assistant/browser/actions/autofill_action.cc b/components/autofill_assistant/browser/actions/autofill_action.cc
index f9f8fef..b84253be 100644
--- a/components/autofill_assistant/browser/actions/autofill_action.cc
+++ b/components/autofill_assistant/browser/actions/autofill_action.cc
@@ -136,13 +136,13 @@
     if (!has_valid_data) {
       // User selected 'Fill manually'.
       delegate->StopCurrentScriptAndShutdown(fill_form_message_);
-      EndAction(/* successful= */ true);
+      EndAction(MANUAL_FALLBACK);
       return;
     }
 
     if (selector_.empty()) {
       // If there is no selector, finish the action directly.
-      EndAction(/* successful= */ true);
+      EndAction(ACTION_APPLIED);
       return;
     }
 
@@ -167,8 +167,8 @@
   delegate->ChooseAddress(std::move(selection_callback));
 }
 
-void AutofillAction::EndAction(bool successful) {
-  UpdateProcessedAction(successful ? ACTION_APPLIED : OTHER_ACTION_STATUS);
+void AutofillAction::EndAction(ProcessedActionStatusProto status) {
+  UpdateProcessedAction(status);
   std::move(process_action_callback_).Run(std::move(processed_action_proto_));
 }
 
@@ -196,13 +196,13 @@
     // If there is no selector, finish the action directly. This can be the case
     // when we want to trigger the selection of address or card at the beginning
     // of the script and use it later.
-    EndAction(/* successful= */ true);
+    EndAction(ACTION_APPLIED);
     return;
   }
 
   if (guid.empty()) {
     delegate->StopCurrentScriptAndShutdown(fill_form_message_);
-    EndAction(/* successful= */ true);
+    EndAction(MANUAL_FALLBACK);
     return;
   }
 
@@ -219,7 +219,7 @@
 void AutofillAction::OnWaitForElement(ActionDelegate* delegate,
                                       bool element_found) {
   if (!element_found) {
-    EndAction(/* successful= */ false);
+    EndAction(ELEMENT_RESOLUTION_FAILED);
     return;
   }
 
@@ -255,7 +255,7 @@
     // Gracefully shutdown the script. The empty message forces the use of the
     // default message.
     delegate->StopCurrentScriptAndShutdown("");
-    EndAction(/* successful= */ true);
+    EndAction(MANUAL_FALLBACK);
     return;
   }
 
@@ -266,7 +266,7 @@
 
 void AutofillAction::OnCardFormFilled(bool successful) {
   // TODO(crbug.com/806868): Implement required fields checking for cards.
-  EndAction(successful);
+  EndAction(successful ? ACTION_APPLIED : OTHER_ACTION_STATUS);
   return;
 }
 
@@ -274,7 +274,7 @@
                                          bool successful) {
   // In case Autofill failed, we fail the action.
   if (!successful) {
-    EndAction(/* successful= */ false);
+    EndAction(OTHER_ACTION_STATUS);
     return;
   }
 
@@ -285,7 +285,7 @@
                                          bool allow_fallback) {
   // If there are no required fields, finish the action successfully.
   if (proto_.use_address().required_fields().empty()) {
-    EndAction(/* successful= */ true);
+    EndAction(ACTION_APPLIED);
     return;
   }
 
@@ -330,7 +330,7 @@
   }
 
   if (validation_successful) {
-    EndAction(/* successful= */ true);
+    EndAction(ACTION_APPLIED);
     return;
   }
 
@@ -338,7 +338,7 @@
     // Validation failed and we don't want to try the fallback, so we stop
     // the script.
     delegate->StopCurrentScriptAndShutdown(check_form_message_);
-    EndAction(/* successful= */ true);
+    EndAction(MANUAL_FALLBACK);
     return;
   }
 
@@ -358,7 +358,7 @@
   }
   if (!has_fallbacks) {
     delegate->StopCurrentScriptAndShutdown(check_form_message_);
-    EndAction(/* successful= */ true);
+    EndAction(MANUAL_FALLBACK);
     return;
   }
 
@@ -414,7 +414,7 @@
   if (!successful) {
     // Fallback failed: we stop the script without checking the fields.
     delegate->StopCurrentScriptAndShutdown(check_form_message_);
-    EndAction(/* successful= */ true);
+    EndAction(MANUAL_FALLBACK);
     return;
   }
   SetFallbackFieldValuesSequentially(delegate, ++required_fields_index);
diff --git a/components/autofill_assistant/browser/actions/autofill_action.h b/components/autofill_assistant/browser/actions/autofill_action.h
index 48ca080..a837f2a 100644
--- a/components/autofill_assistant/browser/actions/autofill_action.h
+++ b/components/autofill_assistant/browser/actions/autofill_action.h
@@ -34,7 +34,7 @@
   void InternalProcessAction(ActionDelegate* delegate,
                              ProcessActionCallback callback) override;
 
-  void EndAction(bool successful);
+  void EndAction(ProcessedActionStatusProto status);
 
   // Called when the user selected the data.
   void OnDataSelected(ActionDelegate* delegate,
diff --git a/components/autofill_assistant/browser/actions/autofill_action_unittest.cc b/components/autofill_assistant/browser/actions/autofill_action_unittest.cc
index 82ca4cb1..b19221c6 100644
--- a/components/autofill_assistant/browser/actions/autofill_action_unittest.cc
+++ b/components/autofill_assistant/browser/actions/autofill_action_unittest.cc
@@ -155,14 +155,13 @@
     return action;
   }
 
-  bool ProcessAction(const ActionProto& action_proto) {
+  ProcessedActionStatusProto ProcessAction(const ActionProto& action_proto) {
     AutofillAction action(action_proto);
     // We can use DirectCallback given that methods in ActionDelegate are mocked
     // and return directly.
     DirectCallback callback;
     action.ProcessAction(&mock_action_delegate_, callback.Get());
-    return callback.GetResultOrDie()->status() ==
-           ProcessedActionStatusProto::ACTION_APPLIED;
+    return callback.GetResultOrDie()->status();
   }
 
   void ExpectActionToStopScript(const ActionProto& action_proto,
@@ -170,9 +169,8 @@
     EXPECT_CALL(mock_action_delegate_,
                 StopCurrentScriptAndShutdown(expected_message));
 
-    // The AutofillAction should finish successfully even when stopping the
-    // current script.
-    EXPECT_TRUE(ProcessAction(action_proto));
+    EXPECT_EQ(ProcessedActionStatusProto::MANUAL_FALLBACK,
+              ProcessAction(action_proto));
   }
 
   MockActionDelegate mock_action_delegate_;
@@ -232,7 +230,8 @@
   ON_CALL(mock_web_controller_, OnGetFieldValue(_, _))
       .WillByDefault(RunOnceCallback<1>(true, "not empty"));
 
-  EXPECT_TRUE(ProcessAction(action_proto));
+  EXPECT_EQ(ProcessedActionStatusProto::ACTION_APPLIED,
+            ProcessAction(action_proto));
 }
 
 TEST_F(AutofillActionTest, FallbackFails) {
@@ -321,7 +320,8 @@
     EXPECT_CALL(mock_web_controller_, OnGetFieldValue(_, _))
         .WillRepeatedly(RunOnceCallback<1>(true, "not empty"));
   }
-  EXPECT_TRUE(ProcessAction(action_proto));
+  EXPECT_EQ(ProcessedActionStatusProto::ACTION_APPLIED,
+            ProcessAction(action_proto));
 }
 }  // namespace
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/actions/mock_action_delegate.h b/components/autofill_assistant/browser/actions/mock_action_delegate.h
index 9ce83889..89287fe 100644
--- a/components/autofill_assistant/browser/actions/mock_action_delegate.h
+++ b/components/autofill_assistant/browser/actions/mock_action_delegate.h
@@ -33,10 +33,11 @@
   MOCK_METHOD2(OnShortWaitForElementExist,
                void(const Selector& selector, base::OnceCallback<void(bool)>&));
 
-  void WaitForElementVisible(base::TimeDelta max_wait_time,
-                             bool allow_interrupt,
-                             const Selector& selector,
-                             base::OnceCallback<void(bool)> callback) override {
+  void WaitForElementVisible(
+      base::TimeDelta max_wait_time,
+      bool allow_interrupt,
+      const Selector& selector,
+      base::OnceCallback<void(ProcessedActionStatusProto)> callback) override {
     OnWaitForElementVisible(max_wait_time, allow_interrupt, selector, callback);
   }
 
@@ -44,7 +45,7 @@
                void(base::TimeDelta,
                     bool,
                     const Selector&,
-                    base::OnceCallback<void(bool)>&));
+                    base::OnceCallback<void(ProcessedActionStatusProto)>&));
 
   MOCK_METHOD1(ShowStatusMessage, void(const std::string& message));
   MOCK_METHOD2(ClickOrTapElement,
diff --git a/components/autofill_assistant/browser/actions/show_details_action.cc b/components/autofill_assistant/browser/actions/show_details_action.cc
index dd5146fb..a5f753d6 100644
--- a/components/autofill_assistant/browser/actions/show_details_action.cc
+++ b/components/autofill_assistant/browser/actions/show_details_action.cc
@@ -37,8 +37,10 @@
                                       bool can_continue) {
   if (!can_continue) {
     delegate->Close();
+    UpdateProcessedAction(MANUAL_FALLBACK);
+  } else {
+    UpdateProcessedAction(ACTION_APPLIED);
   }
-  UpdateProcessedAction(ACTION_APPLIED);
   std::move(callback).Run(std::move(processed_action_proto_));
 }
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/actions/unsupported_action.cc b/components/autofill_assistant/browser/actions/unsupported_action.cc
index 5105db0..587ca5e 100644
--- a/components/autofill_assistant/browser/actions/unsupported_action.cc
+++ b/components/autofill_assistant/browser/actions/unsupported_action.cc
@@ -18,8 +18,7 @@
 
 void UnsupportedAction::InternalProcessAction(ActionDelegate* delegate,
                                               ProcessActionCallback callback) {
-  // TODO(crbug.com/806868): Add 'unsupported action' status to the protocol.
-  UpdateProcessedAction(UNKNOWN_ACTION_STATUS);
+  UpdateProcessedAction(UNSUPPORTED_ACTION);
   std::move(callback).Run(std::move(processed_action_proto_));
 }
 
diff --git a/components/autofill_assistant/browser/actions/wait_for_dom_action.cc b/components/autofill_assistant/browser/actions/wait_for_dom_action.cc
index 2fb25fe2..9b3db5f 100644
--- a/components/autofill_assistant/browser/actions/wait_for_dom_action.cc
+++ b/components/autofill_assistant/browser/actions/wait_for_dom_action.cc
@@ -45,9 +45,8 @@
 }
 
 void WaitForDomAction::OnCheckDone(ProcessActionCallback callback,
-                                   bool element_found) {
-  UpdateProcessedAction(element_found ? ACTION_APPLIED
-                                      : ELEMENT_RESOLUTION_FAILED);
+                                   ProcessedActionStatusProto status) {
+  UpdateProcessedAction(status);
   std::move(callback).Run(std::move(processed_action_proto_));
 }
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/actions/wait_for_dom_action.h b/components/autofill_assistant/browser/actions/wait_for_dom_action.h
index 4f58ba5..05f87ba 100644
--- a/components/autofill_assistant/browser/actions/wait_for_dom_action.h
+++ b/components/autofill_assistant/browser/actions/wait_for_dom_action.h
@@ -26,7 +26,8 @@
   void InternalProcessAction(ActionDelegate* delegate,
                              ProcessActionCallback callback) override;
 
-  void OnCheckDone(ProcessActionCallback callback, bool element_found);
+  void OnCheckDone(ProcessActionCallback callback,
+                   ProcessedActionStatusProto status);
 
   base::WeakPtrFactory<WaitForDomAction> weak_ptr_factory_;
 
diff --git a/components/autofill_assistant/browser/controller.cc b/components/autofill_assistant/browser/controller.cc
index 839b2eba..1cdfb64 100644
--- a/components/autofill_assistant/browser/controller.cc
+++ b/components/autofill_assistant/browser/controller.cc
@@ -246,6 +246,11 @@
                                   const ScriptExecutor::Result& result) {
   if (!allow_autostart_)
     GetUiController()->HideOverlay();
+
+  // We expand the bottom sheet as the end of a script either means that user
+  // interaction is needed or a success/error message is shown.
+  GetUiController()->ExpandBottomSheet();
+
   if (!result.success) {
     LOG(ERROR) << "Failed to execute script " << script_path;
     GetUiController()->ShowStatusMessage(
@@ -257,6 +262,10 @@
   GetUiController()->AllowShowingSoftKeyboard(true);
   switch (result.at_end) {
     case ScriptExecutor::SHUTDOWN:
+    case ScriptExecutor::TERMINATE:
+      // TODO(crbug.com/806868): Distinguish shutdown from terminate: Users
+      // should be allowed to undo shutdown, but not terminate.
+
       GetUiController()->Shutdown();  // indirectly deletes this
       return;
 
diff --git a/components/autofill_assistant/browser/mock_ui_controller.h b/components/autofill_assistant/browser/mock_ui_controller.h
index 9fd7e75..9d92746e 100644
--- a/components/autofill_assistant/browser/mock_ui_controller.h
+++ b/components/autofill_assistant/browser/mock_ui_controller.h
@@ -72,6 +72,7 @@
                void(bool enabled, const std::vector<RectF>& areas));
   MOCK_CONST_METHOD0(GetDebugContext, std::string());
   MOCK_CONST_METHOD0(Terminate, bool());
+  MOCK_METHOD0(ExpandBottomSheet, void());
 };
 
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/script_executor.cc b/components/autofill_assistant/browser/script_executor.cc
index 4078e2f..44bead9 100644
--- a/components/autofill_assistant/browser/script_executor.cc
+++ b/components/autofill_assistant/browser/script_executor.cc
@@ -90,16 +90,18 @@
     base::TimeDelta max_wait_time,
     bool allow_interrupt,
     const Selector& selector,
-    base::OnceCallback<void(bool)> callback) {
+    base::OnceCallback<void(ProcessedActionStatusProto)> callback) {
   if (!allow_interrupt || ordered_interrupts_->empty()) {
     // No interrupts to worry about. Just run normal wait.
-    WaitForElement(max_wait_time, kVisibilityCheck, selector,
-                   std::move(callback));
+    WaitForElement(
+        max_wait_time, kVisibilityCheck, selector,
+        base::BindOnce(&ScriptExecutor::OnWaitForElementVisibleNoInterrupts,
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
     return;
   }
   wait_with_interrupts_ = std::make_unique<WaitWithInterrupts>(
       this, max_wait_time, kVisibilityCheck, selector,
-      base::BindOnce(&ScriptExecutor::OnWaitForElementVisible,
+      base::BindOnce(&ScriptExecutor::OnWaitForElementVisibleWithInterrupts,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   wait_with_interrupts_->Run();
 }
@@ -265,8 +267,13 @@
   } else {
     at_end_ = SHUTDOWN;
   }
+}
+
+void ScriptExecutor::Terminate() {
   if (wait_with_interrupts_)
-    wait_with_interrupts_->Shutdown();
+    wait_with_interrupts_->Terminate();
+  at_end_ = TERMINATE;
+  should_stop_script_ = true;
 }
 
 void ScriptExecutor::Close() {
@@ -310,10 +317,30 @@
 }
 
 void ScriptExecutor::OnGetActions(bool result, const std::string& response) {
-  if (!result) {
+  bool success = result && ProcessNextActionResponse(response);
+  if (should_stop_script_) {
+    // The last action forced the script to stop. Sending the result of the
+    // action is considered best effort in this situation. Report a successful
+    // run to the caller no matter what, so we don't confuse users with an error
+    // message.
+    RunCallback(true);
+    return;
+  }
+
+  if (!success) {
     RunCallback(false);
     return;
   }
+
+  if (!actions_.empty()) {
+    ProcessNextAction();
+    return;
+  }
+
+  RunCallback(true);
+}
+
+bool ScriptExecutor::ProcessNextActionResponse(const std::string& response) {
   processed_actions_.clear();
   actions_.clear();
 
@@ -322,23 +349,15 @@
   bool parse_result = ProtocolUtils::ParseActions(
       response, &last_global_payload_, &last_script_payload_, &actions_,
       &scripts, &should_update_scripts);
-
   if (!parse_result) {
-    RunCallback(false);
-    return;
+    return false;
   }
+
   ReportPayloadsToListener();
   if (should_update_scripts) {
     ReportScriptsUpdateToListener(std::move(scripts));
   }
-
-  if (actions_.empty()) {
-    // Finished executing the script if there are no more actions.
-    RunCallback(true);
-    return;
-  }
-
-  ProcessNextAction();
+  return true;
 }
 
 void ScriptExecutor::ReportPayloadsToListener() {
@@ -418,20 +437,19 @@
     std::unique_ptr<ProcessedActionProto> processed_action_proto) {
   previous_action_type_ = processed_action_proto->action().action_info_case();
   processed_actions_.emplace_back(*processed_action_proto);
-  if (processed_actions_.back().status() !=
-      ProcessedActionStatusProto::ACTION_APPLIED) {
+
+  auto& processed_action = processed_actions_.back();
+  if (at_end_ == TERMINATE) {
+    // Let the backend know that the script has been terminated. The original
+    // action status doesn't matter.
+    processed_action.set_status(
+        ProcessedActionStatusProto::USER_ABORTED_ACTION);
+  }
+  if (processed_action.status() != ProcessedActionStatusProto::ACTION_APPLIED) {
     // Report error immediately, interrupting action processing.
     GetNextActions();
     return;
   }
-
-  if (should_stop_script_) {
-    // Last action called StopCurrentScript(). We simulate a successful end of
-    // script to make sure we don't display any errors.
-    RunCallback(true);
-    return;
-  }
-
   ProcessNextAction();
 }
 
@@ -455,22 +473,30 @@
   std::move(callback).Run(all_found);
 }
 
-void ScriptExecutor::OnWaitForElementVisible(
-    base::OnceCallback<void(bool)> element_found_callback,
+void ScriptExecutor::OnWaitForElementVisibleWithInterrupts(
+    base::OnceCallback<void(ProcessedActionStatusProto)> callback,
     bool element_found,
     const Result* interrupt_result) {
   if (interrupt_result) {
-    RunCallbackWithResult(*interrupt_result);
-
-    // TODO(crbug.com/806868): Let the server know that the original script was
-    // interrupted and that the interrupting script failed. This implementation
-    // just drops the current action flow on the floor by deleting
-    // element_found_callback without calling it.
-    return;
+    if (!interrupt_result->success) {
+      std::move(callback).Run(INTERRUPT_FAILED);
+      return;
+    }
+    if (interrupt_result->at_end != CONTINUE) {
+      at_end_ = interrupt_result->at_end;
+      should_stop_script_ = true;
+      std::move(callback).Run(MANUAL_FALLBACK);
+      return;
+    }
   }
+  OnWaitForElementVisibleNoInterrupts(std::move(callback), element_found);
+}
 
-  // Continue the original script.
-  std::move(element_found_callback).Run(element_found);
+void ScriptExecutor::OnWaitForElementVisibleNoInterrupts(
+    base::OnceCallback<void(ProcessedActionStatusProto)> callback,
+    bool element_found) {
+  std::move(callback).Run(element_found ? ACTION_APPLIED
+                                        : ELEMENT_RESOLUTION_FAILED);
 }
 
 ScriptExecutor::WaitWithInterrupts::WaitWithInterrupts(
@@ -572,6 +598,7 @@
 void ScriptExecutor::WaitWithInterrupts::RunInterrupt(const Script* interrupt) {
   batch_element_checker_.reset();
   SavePreInterruptState();
+  main_script_->ran_interrupts_.emplace_back(interrupt->handle.path);
   interrupt_executor_ = std::make_unique<ScriptExecutor>(
       interrupt->handle.path, main_script_->last_global_payload_,
       main_script_->initial_script_payload_,
@@ -641,9 +668,9 @@
   }
 }
 
-void ScriptExecutor::WaitWithInterrupts::Shutdown() {
+void ScriptExecutor::WaitWithInterrupts::Terminate() {
   if (interrupt_executor_)
-    interrupt_executor_->Shutdown();
+    interrupt_executor_->Terminate();
 }
 
 void ScriptExecutor::OnChosen(
diff --git a/components/autofill_assistant/browser/script_executor.h b/components/autofill_assistant/browser/script_executor.h
index c17be7bb..e332bbd 100644
--- a/components/autofill_assistant/browser/script_executor.h
+++ b/components/autofill_assistant/browser/script_executor.h
@@ -69,7 +69,13 @@
     CLOSE_CUSTOM_TAB,
 
     // Reset all state and restart.
-    RESTART
+    RESTART,
+
+    // Autofill Assistant is shutting down.
+    //
+    // Returned after ScriptExecutor::Terminate has been called while running a
+    // script.
+    TERMINATE,
   };
 
   // Contains the result of the Run operation.
@@ -86,15 +92,20 @@
   using RunScriptCallback = base::OnceCallback<void(const Result&)>;
   void Run(RunScriptCallback callback);
 
+  // Terminates the running scripts. The script finishes running the current
+  // action, then returns a result with at_end set to TERMINATE.
+  void Terminate();
+
   // Override ActionDelegate:
   std::unique_ptr<BatchElementChecker> CreateBatchElementChecker() override;
   void ShortWaitForElementExist(
       const Selector& selector,
       base::OnceCallback<void(bool)> callback) override;
-  void WaitForElementVisible(base::TimeDelta max_wait_time,
-                             bool allow_interrupt,
-                             const Selector& selector,
-                             base::OnceCallback<void(bool)> callback) override;
+  void WaitForElementVisible(
+      base::TimeDelta max_wait_time,
+      bool allow_interrupt,
+      const Selector& selector,
+      base::OnceCallback<void(ProcessedActionStatusProto)> callback) override;
   void ShowStatusMessage(const std::string& message) override;
   void ClickOrTapElement(const Selector& selector,
                          base::OnceCallback<void(bool)> callback) override;
@@ -179,7 +190,7 @@
     ~WaitWithInterrupts() override;
 
     void Run();
-    void Shutdown();
+    void Terminate();
 
    private:
     // Implements ScriptExecutor::Listener
@@ -238,6 +249,7 @@
   friend class WaitWithInterrupts;
 
   void OnGetActions(bool result, const std::string& response);
+  bool ProcessNextActionResponse(const std::string& response);
   void ReportPayloadsToListener();
   void ReportScriptsUpdateToListener(
       std::vector<std::unique_ptr<Script>> scripts);
@@ -252,10 +264,13 @@
                       const Selector& selectors,
                       base::OnceCallback<void(bool)> callback);
   void OnWaitForElement(base::OnceCallback<void(bool)> callback);
-  void OnWaitForElementVisible(
-      base::OnceCallback<void(bool)> element_found_callback,
+  void OnWaitForElementVisibleWithInterrupts(
+      base::OnceCallback<void(ProcessedActionStatusProto)> callback,
       bool element_found,
       const Result* interrupt_result);
+  void OnWaitForElementVisibleNoInterrupts(
+      base::OnceCallback<void(ProcessedActionStatusProto)> callback,
+      bool element_found);
   void OnChosen(base::OnceCallback<void(const std::string&)> callback,
                 const std::string& chosen);
 
@@ -278,6 +293,9 @@
   std::map<std::string, ScriptStatusProto>* scripts_state_;
   std::unique_ptr<BatchElementChecker> batch_element_checker_;
 
+  // Paths of the interrupts that were run during the current action.
+  std::vector<std::string> ran_interrupts_;
+
   // Set of interrupts that might run during wait for dom actions with
   // allow_interrupt. Sorted by priority; an interrupt that appears on the
   // vector first should run first.
diff --git a/components/autofill_assistant/browser/script_executor_unittest.cc b/components/autofill_assistant/browser/script_executor_unittest.cc
index 28d7eb2..9ba34069 100644
--- a/components/autofill_assistant/browser/script_executor_unittest.cc
+++ b/components/autofill_assistant/browser/script_executor_unittest.cc
@@ -26,6 +26,7 @@
 using ::testing::AllOf;
 using ::testing::Contains;
 using ::testing::DoAll;
+using ::testing::ElementsAre;
 using ::testing::Eq;
 using ::testing::Field;
 using ::testing::Invoke;
@@ -33,6 +34,7 @@
 using ::testing::NiceMock;
 using ::testing::Not;
 using ::testing::Pair;
+using ::testing::Property;
 using ::testing::ReturnRef;
 using ::testing::SaveArg;
 using ::testing::SizeIs;
@@ -131,7 +133,7 @@
     wait_action->set_allow_interrupt(true);
     interruptible.add_actions()->mutable_tell()->set_message(path);
     EXPECT_CALL(mock_service_, OnGetActions(StrEq(path), _, _, _, _, _))
-        .WillOnce(RunOnceCallback<5>(true, Serialize(interruptible)));
+        .WillRepeatedly(RunOnceCallback<5>(true, Serialize(interruptible)));
   }
 
   // Creates an interrupt that contains a tell. It will always succeed.
@@ -279,7 +281,7 @@
   executor_->Run(executor_callback_.Get());
 
   ASSERT_EQ(1u, processed_actions_capture.size());
-  EXPECT_EQ(UNKNOWN_ACTION_STATUS, processed_actions_capture[0].status());
+  EXPECT_EQ(UNSUPPORTED_ACTION, processed_actions_capture[0].status());
 }
 
 TEST_F(ScriptExecutorTest, StopAfterEnd) {
@@ -626,6 +628,10 @@
                                               "payload for interrupt", _, _))
       .WillOnce(RunOnceCallback<3>(false, ""));
 
+  EXPECT_CALL(mock_service_, OnGetNextActions("global payload for interrupt",
+                                              "main script payload", _, _))
+      .WillOnce(RunOnceCallback<3>(false, ""));
+
   EXPECT_CALL(executor_callback_, Run(_));
   executor_->Run(executor_callback_.Get());
 
@@ -688,9 +694,21 @@
   SetupInterruptibleScript(kScriptPath, "element");
   SetupInterrupt("interrupt", "interrupt_trigger");
 
+  // The interrupt fails.
   EXPECT_CALL(mock_service_, OnGetNextActions(_, "payload for interrupt", _, _))
       .WillOnce(RunOnceCallback<3>(false, ""));
 
+  // The main script gets a report of the failure from the interrupt, and fails
+  // in turn.
+  EXPECT_CALL(
+      mock_service_,
+      OnGetNextActions(
+          _, "main script payload",
+          ElementsAre(Property(&ProcessedActionProto::status,
+                               ProcessedActionStatusProto::INTERRUPT_FAILED)),
+          _))
+      .WillOnce(RunOnceCallback<3>(false, ""));
+
   EXPECT_CALL(executor_callback_,
               Run(Field(&ScriptExecutor::Result::success, false)));
   executor_->Run(executor_callback_.Get());
@@ -710,11 +728,15 @@
   ActionsResponseProto interrupt_actions;
   interrupt_actions.add_actions()->mutable_stop();
 
+  // Get interrupt actions
   EXPECT_CALL(mock_service_, OnGetActions(StrEq("interrupt"), _, _, _, _, _))
       .WillRepeatedly(RunOnceCallback<5>(true, Serialize(interrupt_actions)));
 
+  // We expect to get result of interrupt action, then result of the main script
+  // action.
   EXPECT_CALL(mock_service_, OnGetNextActions(_, _, _, _))
-      .WillOnce(RunOnceCallback<3>(true, ""));
+      .Times(2)
+      .WillRepeatedly(RunOnceCallback<3>(true, ""));
 
   EXPECT_CALL(executor_callback_,
               Run(AllOf(Field(&ScriptExecutor::Result::success, true),
diff --git a/components/autofill_assistant/browser/script_tracker.cc b/components/autofill_assistant/browser/script_tracker.cc
index 62ea8cd3..78f4511 100644
--- a/components/autofill_assistant/browser/script_tracker.cc
+++ b/components/autofill_assistant/browser/script_tracker.cc
@@ -132,7 +132,7 @@
 
 bool ScriptTracker::Terminate() {
   if (running()) {
-    executor_->Shutdown();
+    executor_->Terminate();
     return false;
   }
   TerminatePendingChecks();
diff --git a/components/autofill_assistant/browser/script_tracker.h b/components/autofill_assistant/browser/script_tracker.h
index efa62fc7..515933e4 100644
--- a/components/autofill_assistant/browser/script_tracker.h
+++ b/components/autofill_assistant/browser/script_tracker.h
@@ -91,7 +91,7 @@
   // useful when analyzing feedback forms and for debugging in general.
   base::Value GetDebugContext() const;
 
-  // Initiates a script tracker shutdown.
+  // Terminates any running scripts.
   //
   // This function returns false when it needs more time to properly shut down
   // the script tracker. It usually means that it either has to wait for a
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto
index b92b4b3..1ae95f37 100644
--- a/components/autofill_assistant/browser/service.proto
+++ b/components/autofill_assistant/browser/service.proto
@@ -299,10 +299,40 @@
 
 enum ProcessedActionStatusProto {
   UNKNOWN_ACTION_STATUS = 0;
+
+  // Element could not be found.
   ELEMENT_RESOLUTION_FAILED = 1;
+
+  // The action was applied successfully.
   ACTION_APPLIED = 2;
+
+  // The action failed (generic error).
   OTHER_ACTION_STATUS = 3;
+
+  // The action failed to get payment information.
   PAYMENT_REQUEST_ERROR = 4;
+
+  // Server asked the client to execute an unknown or unsupported action.
+  UNSUPPORTED_ACTION = 5;
+
+  // The action decided to fallback to manual mode, stopping the script.
+  //
+  // This can happen:
+  // - if an autofill action or an update details action cancels the script,
+  //   possibly, not necessarily, as a result of a user action.
+  // - if an interrupt explicitly stops the main script, for wait for dom
+  MANUAL_FALLBACK = 6;
+
+  // The WaitForDom action failed because an interrupt that ran during
+  // that action failed.
+  INTERRUPT_FAILED = 7;
+
+  // The script was canceled by the user, while it was running.
+  //
+  // This only report such events that happen while a script is running. It can
+  // affect any action. It is a signal that the action or script ran in an
+  // abnormal situation and its outcome cannot be trusted.
+  USER_ABORTED_ACTION = 8;
 }
 
 // The pseudo type values come from
diff --git a/components/autofill_assistant/browser/ui_controller.h b/components/autofill_assistant/browser/ui_controller.h
index 2f80dde..a850a92 100644
--- a/components/autofill_assistant/browser/ui_controller.h
+++ b/components/autofill_assistant/browser/ui_controller.h
@@ -134,6 +134,9 @@
   // when analyzing feedback forms and for debugging in general.
   virtual std::string GetDebugContext() const = 0;
 
+  // Force the bottom sheet to be in the expanded state.
+  virtual void ExpandBottomSheet() = 0;
+
  protected:
   UiController() = default;
 };
diff --git a/components/browser_sync/BUILD.gn b/components/browser_sync/BUILD.gn
index 09c0796..17179c3 100644
--- a/components/browser_sync/BUILD.gn
+++ b/components/browser_sync/BUILD.gn
@@ -105,6 +105,8 @@
     "profile_sync_service_mock.h",
     "profile_sync_test_util.cc",
     "profile_sync_test_util.h",
+    "sync_user_settings_mock.cc",
+    "sync_user_settings_mock.h",
     "test_http_bridge_factory.cc",
     "test_http_bridge_factory.h",
     "test_profile_sync_service.cc",
diff --git a/components/browser_sync/profile_sync_service.h b/components/browser_sync/profile_sync_service.h
index 85b64d0..356a291 100644
--- a/components/browser_sync/profile_sync_service.h
+++ b/components/browser_sync/profile_sync_service.h
@@ -216,7 +216,7 @@
   void OnDataTypeRequestsSyncStartup(syncer::ModelType type) override;
   void StopAndClear() override;
   void RequestStop(SyncStopDataFate data_fate);
-  virtual void RequestStart();  // Virtual for testing.
+  void RequestStart();
   void AddObserver(syncer::SyncServiceObserver* observer) override;
   void RemoveObserver(syncer::SyncServiceObserver* observer) override;
   bool HasObserver(const syncer::SyncServiceObserver* observer) const override;
@@ -224,9 +224,8 @@
   syncer::ModelTypeSet GetForcedDataTypes() const override;
   syncer::ModelTypeSet GetPreferredDataTypes() const override;
   syncer::ModelTypeSet GetActiveDataTypes() const override;
-  // Virtual for testing.
-  virtual void OnUserChoseDatatypes(bool sync_everything,
-                                    syncer::ModelTypeSet chosen_types);
+  void OnUserChoseDatatypes(bool sync_everything,
+                            syncer::ModelTypeSet chosen_types);
   virtual void SetFirstSetupComplete();  // Virtual for testing.
   std::unique_ptr<syncer::SyncSetupInProgressHandle> GetSetupInProgressHandle()
       override;
diff --git a/components/browser_sync/profile_sync_service_mock.cc b/components/browser_sync/profile_sync_service_mock.cc
index c3a20238..cf833f274 100644
--- a/components/browser_sync/profile_sync_service_mock.cc
+++ b/components/browser_sync/profile_sync_service_mock.cc
@@ -6,6 +6,8 @@
 
 #include <utility>
 
+#include "components/sync/base/sync_prefs.h"
+
 namespace browser_sync {
 
 ProfileSyncServiceMock::ProfileSyncServiceMock(InitParams init_params)
@@ -13,10 +15,79 @@
 
 ProfileSyncServiceMock::~ProfileSyncServiceMock() {}
 
+SyncUserSettingsMock* ProfileSyncServiceMock::GetUserSettingsMock() {
+  return &user_settings_;
+}
+
+syncer::SyncUserSettings* ProfileSyncServiceMock::GetUserSettings() {
+  return &user_settings_;
+}
+
+const syncer::SyncUserSettings* ProfileSyncServiceMock::GetUserSettings()
+    const {
+  return &user_settings_;
+}
+
 bool ProfileSyncServiceMock::IsAuthenticatedAccountPrimary() const {
   return true;
 }
 
+syncer::ModelTypeSet ProfileSyncServiceMock::GetPreferredDataTypes() const {
+  return syncer::SyncPrefs::ResolvePrefGroups(
+      /*registered_types=*/syncer::ModelTypeSet::All(),
+      user_settings_.GetChosenDataTypes());
+}
+
+bool ProfileSyncServiceMock::IsPassphraseRequiredForDecryption() const {
+  return user_settings_.IsPassphraseRequiredForDecryption();
+}
+
+base::Time ProfileSyncServiceMock::GetExplicitPassphraseTime() const {
+  return user_settings_.GetExplicitPassphraseTime();
+}
+
+bool ProfileSyncServiceMock::IsUsingSecondaryPassphrase() const {
+  return user_settings_.IsUsingSecondaryPassphrase();
+}
+
+void ProfileSyncServiceMock::EnableEncryptEverything() {
+  user_settings_.EnableEncryptEverything();
+}
+
+bool ProfileSyncServiceMock::IsEncryptEverythingEnabled() const {
+  return user_settings_.IsEncryptEverythingEnabled();
+}
+
+void ProfileSyncServiceMock::SetEncryptionPassphrase(
+    const std::string& passphrase) {
+  user_settings_.SetEncryptionPassphrase(passphrase);
+}
+
+bool ProfileSyncServiceMock::SetDecryptionPassphrase(
+    const std::string& passphrase) {
+  return user_settings_.SetDecryptionPassphrase(passphrase);
+}
+
+bool ProfileSyncServiceMock::IsPassphraseRequired() const {
+  return user_settings_.IsPassphraseRequired();
+}
+
+bool ProfileSyncServiceMock::IsFirstSetupComplete() const {
+  return user_settings_.IsFirstSetupComplete();
+}
+
+void ProfileSyncServiceMock::SetFirstSetupComplete() {
+  user_settings_.SetFirstSetupComplete();
+}
+
+syncer::PassphraseType ProfileSyncServiceMock::GetPassphraseType() const {
+  return user_settings_.GetPassphraseType();
+}
+
+bool ProfileSyncServiceMock::IsEncryptEverythingAllowed() const {
+  return user_settings_.IsEncryptEverythingAllowed();
+}
+
 std::unique_ptr<syncer::SyncSetupInProgressHandle>
 ProfileSyncServiceMock::GetSetupInProgressHandleConcrete() {
   return browser_sync::ProfileSyncService::GetSetupInProgressHandle();
diff --git a/components/browser_sync/profile_sync_service_mock.h b/components/browser_sync/profile_sync_service_mock.h
index d44ed1c8..51cad7e 100644
--- a/components/browser_sync/profile_sync_service_mock.h
+++ b/components/browser_sync/profile_sync_service_mock.h
@@ -10,6 +10,7 @@
 
 #include "base/memory/weak_ptr.h"
 #include "components/browser_sync/profile_sync_service.h"
+#include "components/browser_sync/sync_user_settings_mock.h"
 #include "components/sync/base/model_type.h"
 #include "components/sync/protocol/sync_protocol_error.h"
 #include "google_apis/gaia/google_service_auth_error.h"
@@ -22,7 +23,11 @@
   explicit ProfileSyncServiceMock(InitParams init_params);
   ~ProfileSyncServiceMock() override;
 
+  SyncUserSettingsMock* GetUserSettingsMock();
+
   // SyncService overrides.
+  syncer::SyncUserSettings* GetUserSettings() override;
+  const syncer::SyncUserSettings* GetUserSettings() const override;
   MOCK_CONST_METHOD0(GetDisableReasons, int());
   MOCK_CONST_METHOD0(GetTransportState, TransportState());
   // TODO(crbug.com/871221): Remove this override. This is overridden here to
@@ -35,7 +40,8 @@
                std::unique_ptr<syncer::SyncSetupInProgressHandle>());
   MOCK_CONST_METHOD0(IsSetupInProgress, bool());
 
-  MOCK_CONST_METHOD0(GetPreferredDataTypes, syncer::ModelTypeSet());
+  MOCK_CONST_METHOD0(GetRegisteredDataTypes, syncer::ModelTypeSet());
+  syncer::ModelTypeSet GetPreferredDataTypes() const override;
   MOCK_CONST_METHOD0(GetActiveDataTypes, syncer::ModelTypeSet());
 
   MOCK_METHOD0(StopAndClear, void());
@@ -43,13 +49,13 @@
   MOCK_METHOD1(AddObserver, void(syncer::SyncServiceObserver*));
   MOCK_METHOD1(RemoveObserver, void(syncer::SyncServiceObserver*));
 
-  MOCK_CONST_METHOD0(IsPassphraseRequiredForDecryption, bool());
-  MOCK_CONST_METHOD0(GetExplicitPassphraseTime, base::Time());
-  MOCK_CONST_METHOD0(IsUsingSecondaryPassphrase, bool());
-  MOCK_METHOD0(EnableEncryptEverything, void());
-  MOCK_CONST_METHOD0(IsEncryptEverythingEnabled, bool());
-  MOCK_METHOD1(SetEncryptionPassphrase, void(const std::string& passphrase));
-  MOCK_METHOD1(SetDecryptionPassphrase, bool(const std::string& passphrase));
+  bool IsPassphraseRequiredForDecryption() const override;
+  base::Time GetExplicitPassphraseTime() const override;
+  bool IsUsingSecondaryPassphrase() const override;
+  void EnableEncryptEverything() override;
+  bool IsEncryptEverythingEnabled() const override;
+  void SetEncryptionPassphrase(const std::string& passphrase) override;
+  bool SetDecryptionPassphrase(const std::string& passphrase) override;
 
   MOCK_CONST_METHOD0(GetUserShare, syncer::UserShare*());
 
@@ -78,7 +84,7 @@
   MOCK_METHOD0(OnConfigureStart, void());
 
   // DataTypeEncryptionHandler overrides.
-  MOCK_CONST_METHOD0(IsPassphraseRequired, bool());
+  bool IsPassphraseRequired() const override;
 
   // syncer::UnrecoverableErrorHandler overrides.
   MOCK_METHOD2(OnUnrecoverableError,
@@ -86,17 +92,13 @@
                     const std::string& message));
 
   // ProfileSyncService overrides.
-  MOCK_CONST_METHOD0(IsFirstSetupComplete, bool());
-  MOCK_METHOD0(SetFirstSetupComplete, void());
-  MOCK_METHOD0(RequestStart, void());
-  MOCK_METHOD2(OnUserChoseDatatypes,
-               void(bool sync_everything, syncer::ModelTypeSet chosen_types));
+  bool IsFirstSetupComplete() const override;
+  void SetFirstSetupComplete() override;
 
-  MOCK_CONST_METHOD0(GetRegisteredDataTypes, syncer::ModelTypeSet());
   MOCK_CONST_METHOD1(IsDataTypeControllerRunning, bool(syncer::ModelType));
 
-  MOCK_CONST_METHOD0(GetPassphraseType, syncer::PassphraseType());
-  MOCK_CONST_METHOD0(IsEncryptEverythingAllowed, bool());
+  syncer::PassphraseType GetPassphraseType() const override;
+  bool IsEncryptEverythingAllowed() const override;
 
   MOCK_METHOD0(StartUpSlowEngineComponents, void());
 
@@ -105,6 +107,9 @@
   // Gives access to the real implementation of ProfileSyncService methods:
   std::unique_ptr<syncer::SyncSetupInProgressHandle>
   GetSetupInProgressHandleConcrete();
+
+ private:
+  testing::NiceMock<SyncUserSettingsMock> user_settings_;
 };
 
 }  // namespace browser_sync
diff --git a/components/browser_sync/sync_user_settings_mock.cc b/components/browser_sync/sync_user_settings_mock.cc
new file mode 100644
index 0000000..6a5c199
--- /dev/null
+++ b/components/browser_sync/sync_user_settings_mock.cc
@@ -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.
+
+#include "components/browser_sync/sync_user_settings_mock.h"
+
+namespace browser_sync {
+
+SyncUserSettingsMock::SyncUserSettingsMock() = default;
+
+SyncUserSettingsMock::~SyncUserSettingsMock() = default;
+
+}  // namespace browser_sync
diff --git a/components/browser_sync/sync_user_settings_mock.h b/components/browser_sync/sync_user_settings_mock.h
new file mode 100644
index 0000000..2d5b6351
--- /dev/null
+++ b/components/browser_sync/sync_user_settings_mock.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 COMPONENTS_BROWSER_SYNC_SYNC_USER_SETTINGS_MOCK_H_
+#define COMPONENTS_BROWSER_SYNC_SYNC_USER_SETTINGS_MOCK_H_
+
+#include <string>
+
+#include "components/sync/driver/sync_user_settings.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace browser_sync {
+
+class SyncUserSettingsMock : public syncer::SyncUserSettings {
+ public:
+  SyncUserSettingsMock();
+  ~SyncUserSettingsMock() override;
+
+  MOCK_CONST_METHOD0(IsSyncRequested, bool());
+  MOCK_METHOD1(SetSyncRequested, void(bool));
+
+  MOCK_CONST_METHOD0(IsSyncAllowedByPlatform, bool());
+  MOCK_METHOD1(SetSyncAllowedByPlatform, void(bool));
+
+  MOCK_CONST_METHOD0(IsFirstSetupComplete, bool());
+  MOCK_METHOD0(SetFirstSetupComplete, void());
+
+  MOCK_CONST_METHOD0(IsSyncEverythingEnabled, bool());
+  MOCK_CONST_METHOD0(GetChosenDataTypes, syncer::ModelTypeSet());
+  MOCK_METHOD2(SetChosenDataTypes, void(bool, syncer::ModelTypeSet));
+
+  MOCK_CONST_METHOD0(IsEncryptEverythingAllowed, bool());
+  MOCK_METHOD1(SetEncryptEverythingAllowed, void(bool));
+  MOCK_CONST_METHOD0(IsEncryptEverythingEnabled, bool());
+  MOCK_METHOD0(EnableEncryptEverything, void());
+
+  MOCK_CONST_METHOD0(IsPassphraseRequired, bool());
+  MOCK_CONST_METHOD0(IsPassphraseRequiredForDecryption, bool());
+  MOCK_CONST_METHOD0(IsUsingSecondaryPassphrase, bool());
+  MOCK_CONST_METHOD0(GetExplicitPassphraseTime, base::Time());
+  MOCK_CONST_METHOD0(GetPassphraseType, syncer::PassphraseType());
+
+  MOCK_METHOD1(SetEncryptionPassphrase, void(const std::string&));
+  MOCK_METHOD1(SetDecryptionPassphrase, bool(const std::string&));
+};
+
+}  // namespace browser_sync
+
+#endif  // COMPONENTS_BROWSER_SYNC_SYNC_USER_SETTINGS_MOCK_H_
diff --git a/components/cast_channel/cast_message_handler_unittest.cc b/components/cast_channel/cast_message_handler_unittest.cc
index f047e8c..42528e2 100644
--- a/components/cast_channel/cast_message_handler_unittest.cc
+++ b/components/cast_channel/cast_message_handler_unittest.cc
@@ -7,7 +7,6 @@
 #include "base/json/json_reader.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
-#include "base/test/scoped_task_environment.h"
 #include "base/test/test_simple_task_runner.h"
 #include "components/cast_channel/cast_test_util.h"
 #include "content/public/test/test_browser_thread_bundle.h"
@@ -55,9 +54,8 @@
 class CastMessageHandlerTest : public testing::Test {
  public:
   CastMessageHandlerTest()
-      : environment_(
+      : thread_bundle_(
             base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
-        thread_bundle_(content::TestBrowserThreadBundle::PLAIN_MAINLOOP),
         cast_socket_service_(new base::TestSimpleTaskRunner()),
         handler_(&cast_socket_service_,
                  /* connector */ nullptr,
@@ -99,7 +97,6 @@
   }
 
  protected:
-  base::test::ScopedTaskEnvironment environment_;
   content::TestBrowserThreadBundle thread_bundle_;
   std::unique_ptr<base::RunLoop> run_loop_;
   MockCastSocketService cast_socket_service_;
@@ -229,7 +226,7 @@
                      base::Unretained(this)));
   EXPECT_CALL(*this, DoOnAppAvailability("ABCDEFAB",
                                          GetAppAvailabilityResult::kUnknown));
-  environment_.FastForwardBy(base::TimeDelta::FromSeconds(5));
+  thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(5));
 }
 
 TEST_F(CastMessageHandlerTest, AppAvailabilitySentOnlyOnceWhilePending) {
@@ -276,7 +273,7 @@
   })");
   OnMessage(response);
   // Wait for message to be parsed and handled.
-  environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
 
   // Re-open virtual connection should cause message to be sent.
   EXPECT_CALL(*cast_socket_.mock_transport(), SendMessage(_, _));
@@ -344,7 +341,7 @@
             GetMessageType(virtual_connection_request));
   EXPECT_EQ(CastMessageType::kLaunch, GetMessageType(launch_session_request));
 
-  environment_.FastForwardBy(base::TimeDelta::FromSeconds(30));
+  thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(30));
   EXPECT_EQ(1, session_launch_response_count_);
 }
 
diff --git a/components/cronet/android/BUILD.gn b/components/cronet/android/BUILD.gn
index b03e0bf4..d8fb828 100644
--- a/components/cronet/android/BUILD.gn
+++ b/components/cronet/android/BUILD.gn
@@ -1266,9 +1266,11 @@
   copy("cronet_package_copy_test_files") {
     testonly = true
     sources = [
+      "//net/data/ssl/certificates/expired_cert.pem",
       "//net/data/ssl/certificates/quic-chain.pem",
       "//net/data/ssl/certificates/quic-leaf-cert.key",
       "//net/data/ssl/certificates/quic-leaf-cert.key.pkcs8.pem",
+      "//net/data/ssl/certificates/root_ca_cert.pem",
     ]
     outputs = [
       "$_test_package_dir/assets/test_files/net/data/ssl/certificates/{{source_file_part}}",
diff --git a/components/download/internal/common/download_stats.cc b/components/download/internal/common/download_stats.cc
index 66e21af..2848008 100644
--- a/components/download/internal/common/download_stats.cc
+++ b/components/download/internal/common/download_stats.cc
@@ -403,6 +403,7 @@
     FILE_PATH_LITERAL(".pyd"),
     FILE_PATH_LITERAL(".pyo"),      // 319
     FILE_PATH_LITERAL(".desktop"),  // 320
+    FILE_PATH_LITERAL(".cpi"),      // 321
     // NOTE! When you add a type here, please add the UMA value as a comment.
     // These must all match DownloadItem.DangerousFileType in
     // enums.xml. From 263 onward, they should also match
diff --git a/components/exo/text_input.cc b/components/exo/text_input.cc
index ad34380e..f2534c4c 100644
--- a/components/exo/text_input.cc
+++ b/components/exo/text_input.cc
@@ -172,12 +172,12 @@
   return false;
 }
 
-bool TextInput::GetSelectionRange(gfx::Range* range) const {
+bool TextInput::GetEditableSelectionRange(gfx::Range* range) const {
   NOTIMPLEMENTED_LOG_ONCE();
   return false;
 }
 
-bool TextInput::SetSelectionRange(const gfx::Range& range) {
+bool TextInput::SetEditableSelectionRange(const gfx::Range& range) {
   NOTIMPLEMENTED_LOG_ONCE();
   return false;
 }
diff --git a/components/exo/text_input.h b/components/exo/text_input.h
index 96c6f444..4a47440 100644
--- a/components/exo/text_input.h
+++ b/components/exo/text_input.h
@@ -114,8 +114,8 @@
   ui::TextInputClient::FocusReason GetFocusReason() const override;
   bool GetTextRange(gfx::Range* range) const override;
   bool GetCompositionTextRange(gfx::Range* range) const override;
-  bool GetSelectionRange(gfx::Range* range) const override;
-  bool SetSelectionRange(const gfx::Range& range) override;
+  bool GetEditableSelectionRange(gfx::Range* range) const override;
+  bool SetEditableSelectionRange(const gfx::Range& range) override;
   bool DeleteRange(const gfx::Range& range) override;
   bool GetTextFromRange(const gfx::Range& range,
                         base::string16* text) const override;
diff --git a/components/gcm_driver/gcm_driver_desktop.cc b/components/gcm_driver/gcm_driver_desktop.cc
index f82a3ed..4095b833 100644
--- a/components/gcm_driver/gcm_driver_desktop.cc
+++ b/components/gcm_driver/gcm_driver_desktop.cc
@@ -874,6 +874,9 @@
 
   GCMClient::Result result = EnsureStarted(GCMClient::IMMEDIATE_START);
   if (result != GCMClient::SUCCESS) {
+    DLOG(ERROR)
+        << "Unable to get the InstanceID token: cannot start the GCM Client";
+
     callback.Run(std::string(), result);
     return;
   }
@@ -938,6 +941,8 @@
   if (result != GCMClient::SUCCESS) {
     // Can't tell whether the registration is valid or not, so don't run the
     // callback (let it hang indefinitely).
+    DLOG(ERROR) << "Unable to validate the InstanceID token: cannot start the "
+                   "GCM Client";
     return;
   }
 
@@ -971,6 +976,9 @@
 
   GCMClient::Result result = EnsureStarted(GCMClient::IMMEDIATE_START);
   if (result != GCMClient::SUCCESS) {
+    DLOG(ERROR)
+        << "Unable to delete the InstanceID token: cannot start the GCM Client";
+
     callback.Run(result);
     return;
   }
@@ -1017,8 +1025,11 @@
   DCHECK(ui_thread_->RunsTasksInCurrentSequence());
 
   GCMClient::Result result = EnsureStarted(GCMClient::IMMEDIATE_START);
-  if (result != GCMClient::SUCCESS)
+  if (result != GCMClient::SUCCESS) {
+    DLOG(ERROR)
+        << "Unable to add the InstanceID data: cannot start the GCM Client";
     return;
+  }
 
   // Delay the operation until GCMClient is ready.
   if (!delayed_task_controller_->CanRunTaskWithoutDelay()) {
@@ -1048,8 +1059,11 @@
   DCHECK(ui_thread_->RunsTasksInCurrentSequence());
 
   GCMClient::Result result = EnsureStarted(GCMClient::IMMEDIATE_START);
-  if (result != GCMClient::SUCCESS)
+  if (result != GCMClient::SUCCESS) {
+    DLOG(ERROR)
+        << "Unable to remove the InstanceID data: cannot start the GCM Client";
     return;
+  }
 
   // Delay the operation until GCMClient is ready.
   if (!delayed_task_controller_->CanRunTaskWithoutDelay()) {
@@ -1078,6 +1092,10 @@
 
   GCMClient::Result result = EnsureStarted(GCMClient::IMMEDIATE_START);
   if (result != GCMClient::SUCCESS) {
+    DLOG(ERROR)
+        << "Unable to get the InstanceID data: cannot start the GCM Client";
+
+    // Resolve the |callback| to not leave it hanging indefinitely.
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::BindOnce(callback, std::string(), std::string()));
     return;
diff --git a/components/history/core/common/BUILD.gn b/components/history/core/common/BUILD.gn
index b2f332a..d2f7a71 100644
--- a/components/history/core/common/BUILD.gn
+++ b/components/history/core/common/BUILD.gn
@@ -4,6 +4,8 @@
 
 static_library("common") {
   sources = [
+    "pref_names.cc",
+    "pref_names.h",
     "thumbnail_score.cc",
     "thumbnail_score.h",
   ]
diff --git a/components/history/core/common/pref_names.cc b/components/history/core/common/pref_names.cc
new file mode 100644
index 0000000..4e57e77
--- /dev/null
+++ b/components/history/core/common/pref_names.cc
@@ -0,0 +1,12 @@
+// 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/history/core/common/pref_names.h"
+
+namespace prefs {
+
+// Boolean controlling whether history saving is disabled.
+const char kSavingBrowserHistoryDisabled[] = "history.saving_disabled";
+
+}  // namespace prefs
diff --git a/components/history/core/common/pref_names.h b/components/history/core/common/pref_names.h
new file mode 100644
index 0000000..0c7f7e9a
--- /dev/null
+++ b/components/history/core/common/pref_names.h
@@ -0,0 +1,18 @@
+// 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.
+
+// Constants for the names of various preferences, for easier changing.
+
+#ifndef COMPONENTS_HISTORY_CORE_COMMON_PREF_NAMES_H_
+#define COMPONENTS_HISTORY_CORE_COMMON_PREF_NAMES_H_
+
+#include <stddef.h>
+
+namespace prefs {
+
+extern const char kSavingBrowserHistoryDisabled[];
+
+}  // namespace prefs
+
+#endif  // COMPONENTS_HISTORY_CORE_COMMON_PREF_NAMES_H_
diff --git a/components/invalidation/impl/fcm_invalidation_service.cc b/components/invalidation/impl/fcm_invalidation_service.cc
index 90ba361..2a72bbe9 100644
--- a/components/invalidation/impl/fcm_invalidation_service.cc
+++ b/components/invalidation/impl/fcm_invalidation_service.cc
@@ -180,10 +180,15 @@
   DCHECK(!invalidator_);
   DCHECK(IsReadyToStart());
 
-  PopulateClientID();
   auto network = std::make_unique<syncer::FCMNetworkHandler>(
       gcm_driver_, instance_id_driver_);
+  // The order of calls is important. Do not change.
+  // We should start listening before requesting the id, because
+  // valid id is only generated, once there is an app handler
+  // for the app. StartListening registers the app handler.
   network->StartListening();
+  PopulateClientID();
+
   invalidator_ = std::make_unique<syncer::FCMInvalidator>(
       std::move(network), identity_provider_, pref_service_, loader_factory_,
       parse_json_);
diff --git a/components/payments/content/payment_request_spec.cc b/components/payments/content/payment_request_spec.cc
index 3a75a84..c3406df 100644
--- a/components/payments/content/payment_request_spec.cc
+++ b/components/payments/content/payment_request_spec.cc
@@ -119,7 +119,7 @@
   if (!errors)
     return;
 
-  shipping_address_errors_ = std::move(errors->shipping_address);
+  details_->shipping_address_errors = std::move(errors->shipping_address);
   payer_errors_ = std::move(errors->payer);
   current_update_reason_ = UpdateReason::RETRY;
   NotifyOnSpecUpdated();
@@ -128,38 +128,39 @@
 
 base::string16 PaymentRequestSpec::GetShippingAddressError(
     autofill::ServerFieldType type) {
-  if (!shipping_address_errors_)
+  if (!details_->shipping_address_errors)
     return base::string16();
 
   if (type == autofill::ADDRESS_HOME_STREET_ADDRESS)
-    return base::UTF8ToUTF16(shipping_address_errors_->address_line);
+    return base::UTF8ToUTF16(details_->shipping_address_errors->address_line);
 
   if (type == autofill::ADDRESS_HOME_CITY)
-    return base::UTF8ToUTF16(shipping_address_errors_->city);
+    return base::UTF8ToUTF16(details_->shipping_address_errors->city);
 
   if (type == autofill::ADDRESS_HOME_COUNTRY)
-    return base::UTF8ToUTF16(shipping_address_errors_->country);
+    return base::UTF8ToUTF16(details_->shipping_address_errors->country);
 
   if (type == autofill::ADDRESS_HOME_DEPENDENT_LOCALITY)
-    return base::UTF8ToUTF16(shipping_address_errors_->dependent_locality);
+    return base::UTF8ToUTF16(
+        details_->shipping_address_errors->dependent_locality);
 
   if (type == autofill::COMPANY_NAME)
-    return base::UTF8ToUTF16(shipping_address_errors_->organization);
+    return base::UTF8ToUTF16(details_->shipping_address_errors->organization);
 
   if (type == autofill::PHONE_HOME_WHOLE_NUMBER)
-    return base::UTF8ToUTF16(shipping_address_errors_->phone);
+    return base::UTF8ToUTF16(details_->shipping_address_errors->phone);
 
   if (type == autofill::ADDRESS_HOME_ZIP)
-    return base::UTF8ToUTF16(shipping_address_errors_->postal_code);
+    return base::UTF8ToUTF16(details_->shipping_address_errors->postal_code);
 
   if (type == autofill::NAME_FULL)
-    return base::UTF8ToUTF16(shipping_address_errors_->recipient);
+    return base::UTF8ToUTF16(details_->shipping_address_errors->recipient);
 
   if (type == autofill::ADDRESS_HOME_STATE)
-    return base::UTF8ToUTF16(shipping_address_errors_->region);
+    return base::UTF8ToUTF16(details_->shipping_address_errors->region);
 
   if (type == autofill::ADDRESS_HOME_SORTING_CODE)
-    return base::UTF8ToUTF16(shipping_address_errors_->sorting_code);
+    return base::UTF8ToUTF16(details_->shipping_address_errors->sorting_code);
 
   return base::string16();
 }
@@ -182,18 +183,18 @@
 }
 
 bool PaymentRequestSpec::has_shipping_address_error() const {
-  return shipping_address_errors_ && request_shipping() &&
-         !(shipping_address_errors_->address_line.empty() &&
-           shipping_address_errors_->city.empty() &&
-           shipping_address_errors_->country.empty() &&
-           shipping_address_errors_->dependent_locality.empty() &&
-           shipping_address_errors_->organization.empty() &&
-           shipping_address_errors_->phone.empty() &&
-           shipping_address_errors_->postal_code.empty() &&
-           shipping_address_errors_->recipient.empty() &&
-           shipping_address_errors_->region.empty() &&
-           shipping_address_errors_->region_code.empty() &&
-           shipping_address_errors_->sorting_code.empty());
+  return details_->shipping_address_errors && request_shipping() &&
+         !(details_->shipping_address_errors->address_line.empty() &&
+           details_->shipping_address_errors->city.empty() &&
+           details_->shipping_address_errors->country.empty() &&
+           details_->shipping_address_errors->dependent_locality.empty() &&
+           details_->shipping_address_errors->organization.empty() &&
+           details_->shipping_address_errors->phone.empty() &&
+           details_->shipping_address_errors->postal_code.empty() &&
+           details_->shipping_address_errors->recipient.empty() &&
+           details_->shipping_address_errors->region.empty() &&
+           details_->shipping_address_errors->region_code.empty() &&
+           details_->shipping_address_errors->sorting_code.empty());
 }
 
 bool PaymentRequestSpec::has_payer_error() const {
@@ -205,10 +206,6 @@
 }
 
 void PaymentRequestSpec::RecomputeSpecForDetails() {
-  // Clear the shipping address errors when the merchant updates the price based
-  // on the shipping address that the user has newly fixed or selected.
-  shipping_address_errors_.reset();
-
   // Reparse the |details_| and update the observers.
   UpdateSelectedShippingOption(/*after_update=*/true);
 
@@ -385,10 +382,6 @@
             break;
         }
       }
-
-      // Update shipping address errors
-      if (details_->shipping_address_errors)
-        shipping_address_errors_ = std::move(details_->shipping_address_errors);
     }
     return;
   }
diff --git a/components/payments/content/payment_request_spec.h b/components/payments/content/payment_request_spec.h
index bda25ec..d1b4316 100644
--- a/components/payments/content/payment_request_spec.h
+++ b/components/payments/content/payment_request_spec.h
@@ -237,7 +237,6 @@
   // notified.
   base::ObserverList<Observer>::Unchecked observers_;
 
-  mojom::AddressErrorsPtr shipping_address_errors_;
   mojom::PayerErrorsPtr payer_errors_;
 
   DISALLOW_COPY_AND_ASSIGN(PaymentRequestSpec);
diff --git a/components/policy/proto/chrome_device_policy.proto b/components/policy/proto/chrome_device_policy.proto
index 8d0a85c..f5fcfd3 100644
--- a/components/policy/proto/chrome_device_policy.proto
+++ b/components/policy/proto/chrome_device_policy.proto
@@ -1073,6 +1073,21 @@
   optional int32 rate_days = 1;
 }
 
+// Specifies how long cached Active Directory Group Policy Objects (GPOs) may be
+// reused until they are re-downloaded (a version change also forces a
+// re-download).
+// Applies to Active Directory management mode only.
+message DeviceGpoCacheLifetimeProto {
+  optional int32 lifetime_hours = 1;
+}
+
+// Specifies how long cached Active Directory authentication data may be reused
+// until it is refreshed. This can significantly speed up user authentication.
+// Applies to Active Directory management mode only.
+message DeviceAuthDataCacheLifetimeProto {
+  optional int32 lifetime_hours = 1;
+}
+
 // Setting to control the authentication type for newly added users which log in
 // via SAML.
 message SamlLoginAuthenticationTypeProto {
@@ -1192,4 +1207,7 @@
       device_wifi_fast_transition_enabled = 73;
   optional DeviceDisplayResolutionProto device_display_resolution = 74;
   optional PluginVmAllowedProto plugin_vm_allowed = 75;
+  optional DeviceGpoCacheLifetimeProto device_gpo_cache_lifetime = 76;
+  optional DeviceAuthDataCacheLifetimeProto device_auth_data_cache_lifetime =
+      77;
 }
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 54b31da..6ad3c51 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -5778,6 +5778,48 @@
       Note that passwords might get older than the specified number of days if the client has been offline for a longer period of time.''',
     },
     {
+      'name': 'DeviceGpoCacheLifetime',
+      'type': 'int',
+      'schema': { 'type': 'integer', 'minimum': 0, 'maximum': 9999 },
+      'supported_on': ['chrome_os:73-'],
+      'supported_chrome_os_management': ['active_directory'],
+      'device_only': True,
+      'features': {
+        'dynamic_refresh': True,
+      },
+      'example_value': 0,
+      'id': 508,
+      'caption': '''GPO cache lifetime''',
+      'tags': [],
+      'desc': '''Specifies the lifetime (in hours) of the Group Policy Object (GPO) cache. Instead of re-downloading GPOs on every policy fetch, the system may reuse cached GPOs as long as their version does not change. This policy specifies the maximum duration for which cached GPOs may be reused before they are re-downloaded. Rebooting and logging out clears the cache.
+
+      If the policy is unset, cached GPOs may be reused for up to 25 hours.
+
+      If the policy is set to 0, GPO caching is turned off. Note that this increases server load since GPOs are re-downloaded on every policy fetch, even if they did not change.''',
+    },
+    {
+      'name': 'DeviceAuthDataCacheLifetime',
+      'type': 'int',
+      'schema': { 'type': 'integer', 'minimum': 0, 'maximum': 9999 },
+      'supported_on': ['chrome_os:73-'],
+      'supported_chrome_os_management': ['active_directory'],
+      'device_only': True,
+      'features': {
+        'dynamic_refresh': True,
+      },
+      'example_value': 0,
+      'id': 509,
+      'caption': '''Authentication data cache lifetime''',
+      'tags': ['admin-sharing'],
+      'desc': '''Specifies the lifetime (in hours) of the authentication data cache. The cache is used to speed up sign-in. It contains general data (workgroup name etc.) about affiliated realms, i.e. realms trusted by the machine realm. No user-specific data and no data for unaffiliated realms is cached. Rebooting the device clears the cache.
+
+      If the policy is unset, cached authentication data may be reused for up to 73 hours.
+
+      If the policy is set to 0, authentication data caching is turned off. This can significantly slow down sign-in of affiliated users since realm-specific data has to be fetched on every sign-in.
+
+      Note that realm data is cached even for ephemeral users. The cache should be turned off if tracing the realm of ephemeral users should be prevented.''',
+    },
+    {
       'name': 'CloudPrintSubmitEnabled',
       'type': 'main',
       'schema': { 'type': 'boolean' },
@@ -13983,6 +14025,7 @@
       'name': 'ParentAccessCodeConfig',
       'type': 'dict',
       'schema': {
+        'sensitiveValue': True,
         'type': 'object',
         'properties': {
           'current_config': {
@@ -14017,7 +14060,6 @@
           }
         },
       },
-      'sensitiveValue': True,
       'supported_on': ['chrome_os:73-'],
       'features': {
         'dynamic_refresh': True,
@@ -14210,5 +14252,5 @@
   },
   'placeholders': [],
   'deleted_policy_ids': [412],
-  'highest_id_currently_used': 507,
+  'highest_id_currently_used': 509,
 }
diff --git a/components/policy/tools/schema_validator.py b/components/policy/tools/schema_validator.py
index 263a4d0c..d4c1898 100644
--- a/components/policy/tools/schema_validator.py
+++ b/components/policy/tools/schema_validator.py
@@ -16,14 +16,16 @@
     'boolean': {
         'type': str,  # required
         'id': str,  # optional
-        'description': str  # optional
+        'description': str,  # optional
+        'sensitiveValue': bool  # optional
     },
     'string': {
         'type': str,  # required
         'id': str,  # optional
         'description': str,  # optional
         'enum': list,  # optional
-        'pattern': str  # optional
+        'pattern': str,  # optional
+        'sensitiveValue': bool  # optional
     },
     'integer': {
         'type': str,  # required
@@ -31,13 +33,15 @@
         'description': str,  # optional
         'enum': list,  # optional
         'minimum': int,  # optional
-        'maximum': int  # optional
+        'maximum': int,  # optional
+        'sensitiveValue': bool  # optional
     },
     'array': {
         'type': str,  # required
         'id': str,  # optional
+        'items': dict,  # required,
         'description': str,  # optional
-        'items': dict  # required
+        'sensitiveValue': bool  # optional
     },
     'object': {
         'type': str,  # required
@@ -46,7 +50,8 @@
         'properties': dict,  #           one of these 3 properties is required
         'patternProperties': dict,  #    one of these 3 properties is required
         'additionalProperties': dict,  # one of these 3 properties is required
-        'required': list  # optional
+        'required': list,  # optional
+        'sensitiveValue': bool  # optional
     }
 }
 
diff --git a/components/safe_browsing/db/whitelist_checker_client_unittest.cc b/components/safe_browsing/db/whitelist_checker_client_unittest.cc
index f2299cb..1ef5d18 100644
--- a/components/safe_browsing/db/whitelist_checker_client_unittest.cc
+++ b/components/safe_browsing/db/whitelist_checker_client_unittest.cc
@@ -47,9 +47,8 @@
 class WhitelistCheckerClientTest : public testing::Test {
  public:
   WhitelistCheckerClientTest()
-      : environment_(
+      : thread_bundle_(
             base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
-        thread_bundle_(content::TestBrowserThreadBundle::PLAIN_MAINLOOP),
         target_url_("http://foo.bar") {}
 
   void SetUp() override {
@@ -63,11 +62,10 @@
     // Verify no callback is remaining.
     // TODO(nparker): We should somehow EXPECT that no entry is remaining,
     // rather than just invoking it.
-    environment_.FastForwardUntilNoTasksRemain();
+    thread_bundle_.FastForwardUntilNoTasksRemain();
   }
 
  protected:
-  base::test::ScopedTaskEnvironment environment_;
   content::TestBrowserThreadBundle thread_bundle_;
 
   GURL target_url_;
@@ -118,11 +116,11 @@
   MockBoolCallback callback;
   WhitelistCheckerClient::StartCheckCsdWhitelist(database_manager_, target_url_,
                                                  callback.Get());
-  environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+  thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(1));
   // No callback yet.
 
   EXPECT_CALL(callback, Run(true /* is_whitelisted */));
-  environment_.FastForwardBy(base::TimeDelta::FromSeconds(5));
+  thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(5));
 }
 
 }  // namespace safe_browsing
diff --git a/components/sessions/BUILD.gn b/components/sessions/BUILD.gn
index 615c1c7..49dfb35b 100644
--- a/components/sessions/BUILD.gn
+++ b/components/sessions/BUILD.gn
@@ -112,6 +112,7 @@
 
   deps = [
     "//base",
+    "//components/history/core/common",
     "//components/keyed_service/core",
     "//components/prefs",
     "//components/variations",
diff --git a/components/sessions/DEPS b/components/sessions/DEPS
index 9b0cbfb..2d08392 100644
--- a/components/sessions/DEPS
+++ b/components/sessions/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+  "+components/history/core/common",
   "+components/variations",
   "+ui/base",
   "+ui/gfx",
diff --git a/components/signin/core/browser/about_signin_internals.cc b/components/signin/core/browser/about_signin_internals.cc
index 2f5a530..524ce34 100644
--- a/components/signin/core/browser/about_signin_internals.cc
+++ b/components/signin/core/browser/about_signin_internals.cc
@@ -124,10 +124,6 @@
       return "Gaia Authentication Result";
     case signin_internals_util::REFRESH_TOKEN_RECEIVED:
       return "RefreshToken Received";
-    case signin_internals_util::SIGNIN_STARTED:
-      return "SigninManager Started";
-    case signin_internals_util::SIGNIN_COMPLETED:
-      return "SigninManager Completed";
     case signin_internals_util::TIMED_FIELDS_END:
       NOTREACHED();
       return "Error";
@@ -247,7 +243,7 @@
   signin_observers_.RemoveObserver(observer);
 }
 
-void AboutSigninInternals::NotifySigninValueChanged(
+void AboutSigninInternals::NotifyTimedSigninFieldValueChanged(
     const signin_internals_util::TimedSigninStatusField& field,
     const std::string& value) {
   unsigned int field_index = field - signin_internals_util::TIMED_FIELDS_BEGIN;
@@ -269,8 +265,6 @@
   if (field == signin_internals_util::AUTHENTICATION_RESULT_RECEIVED) {
     ClearPref(client_->GetPrefs(),
               signin_internals_util::REFRESH_TOKEN_RECEIVED);
-    ClearPref(client_->GetPrefs(), signin_internals_util::SIGNIN_STARTED);
-    ClearPref(client_->GetPrefs(), signin_internals_util::SIGNIN_COMPLETED);
   }
 
   NotifyObservers();
@@ -424,13 +418,13 @@
 }
 
 void AboutSigninInternals::OnRefreshTokenReceived(const std::string& status) {
-  NotifySigninValueChanged(signin_internals_util::REFRESH_TOKEN_RECEIVED,
-                           status);
+  NotifyTimedSigninFieldValueChanged(
+      signin_internals_util::REFRESH_TOKEN_RECEIVED, status);
 }
 
 void AboutSigninInternals::OnAuthenticationResultReceived(
     const std::string& status) {
-  NotifySigninValueChanged(
+  NotifyTimedSigninFieldValueChanged(
       signin_internals_util::AUTHENTICATION_RESULT_RECEIVED, status);
 }
 
diff --git a/components/signin/core/browser/about_signin_internals.h b/components/signin/core/browser/about_signin_internals.h
index 0b43ff90..f1b5384a 100644
--- a/components/signin/core/browser/about_signin_internals.h
+++ b/components/signin/core/browser/about_signin_internals.h
@@ -17,7 +17,6 @@
 #include "components/signin/core/browser/gaia_cookie_manager_service.h"
 #include "components/signin/core/browser/signin_client.h"
 #include "components/signin/core/browser/signin_error_controller.h"
-#include "components/signin/core/browser/signin_internals_util.h"
 #include "google_apis/gaia/oauth2_token_service.h"
 #include "services/identity/public/cpp/identity_manager.h"
 
@@ -193,15 +192,11 @@
         signin::AccountConsistencyMethod account_consistency);
   };
 
-  // IdentityMager::DiagnosticsObserver implementations.
+  // IdentityManager::DiagnosticsObserver implementations.
   void OnAccessTokenRequested(const std::string& account_id,
                               const std::string& consumer_id,
                               const identity::ScopeSet& scopes) override;
 
-  void NotifySigninValueChanged(
-      const signin_internals_util::TimedSigninStatusField& field,
-      const std::string& value) override;
-
   // OAuth2TokenService::DiagnosticsObserver implementations.
   void OnFetchAccessTokenComplete(const std::string& account_id,
                                   const std::string& consumer_id,
@@ -228,6 +223,10 @@
   void OnPrimaryAccountCleared(
       const AccountInfo& primary_account_info) override;
 
+  void NotifyTimedSigninFieldValueChanged(
+      const signin_internals_util::TimedSigninStatusField& field,
+      const std::string& value);
+
   void NotifyObservers();
 
   // SigninErrorController::Observer implementation
diff --git a/components/signin/core/browser/profile_oauth2_token_service.cc b/components/signin/core/browser/profile_oauth2_token_service.cc
index 2384e33..582726a7 100644
--- a/components/signin/core/browser/profile_oauth2_token_service.cc
+++ b/components/signin/core/browser/profile_oauth2_token_service.cc
@@ -49,6 +49,8 @@
       return "DiceResponseHandler::Signout";
     case SourceForRefreshTokenOperation::kDiceTurnOnSyncHelper_Abort:
       return "DiceTurnOnSyncHelper::Abort";
+    case SourceForRefreshTokenOperation::kMachineLogon_CredentialProvider:
+      return "MachineLogon::CredentialProvider";
   }
 }
 }  // namespace
diff --git a/components/signin/core/browser/signin_internals_util.cc b/components/signin/core/browser/signin_internals_util.cc
index fa9d492..68884202 100644
--- a/components/signin/core/browser/signin_internals_util.cc
+++ b/components/signin/core/browser/signin_internals_util.cc
@@ -37,8 +37,6 @@
   switch (field) {
     ENUM_CASE(AUTHENTICATION_RESULT_RECEIVED);
     ENUM_CASE(REFRESH_TOKEN_RECEIVED);
-    ENUM_CASE(SIGNIN_STARTED);
-    ENUM_CASE(SIGNIN_COMPLETED);
     case TIMED_FIELDS_END:
       NOTREACHED();
       return std::string();
diff --git a/components/signin/core/browser/signin_internals_util.h b/components/signin/core/browser/signin_internals_util.h
index d397d04..576710b 100644
--- a/components/signin/core/browser/signin_internals_util.h
+++ b/components/signin/core/browser/signin_internals_util.h
@@ -45,8 +45,6 @@
   TIMED_FIELDS_BEGIN = TIMED_FIELDS_BEGIN_UNTYPED,
   AUTHENTICATION_RESULT_RECEIVED = TIMED_FIELDS_BEGIN,
   REFRESH_TOKEN_RECEIVED,
-  SIGNIN_STARTED,
-  SIGNIN_COMPLETED,
   TIMED_FIELDS_END
 };
 
@@ -65,14 +63,6 @@
 std::string SigninStatusFieldToString(UntimedSigninStatusField field);
 std::string SigninStatusFieldToString(TimedSigninStatusField field);
 
-// An Observer class for authentication and token diagnostic information.
-class SigninDiagnosticsObserver {
- public:
-  // Credentials and signin related changes.
-  virtual void NotifySigninValueChanged(const TimedSigninStatusField& field,
-                                        const std::string& value) {}
-};
-
 // Gets the first 6 hex characters of the SHA256 hash of the passed in string.
 // These are enough to perform equality checks across a single users tokens,
 // while preventing outsiders from reverse-engineering the actual token from
diff --git a/components/signin/core/browser/signin_manager.cc b/components/signin/core/browser/signin_manager.cc
index f3c819f..2863a80 100644
--- a/components/signin/core/browser/signin_manager.cc
+++ b/components/signin/core/browser/signin_manager.cc
@@ -90,8 +90,6 @@
   password_.assign(password);
   signin_manager_signed_in_ = false;
   user_info_fetched_by_account_tracker_ = false;
-  NotifyDiagnosticsObservers(signin_internals_util::SIGNIN_STARTED,
-                             SigninTypeToString(type));
   return true;
 }
 
@@ -386,8 +384,6 @@
 }
 
 void SigninManager::CompletePendingSignin() {
-  NotifyDiagnosticsObservers(signin_internals_util::SIGNIN_COMPLETED,
-                             "Successful");
   DCHECK(!possibly_invalid_account_id_.empty());
   OnSignedIn();
 
diff --git a/components/signin/core/browser/signin_manager_base.cc b/components/signin/core/browser/signin_manager_base.cc
index a75a5a1d..85fb881 100644
--- a/components/signin/core/browser/signin_manager_base.cc
+++ b/components/signin/core/browser/signin_manager_base.cc
@@ -56,6 +56,7 @@
   registry->RegisterBooleanPref(prefs::kSigninAllowed, true);
   registry->RegisterInt64Pref(prefs::kSignedInTime,
                               base::Time().ToInternalValue());
+  registry->RegisterBooleanPref(prefs::kSignedInWithCredentialProvider, false);
 
   // Deprecated prefs: will be removed in a future release.
   registry->RegisterStringPref(prefs::kGoogleServicesUsername, std::string());
@@ -245,20 +246,3 @@
 void SigninManagerBase::RemoveObserver(Observer* observer) {
   observer_list_.RemoveObserver(observer);
 }
-
-void SigninManagerBase::AddSigninDiagnosticsObserver(
-    signin_internals_util::SigninDiagnosticsObserver* observer) {
-  signin_diagnostics_observers_.AddObserver(observer);
-}
-
-void SigninManagerBase::RemoveSigninDiagnosticsObserver(
-    signin_internals_util::SigninDiagnosticsObserver* observer) {
-  signin_diagnostics_observers_.RemoveObserver(observer);
-}
-
-void SigninManagerBase::NotifyDiagnosticsObservers(
-    const signin_internals_util::TimedSigninStatusField& field,
-    const std::string& value) {
-  for (auto& observer : signin_diagnostics_observers_)
-    observer.NotifySigninValueChanged(field, value);
-}
diff --git a/components/signin/core/browser/signin_manager_base.h b/components/signin/core/browser/signin_manager_base.h
index e30a2ea..89365f6a 100644
--- a/components/signin/core/browser/signin_manager_base.h
+++ b/components/signin/core/browser/signin_manager_base.h
@@ -154,12 +154,6 @@
   void AddObserver(Observer* observer);
   void RemoveObserver(Observer* observer);
 
-  // Methods to register or remove SigninDiagnosticObservers.
-  void AddSigninDiagnosticsObserver(
-      signin_internals_util::SigninDiagnosticsObserver* observer);
-  void RemoveSigninDiagnosticsObserver(
-      signin_internals_util::SigninDiagnosticsObserver* observer);
-
   // Gives access to the SigninClient instance associated with this instance.
   SigninClient* signin_client() const { return client_; }
 
@@ -196,11 +190,6 @@
   // Makes sure list is empty on destruction.
   base::ObserverList<Observer, true>::Unchecked observer_list_;
 
-  // Helper method to notify all registered diagnostics observers with.
-  void NotifyDiagnosticsObservers(
-      const signin_internals_util::TimedSigninStatusField& field,
-      const std::string& value);
-
  private:
   friend class FakeSigninManagerBase;
   friend class FakeSigninManager;
@@ -218,10 +207,6 @@
   // Account id after successful authentication.
   std::string authenticated_account_id_;
 
-  // The list of SigninDiagnosticObservers.
-  base::ObserverList<signin_internals_util::SigninDiagnosticsObserver,
-                     true>::Unchecked signin_diagnostics_observers_;
-
   // The list of callbacks notified on shutdown.
   base::CallbackList<void()> on_shutdown_callback_list_;
 
diff --git a/components/signin/core/browser/signin_metrics.h b/components/signin/core/browser/signin_metrics.h
index 3b52acd1..deaa45b 100644
--- a/components/signin/core/browser/signin_metrics.h
+++ b/components/signin/core/browser/signin_metrics.h
@@ -342,7 +342,8 @@
   kDiceResponseHandler_Signin,
   kDiceResponseHandler_Signout,
   kDiceTurnOnSyncHelper_Abort,
-  kMaxValue = kDiceTurnOnSyncHelper_Abort
+  kMachineLogon_CredentialProvider,
+  kMaxValue = kMachineLogon_CredentialProvider
 };
 
 // Different types of reporting. This is used as a histogram suffix.
diff --git a/components/signin/core/browser/signin_pref_names.cc b/components/signin/core/browser/signin_pref_names.cc
index 8de4ecc..24308a2 100644
--- a/components/signin/core/browser/signin_pref_names.cc
+++ b/components/signin/core/browser/signin_pref_names.cc
@@ -86,6 +86,11 @@
 // to the browser.
 const char kSignedInTime[] = "signin.signedin_time";
 
+// Boolean indicating if this profile was signed in with information from a
+// credential provider.
+const char kSignedInWithCredentialProvider[] =
+    "signin.with_credential_provider";
+
 // Boolean which stores if the user is allowed to signin to chrome.
 const char kSigninAllowed[] = "signin.allowed";
 
diff --git a/components/signin/core/browser/signin_pref_names.h b/components/signin/core/browser/signin_pref_names.h
index 2ebafcb..0fda78598 100644
--- a/components/signin/core/browser/signin_pref_names.h
+++ b/components/signin/core/browser/signin_pref_names.h
@@ -25,6 +25,7 @@
 extern const char kGoogleServicesUsernamePattern[];
 extern const char kReverseAutologinRejectedEmailList[];
 extern const char kSignedInTime[];
+extern const char kSignedInWithCredentialProvider[];
 extern const char kSigninAllowed[];
 extern const char kTokenServiceDiceCompatible[];
 extern const char kTokenServiceExcludeAllSecondaryAccounts[];
diff --git a/components/storage_monitor/image_capture_device_manager_unittest.mm b/components/storage_monitor/image_capture_device_manager_unittest.mm
index c21da1c..02e1726 100644
--- a/components/storage_monitor/image_capture_device_manager_unittest.mm
+++ b/components/storage_monitor/image_capture_device_manager_unittest.mm
@@ -11,7 +11,6 @@
 #include "base/mac/foundation_util.h"
 #include "base/mac/sdk_forward_declarations.h"
 #include "base/memory/weak_ptr.h"
-#include "base/test/scoped_task_environment.h"
 #include "components/storage_monitor/image_capture_device.h"
 #include "components/storage_monitor/image_capture_device_manager.h"
 #include "components/storage_monitor/test_storage_monitor.h"
@@ -239,9 +238,7 @@
 
 class ImageCaptureDeviceManagerTest : public testing::Test {
  public:
-  ImageCaptureDeviceManagerTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+  ImageCaptureDeviceManagerTest() {}
 
   void SetUp() override { monitor_ = TestStorageMonitor::CreateAndInstall(); }
 
@@ -266,10 +263,9 @@
                   moreGoing:NO];
   }
 
-  void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
+  void RunUntilIdle() { thread_bundle_.RunUntilIdle(); }
 
  protected:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
   content::TestBrowserThreadBundle thread_bundle_;
   TestStorageMonitor* monitor_;
   TestCameraListener listener_;
diff --git a/components/storage_monitor/media_storage_util_unittest.cc b/components/storage_monitor/media_storage_util_unittest.cc
index ba7386d..1ede541 100644
--- a/components/storage_monitor/media_storage_util_unittest.cc
+++ b/components/storage_monitor/media_storage_util_unittest.cc
@@ -10,7 +10,6 @@
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/post_task.h"
-#include "base/test/scoped_task_environment.h"
 #include "components/storage_monitor/media_storage_util.h"
 #include "components/storage_monitor/removable_device_constants.h"
 #include "components/storage_monitor/storage_monitor.h"
@@ -28,9 +27,7 @@
 
 class MediaStorageUtilTest : public testing::Test {
  public:
-  MediaStorageUtilTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+  MediaStorageUtilTest() {}
   ~MediaStorageUtilTest() override {}
 
   // Verify mounted device type.
@@ -69,10 +66,9 @@
     TestStorageMonitor::Destroy();
   }
 
-  void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
+  void RunUntilIdle() { test_browser_thread_bundle_.RunUntilIdle(); }
 
  private:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
   content::TestBrowserThreadBundle test_browser_thread_bundle_;
   TestStorageMonitor* monitor_;
   base::ScopedTempDir scoped_temp_dir_;
diff --git a/components/storage_monitor/storage_monitor_chromeos_unittest.cc b/components/storage_monitor/storage_monitor_chromeos_unittest.cc
index 8edfbfc..2ecc82cd 100644
--- a/components/storage_monitor/storage_monitor_chromeos_unittest.cc
+++ b/components/storage_monitor/storage_monitor_chromeos_unittest.cc
@@ -150,8 +150,6 @@
   StorageMonitor::EjectStatus status_;
 
  private:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-
   content::TestBrowserThreadBundle thread_bundle_;
 
   // Temporary directory for created test data.
@@ -166,9 +164,7 @@
 StorageMonitorCrosTest::StorageMonitorCrosTest()
     : monitor_(NULL),
       disk_mount_manager_mock_(NULL),
-      status_(StorageMonitor::EJECT_FAILURE),
-      scoped_task_environment_(
-          base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+      status_(StorageMonitor::EJECT_FAILURE) {}
 
 StorageMonitorCrosTest::~StorageMonitorCrosTest() {
 }
@@ -197,7 +193,7 @@
 
   disk_mount_manager_mock_ = NULL;
   DiskMountManager::Shutdown();
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
 }
 
 void StorageMonitorCrosTest::MountDevice(
@@ -217,7 +213,7 @@
         true /* on_removable_device */, kFileSystemType);
   }
   monitor_->OnMountEvent(DiskMountManager::MOUNTING, error_code, mount_info);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
 }
 
 void StorageMonitorCrosTest::UnmountDevice(
@@ -226,7 +222,7 @@
   monitor_->OnMountEvent(DiskMountManager::UNMOUNTING, error_code, mount_info);
   if (error_code == chromeos::MOUNT_ERROR_NONE)
     disk_mount_manager_mock_->RemoveDiskEntryForMountDevice(mount_info);
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
 }
 
 uint64_t StorageMonitorCrosTest::GetDeviceStorageSize(
diff --git a/components/sync/engine_impl/non_blocking_type_commit_contribution.cc b/components/sync/engine_impl/non_blocking_type_commit_contribution.cc
index d2e740b5..d0ae42f 100644
--- a/components/sync/engine_impl/non_blocking_type_commit_contribution.cc
+++ b/components/sync/engine_impl/non_blocking_type_commit_contribution.cc
@@ -273,6 +273,13 @@
     commit_proto->set_name("encrypted");
   }
 
+  // See crbug.com/915133: Certain versions of Chrome (e.g. M71) handle corrupt
+  // SESSIONS data poorly. Let's guard against future versions from committing
+  // problematic data that could cause crashes on other syncing devices.
+  if (commit_proto->specifics().session().has_tab()) {
+    CHECK_GE(commit_proto->specifics().session().tab_node_id(), 0);
+  }
+
   // Always include enough specifics to identify the type. Do this even in
   // deletion requests, where the specifics are otherwise invalid.
   AddDefaultFieldValue(type_, commit_proto->mutable_specifics());
diff --git a/components/sync/engine_impl/sync_scheduler_impl_unittest.cc b/components/sync/engine_impl/sync_scheduler_impl_unittest.cc
index 51d71d5..9f36862 100644
--- a/components/sync/engine_impl/sync_scheduler_impl_unittest.cc
+++ b/components/sync/engine_impl/sync_scheduler_impl_unittest.cc
@@ -303,6 +303,13 @@
   base::test::ScopedTaskEnvironment task_environment_;
 
  private:
+  static const base::TickClock* tick_clock_;
+  static base::TimeTicks GetMockTimeTicks() {
+    if (!tick_clock_)
+      return base::TimeTicks();
+    return tick_clock_->NowTicks();
+  }
+
   syncable::Directory* directory() {
     return test_user_share_.user_share()->directory.get();
   }
@@ -321,6 +328,8 @@
   base::WeakPtrFactory<SyncSchedulerImplTest> weak_ptr_factory_;
 };
 
+const base::TickClock* SyncSchedulerImplTest::tick_clock_ = nullptr;
+
 void RecordSyncShareImpl(SyncShareTimes* times) {
   times->push_back(TimeTicks::Now());
 }
diff --git a/components/sync/model_impl/client_tag_based_model_type_processor.cc b/components/sync/model_impl/client_tag_based_model_type_processor.cc
index 8b273a6..6881901d 100644
--- a/components/sync/model_impl/client_tag_based_model_type_processor.cc
+++ b/components/sync/model_impl/client_tag_based_model_type_processor.cc
@@ -977,13 +977,22 @@
   metadata_changes->UpdateModelTypeState(model_type_state_);
 
   for (const UpdateResponseData& update : updates) {
-    if (update.entity->client_tag_hash.empty()) {
+    const std::string& client_tag_hash = update.entity->client_tag_hash;
+    if (client_tag_hash.empty()) {
       // Ignore updates missing a client tag hash (e.g. permanent nodes).
       continue;
     }
     if (update.entity->is_deleted()) {
       DLOG(WARNING) << "Ignoring tombstone found during initial update: "
-                    << "client_tag_hash = " << update.entity->client_tag_hash;
+                    << "client_tag_hash = " << client_tag_hash;
+      continue;
+    }
+    if (bridge_->SupportsGetClientTag() &&
+        client_tag_hash !=
+            GenerateSyncableHash(
+                type_, bridge_->GetClientTag(update.entity.value()))) {
+      DLOG(WARNING) << "Received unexpected client tag hash: "
+                    << client_tag_hash;
       continue;
     }
 
@@ -991,10 +1000,9 @@
     // TODO(crbug.com/872360): The CreateEntity() call below assumes that no
     // entity with this client_tag_hash exists already, but in some cases it
     // does.
-    if (entities_.find(update.entity->client_tag_hash) != entities_.end()) {
-      DLOG(ERROR) << "Received duplicate client_tag_hash "
-                  << update.entity->client_tag_hash << " for "
-                  << ModelTypeToString(type_);
+    if (entities_.find(client_tag_hash) != entities_.end()) {
+      DLOG(ERROR) << "Received duplicate client_tag_hash " << client_tag_hash
+                  << " for " << ModelTypeToString(type_);
     }
 #endif  // DCHECK_IS_ON()
     ProcessorEntityTracker* entity = CreateEntity(update.entity.value());
diff --git a/components/sync_bookmarks/synced_bookmark_tracker.cc b/components/sync_bookmarks/synced_bookmark_tracker.cc
index 8162c6f..00ed4c34 100644
--- a/components/sync_bookmarks/synced_bookmark_tracker.cc
+++ b/components/sync_bookmarks/synced_bookmark_tracker.cc
@@ -532,29 +532,10 @@
 
 void SyncedBookmarkTracker::CheckAllNodesTracked(
     const bookmarks::BookmarkModel* bookmark_model) const {
-  // TODO(crbug.com/516866): The method is added to debug some crashes.
-  // Since it's relatively expensive, it should run on debug enabled
-  // builds only after the root cause is found.
-  ui::TreeNodeIterator<const bookmarks::BookmarkNode> iterator(
-      bookmark_model->root_node());
-  while (iterator.has_next()) {
-    const bookmarks::BookmarkNode* node = iterator.Next();
-    if (!bookmark_model->client()->CanSyncNode(node)) {
-      // TODO(crbug.com/516866): The below CHECK is added to debug some crashes.
-      // Should be converted to a DCHECK after the root cause if found.
-      CHECK(!GetEntityForBookmarkNode(node));
-      continue;
-    }
-    // Mobile bookmarks folder is created on the server only after signing-in
-    // with a mobile client. Therefore, it should not be considered for
-    // validation.
-    if (node == bookmark_model->mobile_node()) {
-      continue;
-    }
-    // TODO(crbug.com/516866): The below CHECK is added to debug some crashes.
-    // Should be converted to a DCHECK after the root cause if found.
-    CHECK(GetEntityForBookmarkNode(node));
-  }
+  // TODO(crbug.com/516866): Introduce logic to validate the invariant of the
+  // tracker.
+  CHECK(GetEntityForBookmarkNode(bookmark_model->bookmark_bar_node()));
+  CHECK(GetEntityForBookmarkNode(bookmark_model->other_node()));
 }
 
 }  // namespace sync_bookmarks
diff --git a/components/sync_sessions/session_sync_bridge.cc b/components/sync_sessions/session_sync_bridge.cc
index 5a79484..b9956b5b 100644
--- a/components/sync_sessions/session_sync_bridge.cc
+++ b/components/sync_sessions/session_sync_bridge.cc
@@ -237,13 +237,15 @@
           continue;
         }
 
-        if (!SessionStore::AreValidSpecifics(specifics) ||
-            change.data().client_tag_hash !=
-                GenerateSyncableHash(syncer::SESSIONS,
-                                     SessionStore::GetClientTag(specifics))) {
+        if (!SessionStore::AreValidSpecifics(specifics)) {
           continue;
         }
 
+        // Guaranteed by the processor.
+        DCHECK_EQ(change.data().client_tag_hash,
+                  GenerateSyncableHash(syncer::SESSIONS,
+                                       SessionStore::GetClientTag(specifics)));
+
         batch->PutAndUpdateTracker(specifics, change.data().modification_time);
         // If a favicon or favicon urls are present, load the URLs and visit
         // times into the in-memory favicon cache.
@@ -280,6 +282,9 @@
 
 std::string SessionSyncBridge::GetClientTag(
     const syncer::EntityData& entity_data) {
+  if (!SessionStore::AreValidSpecifics(entity_data.specifics.session())) {
+    return std::string();
+  }
   return SessionStore::GetClientTag(entity_data.specifics.session());
 }
 
diff --git a/content/browser/appcache/appcache_fuzzer.cc b/content/browser/appcache/appcache_fuzzer.cc
index a1701d6..64822bba 100644
--- a/content/browser/appcache/appcache_fuzzer.cc
+++ b/content/browser/appcache/appcache_fuzzer.cc
@@ -7,7 +7,6 @@
 #include "base/no_destructor.h"
 #include "base/task/post_task.h"
 #include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
 #include "content/browser/appcache/appcache_dispatcher_host.h"
 #include "content/browser/appcache/appcache_fuzzer.pb.h"
 #include "content/browser/appcache/chrome_appcache_service.h"
@@ -26,10 +25,7 @@
 namespace {
 
 struct Env {
-  Env()
-      : scoped_task_environment(
-            base::test::ScopedTaskEnvironment::MainThreadType::IO),
-        thread_bundle(TestBrowserThreadBundle::Options::IO_MAINLOOP) {
+  Env() : thread_bundle(base::test::ScopedTaskEnvironment::MainThreadType::IO) {
     base::CommandLine::Init(0, nullptr);
     logging::SetMinLogLevel(logging::LOG_FATAL);
     mojo::core::Init();
@@ -58,10 +54,9 @@
                        /*resource_context=*/nullptr,
                        /*request_context_getter=*/nullptr,
                        /*special_storage_policy=*/nullptr));
-    scoped_task_environment.RunUntilIdle();
+    thread_bundle.RunUntilIdle();
   }
 
-  base::test::ScopedTaskEnvironment scoped_task_environment;
   TestBrowserThreadBundle thread_bundle;
   base::test::ScopedFeatureList feature_list;
   scoped_refptr<ChromeAppCacheService> appcache_service;
@@ -226,7 +221,7 @@
         break;
       }
       case fuzzing::proto::Command::kRunUntilIdle: {
-        SingletonEnv().scoped_task_environment.RunUntilIdle();
+        SingletonEnv().thread_bundle.RunUntilIdle();
         break;
       }
       case fuzzing::proto::Command::COMMAND_NOT_SET: {
@@ -238,7 +233,7 @@
   host.reset();
   // TODO(nedwilliamson): Investigate removing this or reinitializing
   // the appcache service as a fuzzer command.
-  SingletonEnv().scoped_task_environment.RunUntilIdle();
+  SingletonEnv().thread_bundle.RunUntilIdle();
 }
 
 }  // namespace content
diff --git a/content/browser/appcache/chrome_appcache_service_unittest.cc b/content/browser/appcache/chrome_appcache_service_unittest.cc
index c8489b69d..3e89e9b 100644
--- a/content/browser/appcache/chrome_appcache_service_unittest.cc
+++ b/content/browser/appcache/chrome_appcache_service_unittest.cc
@@ -12,7 +12,6 @@
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/task/post_task.h"
-#include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/browser/appcache/appcache_database.h"
 #include "content/browser/appcache/appcache_storage_impl.h"
@@ -44,12 +43,10 @@
 class ChromeAppCacheServiceTest : public testing::Test {
  public:
   ChromeAppCacheServiceTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::IO),
+      : thread_bundle_(base::test::ScopedTaskEnvironment::MainThreadType::IO),
         kProtectedManifestURL(kProtectedManifest),
         kNormalManifestURL(kNormalManifest),
-        kSessionOnlyManifestURL(kSessionOnlyManifest),
-        thread_bundle_(TestBrowserThreadBundle::Options::IO_MAINLOOP) {}
+        kSessionOnlyManifestURL(kSessionOnlyManifest) {}
 
  protected:
   scoped_refptr<ChromeAppCacheService> CreateAppCacheServiceImpl(
@@ -57,14 +54,13 @@
       bool init_storage);
   void InsertDataIntoAppCache(ChromeAppCacheService* appcache_service);
 
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  TestBrowserThreadBundle thread_bundle_;
   base::ScopedTempDir temp_dir_;
   const GURL kProtectedManifestURL;
   const GURL kNormalManifestURL;
   const GURL kSessionOnlyManifestURL;
 
  private:
-  TestBrowserThreadBundle thread_bundle_;
   TestBrowserContext browser_context_;
 };
 
@@ -86,14 +82,14 @@
           base::RetainedRef(browser_context_.GetRequestContext()),
           mock_policy));
   // Steps needed to initialize the storage of AppCache data.
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   if (init_storage) {
     AppCacheStorageImpl* storage =
         static_cast<AppCacheStorageImpl*>(
             appcache_service->storage());
     storage->database_->db_connection();
     storage->disk_cache();
-    scoped_task_environment_.RunUntilIdle();
+    thread_bundle_.RunUntilIdle();
   }
   return appcache_service;
 }
@@ -131,7 +127,7 @@
 
   // Test: delete the ChromeAppCacheService
   appcache_service = nullptr;
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
 
   // Recreate the appcache (for reading the data back)
   appcache_service = CreateAppCacheServiceImpl(appcache_path, false);
@@ -153,7 +149,7 @@
 
   // Delete and let cleanup tasks run prior to returning.
   appcache_service = nullptr;
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
 }
 
 TEST_F(ChromeAppCacheServiceTest, SaveSessionState) {
@@ -173,7 +169,7 @@
 
   // Test: delete the ChromeAppCacheService
   appcache_service = nullptr;
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
 
   // Recreate the appcache (for reading the data back)
   appcache_service = CreateAppCacheServiceImpl(appcache_path, false);
@@ -195,7 +191,7 @@
 
   // Delete and let cleanup tasks run prior to returning.
   appcache_service = nullptr;
-  scoped_task_environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
 }
 
 }  // namespace content
diff --git a/content/browser/find_request_manager.cc b/content/browser/find_request_manager.cc
index 839088b8..54bc71e7 100644
--- a/content/browser/find_request_manager.cc
+++ b/content/browser/find_request_manager.cc
@@ -39,7 +39,9 @@
     contents = WebContentsImpl::FromFrameTreeNode(node);
     if (node->IsMainFrame() && contents->GetBrowserPluginEmbedder()) {
       for (auto* inner_contents : contents->GetInnerWebContents()) {
-        children.push_back(inner_contents->GetMainFrame()->frame_tree_node());
+        children.push_back(static_cast<WebContentsImpl*>(inner_contents)
+                               ->GetMainFrame()
+                               ->frame_tree_node());
       }
     }
   }
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index caa00ceb..642e956 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -1409,7 +1409,9 @@
   return false;
 }
 
-bool RenderWidgetHostViewAura::GetSelectionRange(gfx::Range* range) const {
+bool RenderWidgetHostViewAura::GetEditableSelectionRange(
+    gfx::Range* range) const {
+  // TODO(yhanada, crbug.com/908762): Return only selections in a text field.
   if (!text_input_manager_ || !GetFocusedWidget())
     return false;
 
@@ -1423,7 +1425,8 @@
   return true;
 }
 
-bool RenderWidgetHostViewAura::SetSelectionRange(const gfx::Range& range) {
+bool RenderWidgetHostViewAura::SetEditableSelectionRange(
+    const gfx::Range& range) {
   // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
   NOTIMPLEMENTED_LOG_ONCE();
   return false;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index e719fb1..1be2dec 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -229,8 +229,8 @@
   ui::TextInputClient::FocusReason GetFocusReason() const override;
   bool GetTextRange(gfx::Range* range) const override;
   bool GetCompositionTextRange(gfx::Range* range) const override;
-  bool GetSelectionRange(gfx::Range* range) const override;
-  bool SetSelectionRange(const gfx::Range& range) override;
+  bool GetEditableSelectionRange(gfx::Range* range) const override;
+  bool SetEditableSelectionRange(const gfx::Range& range) override;
   bool DeleteRange(const gfx::Range& range) override;
   bool GetTextFromRange(const gfx::Range& range,
                         base::string16* text) const override;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index 3d0644a..7628598 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -6453,7 +6453,7 @@
 }
 
 // This test is for selection range.
-TEST_F(InputMethodStateAuraTest, GetSelectionRange) {
+TEST_F(InputMethodStateAuraTest, GetEditableSelectionRange) {
   base::string16 text;
   gfx::Range expected_range(0U, 1U);
 
@@ -6464,7 +6464,8 @@
     gfx::Range range_from_client;
 
     // This method always returns true.
-    EXPECT_TRUE(text_input_client()->GetSelectionRange(&range_from_client));
+    EXPECT_TRUE(
+        text_input_client()->GetEditableSelectionRange(&range_from_client));
     EXPECT_EQ(expected_range, range_from_client);
 
     // Changing range to make sure that the next view has a different text
diff --git a/content/browser/scheduler/browser_task_executor_unittest.cc b/content/browser/scheduler/browser_task_executor_unittest.cc
index 433a701..980c2236 100644
--- a/content/browser/scheduler/browser_task_executor_unittest.cc
+++ b/content/browser/scheduler/browser_task_executor_unittest.cc
@@ -51,10 +51,8 @@
     std::vector<TaskEntry> tasks_;
   };
 
-  base::test::ScopedTaskEnvironment environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
   TestBrowserThreadBundle thread_bundle_{
-      TestBrowserThreadBundle::PLAIN_MAINLOOP};
+      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
   AfterStartupBrowserClient browser_client_;
   ContentBrowserClient* old_browser_client_;
 };
@@ -92,7 +90,7 @@
       FROM_HERE, {BrowserThread::UI, base::TaskPriority::USER_BLOCKING},
       base::BindOnce(&SetBoolFlag, base::Unretained(&ran_user_blocking)));
 
-  environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
 
   EXPECT_FALSE(ran_best_effort);
   EXPECT_TRUE(ran_user_visible);
@@ -127,33 +125,34 @@
   // AfterStartupTaskRunner.
   EXPECT_EQ(browser_client_.tasks_.size(), 2u);
 
-  EXPECT_EQ(environment_.GetPendingMainThreadTaskCount(), 0u);
+  EXPECT_EQ(thread_bundle_.GetPendingMainThreadTaskCount(), 0u);
 
   // Emulate startup complete after 1 sec - this should post the two tasks to
   // the UI thread.
-  environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+  thread_bundle_.FastForwardBy(base::TimeDelta::FromSeconds(1));
   browser_client_.RunTasks();
-  EXPECT_EQ(environment_.GetPendingMainThreadTaskCount(), 2u);
+  EXPECT_EQ(thread_bundle_.GetPendingMainThreadTaskCount(), 2u);
 
   // Run the two tasks including the first BEST_EFFORT task posted as immediate.
   // The three other BEST_EFFORT tasks should remain since they are delayed
   // tasks. They should have been posted with their original delays.
-  environment_.RunUntilIdle();
+  thread_bundle_.RunUntilIdle();
   EXPECT_TRUE(ran_first_task);
-  EXPECT_EQ(environment_.GetPendingMainThreadTaskCount(), 3u);
+  EXPECT_EQ(thread_bundle_.GetPendingMainThreadTaskCount(), 3u);
 
   // Run the delayed tasks one by one.
   for (size_t pending_tasks = 3; pending_tasks > 0; pending_tasks--) {
-    EXPECT_EQ(environment_.NextMainThreadPendingTaskDelay(),
+    EXPECT_EQ(thread_bundle_.NextMainThreadPendingTaskDelay(),
               base::TimeDelta::FromMilliseconds(100));
-    environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(100));
-    EXPECT_EQ(environment_.GetPendingMainThreadTaskCount(), pending_tasks - 1u);
+    thread_bundle_.FastForwardBy(base::TimeDelta::FromMilliseconds(100));
+    EXPECT_EQ(thread_bundle_.GetPendingMainThreadTaskCount(),
+              pending_tasks - 1u);
   }
 
   // Posting another BEST_EFFORT task should bypass the browser_client_.
   ui_best_effort_runner->PostTask(FROM_HERE, base::DoNothing());
   EXPECT_EQ(browser_client_.tasks_.size(), 0u);
-  EXPECT_EQ(environment_.GetPendingMainThreadTaskCount(), 1u);
+  EXPECT_EQ(thread_bundle_.GetPendingMainThreadTaskCount(), 1u);
 }
 
 }  // namespace content
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 72a0b42..e7aa06b8 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -236,9 +236,8 @@
 }
 
 // Helper for GetInnerWebContents().
-bool GetInnerWebContentsHelper(
-    std::vector<WebContentsImpl*>* all_guest_contents,
-    WebContents* guest_contents) {
+bool GetInnerWebContentsHelper(std::vector<WebContents*>* all_guest_contents,
+                               WebContents* guest_contents) {
   auto* web_contents_impl = static_cast<WebContentsImpl*>(guest_contents);
   if (web_contents_impl->GetBrowserPluginGuest()->attached() &&
       !GuestMode::IsCrossProcessFrameGuest(web_contents_impl)) {
@@ -1219,25 +1218,12 @@
   return it->second;
 }
 
-std::vector<WebContentsImpl*> WebContentsImpl::GetInnerWebContents() {
-  std::vector<WebContentsImpl*> all_inner_contents;
-  if (browser_plugin_embedder_) {
-    GetBrowserContext()->GetGuestManager()->ForEachGuest(
-        this,
-        base::BindRepeating(&GetInnerWebContentsHelper, &all_inner_contents));
-  }
-  const auto& inner_contents = node_.GetInnerWebContents();
-  all_inner_contents.insert(all_inner_contents.end(), inner_contents.begin(),
-                            inner_contents.end());
-  return all_inner_contents;
-}
-
 std::vector<WebContentsImpl*> WebContentsImpl::GetWebContentsAndAllInner() {
   std::vector<WebContentsImpl*> all_contents(1, this);
 
   for (size_t i = 0; i != all_contents.size(); ++i) {
     for (auto* inner_contents : all_contents[i]->GetInnerWebContents()) {
-      all_contents.push_back(inner_contents);
+      all_contents.push_back(static_cast<WebContentsImpl*>(inner_contents));
     }
   }
 
@@ -5433,6 +5419,19 @@
     browser_plugin_embedder_.reset();
 }
 
+RenderFrameHostImpl* WebContentsImpl::GetOuterWebContentsFrame() {
+  if (GetOuterDelegateFrameTreeNodeId() ==
+      FrameTreeNode::kFrameTreeNodeInvalidId) {
+    return nullptr;
+  }
+
+  FrameTreeNode* outer_node =
+      FrameTreeNode::GloballyFindByID(GetOuterDelegateFrameTreeNodeId());
+  // The outer node should be in the outer WebContents.
+  DCHECK_EQ(outer_node->frame_tree(), GetOuterWebContents()->GetFrameTree());
+  return outer_node->parent()->current_frame_host();
+}
+
 WebContentsImpl* WebContentsImpl::GetOuterWebContents() {
   if (GuestMode::IsCrossProcessFrameGuest(this))
     return node_.outer_web_contents();
@@ -5443,6 +5442,19 @@
   return node_.outer_web_contents();
 }
 
+std::vector<WebContents*> WebContentsImpl::GetInnerWebContents() {
+  std::vector<WebContents*> all_inner_contents;
+  if (browser_plugin_embedder_) {
+    GetBrowserContext()->GetGuestManager()->ForEachGuest(
+        this,
+        base::BindRepeating(&GetInnerWebContentsHelper, &all_inner_contents));
+  }
+  const auto& inner_contents = node_.GetInnerWebContents();
+  all_inner_contents.insert(all_inner_contents.end(), inner_contents.begin(),
+                            inner_contents.end());
+  return all_inner_contents;
+}
+
 WebContentsImpl* WebContentsImpl::GetFocusedWebContents() {
   return GetOutermostWebContents()->node_.focused_web_contents();
 }
@@ -6500,13 +6512,14 @@
 
   // Concurrent find sessions must not overlap, so destroy any existing
   // FindRequestManagers in any inner WebContentses.
-  for (WebContentsImpl* contents : GetWebContentsAndAllInner()) {
-    if (contents == this)
+  for (WebContents* contents : GetWebContentsAndAllInner()) {
+    auto* web_contents_impl = static_cast<WebContentsImpl*>(contents);
+    if (web_contents_impl == this)
       continue;
-    if (contents->find_request_manager_) {
-      contents->find_request_manager_->StopFinding(
-          content::STOP_FIND_ACTION_CLEAR_SELECTION);
-      contents->find_request_manager_.release();
+    if (web_contents_impl->find_request_manager_) {
+      web_contents_impl->find_request_manager_->StopFinding(
+          STOP_FIND_ACTION_CLEAR_SELECTION);
+      web_contents_impl->find_request_manager_.release();
     }
   }
 
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 5a30b357..2c1f326 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -269,14 +269,6 @@
   // frame. Otherwise, returns this WebContents.
   WebContentsImpl* GetFocusedWebContents();
 
-  // TODO(paulmeyer): Once GuestViews are no longer implemented as
-  // BrowserPluginGuests, frame traversal across WebContents should be moved to
-  // be handled by FrameTreeNode, and |GetInnerWebContents| and
-  // |GetWebContentsAndAllInner| can be removed.
-
-  // Returns a vector to the inner WebContents within this WebContents.
-  std::vector<WebContentsImpl*> GetInnerWebContents();
-
   // Returns a vector containing this WebContents and all inner WebContents
   // within it (recursively).
   std::vector<WebContentsImpl*> GetWebContentsAndAllInner();
@@ -369,8 +361,10 @@
   void AttachToOuterWebContentsFrame(
       std::unique_ptr<WebContents> current_web_contents,
       RenderFrameHost* outer_contents_frame) override;
+  RenderFrameHostImpl* GetOuterWebContentsFrame() override;
   WebContentsImpl* GetOuterWebContents() override;
   WebContentsImpl* GetOutermostWebContents() override;
+  std::vector<WebContents*> GetInnerWebContents() override;
   void DidChangeVisibleSecurityState() override;
   void NotifyPreferencesChanged() override;
 
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index d869999..32fd1702 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -542,6 +542,10 @@
       std::unique_ptr<WebContents> current_web_contents,
       RenderFrameHost* outer_contents_frame) = 0;
 
+  // Returns the outer WebContents frame, the same frame that this WebContents
+  // was attached in AttachToOuterWebContentsFrame().
+  virtual RenderFrameHost* GetOuterWebContentsFrame() = 0;
+
   // Returns the outer WebContents of this WebContents if any.
   // Otherwise, return nullptr.
   virtual WebContents* GetOuterWebContents() = 0;
@@ -550,6 +554,9 @@
   // non-null value.
   virtual WebContents* GetOutermostWebContents() = 0;
 
+  // Returns a vector to the inner WebContents within this WebContents.
+  virtual std::vector<WebContents*> GetInnerWebContents() = 0;
+
   // Invoked when visible security state changes.
   virtual void DidChangeVisibleSecurityState() = 0;
 
diff --git a/content/public/renderer/content_renderer_client.cc b/content/public/renderer/content_renderer_client.cc
index 67755102..078b3f9 100644
--- a/content/public/renderer/content_renderer_client.cc
+++ b/content/public/renderer/content_renderer_client.cc
@@ -6,7 +6,6 @@
 
 #include "content/public/renderer/media_stream_renderer_factory.h"
 #include "media/base/renderer_factory.h"
-#include "third_party/blink/public/platform/modules/webmidi/web_midi_accessor.h"
 #include "third_party/blink/public/platform/web_audio_device.h"
 #include "third_party/blink/public/platform/web_media_stream_center.h"
 #include "third_party/blink/public/platform/web_rtc_peer_connection_handler.h"
@@ -66,12 +65,6 @@
   return false;
 }
 
-std::unique_ptr<blink::WebMIDIAccessor>
-ContentRendererClient::OverrideCreateMIDIAccessor(
-    blink::WebMIDIAccessorClient* client) {
-  return nullptr;
-}
-
 blink::WebThemeEngine* ContentRendererClient::OverrideThemeEngine() {
   return nullptr;
 }
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h
index fd2ee22..86e8152 100644
--- a/content/public/renderer/content_renderer_client.h
+++ b/content/public/renderer/content_renderer_client.h
@@ -42,8 +42,6 @@
 class WebElement;
 class WebFrame;
 class WebLocalFrame;
-class WebMIDIAccessor;
-class WebMIDIAccessorClient;
 class WebPlugin;
 class WebPrescientNetworking;
 class WebSpeechSynthesizer;
@@ -166,11 +164,6 @@
                               bool has_played_media_before,
                               base::OnceClosure closure);
 
-  // Allows the embedder to override creating a WebMIDIAccessor.  If it
-  // returns NULL the content layer will create the MIDI accessor.
-  virtual std::unique_ptr<blink::WebMIDIAccessor> OverrideCreateMIDIAccessor(
-      blink::WebMIDIAccessorClient* client);
-
   // Allows the embedder to override the WebThemeEngine used. If it returns NULL
   // the content layer will provide an engine.
   virtual blink::WebThemeEngine* OverrideThemeEngine();
diff --git a/content/public/test/test_browser_thread_bundle.cc b/content/public/test/test_browser_thread_bundle.cc
index c28e2411..77db4f2 100644
--- a/content/public/test/test_browser_thread_bundle.cc
+++ b/content/public/test/test_browser_thread_bundle.cc
@@ -8,7 +8,6 @@
 #include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
 #include "base/task/post_task.h"
-#include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/browser/after_startup_task_utils.h"
 #include "content/browser/scheduler/browser_task_executor.h"
@@ -36,14 +35,40 @@
 
 }  // namespace
 
-TestBrowserThreadBundle::TestBrowserThreadBundle()
-    : TestBrowserThreadBundle(DEFAULT) {}
+TestBrowserThreadBundle::TestBrowserThreadBundle(
+    base::test::ScopedTaskEnvironment::MainThreadType main_thread_type,
+    base::test::ScopedTaskEnvironment::ExecutionMode execution_control_mode,
+    int options)
+    : base::test::ScopedTaskEnvironment(main_thread_type,
+                                        execution_control_mode),
+      options_(options),
+      threads_created_(false) {
+  // Infer |options_| from |main_thread_type|.
+  switch (main_thread_type) {
+    case base::test::ScopedTaskEnvironment::MainThreadType::DEFAULT:
+    case base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME:
+      options_ |= TestBrowserThreadBundle::PLAIN_MAINLOOP;
+      break;
+    case base::test::ScopedTaskEnvironment::MainThreadType::IO:
+      options_ |= TestBrowserThreadBundle::IO_MAINLOOP;
+      break;
+    case base::test::ScopedTaskEnvironment::MainThreadType::UI:
+    case base::test::ScopedTaskEnvironment::MainThreadType::UI_MOCK_TIME:
+      break;
 
-TestBrowserThreadBundle::TestBrowserThreadBundle(int options)
-    : options_(options), threads_created_(false) {
+    default:
+      NOTREACHED();
+  }
+
   Init();
 }
 
+TestBrowserThreadBundle::TestBrowserThreadBundle(int options)
+    : TestBrowserThreadBundle(
+          GetThreadTypeFromOptions(options),
+          base::test::ScopedTaskEnvironment::ExecutionMode::ASYNC,
+          options) {}
+
 TestBrowserThreadBundle::~TestBrowserThreadBundle() {
   CHECK(threads_created_);
 
@@ -57,13 +82,11 @@
   ui_thread_->Stop();
   base::RunLoop().RunUntilIdle();
 
-  // Skip the following step when TaskScheduler isn't managed by this
-  // TestBrowserThreadBundle, otherwise it can hang (e.g.
-  // RunAllTasksUntilIdle() hangs when the TaskScheduler is managed
-  // by an external ScopedTaskEnvironment with ExecutionMode::QUEUED). This is
-  // fine as (1) it's rare and (2) it mimics production where BrowserThreads are
-  // shutdown before TaskScheduler.
-  if (scoped_task_environment_) {
+  // Skip the following steps when RunAllTasksUntilIdle might result in a hang
+  // (ExecutionMode::QUEUED) or for MainThreadType::MOCK_TIME where we haven't
+  // enforced there being no pending tasks.
+  if (main_thread_type() != MainThreadType::MOCK_TIME &&
+      execution_control_mode() != ExecutionMode::QUEUED) {
     // This is required to ensure we run all remaining MessageLoop and
     // TaskScheduler tasks in an atomic step. This is a bit different than
     // production where the main thread is not flushed after it's done running
@@ -72,15 +95,14 @@
     // blocked upon it could make a test flaky whereas by flushing we guarantee
     // it will blow up).
     RunAllTasksUntilIdle();
-    CHECK(!scoped_task_environment_->MainThreadHasPendingTask());
+    CHECK(!MainThreadHasPendingTask());
   }
 
   BrowserTaskExecutor::ResetForTesting();
 
-  // |scoped_task_environment_| needs to explicitly go away before fake threads
-  // in order for DestructionObservers hooked to the main MessageLoop to be able
-  // to invoke BrowserThread::CurrentlyOn() -- ref. ~TestBrowserThread().
-  scoped_task_environment_.reset();
+  // Run DestructionObservers before our fake threads go away to ensure
+  // BrowserThread::CurrentlyOn() returns the results expected by the observers.
+  NotifyDestructionObserversAndReleaseSequenceManager();
 
 #if defined(OS_WIN)
   com_initializer_.reset();
@@ -109,15 +131,6 @@
 
   BrowserTaskExecutor::Create();
 
-  // Create the ScopedTaskEnvironment if it doesn't already exist. A
-  // ScopedTaskEnvironment may already exist if this TestBrowserThreadBundle is
-  // instantiated in a test whose parent fixture provides a
-  // ScopedTaskEnvironment.
-  if (!base::ThreadTaskRunnerHandle::IsSet()) {
-    scoped_task_environment_ =
-        std::make_unique<base::test::ScopedTaskEnvironment>(
-            GetThreadTypeFromOptions(options_));
-  }
   if (options_ & IO_MAINLOOP)
     CHECK(base::MessageLoopCurrentForIO::IsSet());
   else if (!(options_ & PLAIN_MAINLOOP))
@@ -149,10 +162,6 @@
   SetBrowserStartupIsCompleteForTesting();
 }
 
-void TestBrowserThreadBundle::RunUntilIdle() {
-  scoped_task_environment_->RunUntilIdle();
-}
-
 void TestBrowserThreadBundle::RunIOThreadUntilIdle() {
   // Use a RunLoop to run until idle if already on BrowserThread::IO (which is
   // the main thread unless using Options::REAL_IO_THREAD).
diff --git a/content/public/test/test_browser_thread_bundle.h b/content/public/test/test_browser_thread_bundle.h
index 84348a1..9eb42916 100644
--- a/content/public/test/test_browser_thread_bundle.h
+++ b/content/public/test/test_browser_thread_bundle.h
@@ -85,12 +85,10 @@
 #include <memory>
 
 #include "base/macros.h"
+#include "base/test/scoped_task_environment.h"
 #include "build/build_config.h"
 
 namespace base {
-namespace test {
-class ScopedTaskEnvironment;
-}  // namespace test
 #if defined(OS_WIN)
 namespace win {
 class ScopedCOMInitializer;
@@ -104,7 +102,7 @@
 
 // Note: to drive these threads (e.g. run all tasks until idle), see
 // content/public/test/test_utils.h.
-class TestBrowserThreadBundle {
+class TestBrowserThreadBundle : public base::test::ScopedTaskEnvironment {
  public:
   // Used to specify the type of MessageLoop that backs the UI thread, and
   // which of the named BrowserThreads should be backed by a real
@@ -123,9 +121,17 @@
     PLAIN_MAINLOOP = 1 << 3,
   };
 
-  TestBrowserThreadBundle();
+  // Deprecated.
   explicit TestBrowserThreadBundle(int options);
 
+  // |options| here to support REAL_IO_THREAD & DONT_CREATE_BROWSER_THREADS.
+  TestBrowserThreadBundle(
+      base::test::ScopedTaskEnvironment::MainThreadType main_thread_type =
+          base::test::ScopedTaskEnvironment::MainThreadType::UI,
+      base::test::ScopedTaskEnvironment::ExecutionMode execution_control_mode =
+          base::test::ScopedTaskEnvironment::ExecutionMode::ASYNC,
+      int options = DEFAULT);
+
   // Creates browser threads; should only be called from other classes if the
   // DONT_CREATE_BROWSER_THREADS option was used when the bundle was created.
   void CreateBrowserThreads();
@@ -145,19 +151,17 @@
   //   KickoffAsyncFoo(run_loop.QuitClosure());
   //   run_loop.Run();
   //
-  void RunUntilIdle();
 
   // Flush the IO thread. Replacement for RunLoop::RunUntilIdle() for tests that
   // have a REAL_IO_THREAD. As with RunUntilIdle() above, prefer using
   // RunLoop+QuitClosure() to await an async condition.
   void RunIOThreadUntilIdle();
 
-  ~TestBrowserThreadBundle();
+  ~TestBrowserThreadBundle() override;
 
  private:
   void Init();
 
-  std::unique_ptr<base::test::ScopedTaskEnvironment> scoped_task_environment_;
   std::unique_ptr<TestBrowserThread> ui_thread_;
   std::unique_ptr<TestBrowserThread> io_thread_;
 
diff --git a/content/public/test/test_browser_thread_bundle_unittest.cc b/content/public/test/test_browser_thread_bundle_unittest.cc
index 2ffe38f4..9233eee 100644
--- a/content/public/test/test_browser_thread_bundle_unittest.cc
+++ b/content/public/test/test_browser_thread_bundle_unittest.cc
@@ -7,7 +7,6 @@
 #include "base/atomicops.h"
 #include "base/bind_helpers.h"
 #include "base/task/post_task.h"
-#include "base/test/scoped_task_environment.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -16,33 +15,6 @@
 
 namespace content {
 
-TEST(TestBrowserThreadBundleTest,
-     ScopedTaskEnvironmentAndTestBrowserThreadBundle) {
-  ScopedTaskEnvironment scoped_task_environment(
-      ScopedTaskEnvironment::MainThreadType::UI);
-  TestBrowserThreadBundle test_browser_thread_bundle;
-  base::PostTaskAndReply(FROM_HERE, base::DoNothing(), base::BindOnce([]() {
-                           DCHECK_CURRENTLY_ON(BrowserThread::UI);
-                         }));
-  scoped_task_environment.RunUntilIdle();
-}
-
-// Regression test to verify that ~TestBrowserThreadBundle() doesn't hang when
-// the TaskScheduler is owned by a QUEUED ScopedTaskEnvironment with pending
-// tasks.
-TEST(TestBrowserThreadBundleTest,
-     QueuedScopedTaskEnvironmentAndTestBrowserThreadBundle) {
-  ScopedTaskEnvironment queued_scoped_task_environment(
-      ScopedTaskEnvironment::MainThreadType::UI,
-      ScopedTaskEnvironment::ExecutionMode::QUEUED);
-  base::PostTask(FROM_HERE, base::DoNothing());
-
-  {
-    TestBrowserThreadBundle test_browser_thread_bundle;
-    DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  }  // Would hang here prior to fix.
-}
-
 namespace {
 
 // TestBrowserThreadBundleTest.RunUntilIdle will run kNumTasks tasks that will
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index 3417b866..f6e8b992 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -242,10 +242,6 @@
     "media/media_factory.h",
     "media/media_permission_dispatcher.cc",
     "media/media_permission_dispatcher.h",
-    "media/midi/midi_session_client_impl.cc",
-    "media/midi/midi_session_client_impl.h",
-    "media/midi/renderer_webmidiaccessor_impl.cc",
-    "media/midi/renderer_webmidiaccessor_impl.h",
     "media/render_media_client.cc",
     "media/render_media_client.h",
     "media/render_media_log.cc",
diff --git a/content/renderer/loader/sync_load_context.cc b/content/renderer/loader/sync_load_context.cc
index fcb1472..95bea94 100644
--- a/content/renderer/loader/sync_load_context.cc
+++ b/content/renderer/loader/sync_load_context.cc
@@ -171,7 +171,7 @@
   response_->redirect_info = net::RedirectInfo();
   response_->context_for_redirect = nullptr;
   response_->error_code = net::ERR_ABORTED;
-  CompleteRequest(true);
+  CompleteRequest();
 }
 
 void SyncLoadContext::OnReceivedResponse(
@@ -214,7 +214,7 @@
     request_completed_ = true;
     return;
   }
-  CompleteRequest(true /* remove_pending_request */);
+  CompleteRequest();
 }
 
 scoped_refptr<base::TaskRunner> SyncLoadContext::GetTaskRunner() {
@@ -227,13 +227,13 @@
   blob_finished_ = true;
   response_->downloaded_blob = std::move(blob);
   if (request_completed_)
-    CompleteRequest(true /* remove_pending_request */);
+    CompleteRequest();
 }
 
 void SyncLoadContext::OnAbort(base::WaitableEvent* event) {
   DCHECK(!Completed());
   response_->error_code = net::ERR_ABORTED;
-  CompleteRequest(true /* remove_pending_request */);
+  CompleteRequest();
 }
 
 void SyncLoadContext::OnTimeout() {
@@ -241,18 +241,16 @@
   // the OneShotTimer must have been stopped.
   DCHECK(!Completed());
   response_->error_code = net::ERR_TIMED_OUT;
-  CompleteRequest(true /* remove_pending_request */);
+  CompleteRequest();
 }
 
-void SyncLoadContext::CompleteRequest(bool remove_pending_request) {
+void SyncLoadContext::CompleteRequest() {
   signals_->SignalRedirectOrResponseComplete();
   signals_ = nullptr;
   response_ = nullptr;
 
-  if (remove_pending_request) {
-    // This will indirectly cause this object to be deleted.
-    resource_dispatcher_->RemovePendingRequest(request_id_, task_runner_);
-  }
+  // This will indirectly cause this object to be deleted.
+  resource_dispatcher_->RemovePendingRequest(request_id_, task_runner_);
 }
 
 bool SyncLoadContext::Completed() const {
diff --git a/content/renderer/loader/sync_load_context.h b/content/renderer/loader/sync_load_context.h
index 64ef44e1..eef5d30 100644
--- a/content/renderer/loader/sync_load_context.h
+++ b/content/renderer/loader/sync_load_context.h
@@ -86,7 +86,7 @@
   void OnAbort(base::WaitableEvent* event);
   void OnTimeout();
 
-  void CompleteRequest(bool remove_pending_request);
+  void CompleteRequest();
   bool Completed() const;
 
   // This raw pointer will remain valid for the lifetime of this object because
diff --git a/content/renderer/media/midi/OWNERS b/content/renderer/media/midi/OWNERS
deleted file mode 100644
index f2fe65b..0000000
--- a/content/renderer/media/midi/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-file://media/midi/OWNERS
-
-# TEAM: midi-dev@chromium.org
-# COMPONENT: Blink>WebMIDI
diff --git a/content/renderer/media/midi/midi_session_client_impl.cc b/content/renderer/media/midi/midi_session_client_impl.cc
deleted file mode 100644
index b625d7c2..0000000
--- a/content/renderer/media/midi/midi_session_client_impl.cc
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media/midi/midi_session_client_impl.h"
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/trace_event/trace_event.h"
-#include "content/public/common/service_names.mojom.h"
-#include "content/renderer/render_thread_impl.h"
-#include "ipc/ipc_logging.h"
-#include "services/service_manager/public/cpp/connector.h"
-
-using base::AutoLock;
-using blink::WebString;
-using midi::mojom::PortState;
-
-// The maximum number of bytes which we're allowed to send to the browser
-// before getting acknowledgement back from the browser that they've been
-// successfully sent.
-static const size_t kMaxUnacknowledgedBytesSent = 10 * 1024 * 1024;  // 10 MB.
-
-namespace content {
-
-MidiSessionClientImpl::MidiSessionClientImpl()
-    : session_result_(midi::mojom::Result::NOT_INITIALIZED),
-      unacknowledged_bytes_sent_(0u),
-      binding_(this) {}
-
-MidiSessionClientImpl::~MidiSessionClientImpl() {}
-
-void MidiSessionClientImpl::AddInputPort(midi::mojom::PortInfoPtr info) {
-  inputs_.push_back(*info);
-  const WebString id = WebString::FromUTF8(info->id);
-  const WebString manufacturer = WebString::FromUTF8(info->manufacturer);
-  const WebString name = WebString::FromUTF8(info->name);
-  const WebString version = WebString::FromUTF8(info->version);
-  for (auto* client : clients_)
-    client->DidAddInputPort(id, manufacturer, name, version, info->state);
-}
-
-void MidiSessionClientImpl::AddOutputPort(midi::mojom::PortInfoPtr info) {
-  outputs_.push_back(*info);
-  const WebString id = WebString::FromUTF8(info->id);
-  const WebString manufacturer = WebString::FromUTF8(info->manufacturer);
-  const WebString name = WebString::FromUTF8(info->name);
-  const WebString version = WebString::FromUTF8(info->version);
-  for (auto* client : clients_)
-    client->DidAddOutputPort(id, manufacturer, name, version, info->state);
-}
-
-void MidiSessionClientImpl::SetInputPortState(uint32_t port,
-                                              midi::mojom::PortState state) {
-  if (inputs_[port].state == state)
-    return;
-  inputs_[port].state = state;
-  for (auto* client : clients_)
-    client->DidSetInputPortState(port, state);
-}
-
-void MidiSessionClientImpl::SetOutputPortState(uint32_t port,
-                                               midi::mojom::PortState state) {
-  if (outputs_[port].state == state)
-    return;
-  outputs_[port].state = state;
-  for (auto* client : clients_)
-    client->DidSetOutputPortState(port, state);
-}
-
-void MidiSessionClientImpl::SessionStarted(midi::mojom::Result result) {
-  TRACE_EVENT0("midi", "MidiSessionClientImpl::OnSessionStarted");
-  session_result_ = result;
-
-  // A for-loop using iterators does not work because |client| may touch
-  // |clients_waiting_session_queue_| in callbacks.
-  while (!clients_waiting_session_queue_.empty()) {
-    auto* client = clients_waiting_session_queue_.back();
-    clients_waiting_session_queue_.pop_back();
-    if (result == midi::mojom::Result::OK) {
-      // Add the client's input and output ports.
-      for (const auto& info : inputs_) {
-        client->DidAddInputPort(WebString::FromUTF8(info.id),
-                                WebString::FromUTF8(info.manufacturer),
-                                WebString::FromUTF8(info.name),
-                                WebString::FromUTF8(info.version), info.state);
-      }
-
-      for (const auto& info : outputs_) {
-        client->DidAddOutputPort(WebString::FromUTF8(info.id),
-                                 WebString::FromUTF8(info.manufacturer),
-                                 WebString::FromUTF8(info.name),
-                                 WebString::FromUTF8(info.version), info.state);
-      }
-    }
-    client->DidStartSession(result);
-    clients_.insert(client);
-  }
-}
-
-void MidiSessionClientImpl::AcknowledgeSentData(uint32_t bytes_sent) {
-  DCHECK_GE(unacknowledged_bytes_sent_, bytes_sent);
-  if (unacknowledged_bytes_sent_ >= bytes_sent)
-    unacknowledged_bytes_sent_ -= bytes_sent;
-}
-
-void MidiSessionClientImpl::DataReceived(uint32_t port,
-                                         const std::vector<uint8_t>& data,
-                                         base::TimeTicks timestamp) {
-  TRACE_EVENT0("midi", "MidiSessionClientImpl::OnDataReceived");
-  DCHECK(!data.empty());
-
-  for (auto* client : clients_)
-    client->DidReceiveMIDIData(port, &data[0], data.size(), timestamp);
-}
-
-void MidiSessionClientImpl::AddClient(blink::WebMIDIAccessorClient* client) {
-  TRACE_EVENT0("midi", "MidiSessionClientImpl::AddClient");
-  clients_waiting_session_queue_.push_back(client);
-  if (session_result_ != midi::mojom::Result::NOT_INITIALIZED) {
-    SessionStarted(session_result_);
-  } else if (clients_waiting_session_queue_.size() == 1u) {
-    midi::mojom::MidiSessionClientPtr client_ptr;
-    binding_.Bind(mojo::MakeRequest(&client_ptr));
-    midi::mojom::MidiSessionRequest request = mojo::MakeRequest(&midi_session_);
-    GetMidiSessionProvider().StartSession(std::move(request),
-                                          std::move(client_ptr));
-  }
-}
-
-void MidiSessionClientImpl::RemoveClient(blink::WebMIDIAccessorClient* client) {
-  DCHECK(clients_.find(client) != clients_.end() ||
-         base::ContainsValue(clients_waiting_session_queue_, client))
-      << "RemoveClient call was not ballanced with AddClient call";
-  clients_.erase(client);
-  auto it = std::find(clients_waiting_session_queue_.begin(),
-                      clients_waiting_session_queue_.end(), client);
-  if (it != clients_waiting_session_queue_.end())
-    clients_waiting_session_queue_.erase(it);
-  if (clients_.empty() && clients_waiting_session_queue_.empty()) {
-    session_result_ = midi::mojom::Result::NOT_INITIALIZED;
-    inputs_.clear();
-    outputs_.clear();
-    midi_session_.reset();
-    binding_.Close();
-  }
-}
-
-void MidiSessionClientImpl::SendMidiData(uint32_t port,
-                                         const uint8_t* data,
-                                         size_t length,
-                                         base::TimeTicks timestamp) {
-  if ((kMaxUnacknowledgedBytesSent - unacknowledged_bytes_sent_) < length) {
-    // TODO(toyoshim): buffer up the data to send at a later time.
-    // For now we're just dropping these bytes on the floor.
-    return;
-  }
-
-  unacknowledged_bytes_sent_ += length;
-  std::vector<uint8_t> v(data, data + length);
-  GetMidiSession().SendData(port, v, timestamp);
-}
-
-midi::mojom::MidiSession& MidiSessionClientImpl::GetMidiSession() {
-  DCHECK(midi_session_);
-  return *midi_session_;
-}
-
-midi::mojom::MidiSessionProvider&
-MidiSessionClientImpl::GetMidiSessionProvider() {
-  if (!midi_session_provider_) {
-    ChildThreadImpl::current()->GetConnector()->BindInterface(
-        mojom::kBrowserServiceName, mojo::MakeRequest(&midi_session_provider_));
-  }
-  return *midi_session_provider_;
-}
-
-}  // namespace content
diff --git a/content/renderer/media/midi/midi_session_client_impl.h b/content/renderer/media/midi/midi_session_client_impl.h
deleted file mode 100644
index 6581d54..0000000
--- a/content/renderer/media/midi/midi_session_client_impl.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_MEDIA_MIDI_MIDI_SESSION_CLIENT_IMPL_H_
-#define CONTENT_RENDERER_MEDIA_MIDI_MIDI_SESSION_CLIENT_IMPL_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <set>
-#include <vector>
-
-#include "base/macros.h"
-#include "content/common/content_export.h"
-#include "ipc/message_filter.h"
-#include "media/midi/midi_service.mojom.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "third_party/blink/public/platform/modules/webmidi/web_midi_accessor_client.h"
-
-namespace content {
-
-// Created on render thread, and hosts multiple clients running on multiple
-// frames. All operations are carried out on |main_task_runner_|.
-class CONTENT_EXPORT MidiSessionClientImpl
-    : public midi::mojom::MidiSessionClient {
- public:
-  explicit MidiSessionClientImpl();
-  ~MidiSessionClientImpl() override;
-
-  // midi::mojom::MidiSessionClient implementation.
-  // All of the following methods are run on the main thread.
-  void AddInputPort(midi::mojom::PortInfoPtr info) override;
-  void AddOutputPort(midi::mojom::PortInfoPtr info) override;
-  void SetInputPortState(uint32_t port, midi::mojom::PortState state) override;
-  void SetOutputPortState(uint32_t port, midi::mojom::PortState state) override;
-  void SessionStarted(midi::mojom::Result result) override;
-  void AcknowledgeSentData(uint32_t bytes) override;
-  void DataReceived(uint32_t port,
-                    const std::vector<uint8_t>& data,
-                    base::TimeTicks timestamp) override;
-
-  // Each client registers for MIDI access here.
-  void AddClient(blink::WebMIDIAccessorClient* client);
-  void RemoveClient(blink::WebMIDIAccessorClient* client);
-
-  // Called to clean up if browser terminates session.
-  void RemoveClients();
-
-  // A client will only be able to call this method if it has a suitable
-  // output port (from AddOutputPort()).
-  void SendMidiData(uint32_t port,
-                    const uint8_t* data,
-                    size_t length,
-                    base::TimeTicks timestamp);
-
- private:
-  midi::mojom::MidiSessionProvider& GetMidiSessionProvider();
-  midi::mojom::MidiSession& GetMidiSession();
-
-  // Keeps track of all MIDI clients. This should be std::set so that various
-  // for-loops work correctly. To change the type, make sure that the new type
-  // is safe to modify the container inside for-loops.
-  typedef std::set<blink::WebMIDIAccessorClient*> ClientsSet;
-  ClientsSet clients_;
-
-  // Represents clients that are waiting for a session being open.
-  // Note: std::vector is not safe to invoke callbacks inside iterator based
-  // for-loops.
-  typedef std::vector<blink::WebMIDIAccessorClient*> ClientsQueue;
-  ClientsQueue clients_waiting_session_queue_;
-
-  // Represents a result on starting a session.
-  midi::mojom::Result session_result_;
-
-  // Holds MidiPortInfoList for input ports and output ports.
-  std::vector<midi::mojom::PortInfo> inputs_;
-  std::vector<midi::mojom::PortInfo> outputs_;
-
-  size_t unacknowledged_bytes_sent_;
-
-  midi::mojom::MidiSessionProviderPtr midi_session_provider_;
-  midi::mojom::MidiSessionPtr midi_session_;
-  mojo::Binding<midi::mojom::MidiSessionClient> binding_;
-
-  DISALLOW_COPY_AND_ASSIGN(MidiSessionClientImpl);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_MEDIA_MIDI_MIDI_SESSION_CLIENT_IMPL_H_
diff --git a/content/renderer/media/midi/renderer_webmidiaccessor_impl.cc b/content/renderer/media/midi/renderer_webmidiaccessor_impl.cc
deleted file mode 100644
index 301e10d..0000000
--- a/content/renderer/media/midi/renderer_webmidiaccessor_impl.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media/midi/renderer_webmidiaccessor_impl.h"
-
-#include "base/logging.h"
-#include "content/renderer/media/midi/midi_session_client_impl.h"
-#include "content/renderer/render_thread_impl.h"
-
-namespace content {
-
-RendererWebMIDIAccessorImpl::RendererWebMIDIAccessorImpl(
-    blink::WebMIDIAccessorClient* client)
-    : client_(client), is_client_added_(false) {
-  DCHECK(client_);
-}
-
-RendererWebMIDIAccessorImpl::~RendererWebMIDIAccessorImpl() {
-  if (is_client_added_)
-    midi_session_client_impl()->RemoveClient(client_);
-}
-
-void RendererWebMIDIAccessorImpl::StartSession() {
-  midi_session_client_impl()->AddClient(client_);
-  is_client_added_ = true;
-}
-
-void RendererWebMIDIAccessorImpl::SendMIDIData(unsigned port_index,
-                                               const unsigned char* data,
-                                               size_t length,
-                                               base::TimeTicks timestamp) {
-  midi_session_client_impl()->SendMidiData(port_index, data, length, timestamp);
-}
-
-MidiSessionClientImpl* RendererWebMIDIAccessorImpl::midi_session_client_impl() {
-  return RenderThreadImpl::current()->midi_session_client_impl();
-}
-
-}  // namespace content
diff --git a/content/renderer/media/midi/renderer_webmidiaccessor_impl.h b/content/renderer/media/midi/renderer_webmidiaccessor_impl.h
deleted file mode 100644
index a2a48f30..0000000
--- a/content/renderer/media/midi/renderer_webmidiaccessor_impl.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_MEDIA_MIDI_RENDERER_WEBMIDIACCESSOR_IMPL_H_
-#define CONTENT_RENDERER_MEDIA_MIDI_RENDERER_WEBMIDIACCESSOR_IMPL_H_
-
-#include <stddef.h>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "third_party/blink/public/platform/modules/webmidi/web_midi_accessor.h"
-#include "third_party/blink/public/platform/modules/webmidi/web_midi_accessor_client.h"
-
-namespace content {
-
-class MidiSessionClientImpl;
-
-class RendererWebMIDIAccessorImpl
-    : public blink::WebMIDIAccessor {
- public:
-  explicit RendererWebMIDIAccessorImpl(
-      blink::WebMIDIAccessorClient* client);
-  ~RendererWebMIDIAccessorImpl() override;
-
-  // blink::WebMIDIAccessor implementation.
-  void StartSession() override;
-  void SendMIDIData(unsigned port_index,
-                    const unsigned char* data,
-                    size_t length,
-                    base::TimeTicks timestamp) override;
-
- private:
-  blink::WebMIDIAccessorClient* client_;
-
-  bool is_client_added_;
-
-  MidiSessionClientImpl* midi_session_client_impl();
-
-  DISALLOW_COPY_AND_ASSIGN(RendererWebMIDIAccessorImpl);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_MEDIA_MIDI_RENDERER_WEBMIDIACCESSOR_IMPL_H_
diff --git a/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc b/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc
index 837f67c..886fb45 100644
--- a/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc
+++ b/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc
@@ -121,8 +121,6 @@
   // destroyed.
   void ReleaseSourceOnMainThread();
 
-  void SetContentHint(blink::WebMediaStreamTrack::ContentHintType content_hint);
-
   void OnVideoFrameOnIO(const scoped_refptr<media::VideoFrame>& frame,
                         base::TimeTicks estimated_capture_time);
 
@@ -132,9 +130,6 @@
   void OnVideoFrameOnWorkerThread(
       const scoped_refptr<media::VideoFrame>& frame);
 
-  void SetContentHintOnWorkerThread(
-      blink::WebMediaStreamTrack::ContentHintType content_hint);
-
   virtual ~WebRtcVideoSourceAdapter();
 
   // Called whenever a video frame was just delivered on the IO thread. This
@@ -227,24 +222,6 @@
   video_source_ = nullptr;
 }
 
-void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::SetContentHint(
-    blink::WebMediaStreamTrack::ContentHintType content_hint) {
-  DCHECK(render_thread_checker_.CalledOnValidThread());
-  libjingle_worker_thread_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&WebRtcVideoSourceAdapter::SetContentHintOnWorkerThread,
-                     this, content_hint));
-}
-
-void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::
-    SetContentHintOnWorkerThread(
-        blink::WebMediaStreamTrack::ContentHintType content_hint) {
-  DCHECK(libjingle_worker_thread_->BelongsToCurrentThread());
-  base::AutoLock auto_lock(capture_adapter_stop_lock_);
-  if (capture_adapter_)
-    capture_adapter_->SetContentHint(content_hint);
-}
-
 void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::OnVideoFrameOnIO(
     const scoped_refptr<media::VideoFrame>& frame,
     base::TimeTicks estimated_capture_time) {
@@ -314,8 +291,8 @@
   // by removing the need for and dependency on a cricket::VideoCapturer.
   video_source_ = scoped_refptr<WebRtcVideoSource>(
       new rtc::RefCountedObject<WebRtcVideoSource>(
-          new WebRtcVideoCapturerAdapter(is_screencast, track.ContentHint()),
-          is_screencast, needs_denoising));
+          new WebRtcVideoCapturerAdapter(is_screencast), is_screencast,
+          needs_denoising));
 
   // TODO(pbos): Consolidate the local video track with the source proxy and
   // move into PeerConnectionDependencyFactory. This now separately holds on a
@@ -361,7 +338,6 @@
 void MediaStreamVideoWebRtcSink::OnContentHintChanged(
     blink::WebMediaStreamTrack::ContentHintType content_hint) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  source_adapter_->SetContentHint(content_hint);
   video_track_->set_content_hint(
       ContentHintTypeToWebRtcContentHint(content_hint));
 }
diff --git a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc b/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc
index d00e437c..546b26d 100644
--- a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc
+++ b/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc
@@ -27,12 +27,8 @@
 
 }  // anonymous namespace
 
-WebRtcVideoCapturerAdapter::WebRtcVideoCapturerAdapter(
-    bool is_screencast,
-    blink::WebMediaStreamTrack::ContentHintType content_hint)
-    : is_screencast_(is_screencast),
-      content_hint_(content_hint),
-      running_(false) {
+WebRtcVideoCapturerAdapter::WebRtcVideoCapturerAdapter(bool is_screencast)
+    : is_screencast_(is_screencast), running_(false) {
   thread_checker_.DetachFromThread();
 }
 
@@ -187,12 +183,6 @@
   return true;
 }
 
-void WebRtcVideoCapturerAdapter::SetContentHint(
-    blink::WebMediaStreamTrack::ContentHintType content_hint) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  content_hint_ = content_hint;
-}
-
 bool WebRtcVideoCapturerAdapter::IsScreencast() const {
   return is_screencast_;
 }
diff --git a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h b/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h
index 921b373..2b72f681 100644
--- a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h
+++ b/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h
@@ -32,9 +32,7 @@
 class CONTENT_EXPORT WebRtcVideoCapturerAdapter
     : public cricket::VideoCapturer {
  public:
-  WebRtcVideoCapturerAdapter(
-      bool is_screencast,
-      blink::WebMediaStreamTrack::ContentHintType content_hint);
+  WebRtcVideoCapturerAdapter(bool is_screencast);
   ~WebRtcVideoCapturerAdapter() override;
 
   // OnFrameCaptured delivers video frames to libjingle. It must be called on
@@ -42,8 +40,6 @@
   // This method is virtual for testing purposes.
   virtual void OnFrameCaptured(const scoped_refptr<media::VideoFrame>& frame);
 
-  void SetContentHint(blink::WebMediaStreamTrack::ContentHintType content_hint);
-
  private:
   // cricket::VideoCapturer implementation.
   // These methods are accessed from a libJingle worker thread.
@@ -60,7 +56,6 @@
   base::ThreadChecker thread_checker_;
 
   const bool is_screencast_;
-  blink::WebMediaStreamTrack::ContentHintType content_hint_;
   bool running_;
 
   media::VideoFramePool scaled_frame_pool_;
diff --git a/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc b/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc
index ce12081..996ba07 100644
--- a/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc
+++ b/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc
@@ -18,9 +18,7 @@
       public ::testing::Test {
  public:
   WebRtcVideoCapturerAdapterTest()
-      : adapter_(new WebRtcVideoCapturerAdapter(
-            false,
-            blink::WebMediaStreamTrack::ContentHintType::kNone)),
+      : adapter_(new WebRtcVideoCapturerAdapter(false)),
         output_frame_width_(0),
         output_frame_height_(0) {
     adapter_->AddOrUpdateSink(this, rtc::VideoSinkWants());
@@ -53,52 +51,6 @@
     output_frame_height_ = frame.height();
   }
 
-  void TestContentHintResolutionAdaptation(
-      bool is_screencast,
-      blink::WebMediaStreamTrack::ContentHintType construction_content_hint,
-      bool expect_initial_downscale,
-      blink::WebMediaStreamTrack::ContentHintType set_content_hint,
-      bool expect_final_downscale) {
-    // Reset and configure adapter to the test.
-    adapter_->RemoveSink(this);
-    adapter_.reset(new WebRtcVideoCapturerAdapter(is_screencast,
-                                                  construction_content_hint));
-
-    const int kInputWidth = 1280;
-    const int kInputHeight = 720;
-    const gfx::Size kSize(kInputWidth, kInputHeight);
-    scoped_refptr<media::VideoFrame> frame = media::VideoFrame::CreateFrame(
-        media::PIXEL_FORMAT_I420, kSize, gfx::Rect(kSize), kSize,
-        base::TimeDelta());
-
-    // Request smaller scale to make sure scaling normally kicks in.
-    rtc::VideoSinkWants wants;
-    // TODO(sprang): Remove this type hack when webrtc has updated the sink
-    // wants api. https://codereview.webrtc.org/2781433002/
-    using MaxPixelCountType = decltype(wants.max_pixel_count);
-    wants.max_pixel_count = MaxPixelCountType(kInputWidth * kInputHeight / 2);
-    adapter_->AddOrUpdateSink(this, wants);
-
-    adapter_->OnFrameCaptured(frame);
-    if (expect_initial_downscale) {
-      EXPECT_LT(output_frame_width_, kInputWidth);
-      EXPECT_LT(output_frame_height_, kInputHeight);
-    } else {
-      EXPECT_EQ(kInputWidth, output_frame_width_);
-      EXPECT_EQ(kInputHeight, output_frame_height_);
-    }
-
-    adapter_->SetContentHint(set_content_hint);
-    adapter_->OnFrameCaptured(frame);
-    if (expect_final_downscale) {
-      EXPECT_LT(output_frame_width_, kInputWidth);
-      EXPECT_LT(output_frame_height_, kInputHeight);
-    } else {
-      EXPECT_EQ(kInputWidth, output_frame_width_);
-      EXPECT_EQ(kInputHeight, output_frame_height_);
-    }
-  }
-
  private:
   std::unique_ptr<WebRtcVideoCapturerAdapter> adapter_;
   int output_frame_width_;
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 95e59e7..5cf96a0 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -93,7 +93,6 @@
 #include "content/renderer/low_memory_mode_controller.h"
 #include "content/renderer/media/audio/audio_renderer_mixer_manager.h"
 #include "content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h"
-#include "content/renderer/media/midi/midi_session_client_impl.h"
 #include "content/renderer/media/render_media_client.h"
 #include "content/renderer/media/stream/aec_dump_message_filter.h"
 #include "content/renderer/media/stream/media_stream_center.h"
@@ -788,8 +787,6 @@
 
   audio_output_ipc_factory_.emplace(GetIOTaskRunner());
 
-  midi_session_client_impl_ = std::make_unique<MidiSessionClientImpl>();
-
 #if defined(USE_AURA)
   if (features::IsMultiProcessMash())
     CreateRenderWidgetWindowTreeClientFactory(GetServiceManagerConnection());
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index 578a715..ef2f1af 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -126,7 +126,6 @@
 class FrameSwapMessageQueue;
 class GpuVideoAcceleratorFactoriesImpl;
 class LowMemoryModeController;
-class MidiSessionClientImpl;
 class P2PSocketDispatcher;
 class PeerConnectionDependencyFactory;
 class PeerConnectionTracker;
@@ -324,10 +323,6 @@
     return dom_storage_dispatcher_.get();
   }
 
-  MidiSessionClientImpl* midi_session_client_impl() {
-    return midi_session_client_impl_.get();
-  }
-
   ResourceDispatcher* resource_dispatcher() const {
     return resource_dispatcher_.get();
   }
@@ -600,9 +595,6 @@
   std::unique_ptr<ResourceDispatcher> resource_dispatcher_;
   std::unique_ptr<URLLoaderThrottleProvider> url_loader_throttle_provider_;
 
-  // Used on the renderer and IPC threads.
-  std::unique_ptr<MidiSessionClientImpl> midi_session_client_impl_;
-
   std::unique_ptr<BrowserPluginManager> browser_plugin_manager_;
 
   std::unique_ptr<PeerConnectionDependencyFactory> peer_connection_factory_;
diff --git a/content/renderer/render_thread_impl_browsertest.cc b/content/renderer/render_thread_impl_browsertest.cc
index 52ea7a4..6d720764 100644
--- a/content/renderer/render_thread_impl_browsertest.cc
+++ b/content/renderer/render_thread_impl_browsertest.cc
@@ -16,7 +16,6 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/discardable_memory.h"
-#include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
@@ -153,34 +152,12 @@
 
 class RenderThreadImplBrowserTest : public testing::Test {
  public:
-  // Managing our own main MessageLoop also forces us to manage our own
-  // TaskScheduler. This ensures a basic TaskScheduler is in scope during this
-  // test.
-  class TestTaskScheduler {
-   public:
-    TestTaskScheduler() {
-      base::TaskScheduler::CreateAndStartWithDefaultParams(
-          "RenderThreadImplBrowserTest");
-    }
-
-    ~TestTaskScheduler() {
-      base::TaskScheduler::GetInstance()->Shutdown();
-      base::TaskScheduler::GetInstance()->JoinForTesting();
-      base::TaskScheduler::SetInstance(nullptr);
-    }
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(TestTaskScheduler);
-  };
-
   RenderThreadImplBrowserTest() : field_trial_list_(nullptr) {}
 
   void SetUp() override {
     content_renderer_client_.reset(new ContentRendererClient());
     SetRendererClientForTesting(content_renderer_client_.get());
 
-    main_message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_UI));
-    test_task_scheduler_.reset(new TestTaskScheduler);
     browser_threads_.reset(
         new TestBrowserThreadBundle(TestBrowserThreadBundle::REAL_IO_THREAD));
     scoped_refptr<base::SingleThreadTaskRunner> io_task_runner =
@@ -263,8 +240,6 @@
   TestContentClientInitializer content_client_initializer_;
   std::unique_ptr<ContentRendererClient> content_renderer_client_;
 
-  std::unique_ptr<base::MessageLoop> main_message_loop_;
-  std::unique_ptr<TestTaskScheduler> test_task_scheduler_;
   std::unique_ptr<TestBrowserThreadBundle> browser_threads_;
   std::unique_ptr<TestServiceManagerContext> shell_context_;
   std::unique_ptr<ChildConnection> child_connection_;
@@ -302,9 +277,11 @@
 // Disabled under LeakSanitizer due to memory leaks.
 TEST_F(RenderThreadImplBrowserTest,
        WILL_LEAK(NonResourceDispatchIPCTasksDontGoThroughScheduler)) {
+  // This seems to deflake the test on Android.
+  browser_threads_->RunIOThreadUntilIdle();
+
   // NOTE other than not being a resource message, the actual message is
   // unimportant.
-
   sender()->Send(new TestMsg_QuitRunLoop());
 
   run_loop_->Run();
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index 95c3de9..d6c313f 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -53,7 +53,6 @@
 #include "content/renderer/loader/web_url_loader_impl.h"
 #include "content/renderer/media/audio/audio_device_factory.h"
 #include "content/renderer/media/audio_decoder.h"
-#include "content/renderer/media/midi/renderer_webmidiaccessor_impl.h"
 #include "content/renderer/media/renderer_webaudiodevice_impl.h"
 #include "content/renderer/media_capture_from_element/canvas_capture_handler.h"
 #include "content/renderer/media_capture_from_element/html_audio_element_capturer_source.h"
@@ -91,7 +90,6 @@
 #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
 #include "third_party/blink/public/platform/blame_context.h"
 #include "third_party/blink/public/platform/file_path_conversion.h"
-#include "third_party/blink/public/platform/modules/webmidi/web_midi_accessor.h"
 #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
 #include "third_party/blink/public/platform/url_conversion.h"
 #include "third_party/blink/public/platform/web_audio_latency_hint.h"
@@ -646,19 +644,6 @@
 
 //------------------------------------------------------------------------------
 
-std::unique_ptr<blink::WebMIDIAccessor>
-RendererBlinkPlatformImpl::CreateMIDIAccessor(
-    blink::WebMIDIAccessorClient* client) {
-  std::unique_ptr<blink::WebMIDIAccessor> accessor =
-      GetContentClient()->renderer()->OverrideCreateMIDIAccessor(client);
-  if (accessor)
-    return accessor;
-
-  return std::make_unique<RendererWebMIDIAccessorImpl>(client);
-}
-
-//------------------------------------------------------------------------------
-
 WebBlobRegistry* RendererBlinkPlatformImpl::GetBlobRegistry() {
   // blob_registry_ can be NULL when running some tests.
   return blob_registry_.get();
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h
index aa21cd1d..49a961a 100644
--- a/content/renderer/renderer_blink_platform_impl.h
+++ b/content/renderer/renderer_blink_platform_impl.h
@@ -145,9 +145,6 @@
                            const char* audio_file_data,
                            size_t data_size) override;
 
-  std::unique_ptr<blink::WebMIDIAccessor> CreateMIDIAccessor(
-      blink::WebMIDIAccessorClient* client) override;
-
   blink::WebBlobRegistry* GetBlobRegistry() override;
   std::unique_ptr<blink::WebRTCPeerConnectionHandler>
   CreateRTCPeerConnectionHandler(
diff --git a/content/shell/browser/web_test/blink_test_controller.cc b/content/shell/browser/web_test/blink_test_controller.cc
index 4f1a69e8..0bffe6d 100644
--- a/content/shell/browser/web_test/blink_test_controller.cc
+++ b/content/shell/browser/web_test/blink_test_controller.cc
@@ -671,7 +671,7 @@
     return;
   }
   // Build the frame storage and depth first queue.
-  Node* root = BuildFrameTree(main_window_->web_contents()->GetAllFrames());
+  Node* root = BuildFrameTree(main_window_->web_contents());
   BuildDepthFirstQueue(root);
   // Now asynchronously run through the node queue.
   CompositeNodeQueueThen(std::move(callback));
@@ -684,8 +684,6 @@
   // still valid before using it. To do that, grab the list of all frames
   // again, and make sure it contains the one we're about to composite.
   // See crbug.com/899465 for an example of this problem.
-  std::vector<RenderFrameHost*> current_frames(
-      main_window_->web_contents()->GetAllFrames());
   RenderFrameHost* next_node_host;
   do {
     if (composite_all_frames_node_queue_.empty()) {
@@ -695,9 +693,12 @@
     }
     next_node_host =
         composite_all_frames_node_queue_.front()->render_frame_host;
+    GlobalFrameRoutingId next_node_id =
+        composite_all_frames_node_queue_.front()->render_frame_host_id;
     composite_all_frames_node_queue_.pop();
-    if (std::find(current_frames.begin(), current_frames.end(),
-                  next_node_host) == current_frames.end()) {
+    if (RenderFrameHost::FromID(next_node_id.child_id,
+                                next_node_id.frame_routing_id) !=
+        next_node_host) {
       next_node_host = nullptr;  // This one is now gone
     }
   } while (!next_node_host || !next_node_host->IsRenderFrameLive());
@@ -714,41 +715,68 @@
 }
 
 BlinkTestController::Node* BlinkTestController::BuildFrameTree(
-    const std::vector<RenderFrameHost*>& frames) {
-  // Ensure we don't reallocate during tree construction.
-  composite_all_frames_node_storage_.reserve(frames.size());
-
+    WebContents* web_contents) {
   // Returns a Node for a given RenderFrameHost, or nullptr if doesn't exist.
   auto node_for_frame = [this](RenderFrameHost* rfh) {
     auto it = std::find_if(
         composite_all_frames_node_storage_.begin(),
         composite_all_frames_node_storage_.end(),
-        [rfh](const Node& node) { return node.render_frame_host == rfh; });
-    return it == composite_all_frames_node_storage_.end() ? nullptr : &*it;
+        [rfh](auto& node) { return node->render_frame_host == rfh; });
+    return it == composite_all_frames_node_storage_.end() ? nullptr : it->get();
   };
 
-  // Add all of the frames to storage.
-  for (auto* frame : frames) {
-    DCHECK(!node_for_frame(frame)) << "Frame seen multiple times.";
-    composite_all_frames_node_storage_.emplace_back(frame);
-  }
+  Node* outer_root = nullptr;
+  std::vector<WebContents*> all_web_contents(1, web_contents);
+  for (unsigned i = 0; i < all_web_contents.size(); i++) {
+    WebContents* contents = all_web_contents[i];
 
-  // Construct a tree rooted at |root|.
-  Node* root = nullptr;
-  for (auto* frame : frames) {
-    Node* node = node_for_frame(frame);
-    DCHECK(node);
-    if (!frame->GetParent()) {
-      DCHECK(!root) << "Multiple roots found.";
-      root = node;
-    } else {
-      Node* parent = node_for_frame(frame->GetParent());
-      DCHECK(parent);
-      parent->children.push_back(node);
+    //  Collect all live frames in contents.
+    std::vector<RenderFrameHost*> frames;
+    for (auto* frame : contents->GetAllFrames()) {
+      if (frame->IsRenderFrameLive())
+        frames.push_back(frame);
     }
+
+    // Add all of the frames to storage.
+    for (auto* frame : frames) {
+      DCHECK(!node_for_frame(frame)) << "Frame seen multiple times.";
+      composite_all_frames_node_storage_.emplace_back(
+          std::make_unique<Node>(frame));
+    }
+
+    // Construct a tree rooted at |root|.
+    Node* root = nullptr;
+    for (auto* frame : frames) {
+      Node* node = node_for_frame(frame);
+      DCHECK(node);
+      if (!frame->GetParent()) {
+        DCHECK(!root) << "Multiple roots found.";
+        root = node;
+      } else {
+        Node* parent = node_for_frame(frame->GetParent());
+        DCHECK(parent);
+        parent->children.push_back(node);
+      }
+    }
+    DCHECK(root) << "No root found.";
+
+    // Connect the inner root to the outer node.
+    if (auto* outer_frame = contents->GetOuterWebContentsFrame()) {
+      Node* parent = node_for_frame(outer_frame);
+      DCHECK(parent);
+      parent->children.push_back(root);
+    } else {
+      DCHECK(!outer_root) << "Multiple outer roots found.";
+      outer_root = root;
+    }
+
+    // Traverse all inner contents.
+    for (auto* inner_contents : contents->GetInnerWebContents())
+      all_web_contents.push_back(inner_contents);
   }
-  DCHECK(root) << "No root found.";
-  return root;
+  DCHECK(outer_root) << "No outer root found";
+
+  return outer_root;
 }
 
 bool BlinkTestController::IsMainWindow(WebContents* web_contents) const {
@@ -1371,7 +1399,8 @@
 
 BlinkTestController::Node::Node() = default;
 BlinkTestController::Node::Node(RenderFrameHost* host)
-    : render_frame_host(host) {}
+    : render_frame_host(host),
+      render_frame_host_id(host->GetProcess()->GetID(), host->GetRoutingID()) {}
 BlinkTestController::Node::Node(Node&& other) = default;
 BlinkTestController::Node::~Node() = default;
 
diff --git a/content/shell/browser/web_test/blink_test_controller.h b/content/shell/browser/web_test/blink_test_controller.h
index 07f5f73..2a6ef05b 100644
--- a/content/shell/browser/web_test/blink_test_controller.h
+++ b/content/shell/browser/web_test/blink_test_controller.h
@@ -184,6 +184,7 @@
     ~Node();
 
     RenderFrameHost* render_frame_host = nullptr;
+    GlobalFrameRoutingId render_frame_host_id;
     std::vector<Node*> children;
 
     DISALLOW_COPY_AND_ASSIGN(Node);
@@ -241,7 +242,7 @@
   void CompositeAllFramesThen(base::OnceCallback<void()> callback);
 
  private:
-  Node* BuildFrameTree(const std::vector<RenderFrameHost*>& frames);
+  Node* BuildFrameTree(WebContents* web_contents);
   void CompositeNodeQueueThen(base::OnceCallback<void()> callback);
   void BuildDepthFirstQueue(Node* node);
 
@@ -319,7 +320,7 @@
   bool waiting_for_pixel_results_ = false;
   bool waiting_for_main_frame_dump_ = false;
 
-  std::vector<Node> composite_all_frames_node_storage_;
+  std::vector<std::unique_ptr<Node>> composite_all_frames_node_storage_;
   std::queue<Node*> composite_all_frames_node_queue_;
 
   // Map from one frame to one mojo pipe.
diff --git a/content/shell/renderer/web_test/web_test_content_renderer_client.cc b/content/shell/renderer/web_test/web_test_content_renderer_client.cc
index ab319e4c..afdfc761 100644
--- a/content/shell/renderer/web_test/web_test_content_renderer_client.cc
+++ b/content/shell/renderer/web_test/web_test_content_renderer_client.cc
@@ -34,7 +34,6 @@
 #include "media/base/audio_latency.h"
 #include "media/base/mime_util.h"
 #include "media/media_buildflags.h"
-#include "third_party/blink/public/platform/modules/webmidi/web_midi_accessor.h"
 #include "third_party/blink/public/platform/web_audio_latency_hint.h"
 #include "third_party/blink/public/platform/web_media_stream_center.h"
 #include "third_party/blink/public/platform/web_rtc_peer_connection_handler.h"
@@ -51,8 +50,6 @@
 using blink::WebFrame;
 using blink::WebLocalFrame;
 using blink::WebMediaStreamCenter;
-using blink::WebMIDIAccessor;
-using blink::WebMIDIAccessorClient;
 using blink::WebPlugin;
 using blink::WebPluginParams;
 using blink::WebRTCPeerConnectionHandler;
@@ -98,14 +95,6 @@
   test_runner->Reset(false /* for_new_test */);
 }
 
-std::unique_ptr<WebMIDIAccessor>
-WebTestContentRendererClient::OverrideCreateMIDIAccessor(
-    WebMIDIAccessorClient* client) {
-  test_runner::WebTestInterfaces* interfaces =
-      WebTestRenderThreadObserver::GetInstance()->test_interfaces();
-  return interfaces->CreateMIDIAccessor(client);
-}
-
 WebThemeEngine* WebTestContentRendererClient::OverrideThemeEngine() {
   return WebTestRenderThreadObserver::GetInstance()
       ->test_interfaces()
diff --git a/content/shell/renderer/web_test/web_test_content_renderer_client.h b/content/shell/renderer/web_test/web_test_content_renderer_client.h
index a87d765..e738f8f 100644
--- a/content/shell/renderer/web_test/web_test_content_renderer_client.h
+++ b/content/shell/renderer/web_test/web_test_content_renderer_client.h
@@ -22,8 +22,6 @@
   void RenderThreadStarted() override;
   void RenderFrameCreated(RenderFrame* render_frame) override;
   void RenderViewCreated(RenderView* render_view) override;
-  std::unique_ptr<blink::WebMIDIAccessor> OverrideCreateMIDIAccessor(
-      blink::WebMIDIAccessorClient* client) override;
   blink::WebThemeEngine* OverrideThemeEngine() override;
   std::unique_ptr<MediaStreamRendererFactory> CreateMediaStreamRendererFactory()
       override;
diff --git a/content/shell/test_runner/BUILD.gn b/content/shell/test_runner/BUILD.gn
index 7d26f89..f576a6ba 100644
--- a/content/shell/test_runner/BUILD.gn
+++ b/content/shell/test_runner/BUILD.gn
@@ -45,8 +45,6 @@
     "mock_spell_check.h",
     "mock_web_document_subresource_filter.cc",
     "mock_web_document_subresource_filter.h",
-    "mock_web_midi_accessor.cc",
-    "mock_web_midi_accessor.h",
     "mock_web_theme_engine.cc",
     "mock_web_theme_engine.h",
     "pixel_dump.cc",
diff --git a/content/shell/test_runner/DEPS b/content/shell/test_runner/DEPS
index 42b1e66..2b3abf1 100644
--- a/content/shell/test_runner/DEPS
+++ b/content/shell/test_runner/DEPS
@@ -6,7 +6,6 @@
   "+device/gamepad/public/mojom",
   "+gin",
   "+gpu/command_buffer/client",
-  "+media/midi/midi_service.mojom.h",
   "+mojo/public",
   "+net/base",
   "+services/device/public/cpp/generic_sensor",
diff --git a/content/shell/test_runner/mock_web_midi_accessor.cc b/content/shell/test_runner/mock_web_midi_accessor.cc
deleted file mode 100644
index 8470b213..0000000
--- a/content/shell/test_runner/mock_web_midi_accessor.cc
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/shell/test_runner/mock_web_midi_accessor.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/macros.h"
-#include "base/strings/stringprintf.h"
-#include "content/shell/test_runner/test_interfaces.h"
-#include "content/shell/test_runner/test_runner.h"
-#include "content/shell/test_runner/web_test_delegate.h"
-#include "content/shell/test_runner/web_test_runner.h"
-#include "third_party/blink/public/platform/modules/webmidi/web_midi_accessor_client.h"
-#include "third_party/blink/public/platform/web_string.h"
-
-using midi::mojom::PortState;
-using midi::mojom::Result;
-
-namespace test_runner {
-
-namespace {
-
-constexpr unsigned char kSysexHeader[] = {0xf0, 0x00, 0x02, 0x0d, 0x7f};
-constexpr unsigned char kSysexFooter = 0xf7;
-constexpr size_t kSysexMinimumLength =
-    arraysize(kSysexHeader) + sizeof(kSysexFooter) + 1;
-
-bool isSysexForTesting(const unsigned char* data, size_t length) {
-  // It should have five bytes header, one byte footer, and at least one byte
-  // payload.
-  if (length < kSysexMinimumLength)
-    return false;
-  if (memcmp(data, kSysexHeader, arraysize(kSysexHeader)))
-    return false;
-  return data[length - 1] == kSysexFooter;
-}
-
-}  // namespace
-
-MockWebMIDIAccessor::MockWebMIDIAccessor(blink::WebMIDIAccessorClient* client,
-                                         TestInterfaces* interfaces)
-    : client_(client),
-      interfaces_(interfaces),
-      next_input_port_index_(0),
-      next_output_port_index_(0),
-      weak_factory_(this) {}
-
-MockWebMIDIAccessor::~MockWebMIDIAccessor() {}
-
-void MockWebMIDIAccessor::StartSession() {
-  // Add a mock input and output port.
-  addInputPort(PortState::CONNECTED);
-  addOutputPort(PortState::CONNECTED);
-  interfaces_->GetDelegate()->PostTask(base::BindOnce(
-      &MockWebMIDIAccessor::reportStartedSession, weak_factory_.GetWeakPtr(),
-      interfaces_->GetTestRunner()->midiAccessorResult()));
-}
-
-void MockWebMIDIAccessor::RunDidReceiveMIDIData(unsigned port_index,
-                                                std::vector<unsigned char> data,
-                                                base::TimeTicks timestamp) {
-  client_->DidReceiveMIDIData(port_index, data.data(), data.size(), timestamp);
-}
-
-void MockWebMIDIAccessor::SendMIDIData(unsigned port_index,
-                                       const unsigned char* data,
-                                       size_t length,
-                                       base::TimeTicks timestamp) {
-  // Emulate a loopback device for testing. Make sure if an input port that has
-  // the same index exists.
-  if (port_index < next_input_port_index_) {
-    std::vector<unsigned char> copied_data(data, data + length);
-    interfaces_->GetDelegate()->PostDelayedTask(
-        base::BindOnce(&MockWebMIDIAccessor::RunDidReceiveMIDIData,
-                       weak_factory_.GetWeakPtr(), port_index,
-                       std::move(copied_data), timestamp),
-        std::max(base::TimeDelta(), timestamp - base::TimeTicks::Now()));
-  }
-
-  // Handle special sysex messages for testing.
-  // A special sequence is [0xf0, 0x00, 0x02, 0x0d, 0x7f, <function>, 0xf7].
-  // <function> should be one of following sequences.
-  //  - [0x00, 0x00]: Add an input port as connected.
-  //  - [0x00, 0x01]: Add an output port as connected.
-  //  - [0x00, 0x02]: Add an input port as opened.
-  //  - [0x00, 0x03]: Add an output port as opened.
-  if (!isSysexForTesting(data, length))
-    return;
-  size_t offset = arraysize(kSysexHeader);
-  if (data[offset++] != 0)
-    return;
-  switch (data[offset]) {
-    case 0:
-      addInputPort(PortState::CONNECTED);
-      break;
-    case 1:
-      addOutputPort(PortState::CONNECTED);
-      break;
-    case 2:
-      addInputPort(PortState::OPENED);
-      break;
-    case 3:
-      addOutputPort(PortState::OPENED);
-      break;
-    default:
-      break;
-  }
-}
-
-void MockWebMIDIAccessor::addInputPort(PortState state) {
-  std::string id =
-      base::StringPrintf("MockInputID-%d", next_input_port_index_++);
-  client_->DidAddInputPort(blink::WebString::FromUTF8(id),
-                           "MockInputManufacturer", "MockInputName",
-                           "MockInputVersion", state);
-}
-
-void MockWebMIDIAccessor::addOutputPort(PortState state) {
-  std::string id =
-      base::StringPrintf("MockOutputID-%d", next_output_port_index_++);
-  client_->DidAddOutputPort(blink::WebString::FromUTF8(id),
-                            "MockOutputManufacturer", "MockOutputName",
-                            "MockOutputVersion", state);
-}
-
-void MockWebMIDIAccessor::reportStartedSession(Result result) {
-  client_->DidStartSession(result);
-}
-
-}  // namespace test_runner
diff --git a/content/shell/test_runner/mock_web_midi_accessor.h b/content/shell/test_runner/mock_web_midi_accessor.h
deleted file mode 100644
index 81e5c735..0000000
--- a/content/shell/test_runner/mock_web_midi_accessor.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_SHELL_TEST_RUNNER_MOCK_WEB_MIDI_ACCESSOR_H_
-#define CONTENT_SHELL_TEST_RUNNER_MOCK_WEB_MIDI_ACCESSOR_H_
-
-#include <stddef.h>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "media/midi/midi_service.mojom.h"
-#include "third_party/blink/public/platform/modules/webmidi/web_midi_accessor.h"
-
-namespace blink {
-class WebMIDIAccessorClient;
-}
-
-namespace test_runner {
-
-class TestInterfaces;
-
-class MockWebMIDIAccessor : public blink::WebMIDIAccessor {
- public:
-  MockWebMIDIAccessor(blink::WebMIDIAccessorClient* client,
-                      TestInterfaces* interfaces);
-  ~MockWebMIDIAccessor() override;
-
-  // blink::WebMIDIAccessor implementation.
-  void StartSession() override;
-  void SendMIDIData(unsigned port_index,
-                    const unsigned char* data,
-                    size_t length,
-                    base::TimeTicks timestamp) override;
-
- private:
-  void addInputPort(midi::mojom::PortState state);
-  void addOutputPort(midi::mojom::PortState state);
-  void reportStartedSession(midi::mojom::Result result);
-
-  void RunDidReceiveMIDIData(unsigned port_index,
-                             std::vector<unsigned char> data,
-                             base::TimeTicks time_stamp);
-
-  blink::WebMIDIAccessorClient* client_;
-  TestInterfaces* interfaces_;
-  unsigned next_input_port_index_;
-  unsigned next_output_port_index_;
-
-  base::WeakPtrFactory<MockWebMIDIAccessor> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockWebMIDIAccessor);
-};
-
-}  // namespace test_runner
-
-#endif  // CONTENT_SHELL_TEST_RUNNER_MOCK_WEB_MIDI_ACCESSOR_H_
diff --git a/content/shell/test_runner/test_runner.cc b/content/shell/test_runner/test_runner.cc
index 049e93b0..b9ce921 100644
--- a/content/shell/test_runner/test_runner.cc
+++ b/content/shell/test_runner/test_runner.cc
@@ -245,7 +245,6 @@
   void SetIsolatedWorldSecurityOrigin(int world_id,
                                       v8::Local<v8::Value> origin);
   void SetJavaScriptCanAccessClipboard(bool can_access);
-  void SetMIDIAccessorResult(bool result);
   void SetMockScreenOrientation(const std::string& orientation);
   void SetPOSIXLocale(const std::string& locale);
   void SetPageVisibility(const std::string& new_visibility);
@@ -564,8 +563,6 @@
                  &TestRunnerBindings::SetIsolatedWorldSecurityOrigin)
       .SetMethod("setJavaScriptCanAccessClipboard",
                  &TestRunnerBindings::SetJavaScriptCanAccessClipboard)
-      .SetMethod("setMIDIAccessorResult",
-                 &TestRunnerBindings::SetMIDIAccessorResult)
       .SetMethod("setMainFrameIsFirstResponder",
                  &TestRunnerBindings::NotImplemented)
       .SetMethod("setMockScreenOrientation",
@@ -1276,14 +1273,6 @@
     runner_->SetPOSIXLocale(locale);
 }
 
-void TestRunnerBindings::SetMIDIAccessorResult(bool result) {
-  if (runner_) {
-    runner_->SetMIDIAccessorResult(
-        result ? midi::mojom::Result::OK
-               : midi::mojom::Result::INITIALIZATION_ERROR);
-  }
-}
-
 void TestRunnerBindings::SimulateWebNotificationClick(gin::Arguments* args) {
   DCHECK_GE(args->Length(), 1);
   if (!runner_)
@@ -1591,7 +1580,6 @@
   dump_back_forward_list_ = false;
   test_repaint_ = false;
   sweep_horizontally_ = false;
-  midi_accessor_result_ = midi::mojom::Result::OK;
   animation_requires_raster_ = false;
 
   http_headers_to_clear_.clear();
@@ -1930,10 +1918,6 @@
   return web_test_runtime_flags_.dump_navigation_policy();
 }
 
-midi::mojom::Result TestRunner::midiAccessorResult() {
-  return midi_accessor_result_;
-}
-
 void TestRunner::SetV8CacheDisabled(bool disabled) {
   if (!main_view_) {
     disable_v8_cache_ = disabled;
@@ -2562,10 +2546,6 @@
   delegate_->SetLocale(locale);
 }
 
-void TestRunner::SetMIDIAccessorResult(midi::mojom::Result result) {
-  midi_accessor_result_ = result;
-}
-
 void TestRunner::SimulateWebNotificationClick(
     const std::string& title,
     const base::Optional<int>& action_index,
diff --git a/content/shell/test_runner/test_runner.h b/content/shell/test_runner/test_runner.h
index 6429304..83d63aa 100644
--- a/content/shell/test_runner/test_runner.h
+++ b/content/shell/test_runner/test_runner.h
@@ -20,7 +20,6 @@
 #include "content/shell/test_runner/test_runner_export.h"
 #include "content/shell/test_runner/web_test_runner.h"
 #include "content/shell/test_runner/web_test_runtime_flags.h"
-#include "media/midi/midi_service.mojom.h"
 #include "third_party/blink/public/platform/web_effective_connection_type.h"
 #include "third_party/blink/public/platform/web_image.h"
 #include "v8/include/v8.h"
@@ -159,8 +158,6 @@
   void setDragImage(const SkBitmap& drag_image);
   bool shouldDumpNavigationPolicy() const;
 
-  midi::mojom::Result midiAccessorResult();
-
   bool ShouldDumpConsoleMessages() const;
   // Controls whether console messages produced by the page are dumped
   // to test output.
@@ -487,9 +484,6 @@
   // Resets between tests.
   void SetPOSIXLocale(const std::string& locale);
 
-  // MIDI function to control permission handling.
-  void SetMIDIAccessorResult(midi::mojom::Result result);
-
   // Simulates a click on a Web Notification.
   void SimulateWebNotificationClick(
       const std::string& title,
@@ -551,9 +545,6 @@
   // a series of 1px-wide, view-tall paints across the width of the view.
   bool sweep_horizontally_;
 
-  // startSession() result of MockWebMIDIAccessor for testing.
-  midi::mojom::Result midi_accessor_result_;
-
   std::set<std::string> http_headers_to_clear_;
 
   // WAV audio data is stored here.
diff --git a/content/shell/test_runner/web_test_interfaces.cc b/content/shell/test_runner/web_test_interfaces.cc
index f93cda4a..d535da3 100644
--- a/content/shell/test_runner/web_test_interfaces.cc
+++ b/content/shell/test_runner/web_test_interfaces.cc
@@ -6,12 +6,12 @@
 
 #include <utility>
 
-#include "content/shell/test_runner/mock_web_midi_accessor.h"
 #include "content/shell/test_runner/test_interfaces.h"
 #include "content/shell/test_runner/test_runner.h"
 #include "content/shell/test_runner/web_frame_test_client.h"
 #include "content/shell/test_runner/web_view_test_proxy.h"
-#include "third_party/blink/public/platform/modules/webmidi/web_midi_accessor.h"
+#include "content/shell/test_runner/web_widget_test_client.h"
+#include "content/shell/test_runner/web_widget_test_proxy.h"
 
 namespace test_runner {
 
@@ -56,11 +56,6 @@
   return interfaces_.get();
 }
 
-std::unique_ptr<blink::WebMIDIAccessor> WebTestInterfaces::CreateMIDIAccessor(
-    blink::WebMIDIAccessorClient* client) {
-  return std::make_unique<MockWebMIDIAccessor>(client, interfaces_.get());
-}
-
 std::unique_ptr<WebFrameTestClient> WebTestInterfaces::CreateWebFrameTestClient(
     WebViewTestProxyBase* web_view_test_proxy_base,
     WebFrameTestProxyBase* web_frame_test_proxy_base) {
diff --git a/content/shell/test_runner/web_test_interfaces.h b/content/shell/test_runner/web_test_interfaces.h
index e315089..638833f 100644
--- a/content/shell/test_runner/web_test_interfaces.h
+++ b/content/shell/test_runner/web_test_interfaces.h
@@ -13,8 +13,6 @@
 
 namespace blink {
 class WebLocalFrameClient;
-class WebMIDIAccessor;
-class WebMIDIAccessorClient;
 class WebRTCPeerConnectionHandler;
 class WebRTCPeerConnectionHandlerClient;
 class WebThemeEngine;
@@ -54,9 +52,6 @@
   CreateWebRTCPeerConnectionHandler(
       blink::WebRTCPeerConnectionHandlerClient* client);
 
-  std::unique_ptr<blink::WebMIDIAccessor> CreateMIDIAccessor(
-      blink::WebMIDIAccessorClient* client);
-
   TestInterfaces* GetTestInterfaces();
 
   // Creates a WebLocalFrameClient implementation providing test behavior (i.e.
diff --git a/google_apis/gaia/fake_oauth2_token_service_delegate.cc b/google_apis/gaia/fake_oauth2_token_service_delegate.cc
index 7fc9c28..1e165df 100644
--- a/google_apis/gaia/fake_oauth2_token_service_delegate.cc
+++ b/google_apis/gaia/fake_oauth2_token_service_delegate.cc
@@ -23,7 +23,7 @@
     const std::string& account_id,
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     OAuth2AccessTokenConsumer* consumer) {
-  AccountInfoMap::const_iterator it = refresh_tokens_.find(account_id);
+  auto it = refresh_tokens_.find(account_id);
   DCHECK(it != refresh_tokens_.end());
   return new OAuth2AccessTokenFetcherImpl(consumer, url_loader_factory,
                                           it->second->refresh_token);
@@ -43,7 +43,7 @@
 
 std::string FakeOAuth2TokenServiceDelegate::GetRefreshToken(
     const std::string& account_id) const {
-  AccountInfoMap::const_iterator it = refresh_tokens_.find(account_id);
+  auto it = refresh_tokens_.find(account_id);
   if (it != refresh_tokens_.end())
     return it->second->refresh_token;
   return std::string();
@@ -51,19 +51,15 @@
 
 std::vector<std::string> FakeOAuth2TokenServiceDelegate::GetAccounts() {
   std::vector<std::string> account_ids;
-  for (AccountInfoMap::const_iterator iter = refresh_tokens_.begin();
-       iter != refresh_tokens_.end(); ++iter) {
-    account_ids.push_back(iter->first);
-  }
+  for (const auto& token : refresh_tokens_)
+    account_ids.push_back(token.first);
   return account_ids;
 }
 
 void FakeOAuth2TokenServiceDelegate::RevokeAllCredentials() {
   std::vector<std::string> account_ids = GetAccounts();
-  for (std::vector<std::string>::const_iterator it = account_ids.begin();
-       it != account_ids.end(); it++) {
-    RevokeCredentials(*it);
-  }
+  for (const auto& account : account_ids)
+    RevokeCredentials(account);
 }
 
 void FakeOAuth2TokenServiceDelegate::LoadCredentials(
diff --git a/google_apis/gaia/fake_oauth2_token_service_delegate.h b/google_apis/gaia/fake_oauth2_token_service_delegate.h
index e90d63c..513fca4 100644
--- a/google_apis/gaia/fake_oauth2_token_service_delegate.h
+++ b/google_apis/gaia/fake_oauth2_token_service_delegate.h
@@ -5,8 +5,9 @@
 #ifndef CHROME_BROWSER_SIGNIN_FAKE_OAUTH2_TOKEN_SERVICE_DELEGATE_H_
 #define CHROME_BROWSER_SIGNIN_FAKE_OAUTH2_TOKEN_SERVICE_DELEGATE_H_
 
+#include <memory>
+
 #include "base/macros.h"
-#include "base/memory/linked_ptr.h"
 #include "base/memory/ref_counted.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "google_apis/gaia/oauth2_token_service_delegate.h"
@@ -64,8 +65,7 @@
                                 const std::string& token);
 
   // Maps account ids to info.
-  typedef std::map<std::string, linked_ptr<AccountInfo>> AccountInfoMap;
-  AccountInfoMap refresh_tokens_;
+  std::map<std::string, std::unique_ptr<AccountInfo>> refresh_tokens_;
 
   network::TestURLLoaderFactory test_url_loader_factory_;
   scoped_refptr<network::SharedURLLoaderFactory> shared_factory_;
diff --git a/google_apis/gcm/engine/gcm_store.h b/google_apis/gcm/engine/gcm_store.h
index 828658b..d9d0595b 100644
--- a/google_apis/gcm/engine/gcm_store.h
+++ b/google_apis/gcm/engine/gcm_store.h
@@ -16,7 +16,6 @@
 
 #include "base/callback_forward.h"
 #include "base/macros.h"
-#include "base/memory/linked_ptr.h"
 #include "base/memory/ref_counted.h"
 #include "base/time/time.h"
 #include "google_apis/gcm/base/gcm_export.h"
@@ -36,11 +35,11 @@
   };
 
   // Map of message id to message data for outgoing messages.
-  typedef std::map<std::string, linked_ptr<google::protobuf::MessageLite> >
-      OutgoingMessageMap;
+  using OutgoingMessageMap =
+      std::map<std::string, std::unique_ptr<google::protobuf::MessageLite>>;
 
   // List of account mappings.
-  typedef std::vector<AccountMapping> AccountMappings;
+  using AccountMappings = std::vector<AccountMapping>;
 
   // Container for Load(..) results.
   struct GCM_EXPORT LoadResult {
@@ -66,9 +65,9 @@
     std::map<std::string, std::string> instance_id_data;
   };
 
-  typedef std::vector<std::string> PersistentIdList;
-  typedef base::Callback<void(std::unique_ptr<LoadResult> result)> LoadCallback;
-  typedef base::Callback<void(bool success)> UpdateCallback;
+  using PersistentIdList = std::vector<std::string>;
+  using LoadCallback = base::Callback<void(std::unique_ptr<LoadResult> result)>;
+  using UpdateCallback = base::Callback<void(bool success)>;
 
   GCMStore();
   virtual ~GCMStore();
diff --git a/google_apis/gcm/engine/gcm_store_impl.cc b/google_apis/gcm/engine/gcm_store_impl.cc
index 1bcea40..b29f31f 100644
--- a/google_apis/gcm/engine/gcm_store_impl.cc
+++ b/google_apis/gcm/engine/gcm_store_impl.cc
@@ -1002,7 +1002,7 @@
     }
     DVLOG(1) << "Found outgoing message with id " << id << " of type "
              << base::UintToString(tag);
-    (*outgoing_messages)[id] = make_linked_ptr(message.release());
+    (*outgoing_messages)[id] = std::move(message);
   }
 
   return true;
diff --git a/google_apis/gcm/engine/mcs_client.cc b/google_apis/gcm/engine/mcs_client.cc
index 7ee780f..47ba2023 100644
--- a/google_apis/gcm/engine/mcs_client.cc
+++ b/google_apis/gcm/engine/mcs_client.cc
@@ -263,19 +263,20 @@
   for (std::map<uint64_t, google::protobuf::MessageLite*>::iterator iter =
            ordered_messages.begin();
        iter != ordered_messages.end(); ++iter) {
-    ReliablePacketInfo* packet_info = new ReliablePacketInfo();
+    auto packet_info = std::make_unique<ReliablePacketInfo>();
+    auto* packet_info_ptr = packet_info.get();
     packet_info->protobuf.reset(iter->second);
     packet_info->tag = GetMCSProtoTag(*iter->second);
     packet_info->persistent_id = base::NumberToString(iter->first);
-    to_send_.push_back(make_linked_ptr(packet_info));
+    to_send_.push_back(std::move(packet_info));
 
-    if (packet_info->tag == kDataMessageStanzaTag) {
+    if (packet_info_ptr->tag == kDataMessageStanzaTag) {
       mcs_proto::DataMessageStanza* data_message =
           reinterpret_cast<mcs_proto::DataMessageStanza*>(
-              packet_info->protobuf.get());
+              packet_info_ptr->protobuf.get());
       CollapseKey collapse_key(*data_message);
       if (collapse_key.IsValid())
-        collapse_key_map_[collapse_key] = packet_info;
+        collapse_key_map_[collapse_key] = packet_info_ptr;
     }
   }
 
@@ -369,7 +370,7 @@
     return;
   }
 
-  to_send_.push_back(make_linked_ptr(packet_info.release()));
+  to_send_.push_back(std::move(packet_info));
 
   // Notify that the messages has been succsfully queued for sending.
   // TODO(jianli): We should report QUEUED after writing to GCM store succeeds.
@@ -478,7 +479,7 @@
   // to RMQ, as all messages that reach this point should already have been
   // saved as necessary.
   while (!to_resend_.empty()) {
-    to_send_.push_front(to_resend_.back());
+    to_send_.push_front(std::move(to_resend_.back()));
     to_resend_.pop_back();
   }
 
@@ -489,7 +490,7 @@
     MCSPacketInternal packet = PopMessageForSend();
     if (GetTTL(*packet->protobuf) > 0 &&
         !HasTTLExpired(*packet->protobuf, clock_)) {
-      new_to_send.push_back(packet);
+      new_to_send.push_back(std::move(packet));
     } else {
       // If the TTL was 0 there is no persistent id, so no need to remove the
       // message from the persistent store.
@@ -539,6 +540,7 @@
     return;
 
   MCSPacketInternal packet = PopMessageForSend();
+  ReliablePacketInfo* packet_ptr = packet.get();
   if (HasTTLExpired(*packet->protobuf, clock_)) {
     DCHECK(!packet->persistent_id.empty());
     DVLOG(1) << "Dropping expired message " << packet->persistent_id << ".";
@@ -555,8 +557,8 @@
   }
   DVLOG(1) << "Pending output message found, sending.";
   if (!packet->persistent_id.empty())
-    to_resend_.push_back(packet);
-  SendPacketToWire(packet.get());
+    to_resend_.push_back(std::move(packet));
+  SendPacketToWire(packet_ptr);
 }
 
 void MCSClient::SendPacketToWire(ReliablePacketInfo* packet_info) {
@@ -895,7 +897,7 @@
   // server.
   DVLOG(1) << "Resending " << to_resend_.size() << " messages.";
   while (!to_resend_.empty()) {
-    to_send_.push_front(to_resend_.back());
+    to_send_.push_front(std::move(to_resend_.back()));
     to_resend_.pop_back();
   }
   base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -956,7 +958,7 @@
 }
 
 MCSClient::MCSPacketInternal MCSClient::PopMessageForSend() {
-  MCSPacketInternal packet = to_send_.front();
+  MCSPacketInternal packet = std::move(to_send_.front());
   to_send_.pop_front();
 
   if (packet->tag == kDataMessageStanzaTag) {
diff --git a/google_apis/gcm/engine/mcs_client.h b/google_apis/gcm/engine/mcs_client.h
index 22cecae..1fecfa5 100644
--- a/google_apis/gcm/engine/mcs_client.h
+++ b/google_apis/gcm/engine/mcs_client.h
@@ -15,7 +15,6 @@
 #include "base/containers/circular_deque.h"
 #include "base/files/file_path.h"
 #include "base/macros.h"
-#include "base/memory/linked_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "google_apis/gcm/base/gcm_export.h"
 #include "google_apis/gcm/base/mcs_message.h"
@@ -167,12 +166,12 @@
   }
 
  private:
-  typedef uint32_t StreamId;
-  typedef std::string PersistentId;
-  typedef std::vector<StreamId> StreamIdList;
-  typedef std::vector<PersistentId> PersistentIdList;
-  typedef std::map<StreamId, PersistentId> StreamIdToPersistentIdMap;
-  typedef linked_ptr<ReliablePacketInfo> MCSPacketInternal;
+  using StreamId = uint32_t;
+  using PersistentId = std::string;
+  using StreamIdList = std::vector<StreamId>;
+  using PersistentIdList = std::vector<PersistentId>;
+  using StreamIdToPersistentIdMap = std::map<StreamId, PersistentId>;
+  using MCSPacketInternal = std::unique_ptr<ReliablePacketInfo>;
 
   // Resets the internal state and builds a new login request, acknowledging
   // any pending server-to-device messages and rebuilding the send queue
diff --git a/ios/chrome/app/application_delegate/BUILD.gn b/ios/chrome/app/application_delegate/BUILD.gn
index c5ab852..05b6f35 100644
--- a/ios/chrome/app/application_delegate/BUILD.gn
+++ b/ios/chrome/app/application_delegate/BUILD.gn
@@ -46,11 +46,14 @@
     "//ios/chrome/browser/geolocation",
     "//ios/chrome/browser/metrics",
     "//ios/chrome/browser/ntp_snippets",
+    "//ios/chrome/browser/signin",
+    "//ios/chrome/browser/signin:test_support",
     "//ios/chrome/browser/tabs",
     "//ios/chrome/browser/u2f",
     "//ios/chrome/browser/ui:ui_internal",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/main",
+    "//ios/chrome/browser/ui/main/test",
     "//ios/chrome/browser/ui/safe_mode",
     "//ios/chrome/browser/ui/settings",
     "//ios/chrome/browser/web:tab_id_tab_helper",
diff --git a/ios/chrome/app/application_delegate/app_state.h b/ios/chrome/app/application_delegate/app_state.h
index b0b93ea1..9ed331f 100644
--- a/ios/chrome/app/application_delegate/app_state.h
+++ b/ios/chrome/app/application_delegate/app_state.h
@@ -9,15 +9,12 @@
 
 @protocol AppNavigation;
 @protocol BrowserLauncher;
-@protocol BrowserViewInformation;
-@protocol TabOpening;
-@protocol TabSwitching;
-@protocol StartupInformation;
-@class DeviceSharingManager;
 @class MainApplicationDelegate;
 @class MemoryWarningHelper;
 @class MetricsMediator;
-@class TabModel;
+@protocol StartupInformation;
+@protocol TabOpening;
+@protocol TabSwitching;
 
 // Represents the application state and responds to application state changes
 // and system events.
diff --git a/ios/chrome/app/application_delegate/app_state.mm b/ios/chrome/app/application_delegate/app_state.mm
index eec6c8f..77ed3c13 100644
--- a/ios/chrome/app/application_delegate/app_state.mm
+++ b/ios/chrome/app/application_delegate/app_state.mm
@@ -43,8 +43,7 @@
 #import "ios/chrome/browser/ui/commands/application_commands.h"
 #import "ios/chrome/browser/ui/commands/browser_commands.h"
 #import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
-#import "ios/chrome/browser/ui/main/browser_coordinator.h"
-#import "ios/chrome/browser/ui/main/browser_view_information.h"
+#import "ios/chrome/browser/ui/main/browser_interface_provider.h"
 #import "ios/chrome/browser/ui/safe_mode/safe_mode_coordinator.h"
 #include "ios/chrome/browser/ui/util/ui_util.h"
 #include "ios/net/cookies/cookie_store_ios.h"
@@ -220,13 +219,13 @@
   }
 
   // Do not save cookies if it is already in progress.
-  if ([[_browserLauncher browserViewInformation] currentBVC].browserState &&
-      !_savingCookies) {
+  id<BrowserInterface> currentInterface =
+      _browserLauncher.interfaceProvider.currentInterface;
+  if (currentInterface.browserState && !_savingCookies) {
     // Save cookies to disk. The empty critical closure guarantees that the task
     // will be run before backgrounding.
     scoped_refptr<net::URLRequestContextGetter> getter =
-        [[_browserLauncher browserViewInformation] currentBVC]
-            .browserState->GetRequestContext();
+        currentInterface.browserState->GetRequestContext();
     _savingCookies = YES;
     __block base::OnceClosure criticalClosure =
         base::MakeCriticalClosure(base::BindOnce(^{
@@ -292,12 +291,12 @@
 
   [MetricsMediator
       logLaunchMetricsWithStartupInformation:_startupInformation
-                      browserViewInformation:[_browserLauncher
-                                                 browserViewInformation]];
+                           interfaceProvider:_browserLauncher
+                                                 .interfaceProvider];
   [memoryHelper resetForegroundMemoryWarningCount];
 
   ios::ChromeBrowserState* currentBrowserState =
-      [[_browserLauncher browserViewInformation] currentBrowserState];
+      _browserLauncher.interfaceProvider.currentInterface.browserState;
   if ([SignedInAccountsViewController
           shouldBePresentedForBrowserState:currentBrowserState]) {
     [appNavigation presentSignedInAccountsViewControllerForBrowserState:
@@ -305,9 +304,9 @@
   }
 
   // Use the mainBVC as the ContentSuggestions can only be started in non-OTR.
-  [ContentSuggestionsSchedulerNotifications
-      notifyForeground:[[[_browserLauncher browserViewInformation] mainBVC]
-                           browserState]];
+  ios::ChromeBrowserState* mainBrowserState =
+      _browserLauncher.interfaceProvider.mainInterface.browserState;
+  [ContentSuggestionsSchedulerNotifications notifyForeground:mainBrowserState];
 
   // If the current browser state is not OTR, check for cookie loss.
   if (currentBrowserState && !currentBrowserState->IsOffTheRecord() &&
@@ -339,33 +338,31 @@
   DCHECK([_browserLauncher browserInitializationStage] ==
          INITIALIZATION_STAGE_FOREGROUND);
   _sessionStartTime = base::TimeTicks::Now();
-  [[[_browserLauncher browserViewInformation] mainTabModel]
-      resetSessionMetrics];
+  TabModel* mainTabModel =
+      _browserLauncher.interfaceProvider.mainInterface.tabModel;
+  [mainTabModel resetSessionMetrics];
 
+  id<BrowserInterface> currentInterface =
+      _browserLauncher.interfaceProvider.currentInterface;
   if ([_startupInformation startupParameters]) {
     [UserActivityHandler
         handleStartupParametersWithTabOpener:tabOpener
                           startupInformation:_startupInformation
-                      browserViewInformation:[_browserLauncher
-                                                 browserViewInformation]];
-  } else if ([tabOpener shouldOpenNTPTabOnActivationOfTabModel:
-                            [[_browserLauncher browserViewInformation]
-                                currentTabModel]]) {
+                           interfaceProvider:_browserLauncher
+                                                 .interfaceProvider];
+  } else if ([tabOpener shouldOpenNTPTabOnActivationOfTabModel:currentInterface
+                                                                   .tabModel]) {
     // Opens an NTP if needed.
     // TODO(crbug.com/623491): opening a tab when the application is launched
     // without a tab should not be counted as a user action. Revisit the way tab
     // creation is counted.
     if (![tabSwitcher openNewTabFromTabSwitcher]) {
-      BrowserViewController* bvc =
-          [[_browserLauncher browserViewInformation] currentBVC];
-      BOOL incognito =
-          bvc == [[_browserLauncher browserViewInformation] otrBVC];
-      [bvc.dispatcher
-          openURLInNewTab:[OpenNewTabCommand commandWithIncognito:incognito]];
+      OpenNewTabCommand* command =
+          [OpenNewTabCommand commandWithIncognito:currentInterface.incognito];
+      [currentInterface.bvc.dispatcher openURLInNewTab:command];
     }
   } else {
-    [[[_browserLauncher browserViewInformation] currentBVC]
-        presentBubblesIfEligible];
+    [currentInterface.bvc presentBubblesIfEligible];
   }
 
   [MetricsMediator logStartupDuration:_startupInformation];
@@ -391,7 +388,7 @@
   // down.
   if ([_browserLauncher browserInitializationStage] >=
       INITIALIZATION_STAGE_FOREGROUND) {
-    [[_browserLauncher browserViewInformation] cleanDeviceSharingManager];
+    [_browserLauncher.interfaceProvider cleanDeviceSharingManager];
   }
 
   // Cancel any in-flight distribution notifications.
@@ -403,8 +400,8 @@
   // closing the tabs. Set the BVC to inactive to cancel all the dialogs.
   if ([_browserLauncher browserInitializationStage] >=
       INITIALIZATION_STAGE_FOREGROUND) {
-    [[_browserLauncher browserViewInformation] haltAllTabs];
-    _browserLauncher.browserViewInformation.currentBrowserCoordinator.active =
+    [_browserLauncher.interfaceProvider haltAllTabs];
+    _browserLauncher.interfaceProvider.currentInterface.userInteractionEnabled =
         NO;
   }
 
@@ -431,8 +428,8 @@
   UMA_HISTOGRAM_CUSTOM_TIMES("Session.TotalDurationMax1Day", duration,
                              base::TimeDelta::FromMilliseconds(1),
                              base::TimeDelta::FromHours(24), 50);
-  [[[_browserLauncher browserViewInformation] mainTabModel]
-      recordSessionMetrics];
+  [_browserLauncher.interfaceProvider.currentInterface
+          .tabModel recordSessionMetrics];
 }
 
 - (BOOL)requiresHandlingAfterLaunchWithOptions:(NSDictionary*)launchOptions
diff --git a/ios/chrome/app/application_delegate/app_state_unittest.mm b/ios/chrome/app/application_delegate/app_state_unittest.mm
index 1c81953..28025ce 100644
--- a/ios/chrome/app/application_delegate/app_state_unittest.mm
+++ b/ios/chrome/app/application_delegate/app_state_unittest.mm
@@ -31,13 +31,16 @@
 #include "ios/chrome/browser/experimental_flags.h"
 #import "ios/chrome/browser/geolocation/omnibox_geolocation_config.h"
 #include "ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory.h"
+#import "ios/chrome/browser/signin/authentication_service_factory.h"
+#import "ios/chrome/browser/signin/authentication_service_fake.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
 #import "ios/chrome/browser/ui/browser_view_controller.h"
 #import "ios/chrome/browser/ui/commands/application_commands.h"
 #import "ios/chrome/browser/ui/commands/browser_commands.h"
 #import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
-#import "ios/chrome/browser/ui/main/browser_coordinator.h"
-#import "ios/chrome/browser/ui/main/browser_view_information.h"
+#import "ios/chrome/browser/ui/main/browser_interface_provider.h"
+#import "ios/chrome/browser/ui/main/test/stub_browser_interface.h"
+#import "ios/chrome/browser/ui/main/test/stub_browser_interface_provider.h"
 #import "ios/chrome/browser/ui/safe_mode/safe_mode_coordinator.h"
 #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h"
 #import "ios/chrome/test/base/scoped_block_swizzler.h"
@@ -69,7 +72,7 @@
     id self,
     id<TabOpening> tabOpener,
     id<StartupInformation> startupInformation,
-    id<BrowserViewInformation> browserViewInformation);
+    id<BrowserInterfaceProvider> interfaceProvider);
 
 class FakeAppDistributionProvider : public AppDistributionProvider {
  public:
@@ -120,6 +123,22 @@
 
 }  // namespace
 
+@interface CallTrackingStubBrowserInterfaceProvider
+    : StubBrowserInterfaceProvider
+@property(nonatomic) BOOL tabsHalted;
+@property(nonatomic) BOOL deviceManagerCleaned;
+@end
+@implementation CallTrackingStubBrowserInterfaceProvider
+
+- (void)haltAllTabs {
+  self.tabsHalted = YES;
+}
+
+- (void)cleanDeviceSharingManager {
+  self.deviceManagerCleaned = YES;
+}
+@end
+
 class AppStateTest : public BlockCleanupTest {
  protected:
   AppStateTest() {
@@ -130,8 +149,8 @@
     main_application_delegate_ =
         [OCMockObject mockForClass:[MainApplicationDelegate class]];
     window_ = [OCMockObject mockForClass:[UIWindow class]];
-    browser_view_information_ =
-        [OCMockObject mockForProtocol:@protocol(BrowserViewInformation)];
+
+    interface_provider_ = [[StubBrowserInterfaceProvider alloc] init];
   }
 
   void SetUp() override {
@@ -140,22 +159,25 @@
     test_cbs_builder.AddTestingFactory(
         IOSChromeContentSuggestionsServiceFactory::GetInstance(),
         IOSChromeContentSuggestionsServiceFactory::GetDefaultFactory());
+    test_cbs_builder.AddTestingFactory(
+        AuthenticationServiceFactory::GetInstance(),
+        base::BindRepeating(
+            &AuthenticationServiceFake::CreateAuthenticationService));
     browser_state_ = test_cbs_builder.Build();
   }
 
   void initializeIncognitoBlocker(UIWindow* window) {
     id application = [OCMockObject niceMockForClass:[UIApplication class]];
     id memoryHelper = [OCMockObject mockForClass:[MemoryWarningHelper class]];
-    id browserViewInformation =
-        [OCMockObject mockForProtocol:@protocol(BrowserViewInformation)];
+    StubBrowserInterfaceProvider* interfaceProvider =
+        [[StubBrowserInterfaceProvider alloc] init];
     id tabModel = [OCMockObject mockForClass:[TabModel class]];
 
     [[startup_information_mock_ stub] expireFirstUserActionRecorder];
     [[[memoryHelper stub] andReturnValue:@0] foregroundMemoryWarningCount];
     [[[tabModel stub] andReturnValue:@NO] isEmpty];
-    [[[browser_view_information_ stub] andReturn:tabModel] otrTabModel];
-    stubNullCurrentBrowserState(browserViewInformation);
-    [[[browser_view_information_ stub] andReturn:nil] currentBVC];
+
+    interfaceProvider.mainInterface.tabModel = tabModel;
 
     swizzleMetricsMediatorDisableReporting();
 
@@ -166,20 +188,6 @@
     metrics_mediator_called_ = NO;
   }
 
-  void stubNullCurrentBrowserState(id browserViewInformation) {
-    [[[browserViewInformation stub] andDo:^(NSInvocation* invocation) {
-      ios::ChromeBrowserState* browserState = nullptr;
-      [invocation setReturnValue:&browserState];
-    }] currentBrowserState];
-  }
-
-  void stubBrowserState(id BVC) {
-    [[[BVC stub] andDo:^(NSInvocation* invocation) {
-      ios::ChromeBrowserState* browserState = getBrowserState();
-      [invocation setReturnValue:&browserState];
-    }] browserState];
-  }
-
   void swizzleSafeModeShouldStart(BOOL shouldStart) {
     safe_mode_swizzle_block_ = ^BOOL(id self) {
       return shouldStart;
@@ -203,21 +211,20 @@
 
   void swizzleHandleStartupParameters(
       id<TabOpening> expectedTabOpener,
-      id<BrowserViewInformation> expectedBrowserViewInformation) {
+      id<BrowserInterfaceProvider> expectedInterfaceProvider) {
     handle_startup_swizzle_block_ =
         ^(id self, id<TabOpening> tabOpener,
           id<StartupInformation> startupInformation,
-          id<BrowserViewInformation> browserViewInformation) {
+          id<BrowserInterfaceProvider> interfaceProvider) {
           ASSERT_EQ(startup_information_mock_, startupInformation);
           ASSERT_EQ(expectedTabOpener, tabOpener);
-          ASSERT_EQ(expectedBrowserViewInformation, browserViewInformation);
+          ASSERT_EQ(expectedInterfaceProvider, interfaceProvider);
         };
 
     handle_startup_swizzler_.reset(new ScopedBlockSwizzler(
         [UserActivityHandler class],
         @selector(handleStartupParametersWithTabOpener:
-                                    startupInformation:
-                                browserViewInformation:),
+                                    startupInformation:interfaceProvider:),
         handle_startup_swizzle_block_));
   }
 
@@ -230,24 +237,20 @@
     id memoryHelper = [OCMockObject mockForClass:[MemoryWarningHelper class]];
     id tabOpener = [OCMockObject mockForProtocol:@protocol(TabOpening)];
     id appNavigation = [OCMockObject mockForProtocol:@protocol(AppNavigation)];
-    id tabModel = [OCMockObject mockForClass:[TabModel class]];
+    id tabModel = interface_provider_.currentInterface.tabModel;
 
-    [[[browser_view_information_ stub] andReturn:tabModel] currentTabModel];
     [[metricsMediator stub] updateMetricsStateBasedOnPrefsUserTriggered:NO];
     [[memoryHelper stub] resetForegroundMemoryWarningCount];
     [[[memoryHelper stub] andReturnValue:@0] foregroundMemoryWarningCount];
     [[[tabOpener stub] andReturnValue:@(shouldOpenNTP)]
         shouldOpenNTPTabOnActivationOfTabModel:tabModel];
 
-    stubNullCurrentBrowserState(browser_view_information_);
-
     void (^swizzleBlock)() = ^{
     };
 
     ScopedBlockSwizzler swizzler(
         [MetricsMediator class],
-        @selector(logLaunchMetricsWithStartupInformation:
-                                  browserViewInformation:),
+        @selector(logLaunchMetricsWithStartupInformation:interfaceProvider:),
         swizzleBlock);
 
     [appState applicationWillEnterForeground:application
@@ -288,7 +291,9 @@
   id getStartupInformationMock() { return startup_information_mock_; }
   id getApplicationDelegateMock() { return main_application_delegate_; }
   id getWindowMock() { return window_; }
-  id getBrowserViewInformationMock() { return browser_view_information_; }
+  StubBrowserInterfaceProvider* getInterfaceProvider() {
+    return interface_provider_;
+  }
   ios::ChromeBrowserState* getBrowserState() { return browser_state_.get(); }
 
   BOOL metricsMediatorHasBeenCalled() { return metrics_mediator_called_; }
@@ -300,7 +305,7 @@
   id startup_information_mock_;
   id main_application_delegate_;
   id window_;
-  id browser_view_information_;
+  StubBrowserInterfaceProvider* interface_provider_;
   DecisionBlock safe_mode_swizzle_block_;
   HandleStartupParam handle_startup_swizzle_block_;
   ProceduralBlock metrics_mediator_swizzle_block_;
@@ -479,17 +484,15 @@
   id tabModel = [OCMockObject mockForClass:[TabModel class]];
   [[tabModel expect] recordSessionMetrics];
 
-  id browserViewInformation =
-      [OCMockObject mockForProtocol:@protocol(BrowserViewInformation)];
-
-  [[[browserViewInformation stub] andReturn:tabModel] mainTabModel];
+  StubBrowserInterfaceProvider* interfaceProvider =
+      [[StubBrowserInterfaceProvider alloc] init];
+  interfaceProvider.mainInterface.tabModel = tabModel;
 
   id browserLauncher =
       [OCMockObject mockForProtocol:@protocol(BrowserLauncher)];
   [[[browserLauncher stub] andReturnValue:@(INITIALIZATION_STAGE_FOREGROUND)]
       browserInitializationStage];
-  [[[browserLauncher stub] andReturn:browserViewInformation]
-      browserViewInformation];
+  [[[browserLauncher stub] andReturn:interfaceProvider] interfaceProvider];
 
   id applicationDelegate =
       [OCMockObject mockForClass:[MainApplicationDelegate class]];
@@ -521,24 +524,20 @@
   IOSChromeScopedTestingChromeBrowserProvider provider_(
       std::make_unique<FakeChromeBrowserProvider>());
 
-  id browserCoordinator = OCMClassMock([BrowserCoordinator class]);
   id browserViewController = OCMClassMock([BrowserViewController class]);
-  [[[browserCoordinator stub] andReturn:browserViewController] viewController];
-  OCMExpect([browserCoordinator setActive:NO]);
   id browserLauncher =
       [OCMockObject mockForProtocol:@protocol(BrowserLauncher)];
   id applicationDelegate =
       [OCMockObject mockForClass:[MainApplicationDelegate class]];
   id window = [OCMockObject mockForClass:[UIWindow class]];
-  id browserViewInformation =
-      [OCMockObject mockForProtocol:@protocol(BrowserViewInformation)];
+  CallTrackingStubBrowserInterfaceProvider* interfaceProvider =
+      [[CallTrackingStubBrowserInterfaceProvider alloc] init];
+  interfaceProvider.mainInterface.userInteractionEnabled = YES;
+  interfaceProvider.mainInterface.bvc = browserViewController;
+
   [[[browserLauncher stub] andReturnValue:@(INITIALIZATION_STAGE_FOREGROUND)]
       browserInitializationStage];
-  [[[browserLauncher stub] andReturn:browserViewInformation]
-      browserViewInformation];
-  [[[browserViewInformation stub] andReturn:browserCoordinator]
-      currentBrowserCoordinator];
-  [[[browserViewInformation stub] andReturn:browserViewController] currentBVC];
+  [[[browserLauncher stub] andReturn:interfaceProvider] interfaceProvider];
 
   id settingsNavigationController =
       [OCMockObject mockForClass:[SettingsNavigationController class]];
@@ -548,9 +547,6 @@
       settingsNavigationController];
   [[appNavigation expect] closeSettingsAnimated:NO completion:nil];
 
-  [[browserViewInformation expect] cleanDeviceSharingManager];
-  [[browserViewInformation expect] haltAllTabs];
-
   id startupInformation =
       [OCMockObject mockForProtocol:@protocol(StartupInformation)];
   [[startupInformation expect] stopChromeMain];
@@ -568,12 +564,13 @@
                applicationNavigation:appNavigation];
 
   // Test.
-  EXPECT_OCMOCK_VERIFY(browserCoordinator);
   EXPECT_OCMOCK_VERIFY(browserViewController);
   EXPECT_OCMOCK_VERIFY(startupInformation);
   EXPECT_OCMOCK_VERIFY(appNavigation);
-  EXPECT_OCMOCK_VERIFY(browserViewInformation);
   EXPECT_OCMOCK_VERIFY(application);
+  EXPECT_FALSE(interfaceProvider.mainInterface.userInteractionEnabled);
+  EXPECT_TRUE(interfaceProvider.deviceManagerCleaned);
+  EXPECT_TRUE(interfaceProvider.tabsHalted);
   FakeAppDistributionProvider* provider =
       static_cast<FakeAppDistributionProvider*>(
           ios::GetChromeBrowserProvider()->GetAppDistributionProvider());
@@ -586,12 +583,12 @@
   // Setup.
 
   // BrowserLauncher.
-  id browserViewInformation = getBrowserViewInformationMock();
+  StubBrowserInterfaceProvider* interfaceProvider = getInterfaceProvider();
   [[[getBrowserLauncherMock() stub]
       andReturnValue:@(INITIALIZATION_STAGE_FOREGROUND)]
       browserInitializationStage];
-  [[[getBrowserLauncherMock() stub] andReturn:browserViewInformation]
-      browserViewInformation];
+  [[[getBrowserLauncherMock() stub] andReturn:interfaceProvider]
+      interfaceProvider];
 
   // StartupInformation.
   id appStartupParameters =
@@ -608,13 +605,13 @@
   // BrowserViewInformation.
   id mainTabModel = [OCMockObject mockForClass:[TabModel class]];
   [[mainTabModel expect] resetSessionMetrics];
-  [[[browserViewInformation stub] andReturn:mainTabModel] mainTabModel];
   id mainBVC = [OCMockObject mockForClass:[BrowserViewController class]];
-  stubBrowserState(mainBVC);
-  [[[browserViewInformation stub] andReturn:mainBVC] mainBVC];
+  interfaceProvider.mainInterface.tabModel = mainTabModel;
+  interfaceProvider.mainInterface.bvc = mainBVC;
+  interfaceProvider.mainInterface.browserState = getBrowserState();
 
   // Swizzle Startup Parameters.
-  swizzleHandleStartupParameters(tabOpener, browserViewInformation);
+  swizzleHandleStartupParameters(tabOpener, interfaceProvider);
 
   UIWindow* window = [[UIWindow alloc] init];
   AppState* appState = getAppStateWithOpenNTPAndIncognitoBlock(NO, window);
@@ -635,12 +632,12 @@
 TEST_F(AppStateTest, resumeSessionShouldOpenNTPTabSwitcher) {
   // Setup.
   // BrowserLauncher.
-  id browserViewInformation = getBrowserViewInformationMock();
+  StubBrowserInterfaceProvider* interfaceProvider = getInterfaceProvider();
   [[[getBrowserLauncherMock() stub]
       andReturnValue:@(INITIALIZATION_STAGE_FOREGROUND)]
       browserInitializationStage];
-  [[[getBrowserLauncherMock() stub] andReturn:browserViewInformation]
-      browserViewInformation];
+  [[[getBrowserLauncherMock() stub] andReturn:interfaceProvider]
+      interfaceProvider];
 
   // StartupInformation.
   [[[getStartupInformationMock() stub] andReturn:nil] startupParameters];
@@ -649,8 +646,10 @@
   // BrowserViewInformation.
   id mainTabModel = [OCMockObject mockForClass:[TabModel class]];
   [[mainTabModel expect] resetSessionMetrics];
-  [[[browserViewInformation stub] andReturn:mainTabModel] mainTabModel];
-  [[[browserViewInformation stub] andReturn:mainTabModel] currentTabModel];
+  id mainBVC = [OCMockObject mockForClass:[BrowserViewController class]];
+  interfaceProvider.mainInterface.tabModel = mainTabModel;
+  interfaceProvider.mainInterface.bvc = mainBVC;
+  interfaceProvider.mainInterface.browserState = getBrowserState();
 
   // TabOpening.
   id tabOpener = [OCMockObject mockForProtocol:@protocol(TabOpening)];
@@ -661,9 +660,6 @@
   id tabSwitcher = [OCMockObject mockForProtocol:@protocol(TabSwitching)];
   [[[tabSwitcher stub] andReturnValue:@YES] openNewTabFromTabSwitcher];
 
-  id mainBVC = [OCMockObject mockForClass:[BrowserViewController class]];
-  stubBrowserState(mainBVC);
-  [[[browserViewInformation stub] andReturn:mainBVC] mainBVC];
 
   UIWindow* window = [[UIWindow alloc] init];
   AppState* appState = getAppStateWithOpenNTPAndIncognitoBlock(YES, window);
@@ -683,12 +679,12 @@
 TEST_F(AppStateTest, resumeSessionShouldOpenNTPNoTabSwitcher) {
   // Setup.
   // BrowserLauncher.
-  id browserViewInformation = getBrowserViewInformationMock();
+  StubBrowserInterfaceProvider* interfaceProvider = getInterfaceProvider();
   [[[getBrowserLauncherMock() stub]
       andReturnValue:@(INITIALIZATION_STAGE_FOREGROUND)]
       browserInitializationStage];
-  [[[getBrowserLauncherMock() stub] andReturn:browserViewInformation]
-      browserViewInformation];
+  [[[getBrowserLauncherMock() stub] andReturn:interfaceProvider]
+      interfaceProvider];
 
   // StartupInformation.
   [[[getStartupInformationMock() stub] andReturn:nil] startupParameters];
@@ -702,13 +698,11 @@
   [((id<ApplicationCommands>)[dispatcher expect]) openURLInNewTab:[OCMArg any]];
 
   id currentBVC = [OCMockObject mockForClass:[BrowserViewController class]];
-  stubBrowserState(currentBVC);
   [[[currentBVC stub] andReturn:dispatcher] dispatcher];
 
-  [[[browserViewInformation stub] andReturn:mainTabModel] mainTabModel];
-  [[[browserViewInformation stub] andReturn:mainTabModel] currentTabModel];
-  [[[browserViewInformation stub] andReturn:currentBVC] currentBVC];
-  [[[browserViewInformation stub] andReturn:nil] otrBVC];
+  interfaceProvider.mainInterface.tabModel = mainTabModel;
+  interfaceProvider.mainInterface.bvc = currentBVC;
+  interfaceProvider.mainInterface.browserState = getBrowserState();
 
   // TabOpening.
   id tabOpener = [OCMockObject mockForProtocol:@protocol(TabOpening)];
@@ -719,10 +713,6 @@
   id tabSwitcher = [OCMockObject mockForProtocol:@protocol(TabSwitching)];
   [[[tabSwitcher stub] andReturnValue:@NO] openNewTabFromTabSwitcher];
 
-  id mainBVC = [OCMockObject mockForClass:[BrowserViewController class]];
-  stubBrowserState(mainBVC);
-  [[[browserViewInformation stub] andReturn:mainBVC] mainBVC];
-
   UIWindow* window = [[UIWindow alloc] init];
   AppState* appState = getAppStateWithOpenNTPAndIncognitoBlock(YES, window);
 
@@ -746,7 +736,7 @@
   id application = [OCMockObject mockForClass:[UIApplication class]];
   id metricsMediator = [OCMockObject mockForClass:[MetricsMediator class]];
   id memoryHelper = [OCMockObject mockForClass:[MemoryWarningHelper class]];
-  id browserViewInformation = getBrowserViewInformationMock();
+  StubBrowserInterfaceProvider* interfaceProvider = getInterfaceProvider();
   id tabOpener = [OCMockObject mockForProtocol:@protocol(TabOpening)];
   id appNavigation = [OCMockObject mockForProtocol:@protocol(AppNavigation)];
   id tabModel = [OCMockObject mockForClass:[TabModel class]];
@@ -754,12 +744,13 @@
   BrowserInitializationStageType stage = INITIALIZATION_STAGE_FOREGROUND;
   [[[getBrowserLauncherMock() stub] andReturnValue:@(stage)]
       browserInitializationStage];
-  [[[getBrowserLauncherMock() stub] andReturn:browserViewInformation]
-      browserViewInformation];
-  [[[browserViewInformation stub] andReturn:tabModel] currentTabModel];
+  [[[getBrowserLauncherMock() stub] andReturn:interfaceProvider]
+      interfaceProvider];
   id mainBVC = [OCMockObject mockForClass:[BrowserViewController class]];
-  stubBrowserState(mainBVC);
-  [[[browserViewInformation stub] andReturn:mainBVC] mainBVC];
+  interfaceProvider.mainInterface.tabModel = tabModel;
+  interfaceProvider.mainInterface.bvc = mainBVC;
+  interfaceProvider.mainInterface.browserState = getBrowserState();
+
   [[metricsMediator expect] updateMetricsStateBasedOnPrefsUserTriggered:NO];
   [[memoryHelper expect] resetForegroundMemoryWarningCount];
   [[[memoryHelper stub] andReturnValue:@0] foregroundMemoryWarningCount];
@@ -770,14 +761,12 @@
       OCMClassMock([ContentSuggestionsSchedulerNotifications class]);
   OCMExpect([contentSuggestionsNotifier notifyForeground:getBrowserState()]);
 
-  stubNullCurrentBrowserState(browserViewInformation);
-
   void (^swizzleBlock)() = ^{
   };
 
   ScopedBlockSwizzler swizzler(
       [MetricsMediator class],
-      @selector(logLaunchMetricsWithStartupInformation:browserViewInformation:),
+      @selector(logLaunchMetricsWithStartupInformation:interfaceProvider:),
       swizzleBlock);
 
   // Actions.
@@ -899,7 +888,8 @@
   UIWindow* window = [[UIWindow alloc] init];
   id application = [OCMockObject niceMockForClass:[UIApplication class]];
   id memoryHelper = [OCMockObject mockForClass:[MemoryWarningHelper class]];
-  id browserViewInformation = getBrowserViewInformationMock();
+  StubBrowserInterfaceProvider* interfaceProvider = getInterfaceProvider();
+
   id tabModel = [OCMockObject mockForClass:[TabModel class]];
   id startupInformation = getStartupInformationMock();
   id browserLauncher = getBrowserLauncherMock();
@@ -910,12 +900,9 @@
   [[startupInformation expect] expireFirstUserActionRecorder];
   [[[memoryHelper stub] andReturnValue:@0] foregroundMemoryWarningCount];
   [[[tabModel stub] andReturnValue:@NO] isEmpty];
-  [[[browserViewInformation stub] andReturn:tabModel] otrTabModel];
-  [[[browserViewInformation stub] andReturn:nil] currentBVC];
-  stubNullCurrentBrowserState(browserViewInformation);
+  interfaceProvider.incognitoInterface.tabModel = tabModel;
   [[[browserLauncher stub] andReturnValue:@(stage)] browserInitializationStage];
-  [[[browserLauncher stub] andReturn:browserViewInformation]
-      browserViewInformation];
+  [[[browserLauncher stub] andReturn:interfaceProvider] interfaceProvider];
 
   swizzleMetricsMediatorDisableReporting();
 
@@ -962,7 +949,8 @@
   UIWindow* window = [[UIWindow alloc] init];
   id application = [OCMockObject niceMockForClass:[UIApplication class]];
   id memoryHelper = [OCMockObject mockForClass:[MemoryWarningHelper class]];
-  id browserViewInformation = getBrowserViewInformationMock();
+  StubBrowserInterfaceProvider* interfaceProvider = getInterfaceProvider();
+
   id tabModel = [OCMockObject mockForClass:[TabModel class]];
   id startupInformation = getStartupInformationMock();
   id browserLauncher = getBrowserLauncherMock();
@@ -973,12 +961,9 @@
   [[startupInformation expect] expireFirstUserActionRecorder];
   [[[memoryHelper stub] andReturnValue:@0] foregroundMemoryWarningCount];
   [[[tabModel stub] andReturnValue:@YES] isEmpty];
-  [[[browserViewInformation stub] andReturn:tabModel] otrTabModel];
-  [[[browserViewInformation stub] andReturn:nil] currentBVC];
-  stubNullCurrentBrowserState(browserViewInformation);
+  interfaceProvider.incognitoInterface.tabModel = tabModel;
   [[[browserLauncher stub] andReturnValue:@(stage)] browserInitializationStage];
-  [[[browserLauncher stub] andReturn:browserViewInformation]
-      browserViewInformation];
+  [[[browserLauncher stub] andReturn:interfaceProvider] interfaceProvider];
 
   swizzleMetricsMediatorDisableReporting();
 
diff --git a/ios/chrome/app/application_delegate/browser_launcher.h b/ios/chrome/app/application_delegate/browser_launcher.h
index cbcbab6..6e1be2b 100644
--- a/ios/chrome/app/application_delegate/browser_launcher.h
+++ b/ios/chrome/app/application_delegate/browser_launcher.h
@@ -5,7 +5,7 @@
 #ifndef IOS_CHROME_APP_APPLICATION_DELEGATE_BROWSER_LAUNCHER_H_
 #define IOS_CHROME_APP_APPLICATION_DELEGATE_BROWSER_LAUNCHER_H_
 
-#import "ios/chrome/browser/ui/main/browser_view_information.h"
+#import "ios/chrome/browser/ui/main/browser_interface_provider.h"
 
 // Possible stages of the browser initialization. These states will be reached
 // in sequence, each stage is a requiremant for the following one.
@@ -32,8 +32,7 @@
     BrowserInitializationStageType browserInitializationStage;
 
 // Browser view information created during startup.
-@property(nonatomic, readonly) id<BrowserViewInformation>
-    browserViewInformation;
+@property(nonatomic, readonly) id<BrowserInterfaceProvider> interfaceProvider;
 
 // Initializes the application up to |stage|.
 - (void)startUpBrowserToStage:(BrowserInitializationStageType)stage;
diff --git a/ios/chrome/app/application_delegate/metrics_mediator.h b/ios/chrome/app/application_delegate/metrics_mediator.h
index 6fb6530a9..81e60326 100644
--- a/ios/chrome/app/application_delegate/metrics_mediator.h
+++ b/ios/chrome/app/application_delegate/metrics_mediator.h
@@ -9,7 +9,7 @@
 
 @protocol StartupInformation;
 
-@protocol BrowserViewInformation;
+@protocol BrowserInterfaceProvider;
 @protocol StartupInformation;
 
 namespace metrics_mediator {
@@ -38,8 +38,8 @@
 // Logs the number of tabs open and the start type.
 + (void)logLaunchMetricsWithStartupInformation:
             (id<StartupInformation>)startupInformation
-                        browserViewInformation:
-                            (id<BrowserViewInformation>)browserViewInformation;
+                             interfaceProvider:(id<BrowserInterfaceProvider>)
+                                                   interfaceProvider;
 // Logs in UserDefaults the current date with kAppEnteredBackgroundDateKey as
 // key.
 + (void)logDateInUserDefaults;
diff --git a/ios/chrome/app/application_delegate/metrics_mediator.mm b/ios/chrome/app/application_delegate/metrics_mediator.mm
index 87283879..3346b06 100644
--- a/ios/chrome/app/application_delegate/metrics_mediator.mm
+++ b/ios/chrome/app/application_delegate/metrics_mediator.mm
@@ -24,7 +24,7 @@
 #include "ios/chrome/browser/pref_names.h"
 #import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
-#import "ios/chrome/browser/ui/main/browser_view_information.h"
+#import "ios/chrome/browser/ui/main/browser_interface_provider.h"
 #include "ios/chrome/common/app_group/app_group_metrics_mainapp.h"
 #include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
 #include "ios/public/provider/chrome/browser/distribution/app_distribution_provider.h"
@@ -115,9 +115,10 @@
 
 + (void)logLaunchMetricsWithStartupInformation:
             (id<StartupInformation>)startupInformation
-                        browserViewInformation:
-                            (id<BrowserViewInformation>)browserViewInformation {
-  int numTabs = static_cast<int>([[browserViewInformation mainTabModel] count]);
+                             interfaceProvider:(id<BrowserInterfaceProvider>)
+                                                   interfaceProvider {
+  int numTabs =
+      static_cast<int>(interfaceProvider.mainInterface.tabModel.count);
   if (startupInformation.isColdStart) {
     [self recordNumTabAtStartup:numTabs];
   } else {
@@ -140,7 +141,7 @@
     [startupInformation
         activateFirstUserActionRecorderWithBackgroundTime:interval];
 
-    Tab* currentTab = [[browserViewInformation currentTabModel] currentTab];
+    Tab* currentTab = interfaceProvider.currentInterface.tabModel.currentTab;
     if (currentTab.webState &&
         currentTab.webState->GetLastCommittedURL() == kChromeUINewTabURL) {
       startupInformation.firstUserActionRecorder->RecordStartOnNTP();
diff --git a/ios/chrome/app/application_delegate/metrics_mediator_unittest.mm b/ios/chrome/app/application_delegate/metrics_mediator_unittest.mm
index 27f7ab2..f2b744f 100644
--- a/ios/chrome/app/application_delegate/metrics_mediator_unittest.mm
+++ b/ios/chrome/app/application_delegate/metrics_mediator_unittest.mm
@@ -14,7 +14,9 @@
 #import "ios/chrome/browser/metrics/previous_session_info.h"
 #import "ios/chrome/browser/metrics/previous_session_info_private.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
-#import "ios/chrome/browser/ui/main/browser_view_information.h"
+#import "ios/chrome/browser/ui/main/browser_interface_provider.h"
+#import "ios/chrome/browser/ui/main/test/stub_browser_interface.h"
+#import "ios/chrome/browser/ui/main/test/stub_browser_interface_provider.h"
 #import "ios/chrome/test/base/scoped_block_swizzler.h"
 #import "ios/chrome/test/ocmock/OCMockObject+BreakpadControllerTesting.h"
 #include "net/base/network_change_notifier.h"
@@ -126,9 +128,12 @@
   void initiateMetricsMediator(BOOL coldStart, int tabCount) {
     id mainTabModel = [OCMockObject mockForClass:[TabModel class]];
     [[[mainTabModel stub] andReturnValue:@(tabCount)] count];
-    browser_view_information_ =
-        [OCMockObject mockForProtocol:@protocol(BrowserViewInformation)];
-    [[[browser_view_information_ stub] andReturn:mainTabModel] mainTabModel];
+    [[[mainTabModel stub] andReturn:nil] currentTab];
+
+    StubBrowserInterfaceProvider* concreteProvider =
+        [[StubBrowserInterfaceProvider alloc] init];
+    concreteProvider.mainInterface.tabModel = mainTabModel;
+    interface_provider_ = concreteProvider;
 
     swizzle_block_ = [^(id self, int numTab) {
       has_been_called_ = YES;
@@ -148,10 +153,12 @@
 
   void verifySwizzleHasBeenCalled() { EXPECT_TRUE(has_been_called_); }
 
-  id getBrowserViewInformation() { return browser_view_information_; }
+  id<BrowserInterfaceProvider> getInterfaceProvider() {
+    return interface_provider_;
+  }
 
  private:
-  id browser_view_information_;
+  id<BrowserInterfaceProvider> interface_provider_;
   __block BOOL has_been_called_;
   logLaunchMetricsBlock swizzle_block_;
   std::unique_ptr<ScopedBlockSwizzler> uma_histogram_swizzler_;
@@ -172,12 +179,6 @@
   [[startupInformation expect]
       expireFirstUserActionRecorderAfterDelay:kFirstUserActionTimeout];
 
-  id currentTabModel = [OCMockObject mockForClass:[TabModel class]];
-  [[[currentTabModel stub] andReturn:nil] currentTab];
-
-  id browserViewInformation = getBrowserViewInformation();
-  [[[browserViewInformation stub] andReturn:currentTabModel] currentTabModel];
-
   [[NSUserDefaults standardUserDefaults]
       setObject:[NSDate date]
          forKey:metrics_mediator::kAppEnteredBackgroundDateKey];
@@ -185,7 +186,7 @@
   // Action.
   [MetricsMediator
       logLaunchMetricsWithStartupInformation:startupInformation
-                      browserViewInformation:getBrowserViewInformation()];
+                           interfaceProvider:getInterfaceProvider()];
 
   // Tests.
   NSDate* dateStored = [[NSUserDefaults standardUserDefaults]
@@ -212,7 +213,7 @@
   // Action.
   [MetricsMediator
       logLaunchMetricsWithStartupInformation:startupInformation
-                      browserViewInformation:getBrowserViewInformation()];
+                           interfaceProvider:getInterfaceProvider()];
 
   // Tests.
   verifySwizzleHasBeenCalled();
diff --git a/ios/chrome/app/application_delegate/url_opener_unittest.mm b/ios/chrome/app/application_delegate/url_opener_unittest.mm
index 69724d0c..d7645282 100644
--- a/ios/chrome/app/application_delegate/url_opener_unittest.mm
+++ b/ios/chrome/app/application_delegate/url_opener_unittest.mm
@@ -8,11 +8,13 @@
 
 #include "ios/chrome/app/application_delegate/app_state.h"
 #include "ios/chrome/app/application_delegate/mock_tab_opener.h"
-#include "ios/chrome/app/main_controller.h"
-#import "ios/chrome/app/main_controller_private.h"
+#include "ios/chrome/app/application_delegate/startup_information.h"
 #include "ios/chrome/app/startup/chrome_app_startup_parameters.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
+#import "ios/chrome/browser/ui/main/test/stub_browser_interface.h"
+#import "ios/chrome/browser/ui/main/test/stub_browser_interface_provider.h"
+#import "ios/chrome/browser/web_state_list/web_state_list.h"
 #import "ios/chrome/test/base/scoped_block_swizzler.h"
 #include "ios/web/public/test/test_web_thread_bundle.h"
 #include "testing/gtest_mac.h"
@@ -24,56 +26,53 @@
 #error "This file requires ARC support."
 #endif
 
+@interface StubStartupInformation : NSObject <StartupInformation>
+@end
+@implementation StubStartupInformation
+@synthesize isPresentingFirstRunUI = _isPresentingFirstRunUI;
+@synthesize isColdStart = _isColdStart;
+@synthesize startupParameters = _startupParameters;
+@synthesize appLaunchTime = _appLaunchTime;
+- (FirstUserActionRecorder*)firstUserActionRecorder {
+  return nil;
+}
+
+- (void)resetFirstUserActionRecorder {
+}
+
+- (void)expireFirstUserActionRecorder {
+}
+
+- (void)expireFirstUserActionRecorderAfterDelay:(NSTimeInterval)delay {
+}
+
+- (void)activateFirstUserActionRecorderWithBackgroundTime:
+    (NSTimeInterval)backgroundTime {
+}
+
+- (void)stopChromeMain {
+}
+
+@end
+
 class URLOpenerTest : public PlatformTest {
  protected:
   void TearDown() override {
-    [main_controller_ stopChromeMain];
     PlatformTest::TearDown();
   }
 
-  MainController* GetMainController() {
-    if (!main_controller_) {
-      main_controller_ = [[MainController alloc] init];
-
-      id mainTabModel = [OCMockObject mockForClass:[TabModel class]];
-      [[mainTabModel stub] resetSessionMetrics];
-      [[mainTabModel stub] browserStateDestroyed];
-      [[mainTabModel stub] addObserver:[OCMArg any]];
-      [[mainTabModel stub] removeObserver:[OCMArg any]];
-      [[main_controller_ browserViewInformation] setMainTabModel:mainTabModel];
-
-      id otrTabModel = [OCMockObject mockForClass:[TabModel class]];
-      [[otrTabModel stub] resetSessionMetrics];
-      [[otrTabModel stub] browserStateDestroyed];
-      [[otrTabModel stub] addObserver:[OCMArg any]];
-      [[otrTabModel stub] removeObserver:[OCMArg any]];
-      [[main_controller_ browserViewInformation] setOtrTabModel:otrTabModel];
-      [main_controller_
-          setUpAsForegroundedWithBrowserState:GetChromeBrowserState()];
-    }
-    return main_controller_;
-  }
-
-  ios::ChromeBrowserState* GetChromeBrowserState() {
-    if (!chrome_browser_state_.get()) {
-      TestChromeBrowserState::Builder builder;
-      chrome_browser_state_ = builder.Build();
-    }
-    return chrome_browser_state_.get();
-  }
-
  private:
   web::TestWebThreadBundle thread_bundle_;
-  std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
-  MainController* main_controller_;
 };
 
 TEST_F(URLOpenerTest, HandleOpenURL) {
   // A set of tests for robustness of
   // application:openURL:options:tabOpener:startupInformation:
-  // It verifies that the function handles correctly differents URL parsed by
+  // It verifies that the function handles correctly different URLs parsed by
   // ChromeAppStartupParameters.
-  MainController* controller = GetMainController();
+
+  id<StartupInformation> startupInformation =
+      [[StubStartupInformation alloc] init];
 
   // The array with the different states to tests (active, not active).
   NSArray* applicationStatesToTest = @[ @YES, @NO ];
@@ -84,52 +83,57 @@
   // The keys for this dictionary is the URL to call openURL:. The value
   // from the key is either YES or NO to indicate if this is a valid URL
   // or not.
-  NSNumber* kIsValid = [NSNumber numberWithBool:YES];
-  NSNumber* kNotValid = [NSNumber numberWithBool:NO];
-  NSDictionary* urlsToTest = [NSDictionary
-      dictionaryWithObjectsAndKeys:
-          kNotValid, [NSNull null],
-          // Tests for http, googlechrome, and chromium scheme URLs.
-          kNotValid, @"", kIsValid, @"http://www.google.com/", kIsValid,
-          @"https://www.google.com/settings/account/", kIsValid,
-          @"googlechrome://www.google.com/", kIsValid,
-          @"googlechromes://www.google.com/settings/account/", kIsValid,
-          @"chromium://www.google.com/", kIsValid,
-          @"chromiums://www.google.com/settings/account/",
-          // Google search results page URLs.
-          kIsValid, @"https://www.google.com/search?q=pony&"
-                     "sugexp=chrome,mod=7&sourceid=chrome&ie=UTF-8",
-          kIsValid, @"googlechromes://www.google.com/search?q=pony&"
-                     "sugexp=chrome,mod=7&sourceid=chrome&ie=UTF-8",
-          // Other protocols.
-          kIsValid, @"chromium-x-callback://x-callback-url/open?url=https://"
-                     "www.google.com&x-success=http://success",
-          kIsValid, @"file://localhost/path/to/file.pdf",
-          // Invalid format input URL will be ignored.
-          kNotValid, @"this.is.not.a.valid.url",
-          // Valid format but invalid data.
-          kIsValid, @"this://is/garbage/but/valid", nil];
-  NSArray* sourcesToTest = [NSArray
-      arrayWithObjects:[NSNull null], @"", @"com.google.GoogleMobile",
-                       @"com.google.GooglePlus", @"com.google.SomeOtherProduct",
-                       @"com.apple.mobilesafari",
-                       @"com.othercompany.otherproduct", nil];
+
+  NSDictionary* urlsToTest = @{
+    [NSNull null] : @NO,
+    @"" : @NO,
+    // Tests for http, googlechrome, and chromium scheme URLs.
+    @"http://www.google.com/" : @YES,
+    @"https://www.google.com/settings/account/" : @YES,
+    @"googlechrome://www.google.com/" : @YES,
+    @"googlechromes://www.google.com/settings/account/" : @YES,
+    @"chromium://www.google.com/" : @YES,
+    @"chromiums://www.google.com/settings/account/" : @YES,
+
+    // Google search results page URLs.
+    @"https://www.google.com/search?q=pony&"
+     "sugexp=chrome,mod=7&sourceid=chrome&ie=UTF-8" : @YES,
+    @"googlechromes://www.google.com/search?q=pony&"
+     "sugexp=chrome,mod=7&sourceid=chrome&ie=UTF-8" : @YES,
+
+    // Other protocols.
+    @"chromium-x-callback://x-callback-url/open?url=https://"
+     "www.google.com&x-success=http://success" : @YES,
+    @"file://localhost/path/to/file.pdf" : @YES,
+
+    // Invalid format input URL will be ignored.
+    @"this.is.not.a.valid.url" : @NO,
+
+    // Valid format but invalid data.
+    @"this://is/garbage/but/valid" : @YES
+  };
+
+  NSArray* sourcesToTest = @[
+    [NSNull null], @"", @"com.google.GoogleMobile", @"com.google.GooglePlus",
+    @"com.google.SomeOtherProduct", @"com.apple.mobilesafari",
+    @"com.othercompany.otherproduct"
+  ];
   // See documentation for |annotation| property in
-  // UIDocumentInteractionController Class Reference.  The following values are
-  // mostly to detect garbage-in situations and ensure that the app won't crash
-  // or garbage out.
-  NSArray* annotationsToTest = [NSArray
-      arrayWithObjects:[NSNull null],
-                       [NSArray arrayWithObjects:@"foo", @"bar", nil],
-                       [NSDictionary dictionaryWithObject:@"bar" forKey:@"foo"],
-                       @"a string annotation object", nil];
+  // UIDocumentInteractionstartupInformation Class Reference.  The following
+  // values are mostly to detect garbage-in situations and ensure that the app
+  // won't crash or garbage out.
+  NSArray* annotationsToTest = @[
+    [NSNull null], [NSArray arrayWithObjects:@"foo", @"bar", nil],
+    [NSDictionary dictionaryWithObject:@"bar" forKey:@"foo"],
+    @"a string annotation object"
+  ];
   for (id urlString in [urlsToTest allKeys]) {
     for (id source in sourcesToTest) {
       for (id annotation in annotationsToTest) {
         for (NSNumber* applicationActive in applicationStatesToTest) {
           BOOL applicationIsActive = [applicationActive boolValue];
 
-          controller.startupParameters = nil;
+          startupInformation.startupParameters = nil;
           [tabOpener resetURL];
           NSURL* testUrl = urlString == [NSNull null]
                                ? nil
@@ -153,20 +157,20 @@
                          applicationActive:applicationIsActive
                                    options:options
                                  tabOpener:tabOpener
-                        startupInformation:controller];
+                        startupInformation:startupInformation];
 
           // Tests.
           EXPECT_EQ(isValid, result);
           if (!applicationIsActive) {
             if (result)
               EXPECT_EQ([params externalURL],
-                        controller.startupParameters.externalURL);
+                        startupInformation.startupParameters.externalURL);
             else
-              EXPECT_EQ(nil, controller.startupParameters);
+              EXPECT_EQ(nil, startupInformation.startupParameters);
           } else if (result) {
             EXPECT_EQ([params externalURL], [tabOpener url]);
             tabOpener.completionBlock();
-            EXPECT_EQ(nil, controller.startupParameters);
+            EXPECT_EQ(nil, startupInformation.startupParameters);
           }
         }
       }
diff --git a/ios/chrome/app/application_delegate/user_activity_handler.h b/ios/chrome/app/application_delegate/user_activity_handler.h
index 4cd75d38..94bac7f7 100644
--- a/ios/chrome/app/application_delegate/user_activity_handler.h
+++ b/ios/chrome/app/application_delegate/user_activity_handler.h
@@ -7,7 +7,7 @@
 
 #import <UIKit/UIKit.h>
 
-@protocol BrowserViewInformation;
+@protocol BrowserInterfaceProvider;
 @protocol StartupInformation;
 @protocol TabOpening;
 
@@ -31,8 +31,8 @@
                    completionHandler:(void (^)(BOOL succeeded))completionHandler
                            tabOpener:(id<TabOpening>)tabOpener
                   startupInformation:(id<StartupInformation>)startupInformation
-              browserViewInformation:
-                  (id<BrowserViewInformation>)browserViewInformation;
+                   interfaceProvider:
+                       (id<BrowserInterfaceProvider>)interfaceProvider;
 
 // Returns YES if Chrome is passing a Handoff to itself or if it is an opening
 // from Spotlight.
@@ -42,8 +42,8 @@
 + (void)handleStartupParametersWithTabOpener:(id<TabOpening>)tabOpener
                           startupInformation:
                               (id<StartupInformation>)startupInformation
-                      browserViewInformation:
-                          (id<BrowserViewInformation>)browserViewInformation;
+                           interfaceProvider:
+                               (id<BrowserInterfaceProvider>)interfaceProvider;
 
 @end
 
diff --git a/ios/chrome/app/application_delegate/user_activity_handler.mm b/ios/chrome/app/application_delegate/user_activity_handler.mm
index dba0c30..0982f35 100644
--- a/ios/chrome/app/application_delegate/user_activity_handler.mm
+++ b/ios/chrome/app/application_delegate/user_activity_handler.mm
@@ -26,7 +26,7 @@
 #import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
 #import "ios/chrome/browser/u2f/u2f_controller.h"
-#import "ios/chrome/browser/ui/main/browser_view_information.h"
+#import "ios/chrome/browser/ui/main/browser_interface_provider.h"
 #import "ios/chrome/browser/web/tab_id_tab_helper.h"
 #import "ios/chrome/browser/web_state_list/web_state_list.h"
 #import "net/base/mac/url_conversions.h"
@@ -54,7 +54,7 @@
         startupInformation:(id<StartupInformation>)startupInformation;
 // Routes Universal 2nd Factor (U2F) callback to the correct Tab.
 + (void)routeU2FURL:(const GURL&)URL
-    browserViewInformation:(id<BrowserViewInformation>)browserViewInformation;
+    interfaceProvider:(id<BrowserInterfaceProvider>)interfaceProvider;
 @end
 
 @implementation UserActivityHandler
@@ -199,8 +199,8 @@
                    completionHandler:(void (^)(BOOL succeeded))completionHandler
                            tabOpener:(id<TabOpening>)tabOpener
                   startupInformation:(id<StartupInformation>)startupInformation
-              browserViewInformation:
-                  (id<BrowserViewInformation>)browserViewInformation {
+                   interfaceProvider:
+                       (id<BrowserInterfaceProvider>)interfaceProvider {
   BOOL handledShortcutItem =
       [UserActivityHandler handleShortcutItem:shortcutItem
                            startupInformation:startupInformation];
@@ -208,7 +208,7 @@
     [UserActivityHandler
         handleStartupParametersWithTabOpener:tabOpener
                           startupInformation:startupInformation
-                      browserViewInformation:browserViewInformation];
+                           interfaceProvider:interfaceProvider];
   }
   completionHandler(handledShortcutItem);
 }
@@ -223,8 +223,8 @@
 + (void)handleStartupParametersWithTabOpener:(id<TabOpening>)tabOpener
                           startupInformation:
                               (id<StartupInformation>)startupInformation
-                      browserViewInformation:
-                          (id<BrowserViewInformation>)browserViewInformation {
+                           interfaceProvider:
+                               (id<BrowserInterfaceProvider>)interfaceProvider {
   DCHECK([startupInformation startupParameters]);
   // Do not load the external URL if the user has not accepted the terms of
   // service. This corresponds to the case when the user installed Chrome,
@@ -236,9 +236,9 @@
   // If not, open or reuse tab in main BVC.
   if ([U2FController
           isU2FURL:[[startupInformation startupParameters] externalURL]]) {
-    [UserActivityHandler routeU2FURL:[[startupInformation startupParameters]
-                                         externalURL]
-              browserViewInformation:browserViewInformation];
+    [UserActivityHandler
+              routeU2FURL:[[startupInformation startupParameters] externalURL]
+        interfaceProvider:interfaceProvider];
     // It's OK to clear startup parameters here because routeU2FURL works
     // synchronously.
     [startupInformation setStartupParameters:nil];
@@ -316,7 +316,7 @@
 }
 
 + (void)routeU2FURL:(const GURL&)URL
-    browserViewInformation:(id<BrowserViewInformation>)browserViewInformation {
+    interfaceProvider:(id<BrowserInterfaceProvider>)interfaceProvider {
   // Retrieve the designated TabID from U2F URL.
   NSString* tabID = [U2FController tabIDFromResponseURL:URL];
   if (!tabID) {
@@ -325,7 +325,8 @@
 
   // Iterate through mainTabModel and OTRTabModel to find the corresponding tab.
   NSArray* tabModels = @[
-    [browserViewInformation mainTabModel], [browserViewInformation otrTabModel]
+    interfaceProvider.mainInterface.tabModel,
+    interfaceProvider.incognitoInterface.tabModel
   ];
   for (TabModel* tabModel in tabModels) {
     WebStateList* webStateList = tabModel.webStateList;
diff --git a/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm b/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm
index 3f6cdb6..e5781ee 100644
--- a/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm
+++ b/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm
@@ -29,6 +29,7 @@
 #import "ios/chrome/browser/tabs/tab_model.h"
 #import "ios/chrome/browser/tabs/tab_model_observer.h"
 #import "ios/chrome/browser/u2f/u2f_controller.h"
+#import "ios/chrome/browser/ui/main/test/stub_browser_interface_provider.h"
 #import "ios/chrome/browser/web/tab_id_tab_helper.h"
 #import "ios/chrome/browser/web_state_list/fake_web_state_list_delegate.h"
 #import "ios/chrome/browser/web_state_list/web_state_list.h"
@@ -135,7 +136,7 @@
 typedef void (^startupParameterBlock)(id,
                                       id<TabOpening>,
                                       id<StartupInformation>,
-                                      id<BrowserViewInformation>);
+                                      id<BrowserInterfaceProvider>);
 
 // A block that takes a BOOL argument and returns nothing.
 typedef void (^conditionBlock)(BOOL);
@@ -150,8 +151,7 @@
     user_activity_handler_swizzler_.reset(new ScopedBlockSwizzler(
         [UserActivityHandler class],
         @selector(handleStartupParametersWithTabOpener:
-                                    startupInformation:
-                                browserViewInformation:),
+                                    startupInformation:interfaceProvider:),
         swizzle_block_));
   }
 
@@ -497,14 +497,14 @@
   MockTabOpener* tabOpener = [[MockTabOpener alloc] init];
 
   // The test will fail is a method of this object is called.
-  id browserViewMock =
-      [OCMockObject mockForProtocol:@protocol(BrowserViewInformation)];
+  id interfaceProviderMock =
+      [OCMockObject mockForProtocol:@protocol(BrowserInterfaceProvider)];
 
   // Action.
   [UserActivityHandler
       handleStartupParametersWithTabOpener:tabOpener
                         startupInformation:startupInformationMock
-                    browserViewInformation:browserViewMock];
+                         interfaceProvider:interfaceProviderMock];
   [tabOpener completionBlock]();
 
   // Tests.
@@ -516,9 +516,10 @@
 // Tests that handleStartupParameters with a U2F url opens in the correct tab.
 TEST_F(UserActivityHandlerNoFixtureTest, handleStartupParamsU2F) {
   // Setup.
-  UserActivityHandlerTabModelMock* tabModel =
+  UserActivityHandlerTabModelMock* mockTabModel =
       [[UserActivityHandlerTabModelMock alloc] init];
-  UserActivityHandlerTabMock* tabMock = [tabModel addMockTab];
+  UserActivityHandlerTabMock* tabMock = [mockTabModel addMockTab];
+  id tabModel = static_cast<id>(mockTabModel);
 
   std::string urlRepresentation =
       base::StringPrintf("chromium://u2f-callback?isU2F=1&tabID=%s",
@@ -535,12 +536,10 @@
   [[[startupInformationMock stub] andReturn:startupParams] startupParameters];
   [[startupInformationMock expect] setStartupParameters:nil];
 
-  id browserViewInformationMock =
-      [OCMockObject mockForProtocol:@protocol(BrowserViewInformation)];
-  [[[browserViewInformationMock stub] andReturn:(TabModel*)tabModel]
-      mainTabModel];
-  [[[browserViewInformationMock stub] andReturn:(TabModel*)tabModel]
-      otrTabModel];
+  StubBrowserInterfaceProvider* interfaceProvider =
+      [[StubBrowserInterfaceProvider alloc] init];
+  interfaceProvider.mainInterface.tabModel = tabModel;
+  interfaceProvider.incognitoInterface.tabModel = tabModel;
 
   MockTabOpener* tabOpener = [[MockTabOpener alloc] init];
 
@@ -548,7 +547,7 @@
   [UserActivityHandler
       handleStartupParametersWithTabOpener:tabOpener
                         startupInformation:startupInformationMock
-                    browserViewInformation:browserViewInformationMock];
+                         interfaceProvider:interfaceProvider];
 
   // Tests.
   EXPECT_OCMOCK_VERIFY(startupInformationMock);
@@ -583,16 +582,15 @@
 
     // The test will fail is a method of those objects is called.
     id tabOpenerMock = [OCMockObject mockForProtocol:@protocol(TabOpening)];
-    id browserViewInformationMock =
-        [OCMockObject mockForProtocol:@protocol(BrowserViewInformation)];
+    id interfaceProviderMock =
+        [OCMockObject mockForProtocol:@protocol(BrowserInterfaceProvider)];
 
     // Action.
-    [UserActivityHandler
-        performActionForShortcutItem:shortcut
-                   completionHandler:getCompletionHandler()
-                           tabOpener:tabOpenerMock
-                  startupInformation:fakeStartupInformation
-              browserViewInformation:browserViewInformationMock];
+    [UserActivityHandler performActionForShortcutItem:shortcut
+                                    completionHandler:getCompletionHandler()
+                                            tabOpener:tabOpenerMock
+                                   startupInformation:fakeStartupInformation
+                                    interfaceProvider:interfaceProviderMock];
 
     // Tests.
     EXPECT_EQ(gurlNewTab,
@@ -623,15 +621,15 @@
 
   // The test will fail is a method of those objects is called.
   id tabOpenerMock = [OCMockObject mockForProtocol:@protocol(TabOpening)];
-  id browserViewInformationMock =
-      [OCMockObject mockForProtocol:@protocol(BrowserViewInformation)];
+  id interfaceProviderMock =
+      [OCMockObject mockForProtocol:@protocol(BrowserInterfaceProvider)];
 
   // Action.
   [UserActivityHandler performActionForShortcutItem:shortcut
                                   completionHandler:getCompletionHandler()
                                           tabOpener:tabOpenerMock
                                  startupInformation:startupInformationMock
-                             browserViewInformation:browserViewInformationMock];
+                                  interfaceProvider:interfaceProviderMock];
 
   // Tests.
   EXPECT_TRUE(completionHandlerExecuted());
diff --git a/ios/chrome/app/main_application_delegate.mm b/ios/chrome/app/main_application_delegate.mm
index 5b43293..537c166 100644
--- a/ios/chrome/app/main_application_delegate.mm
+++ b/ios/chrome/app/main_application_delegate.mm
@@ -204,7 +204,7 @@
                  completionHandler:completionHandler
                          tabOpener:_tabOpener
                 startupInformation:_startupInformation
-            browserViewInformation:[_mainController browserViewInformation]];
+                 interfaceProvider:_mainController.interfaceProvider];
 }
 
 #pragma mark Opening a URL-Specified Resource
diff --git a/ios/chrome/app/main_controller.h b/ios/chrome/app/main_controller.h
index 4a7d8509..d300dc6 100644
--- a/ios/chrome/app/main_controller.h
+++ b/ios/chrome/app/main_controller.h
@@ -13,7 +13,6 @@
 #import "ios/chrome/app/application_delegate/tab_opening.h"
 #import "ios/chrome/app/application_delegate/tab_switching.h"
 #import "ios/chrome/browser/ui/commands/application_commands.h"
-#import "ios/chrome/browser/ui/main/browser_view_information.h"
 
 @class AppState;
 @class MetricsMediator;
@@ -31,10 +30,6 @@
                                      TabOpening,
                                      TabSwitching>
 
-// A BrowserViewInformation object to perform BrowserViewController operations.
-@property(weak, nonatomic, readonly) id<BrowserViewInformation>
-    browserViewInformation;
-
 // The application window.
 @property(nonatomic, strong) UIWindow* window;
 
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm
index 2d68f42e..d2009c96 100644
--- a/ios/chrome/app/main_controller.mm
+++ b/ios/chrome/app/main_controller.mm
@@ -397,10 +397,6 @@
   StartupTasks* _startupTasks;
 }
 
-// Redefined from BrowserViewInformation.
-@property(nonatomic, weak, readwrite)
-    BrowserCoordinator* currentBrowserCoordinator;
-
 // The main coordinator, lazily created the first time it is accessed. Manages
 // the main view controller. This property should not be accessed before the
 // browser has started up to the FOREGROUND stage.
@@ -559,20 +555,21 @@
 
 @implementation MainController
 
-@synthesize mainCoordinator = _mainCoordinator;
-@synthesize appState = _appState;
-@synthesize appLaunchTime = _appLaunchTime;
+// Defined by public protocols.
+// - AppNavigation
+@synthesize settingsNavigationController = _settingsNavigationController;
+// - BrowserLauncher
+@synthesize launchOptions = _launchOptions;
 @synthesize browserInitializationStage = _browserInitializationStage;
-@synthesize window = _window;
+// - StartupInformation
 @synthesize isPresentingFirstRunUI = _isPresentingFirstRunUI;
 @synthesize isColdStart = _isColdStart;
+@synthesize startupParameters = _startupParameters;
+@synthesize appLaunchTime = _appLaunchTime;
+// Defined in private interface
+@synthesize mainCoordinator = _mainCoordinator;
 @synthesize NTPActionAfterTabSwitcherDismissal =
     _NTPActionAfterTabSwitcherDismissal;
-@synthesize launchOptions = _launchOptions;
-@synthesize startupParameters = _startupParameters;
-@synthesize metricsMediator = _metricsMediator;
-@synthesize incognitoContentVisible = _incognitoContentVisible;
-@synthesize settingsNavigationController = _settingsNavigationController;
 @synthesize signinInteractionCoordinator = _signinInteractionCoordinator;
 
 #pragma mark - Application lifecycle
@@ -718,7 +715,8 @@
   _browserViewWrangler =
       [[BrowserViewWrangler alloc] initWithBrowserState:_mainBrowserState
                                        tabModelObserver:self
-                             applicationCommandEndpoint:self];
+                             applicationCommandEndpoint:self
+                                        storageSwitcher:self];
 
   // Force an obvious initialization of the AuthenticationService. This must
   // be done before creation of the UI to ensure the service is initialised
@@ -736,7 +734,7 @@
       ->NotifyEvent(feature_engagement::events::kChromeOpened);
 
   // Ensure the main tab model is created.
-  ignore_result([_browserViewWrangler mainTabModel]);
+  [_browserViewWrangler createMainTabModel];
 
   _spotlightManager =
       [SpotlightManager spotlightManagerWithBrowserState:_mainBrowserState];
@@ -770,8 +768,9 @@
                                           : ApplicationMode::NORMAL)];
 
   [self scheduleStartupCleanupTasks];
-  [MetricsMediator logLaunchMetricsWithStartupInformation:self
-                                   browserViewInformation:_browserViewWrangler];
+  [MetricsMediator
+      logLaunchMetricsWithStartupInformation:self
+                           interfaceProvider:self.interfaceProvider];
   if (self.isColdStart) {
     [ContentSuggestionsSchedulerNotifications
         notifyColdStart:_mainBrowserState];
@@ -886,14 +885,14 @@
   if (browsingDataRemover && browsingDataRemover->IsRemoving())
     return;
 
-  [self.mainBrowserCoordinator setActive:YES];
-  [self.incognitoBrowserCoordinator setActive:YES];
+  self.interfaceProvider.mainInterface.userInteractionEnabled = YES;
+  self.interfaceProvider.incognitoInterface.userInteractionEnabled = YES;
   [self.currentBVC setPrimary:YES];
 }
 
 #pragma mark - Property implementation.
 
-- (id<BrowserViewInformation>)browserViewInformation {
+- (id<BrowserInterfaceProvider>)interfaceProvider {
   return _browserViewWrangler;
 }
 
@@ -968,16 +967,6 @@
   return _tabSwitcherIsActive;
 }
 
-#pragma mark - BrowserViewInformation implementation.
-
-- (void)haltAllTabs {
-  [_browserViewWrangler haltAllTabs];
-}
-
-- (void)cleanDeviceSharingManager {
-  [_browserViewWrangler cleanDeviceSharingManager];
-}
-
 #pragma mark - Startup tasks
 
 - (void)sendQueuedFeedback {
@@ -1280,10 +1269,10 @@
   TabModel* tabModel;
   if (launchMode == ApplicationMode::INCOGNITO) {
     tabModel = otrTabModel;
-    self.currentBrowserCoordinator = self.incognitoBrowserCoordinator;
+    [self setCurrentInterfaceForMode:ApplicationMode::INCOGNITO];
   } else {
     tabModel = mainTabModel;
-    self.currentBrowserCoordinator = self.mainBrowserCoordinator;
+    [self setCurrentInterfaceForMode:ApplicationMode::NORMAL];
   }
   if (_tabSwitcherIsActive) {
     DCHECK(!_dismissingTabSwitcher);
@@ -1485,13 +1474,11 @@
                                        transition:ui::PAGE_TRANSITION_TYPED
                                        completion:nil];
     } else {
+      ApplicationMode mode = command.inIncognito ? ApplicationMode::INCOGNITO
+                                                 : ApplicationMode::NORMAL;
       [self
           dismissModalDialogsWithCompletion:^{
-            self.currentBrowserCoordinator =
-                [command inIncognito] ? self.incognitoBrowserCoordinator
-                                      : self.mainBrowserCoordinator;
-            DCHECK(self.currentBVC.browserState->IsOffTheRecord() ==
-                   command.inIncognito);
+            [self setCurrentInterfaceForMode:mode];
             [self.currentBVC webPageOrderedOpen:command];
           }
                              dismissOmnibox:YES];
@@ -1752,65 +1739,49 @@
   }
 }
 
-#pragma mark - BrowserViewInformation properties
+#pragma mark - Helper methods backed by interfaces.
 
 - (BrowserViewController*)mainBVC {
-  DCHECK(_browserViewWrangler);
-  return [_browserViewWrangler mainBVC];
+  DCHECK(self.interfaceProvider);
+  return self.interfaceProvider.mainInterface.bvc;
 }
 
 - (TabModel*)mainTabModel {
-  DCHECK(_browserViewWrangler);
-  return [_browserViewWrangler mainTabModel];
-}
-
-- (void)setMainTabModel:(TabModel*)mainTabModel {
-  DCHECK(_browserViewWrangler);
-  [_browserViewWrangler setMainTabModel:mainTabModel];
+  DCHECK(self.interfaceProvider);
+  return self.interfaceProvider.mainInterface.tabModel;
 }
 
 - (BrowserViewController*)otrBVC {
-  DCHECK(_browserViewWrangler);
-  return [_browserViewWrangler otrBVC];
+  DCHECK(self.interfaceProvider);
+  return self.interfaceProvider.incognitoInterface.bvc;
 }
 
 - (TabModel*)otrTabModel {
-  DCHECK(_browserViewWrangler);
-  return [_browserViewWrangler otrTabModel];
-}
-
-- (void)setOtrTabModel:(TabModel*)otrTabModel {
-  DCHECK(_browserViewWrangler);
-  [_browserViewWrangler setOtrTabModel:otrTabModel];
+  DCHECK(self.interfaceProvider);
+  return self.interfaceProvider.incognitoInterface.tabModel;
 }
 
 - (BrowserViewController*)currentBVC {
-  DCHECK(_browserViewWrangler);
-  return [_browserViewWrangler currentBVC];
-}
-
-- (BrowserCoordinator*)mainBrowserCoordinator {
-  DCHECK(_browserViewWrangler);
-  return _browserViewWrangler.mainBrowserCoordinator;
-}
-
-- (BrowserCoordinator*)incognitoBrowserCoordinator {
-  DCHECK(_browserViewWrangler);
-  return _browserViewWrangler.incognitoBrowserCoordinator;
+  DCHECK(self.interfaceProvider);
+  return self.interfaceProvider.currentInterface.bvc;
 }
 
 // Note that the current tab of |browserCoordinator|'s BVC will normally be
 // reloaded by this method. If a new tab is about to be added, call
 // expectNewForegroundTab on the BVC first to avoid extra work and possible page
 // load side-effects for the tab being replaced.
-- (void)setCurrentBrowserCoordinator:(BrowserCoordinator*)browserCoordinator {
-  DCHECK(browserCoordinator);
-  if (self.currentBrowserCoordinator == browserCoordinator)
+- (void)setCurrentInterfaceForMode:(ApplicationMode)mode {
+  DCHECK(self.interfaceProvider);
+  BOOL incognitio = mode == ApplicationMode::INCOGNITO;
+  id<BrowserInterface> currentInterface =
+      self.interfaceProvider.currentInterface;
+  id<BrowserInterface> newInterface =
+      incognitio ? self.interfaceProvider.incognitoInterface
+                 : self.interfaceProvider.mainInterface;
+  if (currentInterface && currentInterface == newInterface)
     return;
 
-  DCHECK(_browserViewWrangler);
-  [_browserViewWrangler setCurrentBrowserCoordinator:browserCoordinator
-                                     storageSwitcher:self];
+  self.interfaceProvider.currentInterface = newInterface;
 
   if (!_dismissingTabSwitcher)
     [self displayCurrentBVCAndFocusOmnibox:NO];
@@ -1819,11 +1790,6 @@
   [self activateBVCAndMakeCurrentBVCPrimary];
 }
 
-- (BrowserCoordinator*)currentBrowserCoordinator {
-  DCHECK(_browserViewWrangler);
-  return _browserViewWrangler.currentBrowserCoordinator;
-}
-
 #pragma mark - Tab closure handlers
 
 - (void)lastIncognitoTabClosed {
@@ -1857,7 +1823,7 @@
   if ([self.currentTabModel count] == 0U) {
     [self showTabSwitcher];
   } else {
-    self.currentBrowserCoordinator = self.mainBrowserCoordinator;
+    [self setCurrentInterfaceForMode:ApplicationMode::NORMAL];
   }
 }
 
@@ -1878,12 +1844,14 @@
 #pragma mark - Mode Switching
 
 - (void)switchModesAndOpenNewTab:(OpenNewTabCommand*)command {
-  BrowserCoordinator* browserCoordinator =
-      command.inIncognito ? self.incognitoBrowserCoordinator
-                          : self.mainBrowserCoordinator;
-  DCHECK(browserCoordinator);
-  [browserCoordinator.viewController expectNewForegroundTab];
-  self.currentBrowserCoordinator = browserCoordinator;
+  id<BrowserInterface> interface =
+      command.inIncognito ? self.interfaceProvider.incognitoInterface
+                          : self.interfaceProvider.mainInterface;
+  DCHECK(interface);
+  [interface.bvc expectNewForegroundTab];
+  [self setCurrentInterfaceForMode:command.inIncognito
+                                       ? ApplicationMode::INCOGNITO
+                                       : ApplicationMode::NORMAL];
   [self openURLInNewTab:command];
 }
 
@@ -2053,10 +2021,10 @@
   DCHECK(tabModel == self.mainTabModel || tabModel == self.otrTabModel);
 
   _dismissingTabSwitcher = YES;
-  BrowserCoordinator* targetBrowserCoordinator =
-      (tabModel == self.mainTabModel) ? self.mainBrowserCoordinator
-                                      : self.incognitoBrowserCoordinator;
-  self.currentBrowserCoordinator = targetBrowserCoordinator;
+  ApplicationMode mode = (tabModel == self.mainTabModel)
+                             ? ApplicationMode::NORMAL
+                             : ApplicationMode::INCOGNITO;
+  [self setCurrentInterfaceForMode:mode];
 
   // The call to set currentBVC above does not actually display the BVC, because
   // _dismissingTabSwitcher is YES.  So: Force the BVC transition to start.
@@ -2071,10 +2039,10 @@
 
   if (_modeToDisplayOnTabSwitcherDismissal ==
       TabSwitcherDismissalMode::NORMAL) {
-    self.currentBrowserCoordinator = self.mainBrowserCoordinator;
+    [self setCurrentInterfaceForMode:ApplicationMode::NORMAL];
   } else if (_modeToDisplayOnTabSwitcherDismissal ==
              TabSwitcherDismissalMode::INCOGNITO) {
-    self.currentBrowserCoordinator = self.incognitoBrowserCoordinator;
+    [self setCurrentInterfaceForMode:ApplicationMode::INCOGNITO];
   }
 
   _modeToDisplayOnTabSwitcherDismissal = TabSwitcherDismissalMode::NONE;
@@ -2111,8 +2079,8 @@
       // Disables browsing and purges web views.
       // Must be called only on the main thread.
       DCHECK([NSThread isMainThread]);
-      [self.mainBrowserCoordinator setActive:NO];
-      [self.incognitoBrowserCoordinator setActive:NO];
+      self.interfaceProvider.mainInterface.userInteractionEnabled = NO;
+      self.interfaceProvider.incognitoInterface.userInteractionEnabled = NO;
     }
 
     BrowsingDataRemoverFactory::GetForBrowserState(browserState)
@@ -2120,8 +2088,10 @@
                    // Activates browsing and enables web views.
                    // Must be called only on the main thread.
                    DCHECK([NSThread isMainThread]);
-                   [self.mainBrowserCoordinator setActive:YES];
-                   [self.incognitoBrowserCoordinator setActive:YES];
+                   self.interfaceProvider.mainInterface.userInteractionEnabled =
+                       YES;
+                   self.interfaceProvider.incognitoInterface
+                       .userInteractionEnabled = YES;
                    [self.currentBVC setPrimary:YES];
 
                    if (completionBlock)
@@ -2271,11 +2241,11 @@
                       withURL:(const GURL&)url
                    transition:(ui::PageTransition)transition
                    completion:(ProceduralBlock)completion {
-  BrowserCoordinator* targetBrowserCoordinator =
-      targetMode == ApplicationMode::NORMAL ? self.mainBrowserCoordinator
-                                            : self.incognitoBrowserCoordinator;
-  TabModel* targetTabModel = targetBrowserCoordinator.tabModel;
-  NSUInteger tabIndex = targetTabModel.count;
+  id<BrowserInterface> targetInterface =
+      targetMode == ApplicationMode::NORMAL
+          ? self.interfaceProvider.mainInterface
+          : self.interfaceProvider.incognitoInterface;
+  NSUInteger tabIndex = NSNotFound;
   ProceduralBlock startupCompletion =
       [self completionBlockForTriggeringAction:[_startupParameters
                                                    postOpeningAction]];
@@ -2306,9 +2276,8 @@
           targetMode == ApplicationMode::NORMAL
               ? TabSwitcherDismissalMode::NORMAL
               : TabSwitcherDismissalMode::INCOGNITO;
-      [targetBrowserCoordinator.viewController
-          appendTabAddedCompletion:tabOpenedCompletion];
-      tab = [targetTabModel
+      [targetInterface.bvc appendTabAddedCompletion:tabOpenedCompletion];
+      tab = [targetInterface.tabModel
           insertTabWithLoadParams:CreateWebLoadParams(url, transition,
                                                       /*post_data=*/nullptr)
                            opener:nil
@@ -2321,16 +2290,17 @@
       self.NTPActionAfterTabSwitcherDismissal =
           [_startupParameters postOpeningAction];
       [self setStartupParameters:nil];
-      tab = [_tabSwitcher dismissWithNewTabAnimationToModel:targetTabModel
-                                                    withURL:url
-                                                    atIndex:tabIndex
-                                                 transition:transition];
+      tab = [_tabSwitcher
+          dismissWithNewTabAnimationToModel:targetInterface.tabModel
+                                    withURL:url
+                                    atIndex:tabIndex
+                                 transition:transition];
     }
   } else {
     if (!self.currentBVC.presentedViewController) {
-      [targetBrowserCoordinator.viewController expectNewForegroundTab];
+      [targetInterface.bvc expectNewForegroundTab];
     }
-    self.currentBrowserCoordinator = targetBrowserCoordinator;
+    [self setCurrentInterfaceForMode:targetMode];
     tab = [self openOrReuseTabInMode:targetMode
                              withURL:url
                           transition:transition
@@ -2376,7 +2346,7 @@
     DCHECK(self.currentBVC);
     DCHECK(![self isTabSwitcherActive]);
     // This will dismiss the SSO view controller.
-    [self.currentBrowserCoordinator
+    [self.interfaceProvider.currentInterface
         clearPresentedStateWithCompletion:completion
                            dismissOmnibox:dismissOmnibox];
   };
@@ -2639,23 +2609,4 @@
                      fromSourceApplication:sourceApplication];
 }
 
-- (void)setUpAsForegroundedWithBrowserState:
-    (ios::ChromeBrowserState*)browserState {
-  _isColdStart = NO;
-  _browserInitializationStage = INITIALIZATION_STAGE_FOREGROUND;
-  // Create a BrowserViewWrangler with a null browser state. This will trigger
-  // assertions if the BrowserViewWrangler is asked to create any BVC or
-  // tabModel objects, but it will accept assignments to them.
-  [_browserViewWrangler shutdown];
-  _browserViewWrangler =
-      [[BrowserViewWrangler alloc] initWithBrowserState:browserState
-                                       tabModelObserver:self
-                             applicationCommandEndpoint:self];
-  // This is a test utility method that bypasses the ususal setup steps, so
-  // verify that the main coordinator hasn't been created yet, then start it
-  // via lazy initialization.
-  DCHECK(!_mainCoordinator);
-  [self.mainCoordinator start];
-}
-
 @end
diff --git a/ios/chrome/app/main_controller_private.h b/ios/chrome/app/main_controller_private.h
index eb90b82d..a26d4d3f 100644
--- a/ios/chrome/app/main_controller_private.h
+++ b/ios/chrome/app/main_controller_private.h
@@ -11,18 +11,10 @@
 #import "ios/chrome/app/main_controller.h"
 #include "ios/chrome/browser/browsing_data/browsing_data_remove_mask.h"
 
-@class BrowserViewController;
 @class DeviceSharingManager;
 class GURL;
-@class SettingsNavigationController;
-@class SigninInteractionController;
-@class TabModel;
 @protocol TabSwitcher;
 
-namespace ios {
-class ChromeBrowserState;
-}
-
 // Private methods and protocols that are made visible here for tests.
 @interface MainController ()
 
@@ -56,10 +48,6 @@
 // by an external app opening the given URL.
 - (void)setStartupParametersWithURL:(const GURL&)launchURL;
 
-// Sets the internal state to indicate that the app has been foregrounded.
-- (void)setUpAsForegroundedWithBrowserState:
-    (ios::ChromeBrowserState*)browserState;
-
 @end
 
 #endif  // IOS_CHROME_APP_MAIN_CONTROLLER_PRIVATE_H_
diff --git a/ios/chrome/app/startup_tasks.mm b/ios/chrome/app/startup_tasks.mm
index e7eace2..47a63ce2 100644
--- a/ios/chrome/app/startup_tasks.mm
+++ b/ios/chrome/app/startup_tasks.mm
@@ -18,7 +18,6 @@
 #import "ios/chrome/browser/omaha/omaha_service.h"
 #include "ios/chrome/browser/reading_list/reading_list_download_service.h"
 #include "ios/chrome/browser/reading_list/reading_list_download_service_factory.h"
-#import "ios/chrome/browser/ui/main/browser_view_information.h"
 #import "ios/chrome/browser/upgrade/upgrade_center.h"
 #include "ios/chrome/grit/ios_strings.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index 5352907..cb70306 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -204,6 +204,9 @@
       <message name="IDS_IOS_SHOW_ALL_PASSWORDS" desc="Button title in the keyboard accessory bar to open the list of all saved passwords. [Length: 20em] [iOS only]">
         Show All...
       </message>
+      <message name="IDS_IOS_SUGGEST_PASSWORD" desc="Button title in the keyboard accessory bar to show a dialog with a generated password. [Length: 20em] [iOS only]">
+        Suggest  Password...
+      </message>
       <message name="IDS_IOS_APPLICATION_SHORTCUT_NEWINCOGNITOTAB_TITLE" desc="Message when opening a New Incognito Tab from springboard force touch static shortcuts. [Length: unlimited] [iOS only]." meaning="3D Touch entry to create a new Incognito tab.">
         New Incognito Tab
       </message>
diff --git a/ios/chrome/browser/DEPS b/ios/chrome/browser/DEPS
index 0f2369a1..ba931980 100644
--- a/ios/chrome/browser/DEPS
+++ b/ios/chrome/browser/DEPS
@@ -26,6 +26,7 @@
   "+components/google/core",
   "+components/handoff",
   "+components/history/core/browser",
+  "+components/history/core/common",
   "+components/history/ios/browser",
   "+components/image_fetcher/core",
   "+components/image_fetcher/ios",
diff --git a/ios/chrome/browser/metrics/tab_usage_recorder_test_util.mm b/ios/chrome/browser/metrics/tab_usage_recorder_test_util.mm
index 49a4f40..060c56e 100644
--- a/ios/chrome/browser/metrics/tab_usage_recorder_test_util.mm
+++ b/ios/chrome/browser/metrics/tab_usage_recorder_test_util.mm
@@ -10,7 +10,7 @@
 #import "base/test/ios/wait_util.h"
 #import "ios/chrome/app/main_controller.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
-#import "ios/chrome/browser/ui/main/browser_view_information.h"
+#import "ios/chrome/browser/ui/main/browser_interface_provider.h"
 #import "ios/chrome/browser/ui/popup_menu/popup_menu_constants.h"
 #include "ios/chrome/browser/ui/tab_grid/tab_grid_egtest_util.h"
 #include "ios/chrome/browser/ui/util/ui_util.h"
@@ -82,8 +82,8 @@
   ShowTabSwitcher();
 
   // Switch modes and exit the tab grid.
-  TabModel* model = [[chrome_test_util::GetMainController()
-      browserViewInformation] mainTabModel];
+  TabModel* model = chrome_test_util::GetMainController()
+                        .interfaceProvider.mainInterface.tabModel;
   const int tab_index = model.webStateList->active_index();
   [[EarlGrey
       selectElementWithMatcher:chrome_test_util::TabGridOpenTabsPanelButton()]
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_driver.h b/ios/chrome/browser/passwords/ios_chrome_password_manager_driver.h
index acc253b..80ee5eb 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_manager_driver.h
+++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_driver.h
@@ -18,6 +18,7 @@
 namespace password_manager {
 class PasswordAutofillManager;
 class PasswordManager;
+class PasswordGenerationManager;
 }  // namespace password_manager
 
 // Defines the interface the driver needs to the controller.
@@ -34,6 +35,14 @@
 
 // Informs delegate that there are no saved credentials for the current page.
 - (void)onNoSavedCredentials;
+
+// Gets the PasswordGenerationManager owned by this delegate.
+- (password_manager::PasswordGenerationManager*)passwordGenerationManager;
+
+// Informs delegate of form for password generation found.
+- (void)formEligibleForGenerationFound:
+    (const autofill::NewPasswordFormGenerationData&)form;
+
 @end
 
 // An iOS implementation of password_manager::PasswordManagerDriver.
@@ -52,6 +61,8 @@
       const autofill::PasswordForm& form) override;
   void FormsEligibleForGenerationFound(
       const std::vector<autofill::PasswordFormGenerationData>& forms) override;
+  void FormEligibleForGenerationFound(
+      const autofill::NewPasswordFormGenerationData& form) override;
   void GeneratedPasswordAccepted(const base::string16& password) override;
   void FillSuggestion(const base::string16& username,
                       const base::string16& password) override;
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_driver.mm b/ios/chrome/browser/passwords/ios_chrome_password_manager_driver.mm
index 2a5e1bd..0c0dd46 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_manager_driver.mm
+++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_driver.mm
@@ -33,8 +33,11 @@
 }
 
 void IOSChromePasswordManagerDriver::FormsEligibleForGenerationFound(
-    const std::vector<autofill::PasswordFormGenerationData>& forms) {
-  // TODO(crbug.com/569579): Implement.
+    const std::vector<autofill::PasswordFormGenerationData>& forms) {}
+
+void IOSChromePasswordManagerDriver::FormEligibleForGenerationFound(
+    const autofill::NewPasswordFormGenerationData& form) {
+  [delegate_ formEligibleForGenerationFound:form];
 }
 
 void IOSChromePasswordManagerDriver::GeneratedPasswordAccepted(
@@ -66,7 +69,7 @@
 
 PasswordGenerationManager*
 IOSChromePasswordManagerDriver::GetPasswordGenerationManager() {
-  return nullptr;
+  return [delegate_ passwordGenerationManager];
 }
 
 PasswordManager* IOSChromePasswordManagerDriver::GetPasswordManager() {
diff --git a/ios/chrome/browser/passwords/password_controller.mm b/ios/chrome/browser/passwords/password_controller.mm
index 902e885b..4d0d565 100644
--- a/ios/chrome/browser/passwords/password_controller.mm
+++ b/ios/chrome/browser/passwords/password_controller.mm
@@ -21,16 +21,19 @@
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "base/values.h"
+#include "components/autofill/core/browser/popup_item_ids.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/password_form.h"
 #include "components/autofill/core/common/password_form_fill_data.h"
+#include "components/autofill/core/common/password_form_generation_data.h"
 #include "components/autofill/ios/browser/autofill_util.h"
 #import "components/autofill/ios/form_util/form_activity_observer_bridge.h"
 #include "components/browser_sync/profile_sync_service.h"
 #include "components/infobars/core/infobar_manager.h"
 #include "components/password_manager/core/browser/form_parsing/ios_form_parser.h"
 #include "components/password_manager/core/browser/password_bubble_experiment.h"
+#include "components/password_manager/core/browser/password_generation_manager.h"
 #include "components/password_manager/core/browser/password_manager.h"
 #include "components/password_manager/core/browser/password_manager_client.h"
 #include "components/password_manager/core/browser/password_manager_driver.h"
@@ -39,6 +42,7 @@
 #import "components/password_manager/ios/password_suggestion_helper.h"
 #include "components/sync/driver/sync_service.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/chrome/browser/experimental_flags.h"
 #include "ios/chrome/browser/infobars/infobar_manager_impl.h"
 #import "ios/chrome/browser/metrics/ukm_url_recorder.h"
 #include "ios/chrome/browser/passwords/credential_manager.h"
@@ -72,6 +76,7 @@
 using password_manager::FillData;
 using password_manager::GetPageURLAndCheckTrustLevel;
 using password_manager::PasswordFormManagerForUI;
+using password_manager::PasswordGenerationManager;
 using password_manager::PasswordManager;
 using password_manager::PasswordManagerClient;
 using password_manager::PasswordManagerDriver;
@@ -150,6 +155,7 @@
 
 @implementation PasswordController {
   std::unique_ptr<PasswordManager> _passwordManager;
+  std::unique_ptr<PasswordGenerationManager> _passwordGenerationManager;
   std::unique_ptr<PasswordManagerClient> _passwordManagerClient;
   std::unique_ptr<PasswordManagerDriver> _passwordManagerDriver;
   std::unique_ptr<CredentialManager> _credentialManager;
@@ -167,20 +173,12 @@
   // User credential waiting to be displayed in autosign-in snackbar, once tab
   // becomes active.
   std::unique_ptr<autofill::PasswordForm> _pendingAutoSigninPasswordForm;
+
+  // Form data for password generation on this page.
+  std::vector<const autofill::NewPasswordFormGenerationData*>
+      _formGenerationData;
 }
 
-@synthesize baseViewController = _baseViewController;
-
-@synthesize dispatcher = _dispatcher;
-
-@synthesize delegate = _delegate;
-
-@synthesize notifyAutoSigninViewController = _notifyAutoSigninViewController;
-
-@synthesize formHelper = _formHelper;
-
-@synthesize suggestionHelper = _suggestionHelper;
-
 - (instancetype)initWithWebState:(web::WebState*)webState {
   self = [self initWithWebState:webState
                          client:nullptr];
@@ -208,6 +206,12 @@
     _passwordManager.reset(new PasswordManager(_passwordManagerClient.get()));
     _passwordManagerDriver.reset(new IOSChromePasswordManagerDriver(self));
 
+    if (experimental_flags::IsAutomaticPasswordGenerationEnabled() &&
+        !_passwordManagerClient->IsIncognito()) {
+      _passwordGenerationManager.reset(new PasswordGenerationManager(
+          _passwordManagerClient.get(), _passwordManagerDriver.get()));
+    }
+
     if (base::FeatureList::IsEnabled(features::kCredentialManager)) {
       _credentialManager = std::make_unique<CredentialManager>(
           _passwordManagerClient.get(), _webState);
@@ -307,6 +311,7 @@
   _passwordManager.reset();
   _passwordManagerClient.reset();
   _credentialManager.reset();
+  _formGenerationData.clear();
 }
 
 #pragma mark - FormSuggestionProvider
@@ -370,15 +375,36 @@
                                identifier:0]];
   }
 
+  if ([self canGeneratePasswordForForm:formName
+                       fieldIdentifier:fieldIdentifier
+                             fieldType:fieldType]) {
+    // Add "Suggest Password...".
+    NSString* suggestPassword =
+        l10n_util::GetNSString(IDS_IOS_SUGGEST_PASSWORD);
+    [suggestions
+        addObject:
+            [FormSuggestion
+                suggestionWithValue:suggestPassword
+                 displayDescription:nil
+                               icon:nil
+                         identifier:autofill::
+                                        POPUP_ITEM_ID_GENERATE_PASSWORD_ENTRY]];
+  }
+
   // Once Manual Fallback is enabled the access to settings will exist as an
   // option in the new passwords UI.
   if (!autofill::features::IsPasswordManualFallbackEnabled()) {
     // Add "Show all".
     NSString* showAll = l10n_util::GetNSString(IDS_IOS_SHOW_ALL_PASSWORDS);
-    [suggestions addObject:[FormSuggestion suggestionWithValue:showAll
-                                            displayDescription:nil
-                                                          icon:nil
-                                                    identifier:1]];
+    [suggestions
+        addObject:
+            [FormSuggestion
+                suggestionWithValue:showAll
+                 displayDescription:nil
+                               icon:nil
+                         identifier:
+                             autofill::
+                                 POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY]];
   }
   if (suggestions.count) {
     LogSuggestionShown(suggestion_type);
@@ -392,29 +418,36 @@
             fieldIdentifier:(NSString*)fieldIdentifier
                     frameID:(NSString*)frameID
           completionHandler:(SuggestionHandledCompletion)completion {
-  if (suggestion.identifier == 1) {
-    // Navigate to the settings list.
-    [self.delegate displaySavedPasswordList];
-    completion();
-    LogSuggestionClicked(PasswordSuggestionType::SHOW_ALL);
-    return;
-  }
-  LogSuggestionClicked(PasswordSuggestionType::CREDENTIALS);
-  DCHECK([suggestion.value hasSuffix:kSuggestionSuffix]);
-  NSString* username = [suggestion.value
-      substringToIndex:suggestion.value.length - kSuggestionSuffix.length];
-  std::unique_ptr<password_manager::FillData> fillData =
-      [self.suggestionHelper getFillDataForUsername:username];
+  switch (suggestion.identifier) {
+    case autofill::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY:
+      // Navigate to the settings list.
+      [self.delegate displaySavedPasswordList];
+      completion();
+      LogSuggestionClicked(PasswordSuggestionType::SHOW_ALL);
+      return;
+    case autofill::POPUP_ITEM_ID_GENERATE_PASSWORD_ENTRY:
+      // TODO(crbug.com/886583): Display ActionSheet with suggested password.
+      completion();
+      return;
+    default:
+      LogSuggestionClicked(PasswordSuggestionType::CREDENTIALS);
+      DCHECK([suggestion.value hasSuffix:kSuggestionSuffix]);
+      NSString* username = [suggestion.value
+          substringToIndex:suggestion.value.length - kSuggestionSuffix.length];
+      std::unique_ptr<password_manager::FillData> fillData =
+          [self.suggestionHelper getFillDataForUsername:username];
 
-  if (!fillData) {
-    completion();
-    return;
-  }
+      if (!fillData) {
+        completion();
+        return;
+      }
 
-  [self.formHelper fillPasswordFormWithFillData:*fillData
-                              completionHandler:^(BOOL success) {
-                                completion();
-                              }];
+      [self.formHelper fillPasswordFormWithFillData:*fillData
+                                  completionHandler:^(BOOL success) {
+                                    completion();
+                                  }];
+      break;
+  }
 }
 
 #pragma mark - PasswordManagerClientDelegate
@@ -498,6 +531,16 @@
   [self.suggestionHelper processWithNoSavedCredentials];
 }
 
+- (PasswordGenerationManager*)passwordGenerationManager {
+  return _passwordGenerationManager.get();
+}
+
+- (void)formEligibleForGenerationFound:
+    (const autofill::NewPasswordFormGenerationData&)form {
+  _formGenerationData.push_back(
+      new autofill::NewPasswordFormGenerationData(form));
+}
+
 #pragma mark - PasswordFormHelperDelegate
 
 - (void)formHelper:(PasswordFormHelper*)formHelper
@@ -601,4 +644,17 @@
   self.notifyAutoSigninViewController = nil;
 }
 
+- (BOOL)canGeneratePasswordForForm:(NSString*)formName
+                   fieldIdentifier:(NSString*)fieldIdentifier
+                         fieldType:(NSString*)fieldType {
+  if (!experimental_flags::IsAutomaticPasswordGenerationEnabled())
+    return NO;
+  if (![fieldType isEqualToString:@"password"])
+    return NO;
+
+  // TODO(crbug.com/886583): validate field against _formGenerationData;
+
+  return YES;
+}
+
 @end
diff --git a/ios/chrome/browser/passwords/password_tab_helper.h b/ios/chrome/browser/passwords/password_tab_helper.h
index 3891910..e10daff8 100644
--- a/ios/chrome/browser/passwords/password_tab_helper.h
+++ b/ios/chrome/browser/passwords/password_tab_helper.h
@@ -17,6 +17,10 @@
 @protocol PasswordsUiDelegate;
 @class UIViewController;
 
+namespace password_manager {
+class PasswordGenerationManager;
+}
+
 // Class binding a PasswordController to a WebState.
 class PasswordTabHelper : public web::WebStateObserver,
                           public web::WebStateUserData<PasswordTabHelper> {
@@ -42,6 +46,9 @@
   // Returns the PasswordFormFiller from the PasswordController.
   id<PasswordFormFiller> GetPasswordFormFiller();
 
+  // Returns the PasswordGenerationManager owned by the PasswordController.
+  password_manager::PasswordGenerationManager* GetPasswordGenerationManager();
+
  private:
   explicit PasswordTabHelper(web::WebState* web_state);
 
diff --git a/ios/chrome/browser/passwords/password_tab_helper.mm b/ios/chrome/browser/passwords/password_tab_helper.mm
index bcec50d..23c4511b 100644
--- a/ios/chrome/browser/passwords/password_tab_helper.mm
+++ b/ios/chrome/browser/passwords/password_tab_helper.mm
@@ -45,6 +45,11 @@
   return controller_.passwordFormFiller;
 }
 
+password_manager::PasswordGenerationManager*
+PasswordTabHelper::GetPasswordGenerationManager() {
+  return controller_.passwordGenerationManager;
+}
+
 PasswordTabHelper::PasswordTabHelper(web::WebState* web_state)
     : controller_([[PasswordController alloc] initWithWebState:web_state]) {
   web_state->AddObserver(this);
diff --git a/ios/chrome/browser/prefs/BUILD.gn b/ios/chrome/browser/prefs/BUILD.gn
index 89dc301d..1710036 100644
--- a/ios/chrome/browser/prefs/BUILD.gn
+++ b/ios/chrome/browser/prefs/BUILD.gn
@@ -36,6 +36,7 @@
     "//components/flags_ui",
     "//components/gcm_driver",
     "//components/handoff",
+    "//components/history/core/common",
     "//components/invalidation/impl:impl",
     "//components/language/core/browser",
     "//components/metrics",
diff --git a/ios/chrome/browser/prefs/browser_prefs.mm b/ios/chrome/browser/prefs/browser_prefs.mm
index 8901464..70b21dc 100644
--- a/ios/chrome/browser/prefs/browser_prefs.mm
+++ b/ios/chrome/browser/prefs/browser_prefs.mm
@@ -11,6 +11,7 @@
 #include "components/flags_ui/pref_service_flags_storage.h"
 #include "components/gcm_driver/gcm_channel_status_syncer.h"
 #import "components/handoff/handoff_manager.h"
+#include "components/history/core/common/pref_names.h"
 #include "components/invalidation/impl/invalidator_registrar_with_memory.h"
 #include "components/invalidation/impl/per_user_topic_registration_manager.h"
 #include "components/language/core/browser/pref_names.h"
diff --git a/ios/chrome/browser/signin/authentication_service_unittest.mm b/ios/chrome/browser/signin/authentication_service_unittest.mm
index ceb594d..5acdee9 100644
--- a/ios/chrome/browser/signin/authentication_service_unittest.mm
+++ b/ios/chrome/browser/signin/authentication_service_unittest.mm
@@ -159,7 +159,8 @@
   }
 
   void SetExpectationsForSignIn() {
-    EXPECT_CALL(*profile_sync_service_mock_, RequestStart());
+    EXPECT_CALL(*profile_sync_service_mock_->GetUserSettingsMock(),
+                SetSyncRequested(true));
     EXPECT_CALL(*sync_setup_service_mock_, PrepareForFirstSyncSetup());
   }
 
diff --git a/ios/chrome/browser/tabs/tab_helper_util.mm b/ios/chrome/browser/tabs/tab_helper_util.mm
index 2ecffd9..a8cf7700 100644
--- a/ios/chrome/browser/tabs/tab_helper_util.mm
+++ b/ios/chrome/browser/tabs/tab_helper_util.mm
@@ -117,7 +117,9 @@
 
   PasswordTabHelper::CreateForWebState(web_state);
 
-  AutofillTabHelper::CreateForWebState(web_state, nullptr);
+  AutofillTabHelper::CreateForWebState(
+      web_state, PasswordTabHelper::FromWebState(web_state)
+                     ->GetPasswordGenerationManager());
 
   // Depends on favicon::WebFaviconDriver, must be created after it.
   if (base::FeatureList::IsEnabled(kCustomSearchEngines)) {
diff --git a/ios/chrome/browser/ui/authentication/BUILD.gn b/ios/chrome/browser/ui/authentication/BUILD.gn
index 10e9c30..6d19bcb 100644
--- a/ios/chrome/browser/ui/authentication/BUILD.gn
+++ b/ios/chrome/browser/ui/authentication/BUILD.gn
@@ -131,6 +131,7 @@
     "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/signin_interaction/public",
+    "//ios/chrome/browser/ui/table_view:styler",
     "//ios/chrome/browser/unified_consent",
     "//ios/chrome/test:test_support",
     "//ios/public/provider/chrome/browser/signin:test_support",
diff --git a/ios/chrome/browser/ui/authentication/cells/BUILD.gn b/ios/chrome/browser/ui/authentication/cells/BUILD.gn
index dd00ee3..5363891 100644
--- a/ios/chrome/browser/ui/authentication/cells/BUILD.gn
+++ b/ios/chrome/browser/ui/authentication/cells/BUILD.gn
@@ -9,6 +9,8 @@
   sources = [
     "account_control_item.h",
     "account_control_item.mm",
+    "legacy_account_control_item.h",
+    "legacy_account_control_item.mm",
     "signin_promo_item.h",
     "signin_promo_item.mm",
     "signin_promo_view.h",
@@ -17,6 +19,8 @@
     "signin_promo_view_configurator.mm",
     "signin_promo_view_consumer.h",
     "signin_promo_view_delegate.h",
+    "table_view_account_item.h",
+    "table_view_account_item.mm",
     "table_view_signin_promo_item.h",
     "table_view_signin_promo_item.mm",
   ]
@@ -30,6 +34,7 @@
     "//ios/chrome/browser/ui/collection_view/cells",
     "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/commands",
+    "//ios/chrome/browser/ui/settings/cells",
     "//ios/chrome/browser/ui/table_view:styler",
     "//ios/chrome/browser/ui/table_view/cells",
     "//ios/public/provider/chrome/browser",
@@ -44,8 +49,10 @@
   testonly = true
   sources = [
     "account_control_item_unittest.mm",
+    "legacy_account_control_item_unittest.mm",
     "signin_promo_item_unittest.mm",
     "signin_promo_view_unittest.mm",
+    "table_view_account_item_unittest.mm",
   ]
   deps = [
     ":cells",
@@ -73,6 +80,8 @@
     "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/signin_interaction/public",
+    "//ios/chrome/browser/ui/table_view:styler",
+    "//ios/chrome/browser/ui/table_view/cells",
     "//ios/chrome/browser/unified_consent",
     "//ios/chrome/test:test_support",
     "//ios/public/provider/chrome/browser/signin:test_support",
diff --git a/ios/chrome/browser/ui/authentication/cells/account_control_item.h b/ios/chrome/browser/ui/authentication/cells/account_control_item.h
index f60880d..dc35e32 100644
--- a/ios/chrome/browser/ui/authentication/cells/account_control_item.h
+++ b/ios/chrome/browser/ui/authentication/cells/account_control_item.h
@@ -1,4 +1,4 @@
-// Copyright 2016 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.
 
@@ -7,15 +7,10 @@
 
 #import <UIKit/UIKit.h>
 
-#import "ios/chrome/browser/ui/collection_view/cells/collection_view_cell_style.h"
-#import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h"
-#import "ios/third_party/material_components_ios/src/components/CollectionCells/src/MaterialCollectionCells.h"
+#import "ios/chrome/browser/ui/table_view/cells/table_view_item.h"
 
 // Item for account collection view and sign-in confirmation view.
-@interface AccountControlItem : CollectionViewItem
-
-// The style to use for the cell.
-@property(nonatomic, assign) CollectionViewCellStyle cellStyle;
+@interface AccountControlItem : TableViewItem
 
 @property(nonatomic, strong) UIImage* image;
 @property(nonatomic, copy) NSString* text;
@@ -23,13 +18,13 @@
 @property(nonatomic, assign) BOOL shouldDisplayError;
 
 // The accessory type for the represented cell.
-@property(nonatomic) MDCCollectionViewCellAccessoryType accessoryType;
+@property(nonatomic) UITableViewCellAccessoryType accessoryType;
 
 @end
 
 // Cell for account settings view with a leading imageView, title text label,
 // and detail text label. The imageView is top-leading aligned.
-@interface AccountControlCell : MDCCollectionViewCell
+@interface AccountControlCell : UITableViewCell
 
 @property(nonatomic, readonly, strong) UIImageView* imageView;
 @property(nonatomic, readonly, strong) UILabel* textLabel;
diff --git a/ios/chrome/browser/ui/authentication/cells/account_control_item.mm b/ios/chrome/browser/ui/authentication/cells/account_control_item.mm
index 59ac0f5..b97a544b 100644
--- a/ios/chrome/browser/ui/authentication/cells/account_control_item.mm
+++ b/ios/chrome/browser/ui/authentication/cells/account_control_item.mm
@@ -1,42 +1,18 @@
-// Copyright 2016 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.
 
 #import "ios/chrome/browser/ui/authentication/cells/account_control_item.h"
 
-#import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrome.h"
-#include "ios/chrome/browser/ui/collection_view/cells/collection_view_cell_constants.h"
-#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
+#include "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h"
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
-#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
-namespace {
-// Padding used on the leading and trailing edges of the cell.
-const CGFloat kHorizontalPadding = 16;
-
-// Padding used on the top and bottom edges of the cell.
-const CGFloat kVerticalPadding = 16;
-
-// Padding used between the image and text.
-const CGFloat kHorizontalPaddingBetweenImageAndText = 16;
-
-// Padding between top label and detail label.
-const CGFloat kVerticalPaddingBetweenLabelAndDetailLabel = 8;
-}  // namespace
-
 @implementation AccountControlItem
 
-@synthesize cellStyle = _cellStyle;
-@synthesize image = _image;
-@synthesize text = _text;
-@synthesize detailText = _detailText;
-@synthesize accessoryType = _accessoryType;
-@synthesize shouldDisplayError = _shouldDisplayError;
-
 - (instancetype)initWithType:(NSInteger)type {
   self = [super initWithType:type];
   if (self) {
@@ -46,36 +22,22 @@
   return self;
 }
 
-#pragma mark - CollectionViewItem
+#pragma mark - TableViewItem
 
-- (void)configureCell:(AccountControlCell*)cell {
-  [super configureCell:cell];
+- (void)configureCell:(AccountControlCell*)cell
+           withStyler:(ChromeTableViewStyler*)styler {
+  [super configureCell:cell withStyler:styler];
   cell.imageView.image = self.image;
-  [cell cr_setAccessoryType:self.accessoryType];
+  cell.accessoryType = self.accessoryType;
 
-  BOOL uikitStyle = self.cellStyle == CollectionViewCellStyle::kUIKit;
-  UIFont* textFont = uikitStyle ? [UIFont systemFontOfSize:kUIKitMainFontSize]
-                                : [MDCTypography body2Font];
-  UIColor* textColor = uikitStyle ? UIColorFromRGB(kUIKitMainTextColor)
-                                  : [[MDCPalette greyPalette] tint900];
-  UIFont* detailTextFont =
-      uikitStyle ? [UIFont systemFontOfSize:kUIKitMultilineDetailFontSize]
-                 : [MDCTypography body1Font];
+  cell.textLabel.text = self.text;
+  cell.textLabel.textColor = UIColor.blackColor;
 
-  UIColor* detailTextColor =
-      uikitStyle ? UIColorFromRGB(kUIKitMultilineDetailTextColor)
-                 : [[MDCPalette greyPalette] tint700];
-  if (self.shouldDisplayError) {
-    detailTextColor = [[MDCPalette cr_redPalette] tint700];
-  }
-
-  cell.textLabel.attributedText = [self attributedStringForText:self.text
-                                                           font:textFont
-                                                          color:textColor];
-  cell.detailTextLabel.attributedText =
-      [self attributedStringForText:self.detailText
-                               font:detailTextFont
-                              color:detailTextColor];
+  cell.detailTextLabel.text = self.detailText;
+  cell.detailTextLabel.textColor =
+      self.shouldDisplayError
+          ? UIColor.redColor
+          : UIColorFromRGB(kTableViewSecondaryLabelLightGrayTextColor);
 }
 
 #pragma mark - Helper methods
@@ -109,12 +71,12 @@
 @synthesize textLabel = _textLabel;
 @synthesize detailTextLabel = _detailTextLabel;
 
-- (instancetype)initWithFrame:(CGRect)frame {
-  self = [super initWithFrame:frame];
+- (instancetype)initWithStyle:(UITableViewCellStyle)style
+              reuseIdentifier:(NSString*)reuseIdentifier {
+  self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
   if (self) {
     self.isAccessibilityElement = YES;
     [self addSubviews];
-    [self setDefaultViewStyling];
     [self setViewConstraints];
   }
   return self;
@@ -127,25 +89,24 @@
 
   _imageView = [[UIImageView alloc] init];
   _imageView.translatesAutoresizingMaskIntoConstraints = NO;
+  [_imageView
+      setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh + 1
+                                      forAxis:UILayoutConstraintAxisHorizontal];
   [contentView addSubview:_imageView];
 
   _textLabel = [[UILabel alloc] init];
+  _textLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
+  _textLabel.adjustsFontForContentSizeCategory = YES;
   _textLabel.translatesAutoresizingMaskIntoConstraints = NO;
   [contentView addSubview:_textLabel];
 
   _detailTextLabel = [[UILabel alloc] init];
+  _detailTextLabel.font =
+      [UIFont preferredFontForTextStyle:UIFontTextStyleCaption1];
+  _detailTextLabel.adjustsFontForContentSizeCategory = YES;
   _detailTextLabel.translatesAutoresizingMaskIntoConstraints = NO;
-  [contentView addSubview:_detailTextLabel];
-}
-
-// Set default imageView styling and default font and text colors for labels.
-- (void)setDefaultViewStyling {
-  _imageView.contentMode = UIViewContentModeCenter;
-
-  _textLabel.font = [MDCTypography body2Font];
-  _textLabel.textColor = [[MDCPalette greyPalette] tint900];
-  _detailTextLabel.font = [MDCTypography body1Font];
   _detailTextLabel.numberOfLines = 0;
+  [contentView addSubview:_detailTextLabel];
 }
 
 // Set constraints on subviews.
@@ -157,30 +118,32 @@
 
   [NSLayoutConstraint activateConstraints:@[
     // Set leading anchors.
-    [_imageView.leadingAnchor constraintEqualToAnchor:contentView.leadingAnchor
-                                             constant:kHorizontalPadding],
+    [_imageView.leadingAnchor
+        constraintEqualToAnchor:contentView.leadingAnchor
+                       constant:kTableViewHorizontalSpacing],
     [_detailTextLabel.leadingAnchor
         constraintEqualToAnchor:_textLabel.leadingAnchor],
     _textLeadingAnchorConstraint,
 
     // Set vertical anchors.
-    [_textLabel.topAnchor constraintEqualToAnchor:contentView.topAnchor
-                                         constant:kVerticalPadding],
+    [_textLabel.topAnchor
+        constraintEqualToAnchor:contentView.topAnchor
+                       constant:kTableViewLargeVerticalSpacing],
     [_textLabel.bottomAnchor
         constraintEqualToAnchor:_detailTextLabel.topAnchor
-                       constant:-kVerticalPaddingBetweenLabelAndDetailLabel],
+                       constant:-kTableViewVerticalSpacing],
     [_imageView.centerYAnchor constraintEqualToAnchor:_textLabel.centerYAnchor],
     [_detailTextLabel.bottomAnchor
         constraintEqualToAnchor:contentView.bottomAnchor
-                       constant:-kVerticalPadding],
+                       constant:-kTableViewLargeVerticalSpacing],
 
     // Set trailing anchors.
     [_textLabel.trailingAnchor
         constraintLessThanOrEqualToAnchor:contentView.trailingAnchor
-                                 constant:-kHorizontalPadding],
+                                 constant:-kTableViewHorizontalSpacing],
     [_detailTextLabel.trailingAnchor
         constraintLessThanOrEqualToAnchor:contentView.trailingAnchor
-                                 constant:-kHorizontalPadding],
+                                 constant:-kTableViewHorizontalSpacing],
   ]];
 }
 
@@ -191,33 +154,23 @@
 
   // Adjust the text label preferredMaxLayoutWidth when the parent's width
   // changes, for instance on screen rotation.
-  CGFloat parentWidth = self.contentView.frame.size.width;
   if (_imageView.image) {
-    _detailTextLabel.preferredMaxLayoutWidth =
-        parentWidth - 2.f * kHorizontalPadding -
-        kHorizontalPaddingBetweenImageAndText - _imageView.image.size.width;
-    _textLeadingAnchorConstraint.constant =
-        kHorizontalPaddingBetweenImageAndText;
+    _textLeadingAnchorConstraint.constant = kTableViewHorizontalSpacing;
   } else {
-    _detailTextLabel.preferredMaxLayoutWidth =
-        parentWidth - 2.f * kHorizontalPadding;
     _textLeadingAnchorConstraint.constant = 0;
   }
-
-  // Re-layout with the new preferred width to allow the label to adjust its
-  // height.
-  [super layoutSubviews];
 }
 
-#pragma mark - UICollectionReusableView
+#pragma mark - UITableViewCell
 
 - (void)prepareForReuse {
   [super prepareForReuse];
   self.imageView.image = nil;
   self.textLabel.text = nil;
   self.detailTextLabel.text = nil;
-  self.accessoryType = MDCCollectionViewCellAccessoryNone;
-  self.detailTextLabel.textColor = [[MDCPalette greyPalette] tint700];
+  self.detailTextLabel.textColor =
+      UIColorFromRGB(kTableViewSecondaryLabelLightGrayTextColor);
+  self.accessoryType = UITableViewCellAccessoryNone;
 }
 
 #pragma mark - NSObject(Accessibility)
diff --git a/ios/chrome/browser/ui/authentication/cells/account_control_item_unittest.mm b/ios/chrome/browser/ui/authentication/cells/account_control_item_unittest.mm
index e88eaef..2ef8463 100644
--- a/ios/chrome/browser/ui/authentication/cells/account_control_item_unittest.mm
+++ b/ios/chrome/browser/ui/authentication/cells/account_control_item_unittest.mm
@@ -4,7 +4,9 @@
 
 #import "ios/chrome/browser/ui/authentication/cells/account_control_item.h"
 
-#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
+#include "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h"
+#import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h"
+#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
 #include "testing/platform_test.h"
@@ -16,7 +18,7 @@
 using AccountControlItemTest = PlatformTest;
 
 // Tests that the cell is properly configured with image and texts after a call
-// to |configureCell:|. All other cell decorations are default.
+// to |configureCell:withStyler:|. All other cell decorations are default.
 TEST_F(AccountControlItemTest, ConfigureCellDefault) {
   AccountControlItem* item = [[AccountControlItem alloc] initWithType:0];
   UIImage* image = [[UIImage alloc] init];
@@ -35,21 +37,21 @@
   EXPECT_FALSE(accountCell.imageView.image);
   EXPECT_FALSE(accountCell.textLabel.text);
   EXPECT_FALSE(accountCell.detailTextLabel.text);
-  EXPECT_EQ(MDCCollectionViewCellAccessoryNone, accountCell.accessoryType);
-  EXPECT_NSEQ([[MDCPalette greyPalette] tint700],
+  EXPECT_EQ(UITableViewCellAccessoryNone, accountCell.accessoryType);
+  EXPECT_NSEQ(UIColorFromRGB(kTableViewSecondaryLabelLightGrayTextColor),
               accountCell.detailTextLabel.textColor);
 
-  [item configureCell:cell];
+  [item configureCell:cell withStyler:[[ChromeTableViewStyler alloc] init]];
   EXPECT_NSEQ(image, accountCell.imageView.image);
   EXPECT_NSEQ(mainText, accountCell.textLabel.text);
   EXPECT_NSEQ(detailText, accountCell.detailTextLabel.text);
-  EXPECT_EQ(MDCCollectionViewCellAccessoryNone, accountCell.accessoryType);
-  EXPECT_NSEQ([[MDCPalette greyPalette] tint700],
+  EXPECT_EQ(UITableViewCellAccessoryNone, accountCell.accessoryType);
+  EXPECT_NSEQ(UIColorFromRGB(kTableViewSecondaryLabelLightGrayTextColor),
               accountCell.detailTextLabel.textColor);
 }
 
 // Tests that the cell is properly configured with error and an accessory after
-// a call to |configureCell:|.
+// a call to |configureCell:withStyler:|.
 TEST_F(AccountControlItemTest, ConfigureCellWithErrorAndAccessory) {
   AccountControlItem* item = [[AccountControlItem alloc] initWithType:0];
   UIImage* image = [[UIImage alloc] init];
@@ -59,7 +61,7 @@
   item.image = image;
   item.text = mainText;
   item.detailText = detailText;
-  item.accessoryType = MDCCollectionViewCellAccessoryCheckmark;
+  item.accessoryType = UITableViewCellAccessoryCheckmark;
   item.shouldDisplayError = YES;
 
   id cell = [[[item cellClass] alloc] init];
@@ -70,15 +72,14 @@
   EXPECT_FALSE(accountCell.imageView.image);
   EXPECT_FALSE(accountCell.textLabel.text);
   EXPECT_FALSE(accountCell.detailTextLabel.text);
-  EXPECT_EQ(MDCCollectionViewCellAccessoryNone, accountCell.accessoryType);
-  EXPECT_NSEQ([[MDCPalette greyPalette] tint700],
+  EXPECT_EQ(UITableViewCellAccessoryNone, accountCell.accessoryType);
+  EXPECT_NSEQ(UIColorFromRGB(kTableViewSecondaryLabelLightGrayTextColor),
               accountCell.detailTextLabel.textColor);
 
-  [item configureCell:cell];
+  [item configureCell:cell withStyler:[[ChromeTableViewStyler alloc] init]];
   EXPECT_NSEQ(image, accountCell.imageView.image);
   EXPECT_NSEQ(mainText, accountCell.textLabel.text);
   EXPECT_NSEQ(detailText, accountCell.detailTextLabel.text);
-  EXPECT_EQ(MDCCollectionViewCellAccessoryCheckmark, accountCell.accessoryType);
-  EXPECT_NSEQ([[MDCPalette cr_redPalette] tint700],
-              accountCell.detailTextLabel.textColor);
+  EXPECT_EQ(UITableViewCellAccessoryCheckmark, accountCell.accessoryType);
+  EXPECT_NSEQ(UIColor.redColor, accountCell.detailTextLabel.textColor);
 }
diff --git a/ios/chrome/browser/ui/authentication/cells/legacy_account_control_item.h b/ios/chrome/browser/ui/authentication/cells/legacy_account_control_item.h
new file mode 100644
index 0000000..dd3d13e
--- /dev/null
+++ b/ios/chrome/browser/ui/authentication/cells/legacy_account_control_item.h
@@ -0,0 +1,41 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_AUTHENTICATION_CELLS_LEGACY_ACCOUNT_CONTROL_ITEM_H_
+#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_CELLS_LEGACY_ACCOUNT_CONTROL_ITEM_H_
+
+#import <UIKit/UIKit.h>
+
+#import "ios/chrome/browser/ui/collection_view/cells/collection_view_cell_style.h"
+#import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h"
+#import "ios/third_party/material_components_ios/src/components/CollectionCells/src/MaterialCollectionCells.h"
+
+// TODO(crbug.com/894800): Remove this.
+// Item for account collection view and sign-in confirmation view.
+@interface LegacyAccountControlItem : CollectionViewItem
+
+// The style to use for the cell.
+@property(nonatomic, assign) CollectionViewCellStyle cellStyle;
+
+@property(nonatomic, strong) UIImage* image;
+@property(nonatomic, copy) NSString* text;
+@property(nonatomic, copy) NSString* detailText;
+@property(nonatomic, assign) BOOL shouldDisplayError;
+
+// The accessory type for the represented cell.
+@property(nonatomic) MDCCollectionViewCellAccessoryType accessoryType;
+
+@end
+
+// Cell for account settings view with a leading imageView, title text label,
+// and detail text label. The imageView is top-leading aligned.
+@interface LegacyAccountControlCell : MDCCollectionViewCell
+
+@property(nonatomic, readonly, strong) UIImageView* imageView;
+@property(nonatomic, readonly, strong) UILabel* textLabel;
+@property(nonatomic, readonly, strong) UILabel* detailTextLabel;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_AUTHENTICATION_CELLS_LEGACY_ACCOUNT_CONTROL_ITEM_H_
diff --git a/ios/chrome/browser/ui/authentication/cells/legacy_account_control_item.mm b/ios/chrome/browser/ui/authentication/cells/legacy_account_control_item.mm
new file mode 100644
index 0000000..a2b8359
--- /dev/null
+++ b/ios/chrome/browser/ui/authentication/cells/legacy_account_control_item.mm
@@ -0,0 +1,230 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/authentication/cells/legacy_account_control_item.h"
+
+#import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrome.h"
+#include "ios/chrome/browser/ui/collection_view/cells/collection_view_cell_constants.h"
+#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
+#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
+#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+// Padding used on the leading and trailing edges of the cell.
+const CGFloat kHorizontalPadding = 16;
+
+// Padding used on the top and bottom edges of the cell.
+const CGFloat kVerticalPadding = 16;
+
+// Padding used between the image and text.
+const CGFloat kHorizontalPaddingBetweenImageAndText = 16;
+
+// Padding between top label and detail label.
+const CGFloat kVerticalPaddingBetweenLabelAndDetailLabel = 8;
+}  // namespace
+
+@implementation LegacyAccountControlItem
+
+@synthesize cellStyle = _cellStyle;
+@synthesize image = _image;
+@synthesize text = _text;
+@synthesize detailText = _detailText;
+@synthesize accessoryType = _accessoryType;
+@synthesize shouldDisplayError = _shouldDisplayError;
+
+- (instancetype)initWithType:(NSInteger)type {
+  self = [super initWithType:type];
+  if (self) {
+    self.cellClass = [LegacyAccountControlCell class];
+    self.accessibilityTraits |= UIAccessibilityTraitButton;
+  }
+  return self;
+}
+
+#pragma mark - CollectionViewItem
+
+- (void)configureCell:(LegacyAccountControlCell*)cell {
+  [super configureCell:cell];
+  cell.imageView.image = self.image;
+  [cell cr_setAccessoryType:self.accessoryType];
+
+  BOOL uikitStyle = self.cellStyle == CollectionViewCellStyle::kUIKit;
+  UIFont* textFont = uikitStyle ? [UIFont systemFontOfSize:kUIKitMainFontSize]
+                                : [MDCTypography body2Font];
+  UIColor* textColor = uikitStyle ? UIColorFromRGB(kUIKitMainTextColor)
+                                  : [[MDCPalette greyPalette] tint900];
+  UIFont* detailTextFont =
+      uikitStyle ? [UIFont systemFontOfSize:kUIKitMultilineDetailFontSize]
+                 : [MDCTypography body1Font];
+
+  UIColor* detailTextColor =
+      uikitStyle ? UIColorFromRGB(kUIKitMultilineDetailTextColor)
+                 : [[MDCPalette greyPalette] tint700];
+  if (self.shouldDisplayError) {
+    detailTextColor = [[MDCPalette cr_redPalette] tint700];
+  }
+
+  cell.textLabel.attributedText = [self attributedStringForText:self.text
+                                                           font:textFont
+                                                          color:textColor];
+  cell.detailTextLabel.attributedText =
+      [self attributedStringForText:self.detailText
+                               font:detailTextFont
+                              color:detailTextColor];
+}
+
+#pragma mark - Helper methods
+
+- (NSAttributedString*)attributedStringForText:(NSString*)text
+                                          font:(UIFont*)font
+                                         color:(UIColor*)color {
+  NSMutableParagraphStyle* paragraphStyle =
+      [[NSMutableParagraphStyle alloc] init];
+  paragraphStyle.lineHeightMultiple = 1.15;
+  return [[NSAttributedString alloc]
+      initWithString:text
+          attributes:@{
+            NSParagraphStyleAttributeName : paragraphStyle,
+            NSFontAttributeName : font,
+            NSForegroundColorAttributeName : color
+          }];
+}
+
+@end
+
+@interface LegacyAccountControlCell () {
+  // Constraint used to set padding between image and text when image exists.
+  NSLayoutConstraint* _textLeadingAnchorConstraint;
+}
+@end
+
+@implementation LegacyAccountControlCell
+
+@synthesize imageView = _imageView;
+@synthesize textLabel = _textLabel;
+@synthesize detailTextLabel = _detailTextLabel;
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    self.isAccessibilityElement = YES;
+    [self addSubviews];
+    [self setDefaultViewStyling];
+    [self setViewConstraints];
+  }
+  return self;
+}
+
+// Create and add subviews.
+- (void)addSubviews {
+  UIView* contentView = self.contentView;
+  contentView.clipsToBounds = YES;
+
+  _imageView = [[UIImageView alloc] init];
+  _imageView.translatesAutoresizingMaskIntoConstraints = NO;
+  [contentView addSubview:_imageView];
+
+  _textLabel = [[UILabel alloc] init];
+  _textLabel.translatesAutoresizingMaskIntoConstraints = NO;
+  [contentView addSubview:_textLabel];
+
+  _detailTextLabel = [[UILabel alloc] init];
+  _detailTextLabel.translatesAutoresizingMaskIntoConstraints = NO;
+  [contentView addSubview:_detailTextLabel];
+}
+
+// Set default imageView styling and default font and text colors for labels.
+- (void)setDefaultViewStyling {
+  _imageView.contentMode = UIViewContentModeCenter;
+
+  _textLabel.font = [MDCTypography body2Font];
+  _textLabel.textColor = [[MDCPalette greyPalette] tint900];
+  _detailTextLabel.font = [MDCTypography body1Font];
+  _detailTextLabel.numberOfLines = 0;
+}
+
+// Set constraints on subviews.
+- (void)setViewConstraints {
+  UIView* contentView = self.contentView;
+
+  _textLeadingAnchorConstraint = [_textLabel.leadingAnchor
+      constraintEqualToAnchor:_imageView.trailingAnchor];
+
+  [NSLayoutConstraint activateConstraints:@[
+    // Set leading anchors.
+    [_imageView.leadingAnchor constraintEqualToAnchor:contentView.leadingAnchor
+                                             constant:kHorizontalPadding],
+    [_detailTextLabel.leadingAnchor
+        constraintEqualToAnchor:_textLabel.leadingAnchor],
+    _textLeadingAnchorConstraint,
+
+    // Set vertical anchors.
+    [_textLabel.topAnchor constraintEqualToAnchor:contentView.topAnchor
+                                         constant:kVerticalPadding],
+    [_textLabel.bottomAnchor
+        constraintEqualToAnchor:_detailTextLabel.topAnchor
+                       constant:-kVerticalPaddingBetweenLabelAndDetailLabel],
+    [_imageView.centerYAnchor constraintEqualToAnchor:_textLabel.centerYAnchor],
+    [_detailTextLabel.bottomAnchor
+        constraintEqualToAnchor:contentView.bottomAnchor
+                       constant:-kVerticalPadding],
+
+    // Set trailing anchors.
+    [_textLabel.trailingAnchor
+        constraintLessThanOrEqualToAnchor:contentView.trailingAnchor
+                                 constant:-kHorizontalPadding],
+    [_detailTextLabel.trailingAnchor
+        constraintLessThanOrEqualToAnchor:contentView.trailingAnchor
+                                 constant:-kHorizontalPadding],
+  ]];
+}
+
+#pragma mark - UIView
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  // Adjust the text label preferredMaxLayoutWidth when the parent's width
+  // changes, for instance on screen rotation.
+  CGFloat parentWidth = self.contentView.frame.size.width;
+  if (_imageView.image) {
+    _detailTextLabel.preferredMaxLayoutWidth =
+        parentWidth - 2.f * kHorizontalPadding -
+        kHorizontalPaddingBetweenImageAndText - _imageView.image.size.width;
+    _textLeadingAnchorConstraint.constant =
+        kHorizontalPaddingBetweenImageAndText;
+  } else {
+    _detailTextLabel.preferredMaxLayoutWidth =
+        parentWidth - 2.f * kHorizontalPadding;
+    _textLeadingAnchorConstraint.constant = 0;
+  }
+
+  // Re-layout with the new preferred width to allow the label to adjust its
+  // height.
+  [super layoutSubviews];
+}
+
+#pragma mark - UICollectionReusableView
+
+- (void)prepareForReuse {
+  [super prepareForReuse];
+  self.imageView.image = nil;
+  self.textLabel.text = nil;
+  self.detailTextLabel.text = nil;
+  self.accessoryType = MDCCollectionViewCellAccessoryNone;
+  self.detailTextLabel.textColor = [[MDCPalette greyPalette] tint700];
+}
+
+#pragma mark - NSObject(Accessibility)
+
+- (NSString*)accessibilityLabel {
+  return [NSString stringWithFormat:@"%@, %@", self.textLabel.text,
+                                    self.detailTextLabel.text];
+}
+
+@end
diff --git a/ios/chrome/browser/ui/authentication/cells/legacy_account_control_item_unittest.mm b/ios/chrome/browser/ui/authentication/cells/legacy_account_control_item_unittest.mm
new file mode 100644
index 0000000..f9a024d
--- /dev/null
+++ b/ios/chrome/browser/ui/authentication/cells/legacy_account_control_item_unittest.mm
@@ -0,0 +1,86 @@
+// 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 "ios/chrome/browser/ui/authentication/cells/legacy_account_control_item.h"
+
+#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#import "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+using LegacyAccountControlItemTest = PlatformTest;
+
+// Tests that the cell is properly configured with image and texts after a call
+// to |configureCell:|. All other cell decorations are default.
+TEST_F(LegacyAccountControlItemTest, ConfigureCellDefault) {
+  LegacyAccountControlItem* item =
+      [[LegacyAccountControlItem alloc] initWithType:0];
+  UIImage* image = [[UIImage alloc] init];
+  NSString* mainText = @"Main text";
+  NSString* detailText = @"Detail text";
+
+  item.image = image;
+  item.text = mainText;
+  item.detailText = detailText;
+
+  id cell = [[[item cellClass] alloc] init];
+  ASSERT_TRUE([cell isMemberOfClass:[LegacyAccountControlCell class]]);
+
+  LegacyAccountControlCell* accountCell = cell;
+  [accountCell prepareForReuse];
+  EXPECT_FALSE(accountCell.imageView.image);
+  EXPECT_FALSE(accountCell.textLabel.text);
+  EXPECT_FALSE(accountCell.detailTextLabel.text);
+  EXPECT_EQ(MDCCollectionViewCellAccessoryNone, accountCell.accessoryType);
+  EXPECT_NSEQ([[MDCPalette greyPalette] tint700],
+              accountCell.detailTextLabel.textColor);
+
+  [item configureCell:cell];
+  EXPECT_NSEQ(image, accountCell.imageView.image);
+  EXPECT_NSEQ(mainText, accountCell.textLabel.text);
+  EXPECT_NSEQ(detailText, accountCell.detailTextLabel.text);
+  EXPECT_EQ(MDCCollectionViewCellAccessoryNone, accountCell.accessoryType);
+  EXPECT_NSEQ([[MDCPalette greyPalette] tint700],
+              accountCell.detailTextLabel.textColor);
+}
+
+// Tests that the cell is properly configured with error and an accessory after
+// a call to |configureCell:|.
+TEST_F(LegacyAccountControlItemTest, ConfigureCellWithErrorAndAccessory) {
+  LegacyAccountControlItem* item =
+      [[LegacyAccountControlItem alloc] initWithType:0];
+  UIImage* image = [[UIImage alloc] init];
+  NSString* mainText = @"Main text";
+  NSString* detailText = @"Detail text";
+
+  item.image = image;
+  item.text = mainText;
+  item.detailText = detailText;
+  item.accessoryType = MDCCollectionViewCellAccessoryCheckmark;
+  item.shouldDisplayError = YES;
+
+  id cell = [[[item cellClass] alloc] init];
+  ASSERT_TRUE([cell isMemberOfClass:[LegacyAccountControlCell class]]);
+
+  LegacyAccountControlCell* accountCell = cell;
+  [accountCell prepareForReuse];
+  EXPECT_FALSE(accountCell.imageView.image);
+  EXPECT_FALSE(accountCell.textLabel.text);
+  EXPECT_FALSE(accountCell.detailTextLabel.text);
+  EXPECT_EQ(MDCCollectionViewCellAccessoryNone, accountCell.accessoryType);
+  EXPECT_NSEQ([[MDCPalette greyPalette] tint700],
+              accountCell.detailTextLabel.textColor);
+
+  [item configureCell:cell];
+  EXPECT_NSEQ(image, accountCell.imageView.image);
+  EXPECT_NSEQ(mainText, accountCell.textLabel.text);
+  EXPECT_NSEQ(detailText, accountCell.detailTextLabel.text);
+  EXPECT_EQ(MDCCollectionViewCellAccessoryCheckmark, accountCell.accessoryType);
+  EXPECT_NSEQ([[MDCPalette cr_redPalette] tint700],
+              accountCell.detailTextLabel.textColor);
+}
diff --git a/ios/chrome/browser/ui/authentication/cells/table_view_account_item.h b/ios/chrome/browser/ui/authentication/cells/table_view_account_item.h
new file mode 100644
index 0000000..3cb2110
--- /dev/null
+++ b/ios/chrome/browser/ui/authentication/cells/table_view_account_item.h
@@ -0,0 +1,48 @@
+// 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 IOS_CHROME_BROWSER_UI_AUTHENTICATION_CELLS_TABLE_VIEW_ACCOUNT_ITEM_H_
+#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_CELLS_TABLE_VIEW_ACCOUNT_ITEM_H_
+
+#import <UIKit/UIKit.h>
+
+#import "ios/chrome/browser/ui/table_view/cells/table_view_item.h"
+
+@class ChromeIdentity;
+
+// Item for account avatar, used everywhere an account cell is shown.
+@interface TableViewAccountItem : TableViewItem
+
+@property(nonatomic, strong) UIImage* image;
+@property(nonatomic, copy) NSString* text;
+@property(nonatomic, copy) NSString* detailText;
+@property(nonatomic, assign) BOOL shouldDisplayError;
+@property(nonatomic, strong) ChromeIdentity* chromeIdentity;
+@property(nonatomic, assign, getter=isEnabled) BOOL enabled;
+
+// The accessory type for the represented cell.
+@property(nonatomic, assign) UITableViewCellAccessoryType accessoryType;
+
+@end
+
+// Cell for account avatar with a leading avatar imageView, title text label,
+// and detail text label. This looks very similar to the
+// TableViewDetailCell, except that it applies a circular mask to the
+// imageView. The imageView is vertical-centered and leading aligned.
+// If item/cell is disabled the image and text alpha will be set to 0.5 and
+// user interaction will be disabled.
+@interface TableViewAccountCell : UITableViewCell
+
+// Rounded image used for the account user picture.
+@property(nonatomic, readonly, strong) UIImageView* imageView;
+// Cell title.
+@property(nonatomic, readonly, strong) UILabel* textLabel;
+// Cell subtitle.
+@property(nonatomic, readonly, strong) UILabel* detailTextLabel;
+// Error icon that will be displayed on the left side of the cell.
+@property(nonatomic, readonly, strong) UIImageView* errorIcon;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_AUTHENTICATION_CELLS_TABLE_VIEW_ACCOUNT_ITEM_H_
diff --git a/ios/chrome/browser/ui/authentication/cells/table_view_account_item.mm b/ios/chrome/browser/ui/authentication/cells/table_view_account_item.mm
new file mode 100644
index 0000000..08f58640
--- /dev/null
+++ b/ios/chrome/browser/ui/authentication/cells/table_view_account_item.mm
@@ -0,0 +1,267 @@
+// 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 "ios/chrome/browser/ui/authentication/cells/table_view_account_item.h"
+
+#include "base/mac/foundation_util.h"
+#import "ios/chrome/browser/ui/settings/cells/settings_cells_constants.h"
+#include "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h"
+#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+// Padding used between the image and text.
+const CGFloat kHorizontalPaddingBetweenImageAndText = 10;
+
+// Padding used between the text and error icon.
+const CGFloat kHorizontalPaddingBetweenTextAndError = 5;
+
+// Image fixed horizontal size.
+const CGFloat kHorizontalImageFixedSize = 40;
+
+// Error icon fixed horizontal size.
+const CGFloat kHorizontalErrorIconFixedSize = 25;
+}
+
+@implementation TableViewAccountItem
+
+- (instancetype)initWithType:(NSInteger)type {
+  self = [super initWithType:type];
+  if (self) {
+    self.cellClass = [TableViewAccountCell class];
+    self.accessibilityTraits |= UIAccessibilityTraitButton;
+    _enabled = YES;
+  }
+  return self;
+}
+
+#pragma mark - TableViewItem
+
+- (void)configureCell:(TableViewAccountCell*)cell
+           withStyler:(ChromeTableViewStyler*)styler {
+  [super configureCell:cell withStyler:styler];
+
+  cell.imageView.image = self.image;
+  cell.textLabel.text = self.text;
+  cell.detailTextLabel.text = self.detailText;
+  cell.accessoryType = self.accessoryType;
+  if (self.shouldDisplayError) {
+    cell.errorIcon.image = [UIImage imageNamed:@"settings_error"];
+    cell.detailTextLabel.textColor = UIColor.redColor;
+  } else {
+    cell.errorIcon.image = nil;
+    cell.detailTextLabel.textColor =
+        UIColorFromRGB(kTableViewSecondaryLabelLightGrayTextColor);
+  }
+
+  if (self.isEnabled) {
+    cell.userInteractionEnabled = YES;
+    cell.contentView.alpha = 1;
+    UIImageView* accessoryImage =
+        base::mac::ObjCCastStrict<UIImageView>(cell.accessoryView);
+    accessoryImage.tintColor =
+        [accessoryImage.tintColor colorWithAlphaComponent:1];
+  } else {
+    cell.userInteractionEnabled = NO;
+    cell.contentView.alpha = 0.5;
+    UIImageView* accessoryImage =
+        base::mac::ObjCCastStrict<UIImageView>(cell.accessoryView);
+    accessoryImage.tintColor =
+        [accessoryImage.tintColor colorWithAlphaComponent:0.5];
+  }
+}
+
+@end
+
+@interface TableViewAccountCell () {
+  // Constraint used to set padding between image and text when image exists.
+  NSLayoutConstraint* _textLeadingAnchorConstraint;
+
+  // Constraint used to set the errorIcon width depending on it's existence.
+  NSLayoutConstraint* _errorIconWidthConstraint;
+}
+@end
+
+@implementation TableViewAccountCell
+
+@synthesize imageView = _imageView;
+@synthesize textLabel = _textLabel;
+@synthesize detailTextLabel = _detailTextLabel;
+@synthesize errorIcon = _errorIcon;
+
+- (instancetype)initWithStyle:(UITableViewCellStyle)style
+              reuseIdentifier:(NSString*)reuseIdentifier {
+  self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
+  if (self) {
+    self.isAccessibilityElement = YES;
+    [self addSubviews];
+    [self setViewConstraints];
+    _imageView.contentMode = UIViewContentModeCenter;
+    _imageView.layer.masksToBounds = YES;
+    _imageView.contentMode = UIViewContentModeScaleAspectFit;
+
+    _textLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
+    _textLabel.adjustsFontForContentSizeCategory = YES;
+    _textLabel.textColor = UIColor.blackColor;
+    _detailTextLabel.font =
+        [UIFont preferredFontForTextStyle:UIFontTextStyleCaption1];
+    _detailTextLabel.adjustsFontForContentSizeCategory = YES;
+    _detailTextLabel.textColor = UIColorFromRGB(kSettingsCellsDetailTextColor);
+  }
+  return self;
+}
+
+// Create and add subviews.
+- (void)addSubviews {
+  UIView* contentView = self.contentView;
+  contentView.clipsToBounds = YES;
+
+  _imageView = [[UIImageView alloc] init];
+  _imageView.translatesAutoresizingMaskIntoConstraints = NO;
+  [contentView addSubview:_imageView];
+
+  _errorIcon = [[UIImageView alloc] init];
+  _errorIcon.translatesAutoresizingMaskIntoConstraints = NO;
+  [contentView addSubview:_errorIcon];
+
+  _textLabel = [[UILabel alloc] init];
+  _textLabel.translatesAutoresizingMaskIntoConstraints = NO;
+  [contentView addSubview:_textLabel];
+
+  _detailTextLabel = [[UILabel alloc] init];
+  _detailTextLabel.translatesAutoresizingMaskIntoConstraints = NO;
+  [contentView addSubview:_detailTextLabel];
+}
+
+// Set constraints on subviews.
+- (void)setViewConstraints {
+  UIView* contentView = self.contentView;
+
+  // This view is used to center the two leading textLabels.
+  UIView* verticalCenteringView = [[UIView alloc] init];
+  verticalCenteringView.translatesAutoresizingMaskIntoConstraints = NO;
+  [contentView addSubview:verticalCenteringView];
+
+  _textLeadingAnchorConstraint = [_textLabel.leadingAnchor
+      constraintEqualToAnchor:_imageView.trailingAnchor];
+  _errorIconWidthConstraint = [_errorIcon.widthAnchor
+      constraintEqualToConstant:kHorizontalErrorIconFixedSize];
+  [NSLayoutConstraint activateConstraints:@[
+    // Set leading anchors.
+    [_imageView.leadingAnchor
+        constraintEqualToAnchor:contentView.leadingAnchor
+                       constant:kTableViewHorizontalSpacing],
+    [_detailTextLabel.leadingAnchor
+        constraintEqualToAnchor:_textLabel.leadingAnchor],
+
+    // Fix image widths.
+    [_imageView.widthAnchor
+        constraintEqualToConstant:kHorizontalImageFixedSize],
+    [_imageView.heightAnchor constraintEqualToAnchor:_imageView.widthAnchor],
+    _errorIconWidthConstraint,
+
+    // Set vertical anchors.
+    [_imageView.centerYAnchor
+        constraintEqualToAnchor:contentView.centerYAnchor],
+    [_imageView.topAnchor
+        constraintGreaterThanOrEqualToAnchor:contentView.topAnchor
+                                    constant:kTableViewLargeVerticalSpacing],
+    [_imageView.bottomAnchor
+        constraintLessThanOrEqualToAnchor:contentView.bottomAnchor
+                                 constant:-kTableViewLargeVerticalSpacing],
+    [_textLabel.topAnchor
+        constraintEqualToAnchor:verticalCenteringView.topAnchor],
+    [_textLabel.bottomAnchor
+        constraintEqualToAnchor:_detailTextLabel.topAnchor],
+    [_detailTextLabel.bottomAnchor
+        constraintEqualToAnchor:verticalCenteringView.bottomAnchor],
+    [verticalCenteringView.centerYAnchor
+        constraintEqualToAnchor:contentView.centerYAnchor],
+    [_errorIcon.centerYAnchor
+        constraintEqualToAnchor:contentView.centerYAnchor],
+    [contentView.heightAnchor
+        constraintEqualToAnchor:verticalCenteringView.heightAnchor
+                       constant:kTableViewLargeVerticalSpacing],
+
+    // Set trailing anchors.
+    [_errorIcon.trailingAnchor
+        constraintEqualToAnchor:contentView.trailingAnchor
+                       constant:-kHorizontalPaddingBetweenImageAndText],
+    [_detailTextLabel.trailingAnchor
+        constraintEqualToAnchor:_errorIcon.leadingAnchor
+                       constant:-kHorizontalPaddingBetweenTextAndError],
+    _textLeadingAnchorConstraint,
+    [_textLabel.trailingAnchor
+        constraintLessThanOrEqualToAnchor:_errorIcon.leadingAnchor
+                                 constant:
+                                     -kHorizontalPaddingBetweenTextAndError],
+  ]];
+
+  // This is needed so the image doesn't get pushed out if both text and detail
+  // are long.
+  [_textLabel
+      setContentCompressionResistancePriority:UILayoutPriorityDefaultLow
+                                      forAxis:UILayoutConstraintAxisHorizontal];
+  [_detailTextLabel
+      setContentCompressionResistancePriority:UILayoutPriorityDefaultLow
+                                      forAxis:UILayoutConstraintAxisHorizontal];
+}
+
+#pragma mark - UIView
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  // Creates the image rounded corners.
+  _imageView.layer.cornerRadius = _imageView.bounds.size.width / 2.0f;
+
+  // Adjust the leading margin depending on existence of image.
+  if (_imageView.image) {
+    _textLeadingAnchorConstraint.constant =
+        kHorizontalPaddingBetweenImageAndText;
+  } else {
+    _textLeadingAnchorConstraint.constant = 0;
+  }
+
+  if (_errorIcon.image) {
+    _errorIconWidthConstraint.constant = kHorizontalErrorIconFixedSize;
+  } else {
+    _errorIconWidthConstraint.constant = 0;
+  }
+}
+
+#pragma mark - UITableViewCell
+
+- (void)prepareForReuse {
+  [super prepareForReuse];
+  self.imageView.image = nil;
+  self.textLabel.text = nil;
+  self.detailTextLabel.text = nil;
+  self.textLabel.textColor = UIColor.blackColor;
+  self.detailTextLabel.textColor =
+      UIColorFromRGB(kTableViewSecondaryLabelLightGrayTextColor);
+  self.errorIcon.image = nil;
+  self.accessoryType = UITableViewCellAccessoryNone;
+  self.userInteractionEnabled = YES;
+  self.contentView.alpha = 1;
+  UIImageView* accessoryImage =
+      base::mac::ObjCCastStrict<UIImageView>(self.accessoryView);
+  accessoryImage.tintColor =
+      [accessoryImage.tintColor colorWithAlphaComponent:1];
+}
+
+#pragma mark - NSObject(Accessibility)
+
+- (NSString*)accessibilityLabel {
+  return self.textLabel.text;
+}
+
+- (NSString*)accessibilityValue {
+  return self.detailTextLabel.text;
+}
+
+@end
diff --git a/ios/chrome/browser/ui/authentication/cells/table_view_account_item_unittest.mm b/ios/chrome/browser/ui/authentication/cells/table_view_account_item_unittest.mm
new file mode 100644
index 0000000..4796bb5
--- /dev/null
+++ b/ios/chrome/browser/ui/authentication/cells/table_view_account_item_unittest.mm
@@ -0,0 +1,45 @@
+// 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 "ios/chrome/browser/ui/authentication/cells/table_view_account_item.h"
+
+#import <CoreGraphics/CoreGraphics.h>
+#import <UIKit/UIKit.h>
+
+#import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+using AccountControlTableViewItemTest = PlatformTest;
+
+// Tests that the UIImageView and UILabels are set properly after a call to
+// |configureCell:|.
+TEST_F(AccountControlTableViewItemTest, ImageViewAndTextLabels) {
+  TableViewAccountItem* item = [[TableViewAccountItem alloc] initWithType:0];
+  UIImage* image = [[UIImage alloc] init];
+  NSString* mainText = @"Main text";
+  NSString* detailText = @"Detail text";
+
+  item.image = image;
+  item.text = mainText;
+  item.detailText = detailText;
+
+  id cell = [[[item cellClass] alloc] init];
+  ASSERT_TRUE([cell isMemberOfClass:[TableViewAccountCell class]]);
+
+  TableViewAccountCell* accountCell = cell;
+  EXPECT_FALSE(accountCell.imageView.image);
+  EXPECT_FALSE(accountCell.textLabel.text);
+  EXPECT_FALSE(accountCell.detailTextLabel.text);
+
+  [item configureCell:cell withStyler:[[ChromeTableViewStyler alloc] init]];
+  EXPECT_NSEQ(image, accountCell.imageView.image);
+  EXPECT_NSEQ(mainText, accountCell.textLabel.text);
+  EXPECT_NSEQ(detailText, accountCell.detailTextLabel.text);
+}
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 d42e269..1a700de 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
@@ -184,7 +184,7 @@
       NSString* view_name = NSStringFromClass([view class]);
       // Views that don't display strings.
       NSArray* other_views = @[
-        @"AccountControlCell",
+        @"LegacyAccountControlCell",
         @"CollectionViewFooterCell",
         @"IdentityPickerView",
         @"IdentityView",
diff --git a/ios/chrome/browser/ui/authentication/signin_confirmation_view_controller.mm b/ios/chrome/browser/ui/authentication/signin_confirmation_view_controller.mm
index ee4cc6d..0131fe88 100644
--- a/ios/chrome/browser/ui/authentication/signin_confirmation_view_controller.mm
+++ b/ios/chrome/browser/ui/authentication/signin_confirmation_view_controller.mm
@@ -10,7 +10,7 @@
 #include "components/google/core/common/google_util.h"
 #include "ios/chrome/browser/application_context.h"
 #include "ios/chrome/browser/signin/chrome_identity_service_observer_bridge.h"
-#import "ios/chrome/browser/ui/authentication/cells/account_control_item.h"
+#import "ios/chrome/browser/ui/authentication/cells/legacy_account_control_item.h"
 #import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrome.h"
 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_footer_item.h"
 #import "ios/chrome/browser/ui/collection_view/collection_view_model.h"
@@ -260,8 +260,8 @@
 #pragma mark - Model items
 
 - (CollectionViewItem*)syncItem {
-  AccountControlItem* item =
-      [[AccountControlItem alloc] initWithType:ItemTypeSync];
+  LegacyAccountControlItem* item =
+      [[LegacyAccountControlItem alloc] initWithType:ItemTypeSync];
   item.text = [self localizedConsentStringWithId:
                         IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_SYNC_TITLE];
   item.detailText =
@@ -274,8 +274,8 @@
 }
 
 - (CollectionViewItem*)googleServicesItem {
-  AccountControlItem* item =
-      [[AccountControlItem alloc] initWithType:ItemTypeGoogleServices];
+  LegacyAccountControlItem* item =
+      [[LegacyAccountControlItem alloc] initWithType:ItemTypeGoogleServices];
   item.text =
       [self localizedConsentStringWithId:
                 IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_SERVICES_TITLE];
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/card_view_controller_egtest.mm b/ios/chrome/browser/ui/autofill/manual_fill/card_view_controller_egtest.mm
index a36a33f..7f2f7044 100644
--- a/ios/chrome/browser/ui/autofill/manual_fill/card_view_controller_egtest.mm
+++ b/ios/chrome/browser/ui/autofill/manual_fill/card_view_controller_egtest.mm
@@ -19,6 +19,7 @@
 #import "ios/chrome/browser/ui/autofill/manual_fill/card_mediator.h"
 #import "ios/chrome/browser/ui/autofill/manual_fill/card_view_controller.h"
 #import "ios/chrome/browser/ui/autofill/manual_fill/manual_fill_accessory_view_controller.h"
+#import "ios/chrome/browser/ui/settings/autofill_credit_card_table_view_controller.h"
 #import "ios/chrome/browser/ui/util/ui_util.h"
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_actions.h"
@@ -92,7 +93,7 @@
 
 // Returns a matcher for the credit card settings collection view.
 id<GREYMatcher> CreditCardSettingsMatcher() {
-  return grey_accessibilityID(@"kAutofillCollectionViewId");
+  return grey_accessibilityID(kAutofillCreditCardTableViewId);
 }
 
 // Returns a matcher for the CreditCardTableView window.
diff --git a/ios/chrome/browser/ui/collection_view/cells/collection_view_account_item.h b/ios/chrome/browser/ui/collection_view/cells/collection_view_account_item.h
index dadaf0db..054c506 100644
--- a/ios/chrome/browser/ui/collection_view/cells/collection_view_account_item.h
+++ b/ios/chrome/browser/ui/collection_view/cells/collection_view_account_item.h
@@ -13,6 +13,7 @@
 
 @class ChromeIdentity;
 
+// TODO(crbug.com/894800): Remove this.
 // Item for account avatar, used everywhere an account cell is shown.
 @interface CollectionViewAccountItem : CollectionViewItem
 
diff --git a/ios/chrome/browser/ui/download/ar_quick_look_egtest.mm b/ios/chrome/browser/ui/download/ar_quick_look_egtest.mm
index f102de1..d5e7cbd5 100644
--- a/ios/chrome/browser/ui/download/ar_quick_look_egtest.mm
+++ b/ios/chrome/browser/ui/download/ar_quick_look_egtest.mm
@@ -94,9 +94,12 @@
   // QLPreviewController UI is rendered out of host process so EarlGrey matcher
   // can not find QLPreviewController UI. Instead this test relies on view
   // controller presentation as the signal that QLPreviewController UI is shown.
-  UIViewController* BVC = GetMainController().browserViewInformation.mainBVC;
+  id<BrowserInterface> interface =
+      GetMainController().interfaceProvider.mainInterface;
+  UIViewController* viewController = interface.viewController;
   bool shown = WaitUntilConditionOrTimeout(kWaitForDownloadTimeout, ^{
-    UIViewController* presentedController = BVC.presentedViewController;
+    UIViewController* presentedController =
+        viewController.presentedViewController;
     return [presentedController class] == [QLPreviewController class];
   });
   GREYAssert(shown, @"QLPreviewController was not shown.");
@@ -116,9 +119,12 @@
   // QLPreviewController UI is rendered out of host process so EarlGrey matcher
   // can not find QLPreviewController UI. Instead this test relies on view
   // controller presentation as the signal that QLPreviewController UI is shown.
-  UIViewController* BVC = GetMainController().browserViewInformation.mainBVC;
+  id<BrowserInterface> interface =
+      GetMainController().interfaceProvider.mainInterface;
+  UIViewController* viewController = interface.viewController;
   bool shown = WaitUntilConditionOrTimeout(kWaitForUIElementTimeout, ^{
-    UIViewController* presentedController = BVC.presentedViewController;
+    UIViewController* presentedController =
+        viewController.presentedViewController;
     return [presentedController class] == [QLPreviewController class];
   });
   GREYAssertFalse(shown, @"QLPreviewController should not have shown.");
@@ -138,9 +144,12 @@
   // QLPreviewController UI is rendered out of host process so EarlGrey matcher
   // can not find QLPreviewController UI. Instead this test relies on view
   // controller presentation as the signal that QLPreviewController UI is shown.
-  UIViewController* BVC = GetMainController().browserViewInformation.mainBVC;
+  id<BrowserInterface> interface =
+      GetMainController().interfaceProvider.mainInterface;
+  UIViewController* viewController = interface.viewController;
   bool shown = WaitUntilConditionOrTimeout(kWaitForUIElementTimeout, ^{
-    UIViewController* presentedController = BVC.presentedViewController;
+    UIViewController* presentedController =
+        viewController.presentedViewController;
     return [presentedController class] == [QLPreviewController class];
   });
   GREYAssertFalse(shown, @"QLPreviewController should not have shown.");
@@ -160,9 +169,12 @@
   // QLPreviewController UI is rendered out of host process so EarlGrey matcher
   // can not find QLPreviewController UI. Instead this test relies on view
   // controller presentation as the signal that QLPreviewController UI is shown.
-  UIViewController* BVC = GetMainController().browserViewInformation.mainBVC;
+  id<BrowserInterface> interface =
+      GetMainController().interfaceProvider.mainInterface;
+  UIViewController* viewController = interface.viewController;
   bool shown = WaitUntilConditionOrTimeout(kWaitForUIElementTimeout, ^{
-    UIViewController* presentedController = BVC.presentedViewController;
+    UIViewController* presentedController =
+        viewController.presentedViewController;
     return [presentedController class] == [QLPreviewController class];
   });
   GREYAssertFalse(shown, @"QLPreviewController should not have shown.");
diff --git a/ios/chrome/browser/ui/download/pass_kit_egtest.mm b/ios/chrome/browser/ui/download/pass_kit_egtest.mm
index 178d4d8c..4969e0f 100644
--- a/ios/chrome/browser/ui/download/pass_kit_egtest.mm
+++ b/ios/chrome/browser/ui/download/pass_kit_egtest.mm
@@ -105,9 +105,12 @@
   // PKAddPassesViewController UI is rendered out of host process so EarlGrey
   // matcher can not find PassKit Dialog UI. Instead this test relies on view
   // controller presentation as the signal that PassKit Dialog is shown.
-  UIViewController* BVC = GetMainController().browserViewInformation.mainBVC;
+  id<BrowserInterface> interface =
+      GetMainController().interfaceProvider.mainInterface;
+  UIViewController* viewController = interface.viewController;
   bool dialogShown = WaitUntilConditionOrTimeout(kWaitForDownloadTimeout, ^{
-    UIViewController* presentedController = BVC.presentedViewController;
+    UIViewController* presentedController =
+        viewController.presentedViewController;
     return [presentedController class] == [PKAddPassesViewController class];
   });
   GREYAssert(dialogShown, @"PassKit dialog was not shown");
diff --git a/ios/chrome/browser/ui/infobars/infobar_egtest.mm b/ios/chrome/browser/ui/infobars/infobar_egtest.mm
index f8ef228..17dbfab 100644
--- a/ios/chrome/browser/ui/infobars/infobar_egtest.mm
+++ b/ios/chrome/browser/ui/infobars/infobar_egtest.mm
@@ -36,11 +36,11 @@
 // (non-incognito) mode.
 infobars::InfoBarManager* GetCurrentInfoBarManager() {
   MainController* main_controller = chrome_test_util::GetMainController();
-  web::WebState* webState =
-      [[[[main_controller browserViewInformation] mainTabModel] currentTab]
-          webState];
-  if (webState) {
-    return InfoBarManagerImpl::FromWebState(webState);
+  id<BrowserInterface> interface =
+      main_controller.interfaceProvider.mainInterface;
+  web::WebState* web_state = interface.tabModel.currentTab.webState;
+  if (web_state) {
+    return InfoBarManagerImpl::FromWebState(web_state);
   }
   return nullptr;
 }
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
index effb44b..4d27becb 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
+++ b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
@@ -75,6 +75,11 @@
 @property(nonatomic, strong) LocationBarMediator* mediator;
 @property(nonatomic, strong) LocationBarViewController* viewController;
 
+// Tracks calls in progress to -cancelOmniboxEdit to avoid calling it from
+// itself when -resignFirstResponder causes -textFieldWillResignFirstResponder
+// delegate call.
+@property(nonatomic, assign) BOOL isCancellingOmniboxEdit;
+
 @end
 
 @implementation LocationBarCoordinator
@@ -274,8 +279,13 @@
 }
 
 - (void)cancelOmniboxEdit {
+  if (self.isCancellingOmniboxEdit) {
+    return;
+  }
+  self.isCancellingOmniboxEdit = YES;
   [self.omniboxCoordinator endEditing];
   [self.omniboxPopupCoordinator closePopup];
+  self.isCancellingOmniboxEdit = NO;
 }
 
 #pragma mark - LocationBarDelegate
diff --git a/ios/chrome/browser/ui/main/BUILD.gn b/ios/chrome/browser/ui/main/BUILD.gn
index 88a1052d..9341a97c 100644
--- a/ios/chrome/browser/ui/main/BUILD.gn
+++ b/ios/chrome/browser/ui/main/BUILD.gn
@@ -7,7 +7,7 @@
   sources = [
     "browser_coordinator.h",
     "browser_coordinator.mm",
-    "browser_view_information.h",
+    "browser_interface_provider.h",
     "browser_view_wrangler.h",
     "browser_view_wrangler.mm",
     "bvc_container_view_controller.h",
diff --git a/ios/chrome/browser/ui/main/browser_interface_provider.h b/ios/chrome/browser/ui/main/browser_interface_provider.h
new file mode 100644
index 0000000..142e8bb
--- /dev/null
+++ b/ios/chrome/browser/ui/main/browser_interface_provider.h
@@ -0,0 +1,86 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_MAIN_BROWSER_INTERFACE_PROVIDER_H_
+#define IOS_CHROME_BROWSER_UI_MAIN_BROWSER_INTERFACE_PROVIDER_H_
+
+#import <UIKit/UIKit.h>
+
+#include "base/ios/block_types.h"
+
+@class BrowserCoordinator;
+@class BrowserViewController;
+@class TabModel;
+
+namespace ios {
+class ChromeBrowserState;
+}
+
+// A BrowserInterface is an abstraction that exposes an interface to the Chrome
+// user interface (and related model objects) to the application layer. Each
+// BrowserInterface is roughly equivalent to a window on a desktop browser --
+// a collection of tabs (a tab model) associated with a user profile (the
+// browser state) with the UI of the currently visible tab (the view controller)
+// and some other attributes as well.
+// TODO(crbug.com/914306): The long-term goal is to reduce the size of this
+// interface; this protocol allows for easy encapsulation of that process.
+// For legacy reasons, the primary UI entry point for an interface is a visible
+// tab.
+// A given interface is scoped (currently) to a browser state; thus there can
+// be two interfaces available (a one incognito and the other not).
+@protocol BrowserInterface
+
+// The view controller showing the current tab for this interface. This property
+// should be used wherever possible instead of the |bvc| property.
+@property(nonatomic, readonly) UIViewController* viewController;
+// The BrowserViewController showing the current tab. The API surface this
+// property exposes will be refactored so that the BVC class isn't exposed.
+@property(nonatomic, readonly) BrowserViewController* bvc;
+// The tab model to which the current tab belongs.
+@property(nonatomic, readonly) TabModel* tabModel;
+// The browser state for this interface.
+@property(nonatomic, readonly) ios::ChromeBrowserState* browserState;
+// YES if the tab view is available for user interaction.
+@property(nonatomic) BOOL userInteractionEnabled;
+// YES if this interface is incognito.
+@property(nonatomic, readonly) BOOL incognito;
+
+// Asks the implementor to clear any presented state, dismissing the omnibox if
+// |dismissOmnibox| is YES, and calling |completion| once any animations are
+// complete.
+- (void)clearPresentedStateWithCompletion:(ProceduralBlock)completion
+                           dismissOmnibox:(BOOL)dismissOmnibox;
+
+@end
+
+// A BrowserInterfaceProvider is an abstraction that exposes the available
+// interfaces for the Chrome UI.
+@protocol BrowserInterfaceProvider
+
+// One interface must be designated as being the "current" interface.
+// It's typically an error to assign this an interface which is neither of
+// mainInterface| or |incognitoInterface|. The initial value of
+// |currentInterface| is an implementation decision, but |mainInterface| is
+// typical.
+// Changing this value may or may not trigger actual UI changes, or may just be
+// bookkeeping associated with UI changes handled elsewhere. The only invariant
+// is that |currentInterface.current| must be YES, and the |current| value of
+// any other interface must be NO.
+@property(nonatomic, weak) id<BrowserInterface> currentInterface;
+// The "main" (meaning non-incognito -- the nomenclature is legacy) interface.
+// This interface's |incognito| property is expected to be NO.
+@property(nonatomic, readonly) id<BrowserInterface> mainInterface;
+// The incognito interface. Its |incognito| property must be YES.
+@property(nonatomic, readonly) id<BrowserInterface> incognitoInterface;
+
+// Legacy methods that affect multiple (or no) interfaces.
+// Halts all tabs from all interfaces.
+- (void)haltAllTabs;
+
+// Clean up the device sharing manager.
+- (void)cleanDeviceSharingManager;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_MAIN_BROWSER_INTERFACE_PROVIDER_H_
diff --git a/ios/chrome/browser/ui/main/browser_view_information.h b/ios/chrome/browser/ui/main/browser_view_information.h
deleted file mode 100644
index 6e991ce7..0000000
--- a/ios/chrome/browser/ui/main/browser_view_information.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_UI_MAIN_BROWSER_VIEW_INFORMATION_H_
-#define IOS_CHROME_BROWSER_UI_MAIN_BROWSER_VIEW_INFORMATION_H_
-
-#import <Foundation/Foundation.h>
-
-@class BrowserCoordinator;
-@class BrowserViewController;
-@class TabModel;
-
-namespace ios {
-class ChromeBrowserState;
-}
-
-// Information about the Browser View, controllers and tab model.
-@protocol BrowserViewInformation<NSObject>
-
-// The normal (non-incognito, non-OTR) BrowserCoordinator.
-@property(nonatomic, strong, readonly)
-    BrowserCoordinator* mainBrowserCoordinator;
-// The incognito (a.k.a OTR) BrowserCoordinator.
-@property(nonatomic, strong, readonly)
-    BrowserCoordinator* incognitoBrowserCoordinator;
-// The BrowserCoordinator that is currently being used (one of mainBVC or
-// otrBVC). The other, if present, is in suspended mode..
-@property(nonatomic, weak, readonly)
-    BrowserCoordinator* currentBrowserCoordinator;
-
-// The BrowserViewController corresponding to |mainBrowserCoordinator|.
-@property(nonatomic, readonly) BrowserViewController* mainBVC;
-// The normal (non-OTR) TabModel corresponding to |mainBrowserCoordinator|.
-@property(nonatomic, retain) TabModel* mainTabModel;
-// The BrowserViewController corresponding to |incognitoBrowserCoordinator|.
-@property(nonatomic, readonly) BrowserViewController* otrBVC;
-// The OTR TabModel corresponding to |incognitoBrowserCoordinator|.
-@property(nonatomic, retain) TabModel* otrTabModel;
-// The BrowserViewController corresponding to |currentBrowserCoordinator|.
-@property(nonatomic, readonly) BrowserViewController* currentBVC;
-
-// Halts all tabs from all TabModels.
-- (void)haltAllTabs;
-
-// Returns the browser state corresponding to the current browser view.
-- (ios::ChromeBrowserState*)currentBrowserState;
-
-// Returns the tab model corresponding to the current browser view.
-- (TabModel*)currentTabModel;
-
-// Clean up the device sharing manager.
-- (void)cleanDeviceSharingManager;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_MAIN_BROWSER_VIEW_INFORMATION_H_
diff --git a/ios/chrome/browser/ui/main/browser_view_wrangler.h b/ios/chrome/browser/ui/main/browser_view_wrangler.h
index f8783e3a..8a356a60 100644
--- a/ios/chrome/browser/ui/main/browser_view_wrangler.h
+++ b/ios/chrome/browser/ui/main/browser_view_wrangler.h
@@ -7,7 +7,7 @@
 
 #import <UIKit/UIKit.h>
 
-#import "ios/chrome/browser/ui/main/browser_view_information.h"
+#import "ios/chrome/browser/ui/main/browser_interface_provider.h"
 
 @protocol ApplicationCommands;
 @class BrowserCoordinator;
@@ -27,30 +27,30 @@
 // Wrangler (a class in need of further refactoring) for handling the creation
 // and ownership of BrowserViewController instances and their associated
 // TabModels, and a few related methods.
-@interface BrowserViewWrangler : NSObject<BrowserViewInformation>
+@interface BrowserViewWrangler : NSObject <BrowserInterfaceProvider>
 
 // Initialize a new instance of this class using |browserState| as the primary
 // browser state for the tab models and BVCs, and setting |tabModelObserver|, if
 // not nil, as the tab model delegate for any tab models that are created.
 // |applicationCommandEndpoint| is the object that methods in the
 // ApplicationCommands protocol should be dispatched to by any BVCs that are
-// created.
+// created. |storageSwitcher| is used to manage changing any storage associated
+// with the interfaces when the current interface changes; this is handled in
+// the implementation of -setCurrentInterface:.
 - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState
                     tabModelObserver:(id<TabModelObserver>)tabModelObserver
           applicationCommandEndpoint:
               (id<ApplicationCommands>)applicationCommandEndpoint
+                     storageSwitcher:
+                         (id<BrowserStateStorageSwitching>)storageSwitcher
     NS_DESIGNATED_INITIALIZER;
 
 - (instancetype)init NS_UNAVAILABLE;
 
-// Set the current BrowserCoordinator to be |browserCoordinator|, and use
-// |storageSwitcher| to handle the storage switch. |browserCoordinator| should
-// be one of the BrowserCoordinator instances already owned by the receiver
-// (either |mainBrowserCoordinator| or |incognitoBrowserCoordinator|), and this
-// method does not retain or take ownership of |browserCoordinator|.
-- (void)setCurrentBrowserCoordinator:(BrowserCoordinator*)browserCoordinator
-                     storageSwitcher:
-                         (id<BrowserStateStorageSwitching>)storageSwitcher;
+// Creates the main tab model used by the receiver, using the browser state
+// and tab model observer it was configured with. This should be done before
+// the main interface is accessed, usually immediatley after initialization.
+- (void)createMainTabModel;
 
 // Update the device sharing manager. This should be done after updates to the
 // tab model. This class creates and manages the state of the sharing manager.
@@ -66,6 +66,8 @@
 
 @interface BrowserViewWrangler (Testing)
 @property(nonatomic, readonly) DeviceSharingManager* deviceSharingManager;
+@property(nonatomic) TabModel* mainTabModel;
+@property(nonatomic) TabModel* otrTabModel;
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_MAIN_BROWSER_VIEW_WRANGLER_H_
diff --git a/ios/chrome/browser/ui/main/browser_view_wrangler.mm b/ios/chrome/browser/ui/main/browser_view_wrangler.mm
index ea28b5e4..a155e56 100644
--- a/ios/chrome/browser/ui/main/browser_view_wrangler.mm
+++ b/ios/chrome/browser/ui/main/browser_view_wrangler.mm
@@ -26,13 +26,78 @@
 #error "This file requires ARC support."
 #endif
 
+// Internal implementation of BrowserInterface -- for the most part a wrapper
+// around BrowserCoordinator.
+@interface WrangledBrowser : NSObject <BrowserInterface>
+
+@property(nonatomic, weak, readonly) BrowserCoordinator* coordinator;
+
+- (instancetype)initWithCoordinator:(BrowserCoordinator*)coordinator;
+
+@end
+
+@implementation WrangledBrowser
+
+- (instancetype)initWithCoordinator:(BrowserCoordinator*)coordinator {
+  if (self = [super init]) {
+    _coordinator = coordinator;
+  }
+  return self;
+}
+
+- (UIViewController*)viewController {
+  return self.coordinator.viewController;
+}
+
+- (BrowserViewController*)bvc {
+  return self.coordinator.viewController;
+}
+
+- (TabModel*)tabModel {
+  return self.coordinator.tabModel;
+}
+
+- (ios::ChromeBrowserState*)browserState {
+  return self.coordinator.viewController.browserState;
+}
+
+- (BOOL)userInteractionEnabled {
+  return self.coordinator.active;
+}
+
+- (void)setUserInteractionEnabled:(BOOL)userInteractionEnabled {
+  self.coordinator.active = userInteractionEnabled;
+}
+
+- (BOOL)incognito {
+  return self.browserState->IsOffTheRecord();
+}
+
+- (void)clearPresentedStateWithCompletion:(ProceduralBlock)completion
+                           dismissOmnibox:(BOOL)dismissOmnibox {
+  [self.coordinator clearPresentedStateWithCompletion:completion
+                                       dismissOmnibox:dismissOmnibox];
+}
+
+@end
+
 @interface BrowserViewWrangler ()<TabModelObserver> {
   ios::ChromeBrowserState* _browserState;
   __weak id<TabModelObserver> _tabModelObserver;
   __weak id<ApplicationCommands> _applicationCommandEndpoint;
+  __weak id<BrowserStateStorageSwitching> _storageSwitcher;
   BOOL _isShutdown;
 }
 
+@property(nonatomic, strong, readwrite) WrangledBrowser* mainInterface;
+@property(nonatomic, strong, readwrite) WrangledBrowser* incognitoInterface;
+
+// Backing objects.
+@property(nonatomic) BrowserCoordinator* mainBrowserCoordinator;
+@property(nonatomic) BrowserCoordinator* incognitoBrowserCoordinator;
+@property(nonatomic) TabModel* mainTabModel;
+@property(nonatomic) TabModel* otrTabModel;
+
 // Responsible for maintaining all state related to sharing to other devices.
 // Redeclared readwrite from the readonly declaration in the Testing interface.
 @property(nonatomic, strong, readwrite)
@@ -58,23 +123,21 @@
 
 @implementation BrowserViewWrangler
 
-// Properties defined in the BrowserViewInformation protocol.
-@synthesize mainBrowserCoordinator = _mainBrowserCoordinator;
-@synthesize incognitoBrowserCoordinator = _incognitoBrowserCoordinator;
-@synthesize currentBrowserCoordinator = _currentBrowserCoordinator;
+@synthesize currentInterface = _currentInterface;
 @synthesize mainTabModel = _mainTabModel;
 @synthesize otrTabModel = _otrTabModel;
-// Private properies.
-@synthesize deviceSharingManager = _deviceSharingManager;
 
 - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState
                     tabModelObserver:(id<TabModelObserver>)tabModelObserver
           applicationCommandEndpoint:
-              (id<ApplicationCommands>)applicationCommandEndpoint {
+              (id<ApplicationCommands>)applicationCommandEndpoint
+                     storageSwitcher:
+                         (id<BrowserStateStorageSwitching>)storageSwitcher {
   if ((self = [super init])) {
     _browserState = browserState;
     _tabModelObserver = tabModelObserver;
     _applicationCommandEndpoint = applicationCommandEndpoint;
+    _storageSwitcher = storageSwitcher;
   }
   return self;
 }
@@ -83,32 +146,78 @@
   DCHECK(_isShutdown) << "-shutdown must be called before -dealloc";
 }
 
+- (void)createMainTabModel {
+  self.mainTabModel = [self tabModelForBrowserState:_browserState empty:NO];
+  // Follow loaded URLs in the main tab model to send those in case of
+  // crashes.
+  breakpad::MonitorURLsForTabModel(_mainTabModel);
+  ios::GetChromeBrowserProvider()->InitializeCastService(_mainTabModel);
+}
+
 #pragma mark - BrowserViewInformation property implementations
 
-- (BrowserCoordinator*)mainBrowserCoordinator {
-  if (!_mainBrowserCoordinator) {
+- (void)setCurrentInterface:(WrangledBrowser*)interface {
+  DCHECK(interface);
+  // |interface| must be one of the interfaces this class already owns.
+  DCHECK(self.mainInterface == interface ||
+         self.incognitoInterface == interface);
+  if (self.currentInterface == interface) {
+    return;
+  }
+
+  if (self.currentInterface) {
+    // Tell the current BVC it moved to the background.
+    [self.currentInterface.bvc setPrimary:NO];
+
+    // Data storage for the browser is always owned by the current BVC, so it
+    // must be updated when switching between BVCs.
+    [_storageSwitcher
+        changeStorageFromBrowserState:self.currentInterface.browserState
+                       toBrowserState:interface.browserState];
+  }
+
+  _currentInterface = interface;
+
+  // The internal state of the Handoff Manager depends on the current BVC.
+  [self updateDeviceSharingManager];
+}
+
+- (id<BrowserInterface>)mainInterface {
+  if (!_mainInterface) {
+    // The backing coordinator should not have been created yet.
+    DCHECK(!_mainBrowserCoordinator);
     _mainBrowserCoordinator =
         [self coordinatorForBrowserState:_browserState
                                 tabModel:self.mainTabModel];
     [_mainBrowserCoordinator start];
     DCHECK(_mainBrowserCoordinator.viewController);
+    _mainInterface =
+        [[WrangledBrowser alloc] initWithCoordinator:_mainBrowserCoordinator];
   }
-  return _mainBrowserCoordinator;
+  return _mainInterface;
 }
 
-- (BrowserViewController*)mainBVC {
-  DCHECK(self.mainBrowserCoordinator.viewController);
-  return self.mainBrowserCoordinator.viewController;
+- (id<BrowserInterface>)incognitoInterface {
+  if (!_incognitoInterface) {
+    // The backing coordinator should not have been created yet.
+    DCHECK(!_incognitoBrowserCoordinator);
+    ios::ChromeBrowserState* otrBrowserState =
+        _browserState->GetOffTheRecordChromeBrowserState();
+    DCHECK(otrBrowserState);
+    _incognitoBrowserCoordinator =
+        [self coordinatorForBrowserState:otrBrowserState
+                                tabModel:self.otrTabModel];
+    [_incognitoBrowserCoordinator start];
+    DCHECK(_incognitoBrowserCoordinator.viewController);
+    _incognitoInterface = [[WrangledBrowser alloc]
+        initWithCoordinator:_incognitoBrowserCoordinator];
+  }
+  return _incognitoInterface;
 }
 
 - (TabModel*)mainTabModel {
-  if (!_mainTabModel) {
-    self.mainTabModel = [self tabModelForBrowserState:_browserState empty:NO];
-    // Follow loaded URLs in the main tab model to send those in case of
-    // crashes.
-    breakpad::MonitorURLsForTabModel(_mainTabModel);
-    ios::GetChromeBrowserProvider()->InitializeCastService(_mainTabModel);
-  }
+  DCHECK(_mainTabModel)
+      << "-createMainTabModel must be called before -mainTabModel is accessed.";
   return _mainTabModel;
 }
 
@@ -129,25 +238,6 @@
   _mainTabModel = mainTabModel;
 }
 
-- (BrowserCoordinator*)incognitoBrowserCoordinator {
-  if (!_incognitoBrowserCoordinator) {
-    ios::ChromeBrowserState* otrBrowserState =
-        _browserState->GetOffTheRecordChromeBrowserState();
-    DCHECK(otrBrowserState);
-    _incognitoBrowserCoordinator =
-        [self coordinatorForBrowserState:otrBrowserState
-                                tabModel:self.otrTabModel];
-    [_incognitoBrowserCoordinator start];
-    DCHECK(_incognitoBrowserCoordinator.viewController);
-  }
-  return _incognitoBrowserCoordinator;
-}
-
-- (BrowserViewController*)otrBVC {
-  DCHECK(self.incognitoBrowserCoordinator.viewController);
-  return self.incognitoBrowserCoordinator.viewController;
-}
-
 - (TabModel*)otrTabModel {
   if (!_otrTabModel) {
     self.otrTabModel = [self buildOtrTabModel:NO];
@@ -171,50 +261,8 @@
   _otrTabModel = otrTabModel;
 }
 
-- (void)setCurrentBrowserCoordinator:(BrowserCoordinator*)browserCoordinator
-                     storageSwitcher:
-                         (id<BrowserStateStorageSwitching>)storageSwitcher {
-  DCHECK(browserCoordinator);
-  // |browserCoordinator| should be one of the BrowserCoordinators this class
-  // already owns.
-  DCHECK(self.mainBrowserCoordinator == browserCoordinator ||
-         self.incognitoBrowserCoordinator == browserCoordinator);
-  if (self.currentBrowserCoordinator == browserCoordinator) {
-    return;
-  }
-
-  if (self.currentBrowserCoordinator) {
-    // Tell the current BVC it moved to the background.
-    [self.currentBrowserCoordinator.viewController setPrimary:NO];
-
-    // Data storage for the browser is always owned by the current BVC, so it
-    // must be updated when switching between BVCs.
-    [storageSwitcher
-        changeStorageFromBrowserState:self.currentBrowserCoordinator
-                                          .browserState
-                       toBrowserState:browserCoordinator.browserState];
-  }
-
-  _currentBrowserCoordinator = browserCoordinator;
-
-  // The internal state of the Handoff Manager depends on the current BVC.
-  [self updateDeviceSharingManager];
-}
-
-- (BrowserViewController*)currentBVC {
-  return self.currentBrowserCoordinator.viewController;
-}
-
 #pragma mark - BrowserViewInformation methods
 
-- (TabModel*)currentTabModel {
-  return self.currentBrowserCoordinator.tabModel;
-}
-
-- (ios::ChromeBrowserState*)currentBrowserState {
-  return self.currentBrowserCoordinator.browserState;
-}
-
 - (void)haltAllTabs {
   [self.mainTabModel haltAllTabs];
   [self.otrTabModel haltAllTabs];
@@ -246,10 +294,9 @@
   [self.deviceSharingManager updateBrowserState:_browserState];
 
   GURL activeURL;
-  Tab* currentTab = self.currentBrowserCoordinator.tabModel.currentTab;
+  Tab* currentTab = self.currentInterface.tabModel.currentTab;
   // Set the active URL if there's a current tab and the current BVC is not OTR.
-  if (currentTab.webState &&
-      self.currentBrowserCoordinator != self.incognitoBrowserCoordinator) {
+  if (currentTab.webState && !self.currentInterface.incognito) {
     activeURL = currentTab.webState->GetVisibleURL();
   }
   [self.deviceSharingManager updateActiveURL:activeURL];
@@ -267,19 +314,19 @@
 
   // At this stage, a new incognitoBrowserCoordinator shouldn't be lazily
   // constructed by calling the property getter.
-  BOOL otrBVCIsCurrent =
-      self.currentBrowserCoordinator == _incognitoBrowserCoordinator;
+  BOOL otrBVCIsCurrent = self.currentInterface == self.incognitoInterface;
   @autoreleasepool {
     // At this stage, a new incognitoBrowserCoordinator shouldn't be lazily
     // constructed by calling the property getter.
     [_incognitoBrowserCoordinator stop];
     _incognitoBrowserCoordinator = nil;
+    _incognitoInterface = nil;
 
     // There's no guarantee the tab model was ever added to the BVC (or even
     // that the BVC was created), so ensure the tab model gets notified.
     self.otrTabModel = nil;
     if (otrBVCIsCurrent) {
-      _currentBrowserCoordinator = nil;
+      _currentInterface = nil;
     }
   }
 
@@ -294,7 +341,7 @@
   DCHECK(_browserState->HasOffTheRecordChromeBrowserState());
 
   if (otrBVCIsCurrent) {
-    _currentBrowserCoordinator = self.incognitoBrowserCoordinator;
+    self.currentInterface = self.incognitoInterface;
   }
 }
 
diff --git a/ios/chrome/browser/ui/main/browser_view_wrangler_unittest.mm b/ios/chrome/browser/ui/main/browser_view_wrangler_unittest.mm
index 27e6d86a..ecdac90a 100644
--- a/ios/chrome/browser/ui/main/browser_view_wrangler_unittest.mm
+++ b/ios/chrome/browser/ui/main/browser_view_wrangler_unittest.mm
@@ -35,25 +35,23 @@
   @autoreleasepool {
     BrowserViewWrangler* wrangler = [[BrowserViewWrangler alloc]
               initWithBrowserState:chrome_browser_state_.get()
-
                   tabModelObserver:nil
-        applicationCommandEndpoint:(id<ApplicationCommands>)nil];
-    // Test that BVC and tab model are created on demand.
-    BrowserViewController* bvc = [wrangler mainBVC];
+        applicationCommandEndpoint:(id<ApplicationCommands>)nil
+                   storageSwitcher:nil];
+    [wrangler createMainTabModel];
+    // Test that BVC is created on demand.
+    BrowserViewController* bvc = wrangler.mainInterface.bvc;
     EXPECT_NE(bvc, nil);
 
-    TabModel* tabModel = [wrangler mainTabModel];
-    EXPECT_NE(tabModel, nil);
-
-    // Test that once created the BVC and tab model aren't re-created.
-    EXPECT_EQ(bvc, [wrangler mainBVC]);
-    EXPECT_EQ(tabModel, [wrangler mainTabModel]);
+    // Test that once created the BVC isn't re-created.
+    EXPECT_EQ(bvc, wrangler.mainInterface.bvc);
 
     // Test that the OTR objects are (a) OTR and (b) not the same as the non-OTR
     // objects.
-    EXPECT_NE(bvc, [wrangler otrBVC]);
-    EXPECT_NE(tabModel, [wrangler otrTabModel]);
-    EXPECT_TRUE([wrangler otrTabModel].browserState->IsOffTheRecord());
+    EXPECT_NE(bvc, wrangler.incognitoInterface.bvc);
+    EXPECT_NE(wrangler.mainInterface.tabModel,
+              wrangler.incognitoInterface.tabModel);
+    EXPECT_TRUE(wrangler.incognitoInterface.browserState->IsOffTheRecord());
 
     [wrangler shutdown];
   }
diff --git a/ios/chrome/browser/ui/main/test/BUILD.gn b/ios/chrome/browser/ui/main/test/BUILD.gn
new file mode 100644
index 0000000..6af2ba7
--- /dev/null
+++ b/ios/chrome/browser/ui/main/test/BUILD.gn
@@ -0,0 +1,16 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("test") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  sources = [
+    "stub_browser_interface.h",
+    "stub_browser_interface.mm",
+    "stub_browser_interface_provider.h",
+    "stub_browser_interface_provider.mm",
+  ]
+  deps = [
+    "//ios/chrome/browser/ui/main",
+  ]
+}
diff --git a/ios/chrome/browser/ui/main/test/stub_browser_interface.h b/ios/chrome/browser/ui/main/test/stub_browser_interface.h
new file mode 100644
index 0000000..a53b1e1
--- /dev/null
+++ b/ios/chrome/browser/ui/main/test/stub_browser_interface.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 IOS_CHROME_BROWSER_UI_MAIN_TEST_STUB_BROWSER_INTERFACE_H_
+#define IOS_CHROME_BROWSER_UI_MAIN_TEST_STUB_BROWSER_INTERFACE_H_
+
+#import <Foundation/Foundation.h>
+
+#import "ios/chrome/browser/ui/main/browser_interface_provider.h"
+
+@class BrowserViewController;
+namespace ios {
+class ChromeBrowserState;
+}
+@class TabModel;
+
+// Test double for BrowserInterface implementors. All properties are writable,
+// and have nil, nullptr, or NO as default values.
+@interface StubBrowserInterface : NSObject <BrowserInterface>
+@property(nonatomic, readwrite) UIViewController* viewController;
+@property(nonatomic, readwrite) BrowserViewController* bvc;
+@property(nonatomic, readwrite) TabModel* tabModel;
+@property(nonatomic, readwrite) ios::ChromeBrowserState* browserState;
+@property(nonatomic, readwrite) BOOL incognito;
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_MAIN_TEST_STUB_BROWSER_INTERFACE_H_
diff --git a/ios/chrome/browser/ui/main/test/stub_browser_interface.mm b/ios/chrome/browser/ui/main/test/stub_browser_interface.mm
new file mode 100644
index 0000000..615a0c4
--- /dev/null
+++ b/ios/chrome/browser/ui/main/test/stub_browser_interface.mm
@@ -0,0 +1,20 @@
+// 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 "ios/chrome/browser/ui/main/test/stub_browser_interface.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@implementation StubBrowserInterface
+
+@synthesize userInteractionEnabled = _userInteractionEnabled;
+
+- (void)clearPresentedStateWithCompletion:(ProceduralBlock)completion
+                           dismissOmnibox:(BOOL)dismissOmnibox {
+  // no-op
+}
+
+@end
diff --git a/ios/chrome/browser/ui/main/test/stub_browser_interface_provider.h b/ios/chrome/browser/ui/main/test/stub_browser_interface_provider.h
new file mode 100644
index 0000000..3804a01
--- /dev/null
+++ b/ios/chrome/browser/ui/main/test/stub_browser_interface_provider.h
@@ -0,0 +1,31 @@
+// 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 IOS_CHROME_BROWSER_UI_MAIN_TEST_STUB_BROWSER_INTERFACE_PROVIDER_H_
+#define IOS_CHROME_BROWSER_UI_MAIN_TEST_STUB_BROWSER_INTERFACE_PROVIDER_H_
+
+#import <Foundation/Foundation.h>
+
+#import "ios/chrome/browser/ui/main/browser_interface_provider.h"
+#import "ios/chrome/browser/ui/main/test/stub_browser_interface.h"
+
+// Test double for BrowserInterfaceProvider implementors. All properties are
+// writeable. It behaves as follows:
+// - It creates two StubBrowserInterfaces on init.
+// - |currentInterface| is settable and defaults to the main interface.
+// - The current interface is has |current| set to YES on init.
+// - The incoignito interface has |incognito| set to YES on init.
+// - All other methods are no-ops, and there is no control logic to update the
+//   interfaces in any way after init.
+@interface StubBrowserInterfaceProvider : NSObject <BrowserInterfaceProvider>
+
+// Specify concrete (stub) implementations for the interfaces, so tests can
+// set values on them.
+@property(nonatomic, weak, readwrite) StubBrowserInterface* currentInterface;
+@property(nonatomic, readwrite) StubBrowserInterface* mainInterface;
+@property(nonatomic, readwrite) StubBrowserInterface* incognitoInterface;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_MAIN_TEST_STUB_BROWSER_INTERFACE_PROVIDER_H_
diff --git a/ios/chrome/browser/ui/main/test/stub_browser_interface_provider.mm b/ios/chrome/browser/ui/main/test/stub_browser_interface_provider.mm
new file mode 100644
index 0000000..40ce72bc
--- /dev/null
+++ b/ios/chrome/browser/ui/main/test/stub_browser_interface_provider.mm
@@ -0,0 +1,32 @@
+// 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 "ios/chrome/browser/ui/main/test/stub_browser_interface_provider.h"
+
+#import "ios/chrome/browser/ui/main/test/stub_browser_interface.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@implementation StubBrowserInterfaceProvider
+
+- (instancetype)init {
+  if (self = [super init]) {
+    _mainInterface = [[StubBrowserInterface alloc] init];
+    _incognitoInterface = [[StubBrowserInterface alloc] init];
+    _incognitoInterface.incognito = YES;
+    _currentInterface = _mainInterface;
+  }
+  return self;
+}
+
+- (void)haltAllTabs {
+  // no-op
+}
+
+- (void)cleanDeviceSharingManager {
+  // no-op
+}
+@end
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_coordinator.mm b/ios/chrome/browser/ui/omnibox/omnibox_coordinator.mm
index 9c251d38..4793a6e 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_coordinator.mm
+++ b/ios/chrome/browser/ui/omnibox/omnibox_coordinator.mm
@@ -70,8 +70,11 @@
   self.mediator.consumer = self.viewController;
 
   DCHECK(self.editController);
+
+  id<OmniboxFocuser> focuser = static_cast<id<OmniboxFocuser>>(self.dispatcher);
   _editView = std::make_unique<OmniboxViewIOS>(
-      self.textField, self.editController, self.mediator, self.browserState);
+      self.textField, self.editController, self.mediator, self.browserState,
+      focuser);
 
   // Configure the textfield.
   self.textField.suggestionCommandsEndpoint =
@@ -113,7 +116,8 @@
 }
 
 - (void)endEditing {
-  _editView->HideKeyboardAndEndEditing();
+  [self.textField resignFirstResponder];
+  _editView->EndEditing();
 }
 
 - (void)insertTextToOmnibox:(NSString*)text {
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.h b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.h
index d62d68e..a310f787 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.h
+++ b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.h
@@ -15,14 +15,15 @@
 #include "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_provider.h"
 #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_suggestions_delegate.h"
 
-struct AutocompleteMatch;
 class AutocompleteResult;
-@class AutocompleteTextFieldDelegate;
 class GURL;
+class WebOmniboxEditController;
+struct AutocompleteMatch;
+@class AutocompleteTextFieldDelegate;
+@class OmniboxClearButtonBridge;
 @class OmniboxTextFieldIOS;
 @class OmniboxTextFieldPasteDelegate;
-class WebOmniboxEditController;
-@class OmniboxClearButtonBridge;
+@protocol OmniboxFocuser;
 
 namespace ios {
 class ChromeBrowserState;
@@ -37,7 +38,8 @@
   OmniboxViewIOS(OmniboxTextFieldIOS* field,
                  WebOmniboxEditController* controller,
                  id<OmniboxLeftImageConsumer> left_image_consumer,
-                 ios::ChromeBrowserState* browser_state);
+                 ios::ChromeBrowserState* browser_state,
+                 id<OmniboxFocuser> omnibox_focuser);
   ~OmniboxViewIOS() override;
 
   void SetPopupProvider(OmniboxPopupProvider* provider) {
@@ -96,7 +98,7 @@
   void OnDidBeginEditing();
   bool OnWillChange(NSRange range, NSString* new_text);
   void OnDidChange(bool processing_user_input);
-  void OnDidEndEditing();
+  void OnWillEndEditing();
   void OnAccept();
   void OnClear();
   bool OnCopy();
@@ -126,7 +128,7 @@
 
   // Hide keyboard and call OnDidEndEditing.  This dismisses the keyboard and
   // also finalizes the editing state of the omnibox.
-  void HideKeyboardAndEndEditing();
+  void EndEditing();
 
   // Hide keyboard only.  Used when omnibox popups grab focus but editing isn't
   // complete.
@@ -185,6 +187,9 @@
   OmniboxTextFieldPasteDelegate* paste_delegate_;
   WebOmniboxEditController* controller_;  // weak, owns us
   __weak id<OmniboxLeftImageConsumer> left_image_consumer_;
+  // Focuser, used to transition the location bar to focused/defocused state as
+  // necessary.
+  __weak id<OmniboxFocuser> omnibox_focuser_;
 
   State state_before_change_;
   NSString* marked_text_before_change_;
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm
index 69e51ef..e9c642b 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm
+++ b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm
@@ -26,6 +26,7 @@
 #include "ios/chrome/browser/ui/omnibox/omnibox_text_field_paste_delegate.h"
 #import "ios/chrome/browser/ui/omnibox/omnibox_util.h"
 #include "ios/chrome/browser/ui/omnibox/web_omnibox_edit_controller.h"
+#import "ios/chrome/browser/ui/toolbar/public/omnibox_focuser.h"
 #include "ios/chrome/browser/ui/util/ui_util.h"
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
 #include "ios/chrome/grit/ios_strings.h"
@@ -134,13 +135,9 @@
   editView_->OnDidBeginEditing();
 }
 
-// On phone, the omnibox may still be editing when the popup is open, so end
-// editing is called directly in OnDidEndEditing.
-- (void)textFieldDidEndEditing:(UITextField*)textField {
-  if (!IsIPadIdiom() && editView_->IsPopupOpen())
-    return;
-
-  editView_->OnDidEndEditing();
+- (BOOL)textFieldShouldEndEditing:(UITextField*)textField {
+  editView_->OnWillEndEditing();
+  return YES;
 }
 
 // When editing, forward the message on to |editView_|.
@@ -203,7 +200,8 @@
 OmniboxViewIOS::OmniboxViewIOS(OmniboxTextFieldIOS* field,
                                WebOmniboxEditController* controller,
                                id<OmniboxLeftImageConsumer> left_image_consumer,
-                               ios::ChromeBrowserState* browser_state)
+                               ios::ChromeBrowserState* browser_state,
+                               id<OmniboxFocuser> omnibox_focuser)
     : OmniboxView(
           controller,
           std::make_unique<ChromeOmniboxClientIOS>(controller, browser_state)),
@@ -211,6 +209,7 @@
       field_(field),
       controller_(controller),
       left_image_consumer_(left_image_consumer),
+      omnibox_focuser_(omnibox_focuser),
       ignore_popup_updates_(false),
       attributing_display_string_(nil),
       popup_provider_(nullptr) {
@@ -450,26 +449,16 @@
   }
 }
 
-void OmniboxViewIOS::OnDidEndEditing() {
-  CloseOmniboxPopup();
-  model()->OnWillKillFocus();
-  model()->OnKillFocus();
-  if ([field_ isPreEditing])
-    [field_ exitPreEditState];
-
-  UpdateRightDecorations();
-
-  // The controller looks at the current pre-edit state, so the call to
-  // OnKillFocus() must come after exiting pre-edit.
-  controller_->OnKillFocus();
-
-  // Blow away any in-progress edits.
-  RevertAll();
-  DCHECK(![field_ hasAutocompleteText]);
-
-  if (!omnibox_interacted_while_focused_) {
-    RecordAction(
-        UserMetricsAction("Mobile_FocusedDefocusedOmnibox_WithNoAction"));
+void OmniboxViewIOS::OnWillEndEditing() {
+  // On iPad, this will be called when the "hide keyboard" button is pressed
+  // on the software keyboard. This should be equivalent to tapping the typing
+  // shield and should defocus the omnibox, transition the location bar to
+  // steady view, and close the popup.
+  // This will also be called if -resignFirstResponder is called
+  // programmatically. On phone, the omnibox may still be editing when
+  // the popup is open, so the Cancel button calls OnWillEndEditing.
+  if (IsIPadIdiom()) {
+    [omnibox_focuser_ cancelOmniboxEdit];
   }
 }
 
@@ -911,15 +900,26 @@
   return [[field_ text] rangeOfString:objectReplacementChar].length > 0;
 }
 
-void OmniboxViewIOS::HideKeyboardAndEndEditing() {
-  [field_ resignFirstResponder];
+void OmniboxViewIOS::EndEditing() {
+  CloseOmniboxPopup();
+  model()->OnWillKillFocus();
+  model()->OnKillFocus();
+  if ([field_ isPreEditing])
+    [field_ exitPreEditState];
 
-  // Handle the case where a phone-format ombniox has already resigned first
-  // responder because the popup was scrolled.  If the model still has focus,
-  // dismiss again. This should only happen on iPhone.
-  if (model()->has_focus()) {
-    DCHECK(!IsIPadIdiom());
-    this->OnDidEndEditing();
+  UpdateRightDecorations();
+
+  // The controller looks at the current pre-edit state, so the call to
+  // OnKillFocus() must come after exiting pre-edit.
+  controller_->OnKillFocus();
+
+  // Blow away any in-progress edits.
+  RevertAll();
+  DCHECK(![field_ hasAutocompleteText]);
+
+  if (!omnibox_interacted_while_focused_) {
+    RecordAction(
+        UserMetricsAction("Mobile_FocusedDefocusedOmnibox_WithNoAction"));
   }
 }
 
diff --git a/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm b/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm
index 6655745..bec2aa7 100644
--- a/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm
+++ b/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm
@@ -250,7 +250,7 @@
 // checks if all its views and buttons are visible. Checks that no alerts are
 // presented.
 - (void)showQRScannerAndCheckLayoutWithCameraMock:(id)mock {
-  UIViewController* bvc = [self currentBVC];
+  UIViewController* bvc = [self currentViewController];
   [self assertModalOfClass:[QRScannerViewController class]
           isNotPresentedBy:bvc];
   [self assertModalOfClass:[UIAlertController class] isNotPresentedBy:bvc];
@@ -270,14 +270,14 @@
   [self addCameraControllerDismissalExpectations:mock];
   TapButton(QrScannerCloseButton());
   [self waitForModalOfClass:[QRScannerViewController class]
-       toDisappearFromAbove:[self currentBVC]];
+       toDisappearFromAbove:[self currentViewController]];
 }
 
 // Returns the current BrowserViewController.
-- (UIViewController*)currentBVC {
+- (UIViewController*)currentViewController {
   // TODO(crbug.com/629516): Evaluate moving this into a common utility.
   MainController* mainController = chrome_test_util::GetMainController();
-  return [[mainController browserViewInformation] currentBVC];
+  return mainController.interfaceProvider.mainInterface.viewController;
 }
 
 // Checks that the omnibox is visible and contains |text|.
@@ -354,7 +354,8 @@
 // that the title of this alert corresponds to |state|.
 - (void)assertQRScannerIsPresentingADialogForState:(CameraState)state {
   [self assertModalOfClass:[UIAlertController class]
-             isPresentedBy:[[self currentBVC] presentedViewController]];
+             isPresentedBy:[[self currentViewController]
+                               presentedViewController]];
   [[EarlGrey
       selectElementWithMatcher:grey_text([self dialogTitleForState:state])]
       assertWithMatcher:grey_notNil()];
@@ -443,28 +444,32 @@
 // Calls |cameraStateChanged:| on the presented QRScannerViewController.
 - (void)callCameraStateChanged:(CameraState)state {
   QRScannerViewController* vc =
-      (QRScannerViewController*)[[self currentBVC] presentedViewController];
+      (QRScannerViewController*)[[self currentViewController]
+          presentedViewController];
   [vc cameraStateChanged:state];
 }
 
 // Calls |torchStateChanged:| on the presented QRScannerViewController.
 - (void)callTorchStateChanged:(BOOL)torchIsOn {
   QRScannerViewController* vc =
-      (QRScannerViewController*)[[self currentBVC] presentedViewController];
+      (QRScannerViewController*)[[self currentViewController]
+          presentedViewController];
   [vc torchStateChanged:torchIsOn];
 }
 
 // Calls |torchAvailabilityChanged:| on the presented QRScannerViewController.
 - (void)callTorchAvailabilityChanged:(BOOL)torchIsAvailable {
   QRScannerViewController* vc =
-      (QRScannerViewController*)[[self currentBVC] presentedViewController];
+      (QRScannerViewController*)[[self currentViewController]
+          presentedViewController];
   [vc torchAvailabilityChanged:torchIsAvailable];
 }
 
 // Calls |receiveQRScannerResult:| on the presented QRScannerViewController.
 - (void)callReceiveQRScannerResult:(NSString*)result {
   QRScannerViewController* vc =
-      (QRScannerViewController*)[[self currentBVC] presentedViewController];
+      (QRScannerViewController*)[[self currentViewController]
+          presentedViewController];
   [vc receiveQRScannerResult:result loadImmediately:NO];
 }
 
@@ -623,7 +628,7 @@
 // Tests that a UIAlertController is presented instead of the
 // QRScannerViewController if the camera is unavailable.
 - (void)testCameraUnavailableDialog {
-  UIViewController* bvc = [self currentBVC];
+  UIViewController* bvc = [self currentViewController];
   [self assertModalOfClass:[QRScannerViewController class]
           isNotPresentedBy:bvc];
   [self assertModalOfClass:[UIAlertController class] isNotPresentedBy:bvc];
@@ -661,7 +666,7 @@
     // Close the dialog.
     [self addCameraControllerDismissalExpectations:cameraControllerMock];
     TapButton(DialogCancelButton());
-    UIViewController* bvc = [self currentBVC];
+    UIViewController* bvc = [self currentViewController];
     [self waitForModalOfClass:[QRScannerViewController class]
          toDisappearFromAbove:bvc];
     [self assertModalOfClass:[UIAlertController class] isNotPresentedBy:bvc];
@@ -698,9 +703,9 @@
   [self addCameraControllerDismissalExpectations:cameraControllerMock];
   TapButton(DialogCancelButton());
   [self waitForModalOfClass:[QRScannerViewController class]
-       toDisappearFromAbove:[self currentBVC]];
+       toDisappearFromAbove:[self currentViewController]];
   [self assertModalOfClass:[UIAlertController class]
-          isNotPresentedBy:[self currentBVC]];
+          isNotPresentedBy:[self currentViewController]];
 
   [cameraControllerMock verify];
 }
@@ -756,7 +761,7 @@
   [self callReceiveQRScannerResult:base::SysUTF8ToNSString(result)];
 
   [self waitForModalOfClass:[QRScannerViewController class]
-       toDisappearFromAbove:[self currentBVC]];
+       toDisappearFromAbove:[self currentViewController]];
   [cameraControllerMock verify];
 
   // Optionally edit the text in the omnibox before pressing return.
@@ -772,7 +777,7 @@
   [[EarlGrey selectElementWithMatcher:chrome_test_util::BackButton()]
       performAction:grey_tap()];
   [self assertModalOfClass:[QRScannerViewController class]
-          isNotPresentedBy:[self currentBVC]];
+          isNotPresentedBy:[self currentViewController]];
 }
 
 // Test that the correct page is loaded if the scanner result is a URL.
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn
index 6024cd3..b5c25782 100644
--- a/ios/chrome/browser/ui/settings/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -11,10 +11,10 @@
     "accounts_collection_view_controller.mm",
     "alpha_animated_collection_view_flow_layout.h",
     "alpha_animated_collection_view_flow_layout.mm",
-    "autofill_credit_card_collection_view_controller.h",
-    "autofill_credit_card_collection_view_controller.mm",
     "autofill_credit_card_edit_table_view_controller.h",
     "autofill_credit_card_edit_table_view_controller.mm",
+    "autofill_credit_card_table_view_controller.h",
+    "autofill_credit_card_table_view_controller.mm",
     "autofill_edit_table_view_controller+protected.h",
     "autofill_edit_table_view_controller.h",
     "autofill_edit_table_view_controller.mm",
@@ -269,7 +269,7 @@
   testonly = true
   sources = [
     "about_chrome_table_view_controller_unittest.mm",
-    "autofill_credit_card_collection_view_controller_unittest.mm",
+    "autofill_credit_card_table_view_controller_unittest.mm",
     "autofill_profile_edit_table_view_controller_unittest.mm",
     "autofill_profile_table_view_controller_unittest.mm",
     "bandwidth_management_table_view_controller_unittest.mm",
diff --git a/ios/chrome/browser/ui/settings/accounts_collection_egtest.mm b/ios/chrome/browser/ui/settings/accounts_collection_egtest.mm
index 38f520f..688f38b 100644
--- a/ios/chrome/browser/ui/settings/accounts_collection_egtest.mm
+++ b/ios/chrome/browser/ui/settings/accounts_collection_egtest.mm
@@ -15,7 +15,7 @@
 #import "ios/chrome/browser/signin/authentication_service.h"
 #import "ios/chrome/browser/signin/authentication_service_factory.h"
 #include "ios/chrome/browser/sync/profile_sync_service_factory.h"
-#import "ios/chrome/browser/ui/authentication/cells/account_control_item.h"
+#import "ios/chrome/browser/ui/authentication/cells/legacy_account_control_item.h"
 #import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h"
 #import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h"
 #include "ios/chrome/grit/ios_strings.h"
@@ -249,9 +249,10 @@
   // Check that account sync button displays the expected detail text label and
   // an image.
   GREYPerformBlock block = ^BOOL(id element, NSError* __strong* errorOrNil) {
-    GREYAssertTrue([element isKindOfClass:[AccountControlCell class]],
-                   @"Should be AccountControlCell type");
-    AccountControlCell* cell = static_cast<AccountControlCell*>(element);
+    GREYAssertTrue([element isKindOfClass:[LegacyAccountControlCell class]],
+                   @"Should be LegacyAccountControlCell type");
+    LegacyAccountControlCell* cell =
+        static_cast<LegacyAccountControlCell*>(element);
     return
         [cell.detailTextLabel.text isEqualToString:expectedDetailTextLabel] &&
         cell.imageView.image != nil;
diff --git a/ios/chrome/browser/ui/settings/accounts_collection_view_controller.mm b/ios/chrome/browser/ui/settings/accounts_collection_view_controller.mm
index 4d6ff4a..f6ec8dc 100644
--- a/ios/chrome/browser/ui/settings/accounts_collection_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/accounts_collection_view_controller.mm
@@ -26,7 +26,7 @@
 #include "ios/chrome/browser/sync/sync_setup_service.h"
 #include "ios/chrome/browser/sync/sync_setup_service_factory.h"
 #import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h"
-#import "ios/chrome/browser/ui/authentication/cells/account_control_item.h"
+#import "ios/chrome/browser/ui/authentication/cells/legacy_account_control_item.h"
 #import "ios/chrome/browser/ui/authentication/resized_avatar_cache.h"
 #import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrome.h"
 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_account_item.h"
@@ -293,8 +293,8 @@
 }
 
 - (CollectionViewItem*)syncItem {
-  AccountControlItem* item =
-      [[AccountControlItem alloc] initWithType:ItemTypeSync];
+  LegacyAccountControlItem* item =
+      [[LegacyAccountControlItem alloc] initWithType:ItemTypeSync];
   item.cellStyle = CollectionViewCellStyle::kUIKit;
   item.text = l10n_util::GetNSString(IDS_IOS_OPTIONS_ACCOUNTS_SYNC_TITLE);
   item.accessibilityIdentifier = kSettingsAccountsSyncCellId;
@@ -305,7 +305,7 @@
 
 // Updates the sync item according to the sync status (in progress, sync error,
 // mdm error, sync disabled or sync enabled).
-- (void)updateSyncItem:(AccountControlItem*)syncItem {
+- (void)updateSyncItem:(LegacyAccountControlItem*)syncItem {
   SyncSetupService* syncSetupService =
       SyncSetupServiceFactory::GetForBrowserState(_browserState);
   if (!syncSetupService->HasFinishedInitialSetup()) {
@@ -348,8 +348,8 @@
 }
 
 - (CollectionViewItem*)googleActivityControlsItem {
-  AccountControlItem* item =
-      [[AccountControlItem alloc] initWithType:ItemTypeGoogleActivityControls];
+  LegacyAccountControlItem* item = [[LegacyAccountControlItem alloc]
+      initWithType:ItemTypeGoogleActivityControls];
   item.cellStyle = CollectionViewCellStyle::kUIKit;
   item.text = l10n_util::GetNSString(IDS_IOS_OPTIONS_ACCOUNTS_GOOGLE_TITLE);
   item.detailText =
@@ -442,8 +442,9 @@
   CollectionViewModel* model = self.collectionViewModel;
   if ([model numberOfSections] > index.section &&
       [model numberOfItemsInSection:index.section] > index.row) {
-    AccountControlItem* item = base::mac::ObjCCastStrict<AccountControlItem>(
-        [model itemAtIndexPath:index]);
+    LegacyAccountControlItem* item =
+        base::mac::ObjCCastStrict<LegacyAccountControlItem>(
+            [model itemAtIndexPath:index]);
     [self updateSyncItem:item];
     [self.collectionView reloadItemsAtIndexPaths:@[ index ]];
   }
diff --git a/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller.h b/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller.h
deleted file mode 100644
index edf12822..0000000
--- a/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_AUTOFILL_CREDIT_CARD_COLLECTION_VIEW_CONTROLLER_H_
-#define IOS_CHROME_BROWSER_UI_SETTINGS_AUTOFILL_CREDIT_CARD_COLLECTION_VIEW_CONTROLLER_H_
-
-#import "ios/chrome/browser/ui/settings/settings_root_collection_view_controller.h"
-
-namespace ios {
-class ChromeBrowserState;
-}  // namespace ios
-
-// The collection view for the Autofill settings.
-@interface AutofillCreditCardCollectionViewController
-    : SettingsRootCollectionViewController
-
-// The designated initializer. |browserState| must not be nil.
-- (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState
-    NS_DESIGNATED_INITIALIZER;
-- (instancetype)initWithLayout:(UICollectionViewLayout*)layout
-                         style:(CollectionViewControllerStyle)style
-    NS_UNAVAILABLE;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_SETTINGS_AUTOFILL_CREDIT_CARD_COLLECTION_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller.mm b/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller.mm
deleted file mode 100644
index 2e8420f..0000000
--- a/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller.mm
+++ /dev/null
@@ -1,457 +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.
-
-#import "ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller.h"
-
-#include "base/logging.h"
-#include "base/mac/foundation_util.h"
-#include "base/metrics/user_metrics.h"
-#include "base/strings/sys_string_conversions.h"
-#include "components/autofill/core/browser/personal_data_manager.h"
-#include "components/autofill/core/common/autofill_prefs.h"
-#import "components/autofill/ios/browser/credit_card_util.h"
-#import "components/autofill/ios/browser/personal_data_manager_observer_bridge.h"
-#include "components/prefs/pref_service.h"
-#include "components/strings/grit/components_strings.h"
-#include "ios/chrome/browser/application_context.h"
-#include "ios/chrome/browser/autofill/personal_data_manager_factory.h"
-#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
-#import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrome.h"
-#include "ios/chrome/browser/ui/collection_view/cells/collection_view_cell_constants.h"
-#import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h"
-#import "ios/chrome/browser/ui/collection_view/collection_view_model.h"
-#import "ios/chrome/browser/ui/settings/autofill_credit_card_edit_table_view_controller.h"
-#import "ios/chrome/browser/ui/settings/cells/legacy/legacy_autofill_data_item.h"
-#import "ios/chrome/browser/ui/settings/cells/legacy/legacy_settings_switch_item.h"
-#import "ios/chrome/browser/ui/settings/cells/settings_text_item.h"
-#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
-#include "ios/chrome/grit/ios_strings.h"
-#import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h"
-#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h"
-#include "ui/base/l10n/l10n_util.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-namespace {
-
-typedef NS_ENUM(NSInteger, SectionIdentifier) {
-  SectionIdentifierSwitches = kSectionIdentifierEnumZero,
-  SectionIdentifierSubtitle,
-  SectionIdentifierCards,
-};
-
-typedef NS_ENUM(NSInteger, ItemType) {
-  ItemTypeAutofillCardSwitch = kItemTypeEnumZero,
-  ItemTypeAutofillCardSwitchSubtitle,
-  ItemTypeCard,
-  ItemTypeHeader,
-};
-
-}  // namespace
-
-#pragma mark - AutofillCreditCardCollectionViewController
-
-@interface AutofillCreditCardCollectionViewController ()<
-    PersonalDataManagerObserver> {
-  autofill::PersonalDataManager* _personalDataManager;
-
-  ios::ChromeBrowserState* _browserState;
-  std::unique_ptr<autofill::PersonalDataManagerObserverBridge> _observer;
-
-  // Deleting credit cards updates PersonalDataManager resulting in an observer
-  // callback, which handles general data updates with a reloadData.
-  // It is better to handle user-initiated changes with more specific actions
-  // such as inserting or removing items/sections. This boolean is used to
-  // stop the observer callback from acting on user-initiated changes.
-  BOOL _deletionInProgress;
-}
-
-@property(nonatomic, getter=isAutofillCreditCardEnabled)
-    BOOL autofillCreditCardEnabled;
-
-@end
-
-@implementation AutofillCreditCardCollectionViewController
-
-- (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState {
-  DCHECK(browserState);
-  UICollectionViewLayout* layout = [[MDCCollectionViewFlowLayout alloc] init];
-  self =
-      [super initWithLayout:layout style:CollectionViewControllerStyleAppBar];
-  if (self) {
-    self.collectionViewAccessibilityIdentifier = @"kAutofillCollectionViewId";
-    self.title = l10n_util::GetNSString(IDS_AUTOFILL_PAYMENT_METHODS);
-    self.shouldHideDoneButton = YES;
-    _browserState = browserState;
-    _personalDataManager =
-        autofill::PersonalDataManagerFactory::GetForBrowserState(_browserState);
-    _observer.reset(new autofill::PersonalDataManagerObserverBridge(self));
-    _personalDataManager->AddObserver(_observer.get());
-
-    // TODO(crbug.com/764578): -updateEditButton and -loadModel should not be
-    // called from initializer.
-    [self updateEditButton];
-    [self loadModel];
-  }
-  return self;
-}
-
-- (void)dealloc {
-  _personalDataManager->RemoveObserver(_observer.get());
-}
-
-- (void)viewDidLoad {
-  [super viewDidLoad];
-  base::RecordAction(base::UserMetricsAction("AutofillCreditCardsViewed"));
-}
-
-#pragma mark - CollectionViewController
-
-- (void)loadModel {
-  [super loadModel];
-  CollectionViewModel* model = self.collectionViewModel;
-
-  [model addSectionWithIdentifier:SectionIdentifierSwitches];
-  [model addItem:[self cardSwitchItem]
-      toSectionWithIdentifier:SectionIdentifierSwitches];
-
-  [model addSectionWithIdentifier:SectionIdentifierSubtitle];
-  [model addItem:[self cardSwitchSubtitleItem]
-      toSectionWithIdentifier:SectionIdentifierSubtitle];
-
-  [self populateCardSection];
-}
-
-#pragma mark - LoadModel Helpers
-
-// Populates card section using personalDataManager.
-- (void)populateCardSection {
-  CollectionViewModel* model = self.collectionViewModel;
-  const std::vector<autofill::CreditCard*>& creditCards =
-      _personalDataManager->GetCreditCards();
-  if (!creditCards.empty()) {
-    [model addSectionWithIdentifier:SectionIdentifierCards];
-    [model setHeader:[self cardSectionHeader]
-        forSectionWithIdentifier:SectionIdentifierCards];
-    for (autofill::CreditCard* creditCard : creditCards) {
-      DCHECK(creditCard);
-      [model addItem:[self itemForCreditCard:*creditCard]
-          toSectionWithIdentifier:SectionIdentifierCards];
-    }
-  }
-}
-
-- (CollectionViewItem*)cardSwitchItem {
-  LegacySettingsSwitchItem* switchItem = [[LegacySettingsSwitchItem alloc]
-      initWithType:ItemTypeAutofillCardSwitch];
-  switchItem.text =
-      l10n_util::GetNSString(IDS_AUTOFILL_ENABLE_CREDIT_CARDS_TOGGLE_LABEL);
-  switchItem.on = [self isAutofillCreditCardEnabled];
-  switchItem.accessibilityIdentifier = @"cardItem_switch";
-  return switchItem;
-}
-
-- (CollectionViewItem*)cardSwitchSubtitleItem {
-  CollectionViewTextItem* textItem = [[CollectionViewTextItem alloc]
-      initWithType:ItemTypeAutofillCardSwitchSubtitle];
-  textItem.text =
-      l10n_util::GetNSString(IDS_AUTOFILL_ENABLE_CREDIT_CARDS_TOGGLE_SUBLABEL);
-  textItem.textFont = [UIFont systemFontOfSize:kUIKitMultilineDetailFontSize];
-  textItem.textColor = UIColorFromRGB(kUIKitMultilineDetailTextColor);
-  textItem.numberOfTextLines = 0;
-  return textItem;
-}
-
-- (CollectionViewItem*)cardSectionHeader {
-  SettingsTextItem* header = [self genericHeader];
-  header.text = l10n_util::GetNSString(IDS_AUTOFILL_PAYMENT_METHODS);
-  return header;
-}
-
-- (SettingsTextItem*)genericHeader {
-  SettingsTextItem* header =
-      [[SettingsTextItem alloc] initWithType:ItemTypeHeader];
-  header.textColor = [[MDCPalette greyPalette] tint500];
-  return header;
-}
-
-- (CollectionViewItem*)itemForCreditCard:
-    (const autofill::CreditCard&)creditCard {
-  std::string guid(creditCard.guid());
-  NSString* creditCardName = autofill::GetCreditCardName(
-      creditCard, GetApplicationContext()->GetApplicationLocale());
-
-  LegacyAutofillDataItem* item =
-      [[LegacyAutofillDataItem alloc] initWithType:ItemTypeCard];
-  item.text = creditCardName;
-  item.leadingDetailText = autofill::GetCreditCardObfuscatedNumber(creditCard);
-  item.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator;
-  item.accessibilityIdentifier = creditCardName;
-  item.deletable = autofill::IsCreditCardLocal(creditCard);
-  item.GUID = guid;
-  if (![item isDeletable]) {
-    item.trailingDetailText =
-        l10n_util::GetNSString(IDS_IOS_AUTOFILL_WALLET_SERVER_NAME);
-  }
-  return item;
-}
-
-- (BOOL)localCreditCardsExist {
-  return !_personalDataManager->GetLocalCreditCards().empty();
-}
-
-#pragma mark - SettingsRootCollectionViewController
-
-- (BOOL)shouldShowEditButton {
-  return YES;
-}
-
-- (BOOL)editButtonEnabled {
-  return [self localCreditCardsExist];
-}
-
-#pragma mark - UICollectionViewDataSource
-
-- (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView
-                 cellForItemAtIndexPath:(NSIndexPath*)indexPath {
-  UICollectionViewCell* cell =
-      [super collectionView:collectionView cellForItemAtIndexPath:indexPath];
-
-  ItemType itemType = static_cast<ItemType>(
-      [self.collectionViewModel itemTypeForIndexPath:indexPath]);
-  if (itemType == ItemTypeAutofillCardSwitch) {
-    LegacySettingsSwitchCell* switchCell =
-        base::mac::ObjCCastStrict<LegacySettingsSwitchCell>(cell);
-    [switchCell.switchView addTarget:self
-                              action:@selector(autofillCardSwitchChanged:)
-                    forControlEvents:UIControlEventValueChanged];
-  }
-
-  return cell;
-}
-
-#pragma mark - Switch Callbacks
-
-- (void)autofillCardSwitchChanged:(UISwitch*)switchView {
-  [self setSwitchItemOn:[switchView isOn] itemType:ItemTypeAutofillCardSwitch];
-  [self setAutofillCreditCardEnabled:[switchView isOn]];
-}
-
-#pragma mark - Switch Helpers
-
-// Sets switchItem's state to |on|. It is important that there is only one item
-// of |switchItemType| in SectionIdentifierSwitches.
-- (void)setSwitchItemOn:(BOOL)on itemType:(ItemType)switchItemType {
-  NSIndexPath* switchPath =
-      [self.collectionViewModel indexPathForItemType:switchItemType
-                                   sectionIdentifier:SectionIdentifierSwitches];
-  LegacySettingsSwitchItem* switchItem =
-      base::mac::ObjCCastStrict<LegacySettingsSwitchItem>(
-          [self.collectionViewModel itemAtIndexPath:switchPath]);
-  switchItem.on = on;
-}
-
-// Sets switchItem's enabled status to |enabled| and reconfigures the
-// corresponding cell. It is important that there is no more than one item of
-// |switchItemType| in SectionIdentifierSwitches.
-- (void)setSwitchItemEnabled:(BOOL)enabled itemType:(ItemType)switchItemType {
-  CollectionViewModel* model = self.collectionViewModel;
-
-  if (![model hasItemForItemType:switchItemType
-               sectionIdentifier:SectionIdentifierSwitches]) {
-    return;
-  }
-  NSIndexPath* switchPath =
-      [model indexPathForItemType:switchItemType
-                sectionIdentifier:SectionIdentifierSwitches];
-  LegacySettingsSwitchItem* switchItem =
-      base::mac::ObjCCastStrict<LegacySettingsSwitchItem>(
-          [model itemAtIndexPath:switchPath]);
-  [switchItem setEnabled:enabled];
-  [self reconfigureCellsForItems:@[ switchItem ]];
-}
-
-#pragma mark - MDCCollectionViewStylingDelegate
-
-- (CGFloat)collectionView:(UICollectionView*)collectionView
-    cellHeightAtIndexPath:(NSIndexPath*)indexPath {
-  CollectionViewItem* item =
-      [self.collectionViewModel itemAtIndexPath:indexPath];
-  return [MDCCollectionViewCell
-      cr_preferredHeightForWidth:CGRectGetWidth(collectionView.bounds)
-                         forItem:item];
-}
-
-- (BOOL)collectionView:(UICollectionView*)collectionView
-    hidesInkViewAtIndexPath:(NSIndexPath*)indexPath {
-  NSInteger sectionIdentifier =
-      [self.collectionViewModel sectionIdentifierForSection:indexPath.section];
-  return sectionIdentifier == SectionIdentifierSwitches ||
-         sectionIdentifier == SectionIdentifierSubtitle;
-}
-
-- (BOOL)collectionView:(UICollectionView*)collectionView
-    shouldHideItemBackgroundAtIndexPath:(NSIndexPath*)indexPath {
-  NSInteger sectionIdentifier =
-      [self.collectionViewModel sectionIdentifierForSection:indexPath.section];
-  return sectionIdentifier == SectionIdentifierSubtitle;
-}
-
-#pragma mark - UICollectionViewDelegate
-
-- (void)collectionView:(UICollectionView*)collectionView
-    didSelectItemAtIndexPath:(NSIndexPath*)indexPath {
-  [super collectionView:collectionView didSelectItemAtIndexPath:indexPath];
-
-  // Edit mode is the state where the user can select and delete entries. In
-  // edit mode, selection is handled by the superclass. When not in edit mode
-  // selection presents the editing controller for the selected entry.
-  if ([self.editor isEditing]) {
-    return;
-  }
-
-  CollectionViewModel* model = self.collectionViewModel;
-  NSInteger type = [model itemTypeForIndexPath:indexPath];
-  if (type != ItemTypeCard)
-    return;
-
-  const std::vector<autofill::CreditCard*>& creditCards =
-      _personalDataManager->GetCreditCards();
-  AutofillCreditCardEditTableViewController* controller =
-      [[AutofillCreditCardEditTableViewController alloc]
-           initWithCreditCard:*creditCards[indexPath.item]
-          personalDataManager:_personalDataManager];
-  controller.dispatcher = self.dispatcher;
-  [self.navigationController pushViewController:controller animated:YES];
-}
-
-#pragma mark - MDCCollectionViewEditingDelegate
-
-- (BOOL)collectionViewAllowsEditing:(UICollectionView*)collectionView {
-  return YES;
-}
-
-- (void)collectionViewWillBeginEditing:(UICollectionView*)collectionView {
-  [super collectionViewWillBeginEditing:collectionView];
-
-  [self setSwitchItemEnabled:NO itemType:ItemTypeAutofillCardSwitch];
-}
-
-- (void)collectionViewWillEndEditing:(UICollectionView*)collectionView {
-  [super collectionViewWillEndEditing:collectionView];
-
-  [self setSwitchItemEnabled:YES itemType:ItemTypeAutofillCardSwitch];
-}
-
-- (BOOL)collectionView:(UICollectionView*)collectionView
-    canEditItemAtIndexPath:(NSIndexPath*)indexPath {
-  // Only autofill data cells are editable.
-  CollectionViewItem* item =
-      [self.collectionViewModel itemAtIndexPath:indexPath];
-  if ([item isKindOfClass:[LegacyAutofillDataItem class]]) {
-    LegacyAutofillDataItem* autofillItem =
-        base::mac::ObjCCastStrict<LegacyAutofillDataItem>(item);
-    return [autofillItem isDeletable];
-  }
-  return NO;
-}
-
-- (void)collectionView:(UICollectionView*)collectionView
-    willDeleteItemsAtIndexPaths:(NSArray*)indexPaths {
-  _deletionInProgress = YES;
-  for (NSIndexPath* indexPath in indexPaths) {
-    LegacyAutofillDataItem* item =
-        base::mac::ObjCCastStrict<LegacyAutofillDataItem>(
-            [self.collectionViewModel itemAtIndexPath:indexPath]);
-    _personalDataManager->RemoveByGUID([item GUID]);
-  }
-  // Must call super at the end of the child implementation.
-  [super collectionView:collectionView willDeleteItemsAtIndexPaths:indexPaths];
-}
-
-- (void)collectionView:(UICollectionView*)collectionView
-    didDeleteItemsAtIndexPaths:(NSArray*)indexPaths {
-  // If there are no index paths, return early. This can happen if the user
-  // presses the Delete button twice in quick succession.
-  if (![indexPaths count])
-    return;
-
-  // TODO(crbug.com/650390) Generalize removing empty sections
-  [self removeSectionIfEmptyForSectionWithIdentifier:SectionIdentifierCards];
-}
-
-// Remove the section from the model and collectionView if there are no more
-// items in the section.
-- (void)removeSectionIfEmptyForSectionWithIdentifier:
-    (SectionIdentifier)sectionIdentifier {
-  if (![self.collectionViewModel
-          hasSectionForSectionIdentifier:sectionIdentifier]) {
-    return;
-  }
-  NSInteger section =
-      [self.collectionViewModel sectionForSectionIdentifier:sectionIdentifier];
-  if ([self.collectionView numberOfItemsInSection:section] == 0) {
-    // Avoid reference cycle in block.
-    __weak AutofillCreditCardCollectionViewController* weakSelf = self;
-    [self.collectionView performBatchUpdates:^{
-      // Obtain strong reference again.
-      AutofillCreditCardCollectionViewController* strongSelf = weakSelf;
-      if (!strongSelf) {
-        return;
-      }
-
-      // Remove section from model and collectionView.
-      [[strongSelf collectionViewModel]
-          removeSectionWithIdentifier:sectionIdentifier];
-      [[strongSelf collectionView]
-          deleteSections:[NSIndexSet indexSetWithIndex:section]];
-    }
-        completion:^(BOOL finished) {
-          // Obtain strong reference again.
-          AutofillCreditCardCollectionViewController* strongSelf = weakSelf;
-          if (!strongSelf) {
-            return;
-          }
-
-          // Turn off edit mode if there is nothing to edit.
-          if (![strongSelf localCreditCardsExist] &&
-              [strongSelf.editor isEditing]) {
-            [[strongSelf editor] setEditing:NO];
-          }
-          [strongSelf updateEditButton];
-          strongSelf->_deletionInProgress = NO;
-        }];
-  }
-}
-
-#pragma mark PersonalDataManagerObserver
-
-- (void)onPersonalDataChanged {
-  if (_deletionInProgress)
-    return;
-
-  if (![self localCreditCardsExist] && [self.editor isEditing]) {
-    // Turn off edit mode if there exists nothing to edit.
-    [self.editor setEditing:NO];
-  }
-
-  [self updateEditButton];
-  [self reloadData];
-}
-
-#pragma mark - Getters and Setter
-
-- (BOOL)isAutofillCreditCardEnabled {
-  return autofill::prefs::IsCreditCardAutofillEnabled(
-      _browserState->GetPrefs());
-}
-
-- (void)setAutofillCreditCardEnabled:(BOOL)isEnabled {
-  return autofill::prefs::SetCreditCardAutofillEnabled(
-      _browserState->GetPrefs(), isEnabled);
-}
-
-@end
diff --git a/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller_unittest.mm
deleted file mode 100644
index 9aa05b9..0000000
--- a/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller_unittest.mm
+++ /dev/null
@@ -1,142 +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.
-
-#import "ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller.h"
-
-#include "base/guid.h"
-#include "base/mac/foundation_util.h"
-#include "base/strings/utf_string_conversions.h"
-#import "base/test/ios/wait_util.h"
-#include "components/autofill/core/browser/credit_card.h"
-#include "components/autofill/core/browser/personal_data_manager.h"
-#include "ios/chrome/browser/autofill/personal_data_manager_factory.h"
-#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
-#import "ios/chrome/browser/ui/collection_view/collection_view_controller_test.h"
-#include "ios/chrome/browser/ui/settings/personal_data_manager_data_changed_observer.h"
-#include "ios/web/public/test/test_web_thread_bundle.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-@interface SettingsRootCollectionViewController (ExposedForTesting)
-- (void)editButtonPressed;
-@end
-
-namespace {
-
-class AutofillCreditCardCollectionViewControllerTest
-    : public CollectionViewControllerTest {
- protected:
-  AutofillCreditCardCollectionViewControllerTest() {
-    TestChromeBrowserState::Builder test_cbs_builder;
-    chrome_browser_state_ = test_cbs_builder.Build();
-    // Credit card import requires a PersonalDataManager which itself needs the
-    // WebDataService; this is not initialized on a TestChromeBrowserState by
-    // default.
-    chrome_browser_state_->CreateWebDataService();
-  }
-
-  CollectionViewController* InstantiateController() override {
-    return [[AutofillCreditCardCollectionViewController alloc]
-        initWithBrowserState:chrome_browser_state_.get()];
-  }
-
-  void AddCreditCard(const std::string& origin,
-                     const std::string& card_holder_name,
-                     const std::string& card_number) {
-    autofill::PersonalDataManager* personal_data_manager =
-        autofill::PersonalDataManagerFactory::GetForBrowserState(
-            chrome_browser_state_.get());
-    PersonalDataManagerDataChangedObserver observer(personal_data_manager);
-
-    autofill::CreditCard credit_card(base::GenerateGUID(), origin);
-    credit_card.SetRawInfo(autofill::CREDIT_CARD_NAME_FULL,
-                           base::ASCIIToUTF16(card_holder_name));
-    credit_card.SetRawInfo(autofill::CREDIT_CARD_NUMBER,
-                           base::ASCIIToUTF16(card_number));
-    personal_data_manager->OnAcceptedLocalCreditCardSave(credit_card);
-    observer.Wait();  // Wait for completion of the asynchronous operation.
-  }
-
-  web::TestWebThreadBundle thread_bundle_;
-  std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
-};
-
-// Default test case of no credit cards.
-TEST_F(AutofillCreditCardCollectionViewControllerTest, TestInitialization) {
-  CreateController();
-  CheckController();
-
-  // Expect one header section and one subtitle section.
-  EXPECT_EQ(2, NumberOfSections());
-  // Expect header section to contain one row (the credit card Autofill toggle).
-  EXPECT_EQ(1, NumberOfItemsInSection(0));
-  // Expect subtitle section to contain one row (the credit card Autofill toggle
-  // subtitle).
-  EXPECT_EQ(1, NumberOfItemsInSection(1));
-}
-
-// Adding a single credit card results in a credit card section.
-TEST_F(AutofillCreditCardCollectionViewControllerTest, TestOneCreditCard) {
-  AddCreditCard("https://www.example.com/", "John Doe", "378282246310005");
-  CreateController();
-  CheckController();
-
-  // Expect three sections (header, subtitle, and credit card section).
-  EXPECT_EQ(3, NumberOfSections());
-  // Expect credit card section to contain one row (the credit card itself).
-  EXPECT_EQ(1, NumberOfItemsInSection(2));
-}
-
-// Deleting the only credit card results in item deletion and section deletion.
-TEST_F(AutofillCreditCardCollectionViewControllerTest,
-       TestOneCreditCardItemDeleted) {
-  AddCreditCard("https://www.example.com/", "John Doe", "378282246310005");
-  CreateController();
-  CheckController();
-
-  // Expect three sections (header, subtitle, and credit card section).
-  EXPECT_EQ(3, NumberOfSections());
-  // Expect credit card section to contain one row (the credit card itself).
-  EXPECT_EQ(1, NumberOfItemsInSection(2));
-
-  AutofillCreditCardCollectionViewController* view_controller =
-      base::mac::ObjCCastStrict<AutofillCreditCardCollectionViewController>(
-          controller());
-  // Put the collectionView in 'edit' mode.
-  [view_controller editButtonPressed];
-
-  // This is a bit of a shortcut, since actually clicking on the 'delete'
-  // button would be tough.
-  void (^delete_item_with_wait)(int, int) = ^(int i, int j) {
-    __block BOOL completion_called = NO;
-    this->DeleteItem(i, j, ^{
-      completion_called = YES;
-    });
-    EXPECT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
-        base::test::ios::kWaitForUIElementTimeout, ^bool() {
-          return completion_called;
-        }));
-  };
-
-  autofill::PersonalDataManager* personal_data_manager =
-      autofill::PersonalDataManagerFactory::GetForBrowserState(
-          chrome_browser_state_.get());
-  PersonalDataManagerDataChangedObserver observer(personal_data_manager);
-
-  // This call cause a modification of the PersonalDataManager, so wait until
-  // the asynchronous task complete in addition to waiting for the UI update.
-  delete_item_with_wait(2, 0);
-  observer.Wait();  // Wait for completion of the asynchronous operation.
-
-  // Exit 'edit' mode.
-  [view_controller editButtonPressed];
-
-  // Expect credit card section to have been removed.
-  EXPECT_EQ(2, NumberOfSections());
-}
-
-}  // namespace
diff --git a/ios/chrome/browser/ui/settings/autofill_credit_card_settings_egtest.mm b/ios/chrome/browser/ui/settings/autofill_credit_card_settings_egtest.mm
index f0dd299..02ab75b 100644
--- a/ios/chrome/browser/ui/settings/autofill_credit_card_settings_egtest.mm
+++ b/ios/chrome/browser/ui/settings/autofill_credit_card_settings_egtest.mm
@@ -11,6 +11,7 @@
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/strings/grit/components_strings.h"
 #include "ios/chrome/browser/autofill/personal_data_manager_factory.h"
+#import "ios/chrome/browser/ui/settings/autofill_credit_card_table_view_controller.h"
 #include "ios/chrome/grit/ios_strings.h"
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/app/web_view_interaction_test_util.h"
@@ -194,10 +195,9 @@
       performAction:grey_tap()];
 
   // Check the Autofill credit card switch is disabled.
-  [[EarlGrey
-      selectElementWithMatcher:chrome_test_util::LegacySettingsSwitchCell(
-                                   @"cardItem_switch", YES, NO)]
-      assertWithMatcher:grey_notNil()];
+  [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsSwitchCell(
+                                          kAutofillCreditCardSwitchViewId, YES,
+                                          NO)] assertWithMatcher:grey_notNil()];
 
   [self exitSettingsMenu];
 }
@@ -210,9 +210,9 @@
 
   // Toggle the Autofill credit cards switch off.
   [[EarlGrey
-      selectElementWithMatcher:chrome_test_util::LegacySettingsSwitchCell(
-                                   @"cardItem_switch", YES, YES)]
-      performAction:chrome_test_util::TurnLegacySettingsSwitchOn(NO)];
+      selectElementWithMatcher:chrome_test_util::SettingsSwitchCell(
+                                   kAutofillCreditCardSwitchViewId, YES, YES)]
+      performAction:chrome_test_util::TurnSettingsSwitchOn(NO)];
 
   // Expect Autofill credit cards to remain visible.
   [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(
@@ -221,9 +221,9 @@
 
   // Toggle the Autofill credit cards switch back on.
   [[EarlGrey
-      selectElementWithMatcher:chrome_test_util::LegacySettingsSwitchCell(
-                                   @"cardItem_switch", NO, YES)]
-      performAction:chrome_test_util::TurnLegacySettingsSwitchOn(YES)];
+      selectElementWithMatcher:chrome_test_util::SettingsSwitchCell(
+                                   kAutofillCreditCardSwitchViewId, NO, YES)]
+      performAction:chrome_test_util::TurnSettingsSwitchOn(YES)];
 
   // Expect Autofill credit cards to remain visible.
   [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(
diff --git a/ios/chrome/browser/ui/settings/autofill_credit_card_table_view_controller.h b/ios/chrome/browser/ui/settings/autofill_credit_card_table_view_controller.h
new file mode 100644
index 0000000..e3fdf57
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/autofill_credit_card_table_view_controller.h
@@ -0,0 +1,31 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_AUTOFILL_CREDIT_CARD_TABLE_VIEW_CONTROLLER_H_
+#define IOS_CHROME_BROWSER_UI_SETTINGS_AUTOFILL_CREDIT_CARD_TABLE_VIEW_CONTROLLER_H_
+
+#import "ios/chrome/browser/ui/settings/settings_root_table_view_controller.h"
+
+extern NSString* const kAutofillCreditCardTableViewId;
+extern NSString* const kAutofillCreditCardSwitchViewId;
+
+namespace ios {
+class ChromeBrowserState;
+}  // namespace ios
+
+// The table view for the Autofill settings.
+@interface AutofillCreditCardTableViewController
+    : SettingsRootTableViewController
+
+// The designated initializer. |browserState| must not be nil.
+- (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState
+    NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithTableViewStyle:(UITableViewStyle)style
+                           appBarStyle:
+                               (ChromeTableViewControllerStyle)appBarStyle
+    NS_UNAVAILABLE;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_SETTINGS_AUTOFILL_CREDIT_CARD_TABLE_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/settings/autofill_credit_card_table_view_controller.mm b/ios/chrome/browser/ui/settings/autofill_credit_card_table_view_controller.mm
new file mode 100644
index 0000000..41d46ae
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/autofill_credit_card_table_view_controller.mm
@@ -0,0 +1,408 @@
+// 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 "ios/chrome/browser/ui/settings/autofill_credit_card_table_view_controller.h"
+
+#include "base/logging.h"
+#include "base/mac/foundation_util.h"
+#include "base/metrics/user_metrics.h"
+#include "base/strings/sys_string_conversions.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/common/autofill_prefs.h"
+#import "components/autofill/ios/browser/credit_card_util.h"
+#import "components/autofill/ios/browser/personal_data_manager_observer_bridge.h"
+#include "components/prefs/pref_service.h"
+#include "components/strings/grit/components_strings.h"
+#include "ios/chrome/browser/application_context.h"
+#include "ios/chrome/browser/autofill/personal_data_manager_factory.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#import "ios/chrome/browser/ui/settings/autofill_credit_card_edit_table_view_controller.h"
+#import "ios/chrome/browser/ui/settings/cells/autofill_data_item.h"
+#import "ios/chrome/browser/ui/settings/cells/settings_switch_item.h"
+#include "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h"
+#import "ios/chrome/browser/ui/table_view/cells/table_view_link_header_footer_item.h"
+#import "ios/chrome/browser/ui/table_view/cells/table_view_text_header_footer_item.h"
+#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
+#include "ios/chrome/grit/ios_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+NSString* const kAutofillCreditCardTableViewId = @"kAutofillTableViewId";
+NSString* const kAutofillCreditCardSwitchViewId = @"cardItem_switch";
+
+namespace {
+
+typedef NS_ENUM(NSInteger, SectionIdentifier) {
+  SectionIdentifierSwitches = kSectionIdentifierEnumZero,
+  SectionIdentifierCards,
+};
+
+typedef NS_ENUM(NSInteger, ItemType) {
+  ItemTypeAutofillCardSwitch = kItemTypeEnumZero,
+  ItemTypeAutofillCardSwitchSubtitle,
+  ItemTypeCard,
+  ItemTypeHeader,
+};
+
+}  // namespace
+
+#pragma mark - AutofillCreditCardTableViewController
+
+@interface AutofillCreditCardTableViewController () <
+    PersonalDataManagerObserver> {
+  autofill::PersonalDataManager* _personalDataManager;
+
+  ios::ChromeBrowserState* _browserState;
+  std::unique_ptr<autofill::PersonalDataManagerObserverBridge> _observer;
+}
+
+@property(nonatomic, getter=isAutofillCreditCardEnabled)
+    BOOL autofillCreditCardEnabled;
+
+// Deleting credit cards updates PersonalDataManager resulting in an observer
+// callback, which handles general data updates with a reloadData.
+// It is better to handle user-initiated changes with more specific actions
+// such as inserting or removing items/sections. This boolean is used to
+// stop the observer callback from acting on user-initiated changes.
+@property(nonatomic, readwrite, assign) BOOL deletionInProgress;
+
+@end
+
+@implementation AutofillCreditCardTableViewController
+
+- (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState {
+  DCHECK(browserState);
+  self =
+      [super initWithTableViewStyle:UITableViewStyleGrouped
+                        appBarStyle:ChromeTableViewControllerStyleWithAppBar];
+  if (self) {
+    self.title = l10n_util::GetNSString(IDS_AUTOFILL_PAYMENT_METHODS);
+    self.shouldHideDoneButton = YES;
+    _browserState = browserState;
+    _personalDataManager =
+        autofill::PersonalDataManagerFactory::GetForBrowserState(_browserState);
+    _observer.reset(new autofill::PersonalDataManagerObserverBridge(self));
+    _personalDataManager->AddObserver(_observer.get());
+  }
+  return self;
+}
+
+- (void)dealloc {
+  _personalDataManager->RemoveObserver(_observer.get());
+}
+
+#pragma mark - UIViewController
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+  self.tableView.allowsMultipleSelectionDuringEditing = YES;
+  self.tableView.accessibilityIdentifier = kAutofillCreditCardTableViewId;
+
+  base::RecordAction(base::UserMetricsAction("AutofillCreditCardsViewed"));
+  [self updateEditButton];
+  [self loadModel];
+}
+
+- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
+  [super setEditing:editing animated:animated];
+  if (editing) {
+    [self setSwitchItemEnabled:NO itemType:ItemTypeAutofillCardSwitch];
+  } else {
+    [self setSwitchItemEnabled:YES itemType:ItemTypeAutofillCardSwitch];
+  }
+}
+
+#pragma mark - ChromeTableViewController
+
+- (void)loadModel {
+  [super loadModel];
+  TableViewModel* model = self.tableViewModel;
+
+  [model addSectionWithIdentifier:SectionIdentifierSwitches];
+  [model addItem:[self cardSwitchItem]
+      toSectionWithIdentifier:SectionIdentifierSwitches];
+  [model setFooter:[self cardSwitchFooter]
+      forSectionWithIdentifier:SectionIdentifierSwitches];
+
+  [self populateCardSection];
+}
+
+#pragma mark - LoadModel Helpers
+
+// Populates card section using personalDataManager.
+- (void)populateCardSection {
+  TableViewModel* model = self.tableViewModel;
+  const std::vector<autofill::CreditCard*>& creditCards =
+      _personalDataManager->GetCreditCards();
+  if (!creditCards.empty()) {
+    [model addSectionWithIdentifier:SectionIdentifierCards];
+    [model setHeader:[self cardSectionHeader]
+        forSectionWithIdentifier:SectionIdentifierCards];
+    for (autofill::CreditCard* creditCard : creditCards) {
+      DCHECK(creditCard);
+      [model addItem:[self itemForCreditCard:*creditCard]
+          toSectionWithIdentifier:SectionIdentifierCards];
+    }
+  }
+}
+
+- (TableViewItem*)cardSwitchItem {
+  SettingsSwitchItem* switchItem =
+      [[SettingsSwitchItem alloc] initWithType:ItemTypeAutofillCardSwitch];
+  switchItem.text =
+      l10n_util::GetNSString(IDS_AUTOFILL_ENABLE_CREDIT_CARDS_TOGGLE_LABEL);
+  switchItem.on = [self isAutofillCreditCardEnabled];
+  switchItem.accessibilityIdentifier = kAutofillCreditCardSwitchViewId;
+  return switchItem;
+}
+
+- (TableViewHeaderFooterItem*)cardSwitchFooter {
+  TableViewLinkHeaderFooterItem* footer = [[TableViewLinkHeaderFooterItem alloc]
+      initWithType:ItemTypeAutofillCardSwitchSubtitle];
+  footer.text =
+      l10n_util::GetNSString(IDS_AUTOFILL_ENABLE_CREDIT_CARDS_TOGGLE_SUBLABEL);
+  return footer;
+}
+
+- (TableViewHeaderFooterItem*)cardSectionHeader {
+  TableViewTextHeaderFooterItem* header =
+      [[TableViewTextHeaderFooterItem alloc] initWithType:ItemTypeHeader];
+  header.text = l10n_util::GetNSString(IDS_AUTOFILL_PAYMENT_METHODS);
+  return header;
+}
+
+- (TableViewItem*)itemForCreditCard:(const autofill::CreditCard&)creditCard {
+  std::string guid(creditCard.guid());
+  NSString* creditCardName = autofill::GetCreditCardName(
+      creditCard, GetApplicationContext()->GetApplicationLocale());
+
+  AutofillDataItem* item = [[AutofillDataItem alloc] initWithType:ItemTypeCard];
+  item.text = creditCardName;
+  item.leadingDetailText = autofill::GetCreditCardObfuscatedNumber(creditCard);
+  item.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
+  item.accessibilityIdentifier = creditCardName;
+  item.deletable = autofill::IsCreditCardLocal(creditCard);
+  item.GUID = guid;
+  if (![item isDeletable]) {
+    item.trailingDetailText =
+        l10n_util::GetNSString(IDS_IOS_AUTOFILL_WALLET_SERVER_NAME);
+  }
+  return item;
+}
+
+- (BOOL)localCreditCardsExist {
+  return !_personalDataManager->GetLocalCreditCards().empty();
+}
+
+#pragma mark - SettingsRootTableViewController
+
+- (BOOL)shouldShowEditButton {
+  return YES;
+}
+
+- (BOOL)editButtonEnabled {
+  DCHECK([self shouldShowEditButton]);
+  return [self localCreditCardsExist];
+}
+
+- (void)deleteItems:(NSArray<NSIndexPath*>*)indexPaths {
+  // Do not call super as this also deletes the section if it is empty.
+  [self deleteItemAtIndexPaths:indexPaths];
+}
+
+#pragma mark - UITableViewDataSource
+
+- (UITableViewCell*)tableView:(UITableView*)tableView
+        cellForRowAtIndexPath:(NSIndexPath*)indexPath {
+  UITableViewCell* cell = [super tableView:tableView
+                     cellForRowAtIndexPath:indexPath];
+
+  ItemType itemType = static_cast<ItemType>(
+      [self.tableViewModel itemTypeForIndexPath:indexPath]);
+  if (itemType == ItemTypeAutofillCardSwitch) {
+    SettingsSwitchCell* switchCell =
+        base::mac::ObjCCastStrict<SettingsSwitchCell>(cell);
+    [switchCell.switchView addTarget:self
+                              action:@selector(autofillCardSwitchChanged:)
+                    forControlEvents:UIControlEventValueChanged];
+  }
+
+  return cell;
+}
+
+#pragma mark - Switch Callbacks
+
+- (void)autofillCardSwitchChanged:(UISwitch*)switchView {
+  [self setSwitchItemOn:[switchView isOn] itemType:ItemTypeAutofillCardSwitch];
+  [self setAutofillCreditCardEnabled:[switchView isOn]];
+}
+
+#pragma mark - Switch Helpers
+
+// Sets switchItem's state to |on|. It is important that there is only one item
+// of |switchItemType| in SectionIdentifierSwitches.
+- (void)setSwitchItemOn:(BOOL)on itemType:(ItemType)switchItemType {
+  NSIndexPath* switchPath =
+      [self.tableViewModel indexPathForItemType:switchItemType
+                              sectionIdentifier:SectionIdentifierSwitches];
+  SettingsSwitchItem* switchItem =
+      base::mac::ObjCCastStrict<SettingsSwitchItem>(
+          [self.tableViewModel itemAtIndexPath:switchPath]);
+  switchItem.on = on;
+}
+
+// Sets switchItem's enabled status to |enabled| and reconfigures the
+// corresponding cell. It is important that there is no more than one item of
+// |switchItemType| in SectionIdentifierSwitches.
+- (void)setSwitchItemEnabled:(BOOL)enabled itemType:(ItemType)switchItemType {
+  TableViewModel* model = self.tableViewModel;
+
+  if (![model hasItemForItemType:switchItemType
+               sectionIdentifier:SectionIdentifierSwitches]) {
+    return;
+  }
+  NSIndexPath* switchPath =
+      [model indexPathForItemType:switchItemType
+                sectionIdentifier:SectionIdentifierSwitches];
+  SettingsSwitchItem* switchItem =
+      base::mac::ObjCCastStrict<SettingsSwitchItem>(
+          [model itemAtIndexPath:switchPath]);
+  [switchItem setEnabled:enabled];
+  [self reconfigureCellsForItems:@[ switchItem ]];
+}
+
+#pragma mark - UITableViewDelegate
+
+- (void)tableView:(UITableView*)tableView
+    didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
+  [super tableView:tableView didSelectRowAtIndexPath:indexPath];
+
+  // Edit mode is the state where the user can select and delete entries. In
+  // edit mode, selection is handled by the superclass. When not in edit mode
+  // selection presents the editing controller for the selected entry.
+  if (self.editing) {
+    return;
+  }
+
+  [tableView deselectRowAtIndexPath:indexPath animated:YES];
+  TableViewModel* model = self.tableViewModel;
+  NSInteger type = [model itemTypeForIndexPath:indexPath];
+  if (type != ItemTypeCard)
+    return;
+
+  const std::vector<autofill::CreditCard*>& creditCards =
+      _personalDataManager->GetCreditCards();
+  AutofillCreditCardEditTableViewController* controller =
+      [[AutofillCreditCardEditTableViewController alloc]
+           initWithCreditCard:*creditCards[indexPath.item]
+          personalDataManager:_personalDataManager];
+  controller.dispatcher = self.dispatcher;
+  [self.navigationController pushViewController:controller animated:YES];
+}
+
+#pragma mark - UITableViewDataSource
+
+- (BOOL)tableView:(UITableView*)tableView
+    canEditRowAtIndexPath:(NSIndexPath*)indexPath {
+  // Only autofill data cells are editable.
+  TableViewItem* item = [self.tableViewModel itemAtIndexPath:indexPath];
+  if ([item isKindOfClass:[AutofillDataItem class]]) {
+    AutofillDataItem* autofillItem =
+        base::mac::ObjCCastStrict<AutofillDataItem>(item);
+    return [autofillItem isDeletable];
+  }
+  return NO;
+}
+
+- (void)tableView:(UITableView*)tableView
+    commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
+     forRowAtIndexPath:(NSIndexPath*)indexPath {
+  if (editingStyle != UITableViewCellEditingStyleDelete)
+    return;
+  [self deleteItemAtIndexPaths:@[ indexPath ]];
+}
+
+#pragma mark - helper methods
+
+- (void)deleteItemAtIndexPaths:(NSArray<NSIndexPath*>*)indexPaths {
+  self.deletionInProgress = YES;
+  for (NSIndexPath* indexPath in indexPaths) {
+    AutofillDataItem* item = base::mac::ObjCCastStrict<AutofillDataItem>(
+        [self.tableViewModel itemAtIndexPath:indexPath]);
+    _personalDataManager->RemoveByGUID(item.GUID);
+  }
+
+  __weak AutofillCreditCardTableViewController* weakSelf = self;
+  [self.tableView
+      performBatchUpdates:^{
+        // Obtain strong reference again.
+        AutofillCreditCardTableViewController* strongSelf = weakSelf;
+        if (!strongSelf) {
+          return;
+        }
+
+        NSUInteger section = [self.tableViewModel
+            sectionForSectionIdentifier:SectionIdentifierCards];
+        NSUInteger currentCount =
+            [self.tableViewModel numberOfItemsInSection:section];
+        if (currentCount == indexPaths.count) {
+          [[strongSelf tableViewModel]
+              removeSectionWithIdentifier:SectionIdentifierCards];
+          [[strongSelf tableView]
+                deleteSections:[NSIndexSet indexSetWithIndex:section]
+              withRowAnimation:UITableViewRowAnimationAutomatic];
+        } else {
+          [strongSelf removeFromModelItemAtIndexPaths:indexPaths];
+          [strongSelf.tableView
+              deleteRowsAtIndexPaths:indexPaths
+                    withRowAnimation:UITableViewRowAnimationAutomatic];
+        }
+      }
+      completion:^(BOOL finished) {
+        // Obtain strong reference again.
+        AutofillCreditCardTableViewController* strongSelf = weakSelf;
+        if (!strongSelf) {
+          return;
+        }
+
+        // Turn off edit mode if there is nothing to edit.
+        if (![strongSelf localCreditCardsExist] && strongSelf.editing) {
+          [strongSelf setEditing:NO animated:YES];
+        }
+        [strongSelf updateEditButton];
+        strongSelf.deletionInProgress = NO;
+      }];
+}
+
+#pragma mark PersonalDataManagerObserver
+
+- (void)onPersonalDataChanged {
+  if (self.deletionInProgress)
+    return;
+
+  if (![self localCreditCardsExist] && self.editing) {
+    // Turn off edit mode if there exists nothing to edit.
+    [self setEditing:NO animated:YES];
+  }
+
+  [self updateEditButton];
+  [self reloadData];
+}
+
+#pragma mark - Getters and Setter
+
+- (BOOL)isAutofillCreditCardEnabled {
+  return autofill::prefs::IsCreditCardAutofillEnabled(
+      _browserState->GetPrefs());
+}
+
+- (void)setAutofillCreditCardEnabled:(BOOL)isEnabled {
+  return autofill::prefs::SetCreditCardAutofillEnabled(
+      _browserState->GetPrefs(), isEnabled);
+}
+
+@end
diff --git a/ios/chrome/browser/ui/settings/autofill_credit_card_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/autofill_credit_card_table_view_controller_unittest.mm
new file mode 100644
index 0000000..be41c32c
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/autofill_credit_card_table_view_controller_unittest.mm
@@ -0,0 +1,117 @@
+// 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 "ios/chrome/browser/ui/settings/autofill_credit_card_table_view_controller.h"
+
+#include "base/guid.h"
+#include "base/mac/foundation_util.h"
+#include "base/strings/utf_string_conversions.h"
+#import "base/test/ios/wait_util.h"
+#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "ios/chrome/browser/autofill/personal_data_manager_factory.h"
+#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
+#include "ios/chrome/browser/ui/settings/personal_data_manager_data_changed_observer.h"
+#import "ios/chrome/browser/ui/table_view/chrome_table_view_controller_test.h"
+#include "ios/web/public/test/test_web_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+
+class AutofillCreditCardTableViewControllerTest
+    : public ChromeTableViewControllerTest {
+ protected:
+  AutofillCreditCardTableViewControllerTest() {
+    TestChromeBrowserState::Builder test_cbs_builder;
+    chrome_browser_state_ = test_cbs_builder.Build();
+    // Credit card import requires a PersonalDataManager which itself needs the
+    // WebDataService; this is not initialized on a TestChromeBrowserState by
+    // default.
+    chrome_browser_state_->CreateWebDataService();
+  }
+
+  ChromeTableViewController* InstantiateController() override {
+    return [[AutofillCreditCardTableViewController alloc]
+        initWithBrowserState:chrome_browser_state_.get()];
+  }
+
+  void AddCreditCard(const std::string& origin,
+                     const std::string& card_holder_name,
+                     const std::string& card_number) {
+    autofill::PersonalDataManager* personal_data_manager =
+        autofill::PersonalDataManagerFactory::GetForBrowserState(
+            chrome_browser_state_.get());
+    PersonalDataManagerDataChangedObserver observer(personal_data_manager);
+
+    autofill::CreditCard credit_card(base::GenerateGUID(), origin);
+    credit_card.SetRawInfo(autofill::CREDIT_CARD_NAME_FULL,
+                           base::ASCIIToUTF16(card_holder_name));
+    credit_card.SetRawInfo(autofill::CREDIT_CARD_NUMBER,
+                           base::ASCIIToUTF16(card_number));
+    personal_data_manager->OnAcceptedLocalCreditCardSave(credit_card);
+    observer.Wait();  // Wait for completion of the asynchronous operation.
+  }
+
+  // Deletes the item at (section, row) and waits util condition returns true or
+  // timeout.
+  bool deleteItemAndWait(int section, int row, ConditionBlock condition) {
+    AutofillCreditCardTableViewController* view_controller =
+        base::mac::ObjCCastStrict<AutofillCreditCardTableViewController>(
+            controller());
+    [view_controller deleteItems:@[ [NSIndexPath indexPathForRow:row
+                                                       inSection:section] ]];
+    return base::test::ios::WaitUntilConditionOrTimeout(
+        base::test::ios::kWaitForUIElementTimeout, condition);
+  }
+
+  web::TestWebThreadBundle thread_bundle_;
+  std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
+};
+
+// Default test case of no credit cards.
+TEST_F(AutofillCreditCardTableViewControllerTest, TestInitialization) {
+  CreateController();
+  CheckController();
+
+  // Expect one switch section.
+  EXPECT_EQ(1, NumberOfSections());
+  // Expect switch section to contain one row (the credit card Autofill toggle).
+  EXPECT_EQ(1, NumberOfItemsInSection(0));
+}
+
+// Adding a single credit card results in a credit card section.
+TEST_F(AutofillCreditCardTableViewControllerTest, TestOneCreditCard) {
+  AddCreditCard("https://www.example.com/", "John Doe", "378282246310005");
+  CreateController();
+  CheckController();
+
+  // Expect two sections (switch and credit card section).
+  EXPECT_EQ(2, NumberOfSections());
+  // Expect credit card section to contain one row (the credit card itself).
+  EXPECT_EQ(1, NumberOfItemsInSection(1));
+}
+
+// Deleting the only credit card results in item deletion and section deletion.
+TEST_F(AutofillCreditCardTableViewControllerTest,
+       TestOneCreditCardItemDeleted) {
+  AddCreditCard("https://www.example.com/", "John Doe", "378282246310005");
+  CreateController();
+  CheckController();
+
+  // Expect two sections (switch and credit card section).
+  EXPECT_EQ(2, NumberOfSections());
+  // Expect credit card section to contain one row (the credit card itself).
+  EXPECT_EQ(1, NumberOfItemsInSection(1));
+
+  // Delete the credit card item and check that the section is removed.
+  EXPECT_TRUE(deleteItemAndWait(1, 0, ^{
+    return NumberOfSections() == 1;
+  }));
+}
+
+}  // namespace
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/clear_browsing_data_collection_view_controller_unittest.mm
index 530114a..0cf03c9 100644
--- a/ios/chrome/browser/ui/settings/clear_browsing_data_collection_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data_collection_view_controller_unittest.mm
@@ -179,11 +179,13 @@
       .WillRepeatedly(Return(syncer::SyncService::DISABLE_REASON_NONE));
   EXPECT_CALL(*mock_sync_service_, GetTransportState())
       .WillRepeatedly(Return(syncer::SyncService::TransportState::ACTIVE));
-  EXPECT_CALL(*mock_sync_service_, IsFirstSetupComplete())
+  EXPECT_CALL(*mock_sync_service_->GetUserSettingsMock(),
+              IsFirstSetupComplete())
       .WillRepeatedly(Return(true));
   EXPECT_CALL(*mock_sync_service_, GetActiveDataTypes())
       .WillRepeatedly(Return(syncer::ModelTypeSet()));
-  EXPECT_CALL(*mock_sync_service_, IsUsingSecondaryPassphrase())
+  EXPECT_CALL(*mock_sync_service_->GetUserSettingsMock(),
+              IsUsingSecondaryPassphrase())
       .WillRepeatedly(Return(true));
 
   identity_test_env()->SetPrimaryAccount("syncuser@example.com");
diff --git a/ios/chrome/browser/ui/settings/material_cell_catalog_view_controller.mm b/ios/chrome/browser/ui/settings/material_cell_catalog_view_controller.mm
index 075434d..a0813cf 100644
--- a/ios/chrome/browser/ui/settings/material_cell_catalog_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/material_cell_catalog_view_controller.mm
@@ -10,7 +10,7 @@
 #include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/grit/components_scaled_resources.h"
-#import "ios/chrome/browser/ui/authentication/cells/account_control_item.h"
+#import "ios/chrome/browser/ui/authentication/cells/legacy_account_control_item.h"
 #import "ios/chrome/browser/ui/authentication/cells/signin_promo_item.h"
 #import "ios/chrome/browser/ui/authentication/cells/signin_promo_view_configurator.h"
 #import "ios/chrome/browser/ui/authentication/cells/signin_promo_view_delegate.h"
@@ -597,7 +597,7 @@
 }
 
 - (CollectionViewItem*)accountControlItem {
-  AccountControlItem* item = [[AccountControlItem alloc]
+  LegacyAccountControlItem* item = [[LegacyAccountControlItem alloc]
       initWithType:ItemTypeAccountControlDynamicHeight];
   item.cellStyle = CollectionViewCellStyle::kUIKit;
   item.image = [UIImage imageNamed:@"settings_sync"];
@@ -608,7 +608,7 @@
 }
 
 - (CollectionViewItem*)accountControlItemWithExtraLongText {
-  AccountControlItem* item = [[AccountControlItem alloc]
+  LegacyAccountControlItem* item = [[LegacyAccountControlItem alloc]
       initWithType:ItemTypeAccountControlDynamicHeight];
   item.cellStyle = CollectionViewCellStyle::kUIKit;
   item.image = [ChromeIcon infoIcon];
diff --git a/ios/chrome/browser/ui/settings/passphrase_collection_view_controller_test.mm b/ios/chrome/browser/ui/settings/passphrase_collection_view_controller_test.mm
index 2807513..123e9a06 100644
--- a/ios/chrome/browser/ui/settings/passphrase_collection_view_controller_test.mm
+++ b/ios/chrome/browser/ui/settings/passphrase_collection_view_controller_test.mm
@@ -87,7 +87,7 @@
   fake_sync_service_->Initialize();
 
   // Set up non-default return values for our sync service mock.
-  ON_CALL(*fake_sync_service_, IsPassphraseRequired())
+  ON_CALL(*fake_sync_service_->GetUserSettingsMock(), IsPassphraseRequired())
       .WillByDefault(Return(true));
   ON_CALL(*fake_sync_service_, GetTransportState())
       .WillByDefault(Return(syncer::SyncService::TransportState::ACTIVE));
diff --git a/ios/chrome/browser/ui/settings/search_engine_table_view_controller.mm b/ios/chrome/browser/ui/settings/search_engine_table_view_controller.mm
index afa731b..42eaebb 100644
--- a/ios/chrome/browser/ui/settings/search_engine_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/search_engine_table_view_controller.mm
@@ -43,7 +43,7 @@
 
 }  // namespace
 
-@interface SearchEngineTableViewController ()<SearchEngineObserving>
+@interface SearchEngineTableViewController () <SearchEngineObserving>
 @end
 
 @implementation SearchEngineTableViewController {
@@ -141,6 +141,7 @@
 - (void)tableView:(UITableView*)tableView
     didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
   [super tableView:tableView didSelectRowAtIndexPath:indexPath];
+  [tableView deselectRowAtIndexPath:indexPath animated:YES];
   TableViewModel* model = self.tableViewModel;
 
   // Only handle taps on search engine items.
@@ -209,7 +210,6 @@
               [model indexInItemTypeForIndexPath:indexPath]];
 
   [self reconfigureCellsForItems:modifiedItems];
-  [tableView deselectRowAtIndexPath:indexPath animated:YES];
 }
 
 #pragma mark Internal methods
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 026f2c8..4bc11b2 100644
--- a/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm
@@ -44,7 +44,7 @@
 #import "ios/chrome/browser/ui/commands/settings_main_page_commands.h"
 #import "ios/chrome/browser/ui/settings/about_chrome_table_view_controller.h"
 #import "ios/chrome/browser/ui/settings/accounts_collection_view_controller.h"
-#import "ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller.h"
+#import "ios/chrome/browser/ui/settings/autofill_credit_card_table_view_controller.h"
 #import "ios/chrome/browser/ui/settings/autofill_profile_table_view_controller.h"
 #import "ios/chrome/browser/ui/settings/bandwidth_management_table_view_controller.h"
 #import "ios/chrome/browser/ui/settings/cells/account_signin_item.h"
@@ -863,7 +863,7 @@
           initWithBrowserState:_browserState];
       break;
     case ItemTypeAutofillCreditCard:
-      controller = [[AutofillCreditCardCollectionViewController alloc]
+      controller = [[AutofillCreditCardTableViewController alloc]
           initWithBrowserState:_browserState];
       break;
     case ItemTypeAutofillProfile:
diff --git a/ios/chrome/browser/ui/settings/settings_egtest.mm b/ios/chrome/browser/ui/settings/settings_egtest.mm
index 3ad6f18..7ed6a20 100644
--- a/ios/chrome/browser/ui/settings/settings_egtest.mm
+++ b/ios/chrome/browser/ui/settings/settings_egtest.mm
@@ -22,7 +22,6 @@
 #include "ios/chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "ios/chrome/browser/pref_names.h"
 #import "ios/chrome/browser/ui/authentication/cells/signin_promo_view.h"
-#import "ios/chrome/browser/ui/browser_view_controller.h"
 #include "ios/chrome/grit/ios_chromium_strings.h"
 #include "ios/chrome/grit/ios_strings.h"
 #include "ios/chrome/grit/ios_theme_resources.h"
@@ -662,10 +661,10 @@
       assertWithMatcher:grey_notNil()];
 
   // Verify that the Settings register keyboard commands.
-  MainController* mainController = chrome_test_util::GetMainController();
-  BrowserViewController* bvc =
-      [[mainController browserViewInformation] currentBVC];
-  UIViewController* settings = bvc.presentedViewController;
+  UIViewController* viewController =
+      chrome_test_util::GetMainController()
+          .interfaceProvider.mainInterface.viewController;
+  UIViewController* settings = viewController.presentedViewController;
   GREYAssertNotNil(settings.keyCommands,
                    @"Settings should register key commands when presented.");
 
diff --git a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
index 577117a..c3fc3fa 100644
--- a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
+++ b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
@@ -14,7 +14,7 @@
 #import "ios/chrome/browser/ui/material_components/app_bar_view_controller_presenting.h"
 #import "ios/chrome/browser/ui/material_components/utils.h"
 #import "ios/chrome/browser/ui/settings/accounts_collection_view_controller.h"
-#import "ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller.h"
+#import "ios/chrome/browser/ui/settings/autofill_credit_card_table_view_controller.h"
 #import "ios/chrome/browser/ui/settings/autofill_profile_table_view_controller.h"
 #import "ios/chrome/browser/ui/settings/google_services_settings_coordinator.h"
 #import "ios/chrome/browser/ui/settings/google_services_settings_view_controller.h"
@@ -261,8 +261,8 @@
 newAutofillCreditCardController:(ios::ChromeBrowserState*)browserState
                        delegate:
                            (id<SettingsNavigationControllerDelegate>)delegate {
-  AutofillCreditCardCollectionViewController* controller =
-      [[AutofillCreditCardCollectionViewController alloc]
+  AutofillCreditCardTableViewController* controller =
+      [[AutofillCreditCardTableViewController alloc]
           initWithBrowserState:browserState];
   controller.dispatcher = [delegate dispatcherForSettings];
 
@@ -570,8 +570,8 @@
 // TODO(crbug.com/779791) : Do not pass |baseViewController| through dispatcher.
 - (void)showCreditCardSettingsFromViewController:
     (UIViewController*)baseViewController {
-  AutofillCreditCardCollectionViewController* controller =
-      [[AutofillCreditCardCollectionViewController alloc]
+  AutofillCreditCardTableViewController* controller =
+      [[AutofillCreditCardTableViewController alloc]
           initWithBrowserState:mainBrowserState_];
   controller.dispatcher = [delegate_ dispatcherForSettings];
   [self pushViewController:controller animated:YES];
diff --git a/ios/chrome/browser/ui/settings/settings_root_table_view_controller.h b/ios/chrome/browser/ui/settings/settings_root_table_view_controller.h
index 476f446..506e074 100644
--- a/ios/chrome/browser/ui/settings/settings_root_table_view_controller.h
+++ b/ios/chrome/browser/ui/settings/settings_root_table_view_controller.h
@@ -61,6 +61,19 @@
 // Default implementation removes the items.
 - (void)deleteItems:(NSArray<NSIndexPath*>*)indexPaths;
 
+// Prevents user interaction until |-allowUserInteraction| is called by doing
+// the following:
+// * Disables user interaction with the navigation bar.
+// * Replaces the done button with an activity indicator.
+// * Covers the TableView with a transparent veil.
+- (void)preventUserInteraction;
+
+// Allows user interaction:
+// * Enables user interaction with the navigation bar.
+// * Restores the done button.
+// * Removes the transparent veil.
+- (void)allowUserInteraction;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_SETTINGS_SETTINGS_ROOT_TABLE_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm b/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm
index 100a0f94..baa7b4a7 100644
--- a/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm
@@ -8,6 +8,7 @@
 #import "ios/chrome/browser/ui/commands/application_commands.h"
 #import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
 #import "ios/chrome/browser/ui/material_components/utils.h"
+#import "ios/chrome/browser/ui/settings/bar_button_activity_indicator.h"
 #import "ios/chrome/browser/ui/settings/cells/settings_cells_constants.h"
 #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h"
 #import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h"
@@ -20,12 +21,21 @@
 #endif
 
 namespace {
-constexpr CGFloat kTableViewSeparatorInset = 16;
 // Height of the space used by header/footer when none is set. Default is
 // |estimatedSection{Header|Footer}Height|.
 const CGFloat kDefaultHeaderFooterHeight = 10;
 // Estimated height of the header/footer, used to speed the constraints.
 const CGFloat kEstimatedHeaderFooterHeight = 35;
+
+enum SavedBarButtomItemPositionEnum {
+  kUndefinedBarButtonItemPosition,
+  kLeftBarButtonItemPosition,
+  kRightBarButtonItemPosition
+};
+
+// Dimension of the authentication operation activity indicator frame.
+const CGFloat kActivityIndicatorDimensionIPad = 64;
+const CGFloat kActivityIndicatorDimensionIPhone = 56;
 }  // namespace
 
 NSString* const kSettingsToolbarDeleteButtonId =
@@ -36,11 +46,21 @@
 // Delete button for the toolbar.
 @property(nonatomic, strong) UIBarButtonItem* deleteButton;
 
+// Item displayed before the user interactions are prevented. This is used to
+// store the item while the interaction is prevented.
+@property(nonatomic, strong) UIBarButtonItem* savedBarButtonItem;
+
+// Veil preventing interactions with the TableView.
+@property(nonatomic, strong) UIView* veil;
+
+// Position of the saved button.
+@property(nonatomic, assign)
+    SavedBarButtomItemPositionEnum savedBarButtonItemPosition;
+
 @end
 
 @implementation SettingsRootTableViewController
 
-@synthesize deleteButton = _deleteButton;
 @synthesize dispatcher = _dispatcher;
 
 #pragma mark - Public
@@ -99,8 +119,8 @@
   self.tableView.estimatedSectionHeaderHeight = kEstimatedHeaderFooterHeight;
   self.tableView.estimatedRowHeight = kSettingsCellDefaultHeight;
   self.tableView.estimatedSectionFooterHeight = kEstimatedHeaderFooterHeight;
-  self.tableView.separatorInset = UIEdgeInsetsMake(0, kTableViewSeparatorInset,
-                                                   0, kTableViewSeparatorInset);
+  self.tableView.separatorInset =
+      UIEdgeInsetsMake(0, kTableViewSeparatorInset, 0, 0);
   // Do not set the estimated height of the footer/header as if there is no
   // header/footer, there is an empty space.
 }
@@ -231,4 +251,80 @@
                completion:nil];
 }
 
+- (void)preventUserInteraction {
+  DCHECK(!self.savedBarButtonItem);
+  DCHECK_EQ(kUndefinedBarButtonItemPosition, self.savedBarButtonItemPosition);
+
+  // Create |waitButton|.
+  BOOL displayActivityIndicatorOnTheRight =
+      self.navigationItem.rightBarButtonItem != nil;
+  CGFloat activityIndicatorDimension = IsIPadIdiom()
+                                           ? kActivityIndicatorDimensionIPad
+                                           : kActivityIndicatorDimensionIPhone;
+  BarButtonActivityIndicator* indicator = [[BarButtonActivityIndicator alloc]
+      initWithFrame:CGRectMake(0.0, 0.0, activityIndicatorDimension,
+                               activityIndicatorDimension)];
+  UIBarButtonItem* waitButton =
+      [[UIBarButtonItem alloc] initWithCustomView:indicator];
+
+  if (displayActivityIndicatorOnTheRight) {
+    // If there is a right bar button item, then it is the "Done" button.
+    self.savedBarButtonItem = self.navigationItem.rightBarButtonItem;
+    self.savedBarButtonItemPosition = kRightBarButtonItemPosition;
+    self.navigationItem.rightBarButtonItem = waitButton;
+    [self.navigationItem.leftBarButtonItem setEnabled:NO];
+  } else {
+    self.savedBarButtonItem = self.navigationItem.leftBarButtonItem;
+    self.savedBarButtonItemPosition = kLeftBarButtonItemPosition;
+    self.navigationItem.leftBarButtonItem = waitButton;
+  }
+
+  // Adds a veil that covers the collection view and prevents user interaction.
+  DCHECK(self.view);
+  DCHECK(!self.veil);
+  self.veil = [[UIView alloc] initWithFrame:self.view.bounds];
+  [self.veil setAutoresizingMask:(UIViewAutoresizingFlexibleWidth |
+                                  UIViewAutoresizingFlexibleHeight)];
+  [self.veil setBackgroundColor:[UIColor colorWithWhite:1.0 alpha:0.5]];
+  [self.view addSubview:self.veil];
+
+  // Disable user interaction for the navigation controller view to ensure
+  // that the user cannot go back by swipping the navigation's top view
+  // controller
+  [self.navigationController.view setUserInteractionEnabled:NO];
+}
+
+- (void)allowUserInteraction {
+  DCHECK(self.navigationController)
+      << "|allowUserInteraction| should always be called before this settings"
+         " controller is popped or dismissed.";
+  [self.navigationController.view setUserInteractionEnabled:YES];
+
+  // Removes the veil that prevents user interaction.
+  DCHECK(self.veil);
+  [UIView animateWithDuration:0.3
+      animations:^{
+        [self.veil removeFromSuperview];
+      }
+      completion:^(BOOL finished) {
+        self.veil = nil;
+      }];
+
+  DCHECK(self.savedBarButtonItem);
+  switch (self.savedBarButtonItemPosition) {
+    case kLeftBarButtonItemPosition:
+      self.navigationItem.leftBarButtonItem = self.savedBarButtonItem;
+      break;
+    case kRightBarButtonItemPosition:
+      self.navigationItem.rightBarButtonItem = self.savedBarButtonItem;
+      [self.navigationItem.leftBarButtonItem setEnabled:YES];
+      break;
+    default:
+      NOTREACHED();
+      break;
+  }
+  self.savedBarButtonItem = nil;
+  self.savedBarButtonItemPosition = kUndefinedBarButtonItemPosition;
+}
+
 @end
diff --git a/ios/chrome/browser/ui/settings/sync_create_passphrase_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/sync_create_passphrase_collection_view_controller_unittest.mm
index a322497..58d3fb5 100644
--- a/ios/chrome/browser/ui/settings/sync_create_passphrase_collection_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/sync_create_passphrase_collection_view_controller_unittest.mm
@@ -57,7 +57,9 @@
        TestConstructorDestructor) {
   CreateController();
   CheckController();
-  EXPECT_CALL(*fake_sync_service_, SetEncryptionPassphrase(_)).Times(0);
+  EXPECT_CALL(*fake_sync_service_->GetUserSettingsMock(),
+              SetEncryptionPassphrase(_))
+      .Times(0);
   // Simulate the view appearing.
   [controller() viewDidAppear:YES];
 }
@@ -98,7 +100,9 @@
        TestCredentialsOkPressed) {
   SyncCreatePassphraseCollectionViewController* sync_controller =
       SyncController();
-  EXPECT_CALL(*fake_sync_service_, SetEncryptionPassphrase(_)).Times(0);
+  EXPECT_CALL(*fake_sync_service_->GetUserSettingsMock(),
+              SetEncryptionPassphrase(_))
+      .Times(0);
   EXPECT_FALSE([[sync_controller navigationItem].rightBarButtonItem isEnabled]);
   [sync_controller signInPressed];
 }
@@ -110,7 +114,8 @@
   // With matching text, this should cause an attempt to set the passphrase.
   EXPECT_CALL(*fake_sync_service_, AddObserver(_)).Times(AtLeast(1));
   EXPECT_CALL(*fake_sync_service_, RemoveObserver(_)).Times(AtLeast(1));
-  EXPECT_CALL(*fake_sync_service_, SetEncryptionPassphrase("decodeme"));
+  EXPECT_CALL(*fake_sync_service_->GetUserSettingsMock(),
+              SetEncryptionPassphrase("decodeme"));
   [[sync_controller passphrase] setText:@"decodeme"];
   [sync_controller textFieldDidChange:[sync_controller passphrase]];
   [sync_controller textFieldDidEndEditing:[sync_controller passphrase]];
@@ -123,7 +128,9 @@
        TestOneTextFieldEmpty) {
   SyncCreatePassphraseCollectionViewController* sync_controller =
       SyncController();
-  EXPECT_CALL(*fake_sync_service_, SetEncryptionPassphrase(_)).Times(0);
+  EXPECT_CALL(*fake_sync_service_->GetUserSettingsMock(),
+              SetEncryptionPassphrase(_))
+      .Times(0);
   [[sync_controller passphrase] setText:@"decodeme"];
   [sync_controller textFieldDidChange:[sync_controller passphrase]];
   // Expect the right button to be visible.
@@ -139,7 +146,9 @@
   // Mismatching text fields should not get to the point of trying to set the
   // passphrase and adding the sync observer.
   EXPECT_CALL(*fake_sync_service_, AddObserver(_)).Times(0);
-  EXPECT_CALL(*fake_sync_service_, SetEncryptionPassphrase(_)).Times(0);
+  EXPECT_CALL(*fake_sync_service_->GetUserSettingsMock(),
+              SetEncryptionPassphrase(_))
+      .Times(0);
   [[sync_controller passphrase] setText:@"decodeme"];
   [[sync_controller confirmPassphrase] setText:@"donothing"];
   [sync_controller textFieldDidChange:[sync_controller passphrase]];
@@ -159,7 +168,8 @@
   // Matching text should cause an attempt to set it and add a sync observer.
   EXPECT_CALL(*fake_sync_service_, AddObserver(_)).Times(AtLeast(1));
   EXPECT_CALL(*fake_sync_service_, RemoveObserver(_)).Times(AtLeast(1));
-  EXPECT_CALL(*fake_sync_service_, SetEncryptionPassphrase("decodeme"));
+  EXPECT_CALL(*fake_sync_service_->GetUserSettingsMock(),
+              SetEncryptionPassphrase("decodeme"));
   [[sync_controller passphrase] setText:@"decodeme"];
   [[sync_controller confirmPassphrase] setText:@"decodeme"];
   [sync_controller textFieldDidChange:[sync_controller passphrase]];
@@ -173,9 +183,10 @@
   EXPECT_EQ([nav_controller_ topViewController], sync_controller);
 
   // Set up the fake sync service to have accepted the passphrase.
-  ON_CALL(*fake_sync_service_, IsPassphraseRequired())
+  ON_CALL(*fake_sync_service_->GetUserSettingsMock(), IsPassphraseRequired())
       .WillByDefault(Return(false));
-  ON_CALL(*fake_sync_service_, IsUsingSecondaryPassphrase())
+  ON_CALL(*fake_sync_service_->GetUserSettingsMock(),
+          IsUsingSecondaryPassphrase())
       .WillByDefault(Return(true));
   [sync_controller onSyncStateChanged];
   // Calling -onStateChanged with an accepted secondary passphrase should
@@ -205,9 +216,10 @@
   sync_controller.navigationItem.leftBarButtonItem = leftBarButtonItem;
 
   // Set up the fake sync service to be in a passphrase creation state.
-  ON_CALL(*fake_sync_service_, IsPassphraseRequired())
+  ON_CALL(*fake_sync_service_->GetUserSettingsMock(), IsPassphraseRequired())
       .WillByDefault(Return(false));
-  ON_CALL(*fake_sync_service_, IsUsingSecondaryPassphrase())
+  ON_CALL(*fake_sync_service_->GetUserSettingsMock(),
+          IsUsingSecondaryPassphrase())
       .WillByDefault(Return(false));
   [sync_controller onSyncStateChanged];
   EXPECT_EQ([nav_controller_ topViewController], sync_controller);
diff --git a/ios/chrome/browser/ui/settings/sync_encryption_passphrase_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/sync_encryption_passphrase_collection_view_controller_unittest.mm
index bc5617f..c2e1cc2 100644
--- a/ios/chrome/browser/ui/settings/sync_encryption_passphrase_collection_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/sync_encryption_passphrase_collection_view_controller_unittest.mm
@@ -117,7 +117,9 @@
        TestConstructorDestructor) {
   CreateController();
   CheckController();
-  EXPECT_CALL(*fake_sync_service_, SetDecryptionPassphrase(_)).Times(0);
+  EXPECT_CALL(*fake_sync_service_->GetUserSettingsMock(),
+              SetDecryptionPassphrase(_))
+      .Times(0);
   // Simulate the view appearing.
   [controller() viewWillAppear:YES];
   [controller() viewDidAppear:YES];
@@ -140,10 +142,12 @@
       SyncController();
   EXPECT_CALL(*fake_sync_service_, AddObserver(_)).Times(AtLeast(1));
   EXPECT_CALL(*fake_sync_service_, RemoveObserver(_)).Times(AtLeast(1));
-  EXPECT_CALL(*fake_sync_service_, SetDecryptionPassphrase(_));
+  EXPECT_CALL(*fake_sync_service_->GetUserSettingsMock(),
+              SetDecryptionPassphrase(_));
   [[sync_controller passphrase] setText:@"decodeme"];
   // Set the return value for setting the passphrase to failure.
-  ON_CALL(*fake_sync_service_, SetDecryptionPassphrase(_))
+  ON_CALL(*fake_sync_service_->GetUserSettingsMock(),
+          SetDecryptionPassphrase(_))
       .WillByDefault(Return(false));
   [sync_controller signInPressed];
 }
@@ -154,10 +158,12 @@
       SyncController();
   EXPECT_CALL(*fake_sync_service_, AddObserver(_)).Times(AtLeast(1));
   EXPECT_CALL(*fake_sync_service_, RemoveObserver(_)).Times(AtLeast(1));
-  EXPECT_CALL(*fake_sync_service_, SetDecryptionPassphrase(_));
+  EXPECT_CALL(*fake_sync_service_->GetUserSettingsMock(),
+              SetDecryptionPassphrase(_));
   [[sync_controller passphrase] setText:@"decodeme"];
   // Set the return value for setting the passphrase to success.
-  ON_CALL(*fake_sync_service_, SetDecryptionPassphrase(_))
+  ON_CALL(*fake_sync_service_->GetUserSettingsMock(),
+          SetDecryptionPassphrase(_))
       .WillByDefault(Return(true));
   [sync_controller signInPressed];
 }
@@ -172,7 +178,7 @@
   EXPECT_EQ([nav_controller_ topViewController], sync_controller);
 
   // Set up the fake sync service to still require the passphrase.
-  ON_CALL(*fake_sync_service_, IsPassphraseRequired())
+  ON_CALL(*fake_sync_service_->GetUserSettingsMock(), IsPassphraseRequired())
       .WillByDefault(Return(true));
   [sync_controller onSyncStateChanged];
   // The controller should only reload. Because there is text in the passphrase
@@ -190,9 +196,10 @@
   EXPECT_EQ([nav_controller_ topViewController], sync_controller);
 
   // Set up the fake sync service to have accepted the passphrase.
-  ON_CALL(*fake_sync_service_, IsPassphraseRequired())
+  ON_CALL(*fake_sync_service_->GetUserSettingsMock(), IsPassphraseRequired())
       .WillByDefault(Return(false));
-  ON_CALL(*fake_sync_service_, IsUsingSecondaryPassphrase())
+  ON_CALL(*fake_sync_service_->GetUserSettingsMock(),
+          IsUsingSecondaryPassphrase())
       .WillByDefault(Return(true));
   [sync_controller onSyncStateChanged];
   // Calling -onStateChanged with an accepted secondary passphrase should
diff --git a/ios/chrome/browser/ui/settings/sync_encryption_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/sync_encryption_table_view_controller_unittest.mm
index 2049f01..6cae9e6 100644
--- a/ios/chrome/browser/ui/settings/sync_encryption_table_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/sync_encryption_table_view_controller_unittest.mm
@@ -56,7 +56,8 @@
                 chrome_browser_state_.get()));
     ON_CALL(*mock_profile_sync_service_, GetTransportState())
         .WillByDefault(Return(syncer::SyncService::TransportState::ACTIVE));
-    ON_CALL(*mock_profile_sync_service_, IsUsingSecondaryPassphrase())
+    ON_CALL(*mock_profile_sync_service_->GetUserSettingsMock(),
+            IsUsingSecondaryPassphrase())
         .WillByDefault(Return(true));
 
     CreateController();
diff --git a/ios/chrome/browser/ui/settings/sync_settings_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/sync_settings_collection_view_controller_unittest.mm
index 97b7fb6..820faf4 100644
--- a/ios/chrome/browser/ui/settings/sync_settings_collection_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/sync_settings_collection_view_controller_unittest.mm
@@ -193,7 +193,8 @@
     ON_CALL(*mock_profile_sync_service_, GetRegisteredDataTypes())
         .WillByDefault(Return(syncer::ModelTypeSet()));
     mock_profile_sync_service_->Initialize();
-    EXPECT_CALL(*mock_profile_sync_service_, GetPreferredDataTypes())
+    EXPECT_CALL(*mock_profile_sync_service_->GetUserSettingsMock(),
+                GetChosenDataTypes())
         .WillRepeatedly(Return(syncer::UserSelectableTypes()));
   }
 
diff --git a/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.mm b/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.mm
index 57df57d6..0f049f75 100644
--- a/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.mm
@@ -4,7 +4,10 @@
 
 #import "ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.h"
 
+#import "ios/chrome/browser/ui/authentication/cells/account_control_item.h"
+#import "ios/chrome/browser/ui/authentication/cells/table_view_account_item.h"
 #import "ios/chrome/browser/ui/autofill/cells/autofill_edit_item.h"
+#import "ios/chrome/browser/ui/icons/chrome_icon.h"
 #import "ios/chrome/browser/ui/settings/cells/autofill_data_item.h"
 #import "ios/chrome/browser/ui/settings/cells/encryption_item.h"
 #import "ios/chrome/browser/ui/settings/cells/settings_detail_item.h"
@@ -30,6 +33,7 @@
   SectionIdentifierText = kSectionIdentifierEnumZero,
   SectionIdentifierSettings,
   SectionIdentifierAutofill,
+  SectionIdentifierAccount,
   SectionIdentifierURL,
 };
 
@@ -52,6 +56,7 @@
   ItemTypeSettingsSwitch,
   ItemTypeAutofillEditItem,
   ItemTypeAutofillData,
+  ItemTypeAccount,
 };
 }
 
@@ -83,6 +88,7 @@
   [model addSectionWithIdentifier:SectionIdentifierText];
   [model addSectionWithIdentifier:SectionIdentifierSettings];
   [model addSectionWithIdentifier:SectionIdentifierAutofill];
+  [model addSectionWithIdentifier:SectionIdentifierAccount];
   [model addSectionWithIdentifier:SectionIdentifierURL];
 
   // SectionIdentifierText.
@@ -247,6 +253,58 @@
   [model addItem:autofillItemWithAllTexts
       toSectionWithIdentifier:SectionIdentifierAutofill];
 
+  // SectionIdentifierAccount.
+  TableViewAccountItem* accountItemDetailWithError =
+      [[TableViewAccountItem alloc] initWithType:ItemTypeAccount];
+  // TODO(crbug.com/754032): ios_default_avatar image is from a downstream iOS
+  // internal repository. It should be used through a provider API instead.
+  accountItemDetailWithError.image = [UIImage imageNamed:@"ios_default_avatar"];
+  accountItemDetailWithError.text = @"Account User Name";
+  accountItemDetailWithError.detailText =
+      @"Syncing to AccountUserNameAccount@example.com";
+  accountItemDetailWithError.accessoryType =
+      UITableViewCellAccessoryDisclosureIndicator;
+  accountItemDetailWithError.shouldDisplayError = YES;
+  [model addItem:accountItemDetailWithError
+      toSectionWithIdentifier:SectionIdentifierAccount];
+
+  TableViewAccountItem* accountItemCheckMark =
+      [[TableViewAccountItem alloc] initWithType:ItemTypeAccount];
+  // TODO(crbug.com/754032): ios_default_avatar image is from a downstream iOS
+  // internal repository. It should be used through a provider API instead.
+  accountItemCheckMark.image = [UIImage imageNamed:@"ios_default_avatar"];
+  accountItemCheckMark.text = @"Lorem ipsum dolor sit amet, consectetur "
+                              @"adipiscing elit, sed do eiusmod tempor "
+                              @"incididunt ut labore et dolore magna aliqua.";
+  accountItemCheckMark.detailText =
+      @"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
+      @"eiusmod tempor incididunt ut labore et dolore magna aliqua.";
+  accountItemCheckMark.accessoryType = UITableViewCellAccessoryCheckmark;
+  [model addItem:accountItemCheckMark
+      toSectionWithIdentifier:SectionIdentifierAccount];
+
+  AccountControlItem* accountControlItem =
+      [[AccountControlItem alloc] initWithType:ItemTypeAccount];
+  accountControlItem.image = [UIImage imageNamed:@"settings_sync"];
+  accountControlItem.text = @"Account Sync Settings";
+  accountControlItem.detailText = @"Detail text";
+  accountControlItem.accessoryType =
+      UITableViewCellAccessoryDisclosureIndicator;
+  [model addItem:accountControlItem
+      toSectionWithIdentifier:SectionIdentifierAccount];
+
+  AccountControlItem* accountControlItemWithExtraLongText =
+      [[AccountControlItem alloc] initWithType:ItemTypeAccount];
+  accountControlItemWithExtraLongText.image = [ChromeIcon infoIcon];
+  accountControlItemWithExtraLongText.text =
+      @"Account Control Settings - long title";
+  accountControlItemWithExtraLongText.detailText =
+      @"Detail text detail text detail text detail text detail text.";
+  accountControlItemWithExtraLongText.accessoryType =
+      UITableViewCellAccessoryDisclosureIndicator;
+  [model addItem:accountControlItemWithExtraLongText
+      toSectionWithIdentifier:SectionIdentifierAccount];
+
   // SectionIdentifierURL.
   TableViewURLItem* item =
       [[TableViewURLItem alloc] initWithType:ItemTypeURLNoMetadata];
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_transition_egtest.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_transition_egtest.mm
index acecb42..de19b556 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_transition_egtest.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_transition_egtest.mm
@@ -45,8 +45,8 @@
 
 // Returns the tab model for non-incognito tabs.
 TabModel* GetNormalTabModel() {
-  return [[chrome_test_util::GetMainController() browserViewInformation]
-      mainTabModel];
+  return chrome_test_util::GetMainController()
+      .interfaceProvider.mainInterface.tabModel;
 }
 
 // Shows the tab switcher by tapping the switcher button.  Works on both phone
diff --git a/ios/chrome/browser/ui/table_view/chrome_table_view_controller.h b/ios/chrome/browser/ui/table_view/chrome_table_view_controller.h
index a66bbc8f..a970f82f 100644
--- a/ios/chrome/browser/ui/table_view/chrome_table_view_controller.h
+++ b/ios/chrome/browser/ui/table_view/chrome_table_view_controller.h
@@ -12,6 +12,12 @@
 #import "ios/chrome/browser/ui/table_view/chrome_table_view_consumer.h"
 #import "ios/chrome/browser/ui/table_view/table_view_model.h"
 
+// The leading inset for the separator of UITableView without leading icons.
+extern const CGFloat kTableViewSeparatorInset;
+// The leading inset for the separator of UITableView with leading icons. This
+// is the default value for ChromeTableViewController.
+extern const CGFloat kTableViewSeparatorInsetWithIcon;
+
 @class ChromeTableViewStyler;
 @class TableViewItem;
 
@@ -22,8 +28,8 @@
 
 // Chrome-specific TableViewController.
 @interface ChromeTableViewController
-    : UITableViewController<AppBarViewControllerPresenting,
-                            ChromeTableViewConsumer>
+    : UITableViewController <AppBarViewControllerPresenting,
+                             ChromeTableViewConsumer>
 
 // The model of this controller.
 @property(nonatomic, readonly, strong)
diff --git a/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm b/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm
index 843aa21c..6401926 100644
--- a/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm
+++ b/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm
@@ -19,6 +19,9 @@
 #error "This file requires ARC support."
 #endif
 
+const CGFloat kTableViewSeparatorInset = 16;
+const CGFloat kTableViewSeparatorInsetWithIcon = 56;
+
 @interface ChromeTableViewController ()
 // The loading displayed by [self startLoadingIndicatorWithLoadingMessage:].
 @property(nonatomic, strong) TableViewLoadingView* loadingView;
@@ -86,7 +89,9 @@
 
   [self.tableView setBackgroundColor:self.styler.tableViewBackgroundColor];
   [self.tableView setSeparatorColor:self.styler.cellSeparatorColor];
-  [self.tableView setSeparatorInset:UIEdgeInsetsMake(0, 56, 0, 0)];
+  [self.tableView
+      setSeparatorInset:UIEdgeInsetsMake(0, kTableViewSeparatorInsetWithIcon, 0,
+                                         0)];
 
   // Configure the app bar if needed.
   if (_appBarViewController) {
diff --git a/ios/chrome/test/app/chrome_test_util.mm b/ios/chrome/test/app/chrome_test_util.mm
index 1716d369..5fcbf53 100644
--- a/ios/chrome/test/app/chrome_test_util.mm
+++ b/ios/chrome/test/app/chrome_test_util.mm
@@ -107,14 +107,14 @@
 }
 
 NSUInteger GetRegisteredKeyCommandsCount() {
-  BrowserViewController* mainBVC =
-      GetMainController().browserViewInformation.mainBVC;
-  return mainBVC.keyCommands.count;
+  UIViewController* mainViewController =
+      GetMainController().interfaceProvider.mainInterface.viewController;
+  return mainViewController.keyCommands.count;
 }
 
 id<BrowserCommands> BrowserCommandDispatcherForMainBVC() {
   BrowserViewController* mainBVC =
-      GetMainController().browserViewInformation.mainBVC;
+      GetMainController().interfaceProvider.mainInterface.bvc;
   return mainBVC.dispatcher;
 }
 
diff --git a/ios/chrome/test/app/tab_test_util.mm b/ios/chrome/test/app/tab_test_util.mm
index eb492e24f..31dbfeb 100644
--- a/ios/chrome/test/app/tab_test_util.mm
+++ b/ios/chrome/test/app/tab_test_util.mm
@@ -36,20 +36,13 @@
 
 // Returns the tab model for the current mode (incognito or normal).
 TabModel* GetCurrentTabModel() {
-  return IsIncognitoMode()
-             ? [[GetMainController() browserViewInformation] otrTabModel]
-             : [[GetMainController() browserViewInformation] mainTabModel];
+  return GetMainController().interfaceProvider.currentInterface.tabModel;
 }
 
 }  // namespace
 
 BOOL IsIncognitoMode() {
-  MainController* main_controller = GetMainController();
-  BrowserViewController* otr_bvc =
-      [[main_controller browserViewInformation] otrBVC];
-  BrowserViewController* current_bvc =
-      [[main_controller browserViewInformation] currentBVC];
-  return otr_bvc == current_bvc;
+  return GetMainController().interfaceProvider.currentInterface.incognito;
 }
 
 void OpenNewTab() {
@@ -60,15 +53,15 @@
     if (BVCDispatcher) {
       [BVCDispatcher openURLInNewTab:command];
       return;
-      }
+    }
       // The TabGrid is currently presented.
-      [GetMainController().tabSwitcher
-          dismissWithNewTabAnimationToModel:[[GetMainController()
-                                                browserViewInformation]
-                                                mainTabModel]
-                                    withURL:GURL(kChromeUINewTabURL)
-                                    atIndex:NSNotFound
-                                 transition:ui::PAGE_TRANSITION_TYPED];
+    TabModel* tabModel =
+        GetMainController().interfaceProvider.mainInterface.tabModel;
+    [GetMainController().tabSwitcher
+        dismissWithNewTabAnimationToModel:tabModel
+                                  withURL:GURL(kChromeUINewTabURL)
+                                  atIndex:NSNotFound
+                               transition:ui::PAGE_TRANSITION_TYPED];
   }
 }
 
@@ -80,15 +73,15 @@
     if (BVCDispatcher) {
       [BVCDispatcher openURLInNewTab:command];
       return;
-      }
+    }
       // The TabGrid is currently presented.
-      [GetMainController().tabSwitcher
-          dismissWithNewTabAnimationToModel:[[GetMainController()
-                                                browserViewInformation]
-                                                otrTabModel]
-                                    withURL:GURL(kChromeUINewTabURL)
-                                    atIndex:NSNotFound
-                                 transition:ui::PAGE_TRANSITION_TYPED];
+    TabModel* tabModel =
+        GetMainController().interfaceProvider.incognitoInterface.tabModel;
+    [GetMainController().tabSwitcher
+        dismissWithNewTabAnimationToModel:tabModel
+                                  withURL:GURL(kChromeUINewTabURL)
+                                  atIndex:NSNotFound
+                               transition:ui::PAGE_TRANSITION_TYPED];
   }
 }
 
@@ -126,10 +119,11 @@
 
 void CloseAllTabs() {
   if (GetIncognitoTabCount()) {
-    [[[GetMainController() browserViewInformation] otrTabModel] closeAllTabs];
+    [GetMainController()
+            .interfaceProvider.incognitoInterface.tabModel closeAllTabs];
   }
   if (GetMainTabCount()) {
-    [[[GetMainController() browserViewInformation] mainTabModel] closeAllTabs];
+    [GetMainController().interfaceProvider.mainInterface.tabModel closeAllTabs];
   }
 }
 
@@ -141,11 +135,12 @@
 }
 
 NSUInteger GetMainTabCount() {
-  return [[[GetMainController() browserViewInformation] mainTabModel] count];
+  return GetMainController().interfaceProvider.mainInterface.tabModel.count;
 }
 
 NSUInteger GetIncognitoTabCount() {
-  return [[[GetMainController() browserViewInformation] otrTabModel] count];
+  return GetMainController()
+      .interfaceProvider.incognitoInterface.tabModel.count;
 }
 
 BOOL ResetTabUsageRecorder() {
@@ -180,22 +175,23 @@
 }
 
 void EvictOtherTabModelTabs() {
-  TabModel* otherTabModel =
-      IsIncognitoMode()
-          ? [GetMainController().browserViewInformation mainTabModel]
-          : [GetMainController().browserViewInformation otrTabModel];
+  id<BrowserInterfaceProvider> provider = GetMainController().interfaceProvider;
+  ios::ChromeBrowserState* otherBrowserState =
+      IsIncognitoMode() ? provider.mainInterface.browserState
+                        : provider.incognitoInterface.browserState;
   // Disabling and enabling web usage will evict all web views.
   WebStateListWebUsageEnabler* enabler =
       WebStateListWebUsageEnablerFactory::GetInstance()->GetForBrowserState(
-          otherTabModel.browserState);
+          otherBrowserState);
   enabler->SetWebUsageEnabled(false);
   enabler->SetWebUsageEnabled(true);
 }
 
 BOOL CloseAllIncognitoTabs() {
-  MainController* main_controller = chrome_test_util::GetMainController();
+  MainController* main_controller = GetMainController();
   DCHECK(main_controller);
-  TabModel* tabModel = [[main_controller browserViewInformation] otrTabModel];
+  TabModel* tabModel =
+      GetMainController().interfaceProvider.incognitoInterface.tabModel;
   DCHECK(tabModel);
   [tabModel closeAllTabs];
   if (!IsIPadIdiom() && !IsUIRefreshPhase1Enabled()) {
@@ -210,11 +206,11 @@
 }
 
 NSUInteger GetEvictedMainTabCount() {
-  if (![[GetMainController() browserViewInformation] mainTabModel]
-           .tabUsageRecorder)
+  TabModel* tabModel =
+      GetMainController().interfaceProvider.mainInterface.tabModel;
+  if (!tabModel.tabUsageRecorder)
     return 0;
-  return [[GetMainController() browserViewInformation] mainTabModel]
-      .tabUsageRecorder->EvictedTabsMapSize();
+  return tabModel.tabUsageRecorder->EvictedTabsMapSize();
 }
 
 }  // namespace chrome_test_util
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn
index 6e8926e..4ba52f6 100644
--- a/ios/web/BUILD.gn
+++ b/ios/web/BUILD.gn
@@ -454,7 +454,6 @@
     "web_state/js/context_menu_js_unittest.mm",
     "web_state/js/crw_js_injection_manager_unittest.mm",
     "web_state/js/crw_js_post_request_loader_unittest.mm",
-    "web_state/js/crw_js_window_id_manager_unittest.mm",
     "web_state/js/message_js_unittest.mm",
     "web_state/js/page_script_util_unittest.mm",
   ]
@@ -666,7 +665,6 @@
 
   sources = [
     "web_state/js/resources/post_request.js",
-    "web_state/js/resources/window_id.js",
   ]
 }
 
diff --git a/ios/web/web_state/js/BUILD.gn b/ios/web/web_state/js/BUILD.gn
index de76bc5b..9140bf4 100644
--- a/ios/web/web_state/js/BUILD.gn
+++ b/ios/web/web_state/js/BUILD.gn
@@ -17,8 +17,6 @@
     "crw_js_injection_receiver.mm",
     "crw_js_post_request_loader.h",
     "crw_js_post_request_loader.mm",
-    "crw_js_window_id_manager.h",
-    "crw_js_window_id_manager.mm",
   ]
 
   configs += [ "//build/config/compiler:enable_arc" ]
diff --git a/ios/web/web_state/js/crw_js_window_id_manager.h b/ios/web/web_state/js/crw_js_window_id_manager.h
deleted file mode 100644
index f334b6a..0000000
--- a/ios/web/web_state/js/crw_js_window_id_manager.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_WEB_WEB_STATE_JS_CRW_JS_WINDOW_ID_MANAGER_H_
-#define IOS_WEB_WEB_STATE_JS_CRW_JS_WINDOW_ID_MANAGER_H_
-
-#import <Foundation/Foundation.h>
-#import <WebKit/WebKit.h>
-
-// Injects the JavaScript file window_id.js which sets __gCrWeb.windowId and
-// manages the windowId for Page->Native->Page messages.
-@interface CRWJSWindowIDManager : NSObject
-
-// A unique window ID is assigned when the script is injected. Can not be null.
-@property(nonatomic, copy, readonly) NSString* windowID;
-
-- (instancetype)init NS_UNAVAILABLE;
-
-// Initializes CRWJSWindowIDManager. |webView| will be used for script
-// evaluation to inject window ID and can not be null.
-- (instancetype)initWithWebView:(WKWebView*)webView NS_DESIGNATED_INITIALIZER;
-
-// Injects windowId to a web page.
-- (void)inject;
-
-@end
-
-#endif  // IOS_WEB_WEB_STATE_JS_CRW_JS_WINDOW_ID_MANAGER_H_
diff --git a/ios/web/web_state/js/crw_js_window_id_manager.mm b/ios/web/web_state/js/crw_js_window_id_manager.mm
deleted file mode 100644
index f0362b7..0000000
--- a/ios/web/web_state/js/crw_js_window_id_manager.mm
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/web/web_state/js/crw_js_window_id_manager.h"
-
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/sys_string_conversions.h"
-#include "crypto/random.h"
-#import "ios/web/web_state/js/page_script_util.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-namespace {
-// Number of random bytes in unique key for window ID. The length of the
-// window ID will be twice this number, as it is hexadecimal encoded.
-const size_t kUniqueKeyLength = 16;
-}  // namespace
-
-@interface CRWJSWindowIDManager () {
-  // Web view used for script evaluation to inject window ID.
-  WKWebView* _webView;
-  // Backs up property with the same name.
-  NSString* _windowID;
-}
-
-// Returns a string of randomized ASCII characters.
-+ (NSString*)newUniqueKey;
-
-@end
-
-@implementation CRWJSWindowIDManager
-
-- (NSString*)windowID {
-  return _windowID;
-}
-
-- (instancetype)initWithWebView:(WKWebView*)webView {
-  if ((self = [super init])) {
-    _webView = webView;
-    _windowID = [[self class] newUniqueKey];
-  }
-  return self;
-}
-
-- (void)inject {
-  _windowID = [[self class] newUniqueKey];
-  NSString* script = [web::GetPageScript(@"window_id")
-      stringByReplacingOccurrencesOfString:@"$(WINDOW_ID)"
-                                withString:_windowID];
-  // WKUserScript may not be injected yet. Make windowID script return boolean
-  // indicating whether the injection was successful.
-  NSString* scriptWithResult = [NSString
-      stringWithFormat:@"if (!window.__gCrWeb) {false; } else { %@; true; }",
-                       script];
-
-  __weak CRWJSWindowIDManager* weakSelf = self;
-  [_webView evaluateJavaScript:scriptWithResult
-             completionHandler:^(id result, NSError* error) {
-               if (error) {
-                 DCHECK(error.code == WKErrorWebViewInvalidated ||
-                        error.code == WKErrorWebContentProcessTerminated);
-                 return;
-               }
-
-               DCHECK_EQ(CFBooleanGetTypeID(),
-                         CFGetTypeID((__bridge CFTypeRef)result));
-               if (![result boolValue]) {
-                 // WKUserScript has not been injected yet. Retry window id
-                 // injection, because it is critical for the system to
-                 // function.
-                 [weakSelf inject];
-               }
-             }];
-}
-
-#pragma mark - Private
-
-+ (NSString*)newUniqueKey {
-  char randomBytes[kUniqueKeyLength];
-  crypto::RandBytes(randomBytes, kUniqueKeyLength);
-  std::string result = base::HexEncode(randomBytes, kUniqueKeyLength);
-  return base::SysUTF8ToNSString(result);
-}
-
-@end
diff --git a/ios/web/web_state/js/crw_js_window_id_manager_unittest.mm b/ios/web/web_state/js/crw_js_window_id_manager_unittest.mm
deleted file mode 100644
index 2b96e44..0000000
--- a/ios/web/web_state/js/crw_js_window_id_manager_unittest.mm
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/web/web_state/js/crw_js_window_id_manager.h"
-
-#import <WebKit/WebKit.h>
-
-#include "ios/web/public/test/fakes/test_browser_state.h"
-#import "ios/web/public/test/js_test_util.h"
-#import "ios/web/web_state/js/page_script_util.h"
-#import "testing/gtest_mac.h"
-#import "testing/platform_test.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-namespace web {
-
-// Test fixture for testing CRWJSWindowIDManager class.
-class JSWindowIDManagerTest : public PlatformTest {
- protected:
-  TestBrowserState browser_state_;
-};
-
-// Tests that window ID injection by a second manager results in a different
-// window ID.
-TEST_F(JSWindowIDManagerTest, WindowIDDifferentManager) {
-  // Inject the first manager.
-  WKWebView* web_view = [[WKWebView alloc] init];
-  test::ExecuteJavaScript(web_view,
-                          GetDocumentStartScriptForAllFrames(&browser_state_));
-
-  CRWJSWindowIDManager* manager =
-      [[CRWJSWindowIDManager alloc] initWithWebView:web_view];
-  [manager inject];
-  EXPECT_NSEQ([manager windowID],
-              test::ExecuteJavaScript(web_view, @"window.__gCrWeb.windowId"));
-
-  // Inject the second manager.
-  WKWebView* web_view2 = [[WKWebView alloc] init];
-  test::ExecuteJavaScript(web_view2,
-                          GetDocumentStartScriptForAllFrames(&browser_state_));
-
-  CRWJSWindowIDManager* manager2 =
-      [[CRWJSWindowIDManager alloc] initWithWebView:web_view2];
-  [manager2 inject];
-  EXPECT_NSEQ([manager2 windowID],
-              test::ExecuteJavaScript(web_view2, @"window.__gCrWeb.windowId"));
-
-  // Window IDs must be different.
-  EXPECT_NSNE([manager windowID], [manager2 windowID]);
-}
-
-// Tests that injecting multiple times creates a new window ID.
-TEST_F(JSWindowIDManagerTest, MultipleInjections) {
-  WKWebView* web_view = [[WKWebView alloc] init];
-  test::ExecuteJavaScript(web_view,
-                          GetDocumentStartScriptForAllFrames(&browser_state_));
-
-  // First injection.
-  CRWJSWindowIDManager* manager =
-      [[CRWJSWindowIDManager alloc] initWithWebView:web_view];
-  [manager inject];
-  NSString* windowID = [manager windowID];
-  EXPECT_NSEQ(windowID,
-              test::ExecuteJavaScript(web_view, @"window.__gCrWeb.windowId"));
-
-  // Second injection.
-  [manager inject];
-  EXPECT_NSEQ([manager windowID],
-              test::ExecuteJavaScript(web_view, @"window.__gCrWeb.windowId"));
-
-  EXPECT_NSNE(windowID, [manager windowID]);
-}
-
-// Tests that injection will retry if |window.__gCrWeb| is not present.
-TEST_F(JSWindowIDManagerTest, InjectionRetry) {
-  WKWebView* web_view = [[WKWebView alloc] init];
-
-  CRWJSWindowIDManager* manager =
-      [[CRWJSWindowIDManager alloc] initWithWebView:web_view];
-  [manager inject];
-  EXPECT_TRUE([manager windowID]);
-  EXPECT_FALSE(test::ExecuteJavaScript(web_view, @"window.__gCrWeb"));
-
-  // Now inject window.__gCrWeb and check if window ID injection retried.
-  test::ExecuteJavaScript(web_view,
-                          GetDocumentStartScriptForAllFrames(&browser_state_));
-  EXPECT_NSEQ([manager windowID],
-              test::ExecuteJavaScript(web_view, @"window.__gCrWeb.windowId"));
-}
-
-}  // namespace web
diff --git a/ios/web/web_state/js/page_script_util.mm b/ios/web/web_state/js/page_script_util.mm
index b6aa8f0e..0bfa89c 100644
--- a/ios/web/web_state/js/page_script_util.mm
+++ b/ios/web/web_state/js/page_script_util.mm
@@ -20,9 +20,7 @@
 // Make sure that script is injected only once. For example, content of
 // WKUserScript can be injected into the same page multiple times
 // without notifying WKNavigationDelegate (e.g. after window.document.write
-// JavaScript call). Injecting the script multiple times invalidates the
-// __gCrWeb.windowId variable and will break the ability to send messages from
-// JS to the native code. Wrapping injected script into "if (!injected)" check
+// JavaScript call). Wrapping injected script into "if (!injected)" check
 // prevents multiple injections into the same page. |script_identifier| should
 // identify the script being injected in order to enforce the injection of
 // |script| to only once.
diff --git a/ios/web/web_state/js/resources/message.js b/ios/web/web_state/js/resources/message.js
index 3260fc5..51710c5 100644
--- a/ios/web/web_state/js/resources/message.js
+++ b/ios/web/web_state/js/resources/message.js
@@ -104,21 +104,6 @@
     return;
   }
 
-  var windowId = null;
-  try {
-    windowId = window.top.__gCrWeb['windowId'];
-    // Do nothing if windowId has not been set.
-    if (typeof windowId != 'string') {
-      return;
-    }
-  } catch (e) {
-    // A SecurityError will be thrown if this is a cross origin iframe. Allow
-    // sending the message in this case and it will be filtered by frameID.
-    if (e.name !== 'SecurityError') {
-      throw e;
-    }
-  }
-
   // Some pages/plugins implement Object.prototype.toJSON, which can result
   // in serializing messageQueue_ to an invalid format.
   var originalObjectToJSON = Object.prototype.toJSON;
@@ -129,9 +114,6 @@
       'crwCommand': command,
       'crwFrameId': __gCrWeb.message['getFrameId']()
     };
-    if (windowId) {
-      message['crwWindowId'] = windowId;
-    }
     __gCrWeb.common.sendWebKitMessage(queueObject.scheme, message);
   });
   queueObject.reset();
diff --git a/ios/web/web_state/js/resources/window_id.js b/ios/web/web_state/js/resources/window_id.js
deleted file mode 100644
index 563a48a..0000000
--- a/ios/web/web_state/js/resources/window_id.js
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file adheres to closure-compiler conventions in order to enable
-// compilation with ADVANCED_OPTIMIZATIONS. See http://goo.gl/FwOgy
-
-// Script to set windowId.
-(function() {
-// CRWJSWindowIDManager replaces $(WINDOW_ID) with appropriate string upon
-// injection.
-__gCrWeb['windowId'] = '$(WINDOW_ID)';
-
-// Send messages queued since message.js injection.
-__gCrWeb.message.invokeQueues();
-}());
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index 680b858..345c0d8 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -86,7 +86,6 @@
 #include "ios/web/public/webui/web_ui_ios.h"
 #import "ios/web/web_state/error_translation_util.h"
 #import "ios/web/web_state/js/crw_js_post_request_loader.h"
-#import "ios/web/web_state/js/crw_js_window_id_manager.h"
 #import "ios/web/web_state/navigation_context_impl.h"
 #import "ios/web/web_state/page_viewport_state.h"
 #import "ios/web/web_state/ui/crw_context_menu_controller.h"
@@ -145,6 +144,16 @@
   CFAbsoluteTime time;
 };
 
+// Struct to store a queued script and corresponding completion block.
+struct QueuedScript {
+  QueuedScript(NSString* script, web::JavaScriptResultBlock block)
+      : script_string(script), completion_block(block) {}
+  // The script to execute.
+  NSString* script_string;
+  // The completion block to run with the result of the script execution.
+  web::JavaScriptResultBlock completion_block;
+};
+
 // Keys for JavaScript command handlers context.
 NSString* const kUserIsInteractingKey = @"userIsInteracting";
 NSString* const kOriginURLKey = @"originURL";
@@ -364,9 +373,6 @@
   // idempotent.
   NSMutableSet* _injectedScriptManagers;
 
-  // Script manager for setting the windowID.
-  CRWJSWindowIDManager* _windowIDJSManager;
-
   // The receiver of JavaScripts.
   CRWJSInjectionReceiver* _jsInjectionReceiver;
 
@@ -408,6 +414,9 @@
   // cert status from |didReceiveAuthenticationChallenge:| to
   // |didFailProvisionalNavigation:| delegate method.
   std::unique_ptr<CertVerificationErrorsCacheType> _certVerificationErrors;
+
+  // Scripts queued while waiting for the main WebFrame to become available.
+  std::vector<QueuedScript> _queuedScripts;
 }
 
 // If |contentView_| contains a web view, this is the web view it contains.
@@ -622,9 +631,9 @@
              senderFrame:(web::WebFrame*)senderFrame;
 // Called when web controller receives a new message from the web page.
 - (void)didReceiveScriptMessage:(WKScriptMessage*)message;
-// Returns a new script which wraps |script| with windowID check so |script| is
-// not evaluated on windowID mismatch.
-- (NSString*)scriptByAddingWindowIDCheckForScript:(NSString*)script;
+// Returns a new script which wraps |script| with frameID check so |script| is
+// not evaluated on frameID mismatch.
+- (NSString*)scriptByAddingFrameIDCheckForScript:(NSString*)script;
 // Attempts to handle a script message. Returns YES on success, NO otherwise.
 - (BOOL)respondToWKScriptMessage:(WKScriptMessage*)scriptMessage;
 // Handles frame became available message.
@@ -920,6 +929,11 @@
 // Clears WebUI, if one exists.
 - (void)clearWebUI;
 
+// Executes the supplied JavaScript in the WebView by wrapping it with a
+// frameId check to ensure it is executed only in the expected page.
+- (void)safelyExecuteJavaScript:(NSString*)script
+              completionHandler:(web::JavaScriptResultBlock)completionHandler;
+
 @end
 
 namespace {
@@ -2383,7 +2397,17 @@
 
 - (void)executeJavaScript:(NSString*)script
         completionHandler:(web::JavaScriptResultBlock)completionHandler {
-  NSString* safeScript = [self scriptByAddingWindowIDCheckForScript:script];
+  if (!web::WebFramesManager::FromWebState([self webState])
+           ->GetMainWebFrame()) {
+    _queuedScripts.push_back(QueuedScript(script, completionHandler));
+  } else {
+    [self safelyExecuteJavaScript:script completionHandler:completionHandler];
+  }
+}
+
+- (void)safelyExecuteJavaScript:(NSString*)script
+              completionHandler:(web::JavaScriptResultBlock)completionHandler {
+  NSString* safeScript = [self scriptByAddingFrameIDCheckForScript:script];
   web::ExecuteJavaScript(_webView, safeScript, completionHandler);
 }
 
@@ -2502,10 +2526,12 @@
   }
 }
 
-- (NSString*)scriptByAddingWindowIDCheckForScript:(NSString*)script {
-  NSString* kTemplate = @"if (__gCrWeb['windowId'] === '%@') { %@; }";
-  return [NSString
-      stringWithFormat:kTemplate, [_windowIDJSManager windowID], script];
+- (NSString*)scriptByAddingFrameIDCheckForScript:(NSString*)script {
+  NSString* kTemplate = @"if (__gCrWeb.message.getFrameId() === '%@') { %@; }";
+  web::WebFrame* mainWebFrame =
+      web::WebFramesManager::FromWebState([self webState])->GetMainWebFrame();
+  NSString* frameID = base::SysUTF8ToNSString(mainWebFrame->GetFrameId());
+  return [NSString stringWithFormat:kTemplate, frameID, script];
 }
 
 - (BOOL)respondToWKScriptMessage:(WKScriptMessage*)scriptMessage {
@@ -2543,18 +2569,6 @@
       // different origins.
       return NO;
     }
-
-    std::string windowID;
-    // If windowID exists, it must match the ID from the main frame.
-    if (message->GetString("crwWindowId", &windowID)) {
-      if (base::SysNSStringToUTF8([_windowIDJSManager windowID]) != windowID) {
-        DLOG(WARNING)
-            << "Message from JS ignored due to non-matching windowID: "
-            << base::SysNSStringToUTF8([_windowIDJSManager windowID])
-            << " != " << windowID;
-        return NO;
-      }
-    }
   }
 
   base::DictionaryValue* command = nullptr;
@@ -2616,6 +2630,14 @@
     framesManager->AddFrame(std::move(newFrame));
     _webStateImpl->OnWebFrameAvailable(framesManager->GetFrameWithId(frameID));
   }
+
+  if (!_queuedScripts.empty() && message.frameInfo.mainFrame) {
+    std::vector<QueuedScript> queue = std::move(_queuedScripts);
+    for (const QueuedScript& queuedScript : queue) {
+      [self safelyExecuteJavaScript:queuedScript.script_string
+                  completionHandler:queuedScript.completion_block];
+    }
+  }
 }
 
 - (void)frameBecameUnavailableWithMessage:(WKScriptMessage*)message {
@@ -4068,10 +4090,6 @@
     }
                                       name:kFrameBecameUnavailableMessageName
                                    webView:webView];
-
-    _windowIDJSManager = [[CRWJSWindowIDManager alloc] initWithWebView:webView];
-  } else {
-    _windowIDJSManager = nil;
   }
   [_webView setNavigationDelegate:self];
   [_webView setUIDelegate:self];
@@ -4881,13 +4899,17 @@
       !IsPlaceholderUrl(webViewURL)) {
     _injectedScriptManagers = [[NSMutableSet alloc] init];
     if ([self contentIsHTML] || [self contentIsImage] ||
+        // In unit tests MIME type will be empty, because loadHTML:forURL: does
+        // not notify web view delegate about received response, so web
+        // controller does not get a chance to properly update MIME type.
         self.webState->GetContentsMimeType().empty()) {
-      // In unit tests MIME type will be empty, because loadHTML:forURL: does
-      // not notify web view delegate about received response, so web controller
-      // does not get a chance to properly update MIME type.
-      [_windowIDJSManager inject];
-      web::WebFramesManagerImpl::FromWebState(self.webState)
-          ->RegisterExistingFrames();
+      // This JavaScript call bypasses adding the frameId check because no main
+      // frame may be registered yet until after the response triggered by this
+      // call. For example, when a page is loaded from WebKit's PageCache.
+      // TODO(crbug.com/872134): Remove this call once JavaScript pageshow and
+      // pagehide APIs are reliable.
+      NSString* registerFramesScript = @"__gCrWeb.message.getExistingFrames();";
+      web::ExecuteJavaScript(_webView, registerFramesScript, nil);
     }
   }
 
diff --git a/ios/web/web_state/ui/crw_web_controller_unittest.mm b/ios/web/web_state/ui/crw_web_controller_unittest.mm
index b7d559e..81e25e1 100644
--- a/ios/web/web_state/ui/crw_web_controller_unittest.mm
+++ b/ios/web/web_state/ui/crw_web_controller_unittest.mm
@@ -480,21 +480,6 @@
   EXPECT_NSEQ(@NO, ExecuteJavaScript(@"false"));
 }
 
-// Tests that a script is not executed on windowID mismatch.
-TEST_P(CRWWebControllerJSExecutionTest, WindowIdMissmatch) {
-  LoadHtml(@"<p></p>");
-  // Script is evaluated since windowID is matched.
-  ExecuteJavaScript(@"window.test1 = '1';");
-  EXPECT_NSEQ(@"1", ExecuteJavaScript(@"window.test1"));
-
-  // Change windowID.
-  ExecuteJavaScript(@"__gCrWeb['windowId'] = '';");
-
-  // Script is not evaluated because of windowID mismatch.
-  ExecuteJavaScript(@"window.test2 = '2';");
-  EXPECT_FALSE(ExecuteJavaScript(@"window.test2"));
-}
-
 INSTANTIATE_TEST_CASES(CRWWebControllerJSExecutionTest);
 
 // Test fixture to test decidePolicyForNavigationResponse:decisionHandler:
diff --git a/ios/web/web_state/web_frames_manager_impl.h b/ios/web/web_state/web_frames_manager_impl.h
index dba457a7..7b0abb0 100644
--- a/ios/web/web_state/web_frames_manager_impl.h
+++ b/ios/web/web_state/web_frames_manager_impl.h
@@ -31,9 +31,6 @@
   void RemoveFrameWithId(const std::string& frame_id);
   // Removes all web frames from the list of associated web frames.
   void RemoveAllWebFrames();
-  // Broadcasts a (not encrypted) JavaScript message to get the identifiers
-  // and keys of existing frames.
-  void RegisterExistingFrames();
 
   // WebFramesManager overrides
   std::set<WebFrame*> GetAllWebFrames() override;
diff --git a/ios/web/web_state/web_frames_manager_impl.mm b/ios/web/web_state/web_frames_manager_impl.mm
index e20075f..e1ce5087 100644
--- a/ios/web/web_state/web_frames_manager_impl.mm
+++ b/ios/web/web_state/web_frames_manager_impl.mm
@@ -100,9 +100,4 @@
   return main_web_frame_;
 }
 
-void WebFramesManagerImpl::RegisterExistingFrames() {
-  web_state_->ExecuteJavaScript(
-      base::UTF8ToUTF16("__gCrWeb.message.getExistingFrames();"));
-}
-
 }  // namespace
diff --git a/ios/web_view/BUILD.gn b/ios/web_view/BUILD.gn
index 3c336d1..482d55f 100644
--- a/ios/web_view/BUILD.gn
+++ b/ios/web_view/BUILD.gn
@@ -266,6 +266,7 @@
   "//components/content_settings/core/browser",
   "//components/flags_ui",
   "//components/gcm_driver",
+  "//components/history/core/common",
   "//components/image_fetcher/ios",
   "//components/invalidation/impl",
   "//components/infobars/core",
diff --git a/ios/web_view/internal/DEPS b/ios/web_view/internal/DEPS
index 8fce52b..13ca8986 100644
--- a/ios/web_view/internal/DEPS
+++ b/ios/web_view/internal/DEPS
@@ -5,6 +5,7 @@
   "+components/content_settings/core",
   "+components/flags_ui",
   "+components/gcm_driver",
+  "+components/history/core/common",
   "+components/image_fetcher/ios",
   "+components/infobars/core",
   "+components/invalidation/impl",
diff --git a/ios/web_view/internal/sync/cwv_sync_controller_unittest.mm b/ios/web_view/internal/sync/cwv_sync_controller_unittest.mm
index 2229a27..90676901 100644
--- a/ios/web_view/internal/sync/cwv_sync_controller_unittest.mm
+++ b/ios/web_view/internal/sync/cwv_sync_controller_unittest.mm
@@ -213,10 +213,11 @@
 
 // Verifies CWVSyncController's passphrase API.
 TEST_F(CWVSyncControllerTest, Passphrase) {
-  EXPECT_CALL(*profile_sync_service_, IsPassphraseRequiredForDecryption())
+  EXPECT_CALL(*profile_sync_service_->GetUserSettingsMock(),
+              IsPassphraseRequiredForDecryption())
       .WillOnce(Return(true));
   EXPECT_TRUE(sync_controller_.passphraseNeeded);
-  EXPECT_CALL(*profile_sync_service_,
+  EXPECT_CALL(*profile_sync_service_->GetUserSettingsMock(),
               SetDecryptionPassphrase("dummy-passphrase"))
       .WillOnce(Return(true));
   EXPECT_TRUE([sync_controller_ unlockWithPassphrase:@"dummy-passphrase"]);
diff --git a/ios/web_view/internal/sync/web_view_sync_client.mm b/ios/web_view/internal/sync/web_view_sync_client.mm
index 66ae070..4c014d2 100644
--- a/ios/web_view/internal/sync/web_view_sync_client.mm
+++ b/ios/web_view/internal/sync/web_view_sync_client.mm
@@ -17,6 +17,7 @@
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/browser_sync/browser_sync_switches.h"
 #include "components/browser_sync/profile_sync_components_factory_impl.h"
+#include "components/history/core/common/pref_names.h"
 #include "components/invalidation/impl/profile_invalidation_provider.h"
 #include "components/keyed_service/core/service_access_type.h"
 #include "components/password_manager/core/browser/password_store.h"
diff --git a/ios/web_view/internal/web_view_browser_state.mm b/ios/web_view/internal/web_view_browser_state.mm
index eb6a111..ab3a3fe 100644
--- a/ios/web_view/internal/web_view_browser_state.mm
+++ b/ios/web_view/internal/web_view_browser_state.mm
@@ -14,6 +14,7 @@
 #include "base/threading/thread_restrictions.h"
 #include "components/autofill/core/common/autofill_prefs.h"
 #include "components/gcm_driver/gcm_channel_status_syncer.h"
+#include "components/history/core/common/pref_names.h"
 #include "components/keyed_service/ios/browser_state_dependency_manager.h"
 #include "components/password_manager/core/browser/password_manager.h"
 #include "components/pref_registry/pref_registry_syncable.h"
diff --git a/media/gpu/video_encode_accelerator_unittest.cc b/media/gpu/video_encode_accelerator_unittest.cc
index 54ae25b9..722bc3e 100644
--- a/media/gpu/video_encode_accelerator_unittest.cc
+++ b/media/gpu/video_encode_accelerator_unittest.cc
@@ -500,7 +500,8 @@
       bool run_at_fps,
       bool needs_encode_latency,
       bool verify_all_output)
-      : test_stream_data_(std::move(data)),
+      : rendering_thread_("GLRenderingVEAClientThread"),
+        test_stream_data_(std::move(data)),
         log_path_(log_path),
         frame_stats_path_(frame_stats_path),
         run_at_fps_(run_at_fps),
@@ -520,13 +521,39 @@
     ui::OzonePlatform::InitParams params;
     params.single_process = false;
     ui::OzonePlatform::InitializeForUI(params);
+
+    base::Thread::Options options;
+    options.message_loop_type = base::MessageLoop::TYPE_UI;
+    ASSERT_TRUE(rendering_thread_.StartWithOptions(options));
+    base::WaitableEvent done(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+                             base::WaitableEvent::InitialState::NOT_SIGNALED);
+    rendering_thread_.task_runner()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&VideoEncodeAcceleratorTestEnvironment::SetupOzone,
+                       &done));
+    done.Wait();
+
+    // To create dmabuf through gbm, Ozone needs to be set up.
+    gpu_helper.reset(new ui::OzoneGpuTestHelper());
+    gpu_helper->Initialize(base::ThreadTaskRunnerHandle::Get());
+
+#else
+    ASSERT_TRUE(rendering_thread_.Start());
 #endif
   }
 
   virtual void TearDown() {
     log_file_.reset();
+
+    rendering_thread_.Stop();
   }
 
+  scoped_refptr<base::SingleThreadTaskRunner> GetRenderingTaskRunner() const {
+    return rendering_thread_.task_runner();
+  }
+
+  void FlushRenderingThread() { rendering_thread_.FlushForTesting(); }
+
   // Log one entry of machine-readable data to file and LOG(INFO).
   // The log has one data entry per line in the format of "<key>: <value>".
   // Note that Chrome OS video_VEAPerf autotest parses the output key and value
@@ -557,6 +584,7 @@
   std::vector<std::unique_ptr<TestStream>> test_streams_;
 
  private:
+  base::Thread rendering_thread_;
   std::unique_ptr<base::FilePath::StringType> test_stream_data_;
   base::FilePath log_path_;
   base::FilePath frame_stats_path_;
@@ -564,6 +592,20 @@
   bool run_at_fps_;
   bool needs_encode_latency_;
   bool verify_all_output_;
+
+#if defined(USE_OZONE)
+  std::unique_ptr<ui::OzoneGpuTestHelper> gpu_helper;
+
+  static void SetupOzone(base::WaitableEvent* done) {
+    base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
+    cmd_line->AppendSwitchASCII(switches::kUseGL, gl::kGLImplementationEGLName);
+    ui::OzonePlatform::InitParams params;
+    params.single_process = true;
+    ui::OzonePlatform::InitializeForGPU(params);
+    ui::OzonePlatform::GetInstance()->AfterSandboxEntry();
+    done->Signal();
+  }
+#endif
 };
 
 enum ClientState {
@@ -2340,34 +2382,6 @@
   encoder_->Encode(video_frame, false);
 }
 
-#if defined(USE_OZONE)
-void SetupOzone(base::WaitableEvent* done) {
-  base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
-  cmd_line->AppendSwitchASCII(switches::kUseGL, gl::kGLImplementationEGLName);
-  ui::OzonePlatform::InitParams params;
-  params.single_process = true;
-  ui::OzonePlatform::InitializeForGPU(params);
-  ui::OzonePlatform::GetInstance()->AfterSandboxEntry();
-  done->Signal();
-}
-#endif
-
-void StartVEAThread(base::Thread* vea_client_thread) {
-#if defined(USE_OZONE)
-  // If USE_OZONE, some additional setups are required.
-  base::Thread::Options options;
-  options.message_loop_type = base::MessageLoop::TYPE_UI;
-  ASSERT_TRUE(vea_client_thread->StartWithOptions(options));
-  base::WaitableEvent done(base::WaitableEvent::ResetPolicy::AUTOMATIC,
-                           base::WaitableEvent::InitialState::NOT_SIGNALED);
-  vea_client_thread->task_runner()->PostTask(
-      FROM_HERE, base::BindOnce(&SetupOzone, &done));
-  done.Wait();
-#else
-  ASSERT_TRUE(vea_client_thread->Start());
-#endif
-}
-
 // Test parameters:
 // - Number of concurrent encoders. The value takes effect when there is only
 //   one input stream; otherwise, one encoder per input stream will be
@@ -2401,15 +2415,6 @@
       std::unique_ptr<media::test::ClientStateNotification<ClientState>>>
       notes;
   std::vector<std::unique_ptr<VEAClient>> clients;
-  base::Thread vea_client_thread("EncoderClientThread");
-  StartVEAThread(&vea_client_thread);
-
-#if defined(USE_OZONE)
-  std::unique_ptr<ui::OzoneGpuTestHelper> gpu_helper;
-  // To create dmabuf through gbm, Ozone needs to be set up.
-  gpu_helper.reset(new ui::OzoneGpuTestHelper());
-  gpu_helper->Initialize(base::ThreadTaskRunnerHandle::Get());
-#endif
 
   if (g_env->test_streams_.size() > 1)
     num_concurrent_encoders = g_env->test_streams_.size();
@@ -2430,7 +2435,7 @@
         mid_stream_bitrate_switch, mid_stream_framerate_switch, verify_output,
         verify_output_timestamp));
 
-    vea_client_thread.task_runner()->PostTask(
+    g_env->GetRenderingTaskRunner()->PostTask(
         FROM_HERE, base::BindOnce(&VEAClient::CreateEncoder,
                                   base::Unretained(clients.back().get())));
   }
@@ -2457,13 +2462,12 @@
   }
 
   for (size_t i = 0; i < num_concurrent_encoders; ++i) {
-    vea_client_thread.task_runner()->PostTask(
+    g_env->GetRenderingTaskRunner()->PostTask(
         FROM_HERE, base::BindOnce(&VEAClient::DestroyEncoder,
                                   base::Unretained(clients[i].get())));
   }
 
-  // This ensures all tasks have finished.
-  vea_client_thread.Stop();
+  g_env->FlushRenderingThread();
 }
 
 // Test parameters:
diff --git a/services/identity/public/cpp/identity_manager.cc b/services/identity/public/cpp/identity_manager.cc
index 5783eaf..77465a5 100644
--- a/services/identity/public/cpp/identity_manager.cc
+++ b/services/identity/public/cpp/identity_manager.cc
@@ -360,6 +360,14 @@
   }
 }
 
+void IdentityManager::OnAddAccountToCookieCompleted(
+    const std::string& account_id,
+    const GoogleServiceAuthError& error) {
+  for (auto& observer : observer_list_) {
+    observer.OnAddAccountToCookieCompleted(account_id, error);
+  }
+}
+
 void IdentityManager::OnAccessTokenRequested(
     const std::string& account_id,
     const std::string& consumer_id,
@@ -371,13 +379,4 @@
   }
 }
 
-void IdentityManager::NotifySigninValueChanged(
-    const signin_internals_util::TimedSigninStatusField& field,
-    const std::string& value) {
-  // TODO(843510): Consider notifying observers asynchronously once there
-  // are no direct clients of ProfileOAuth2TokenService.
-  for (auto& observer : diagnostics_observer_list_)
-    observer.NotifySigninValueChanged(field, value);
-}
-
 }  // namespace identity
diff --git a/services/identity/public/cpp/identity_manager.h b/services/identity/public/cpp/identity_manager.h
index 75fa904..161e0a31 100644
--- a/services/identity/public/cpp/identity_manager.h
+++ b/services/identity/public/cpp/identity_manager.h
@@ -55,7 +55,6 @@
 class IdentityManager : public SigninManagerBase::Observer,
                         public OAuth2TokenService::DiagnosticsObserver,
                         public OAuth2TokenService::Observer,
-                        public signin_internals_util::SigninDiagnosticsObserver,
                         public GaiaCookieManagerService::Observer {
  public:
   class Observer {
@@ -122,6 +121,13 @@
     virtual void OnAccountsInCookieUpdated(
         const std::vector<AccountInfo>& accounts) {}
 
+    // Called whenever an attempt to add |account_id| to the list of Gaia
+    // accounts in the cookie jar has finished. If |error| is equal to
+    // GoogleServiceAuthError::AuthErrorNone() then the addittion succeeded.
+    virtual void OnAddAccountToCookieCompleted(
+        const std::string& account_id,
+        const GoogleServiceAuthError& error) {}
+
     // Called before a batch of refresh token state changes is started.
     virtual void OnStartBatchOfRefreshTokenStateChanges() {}
 
@@ -143,11 +149,6 @@
     virtual void OnAccessTokenRequested(const std::string& account_id,
                                         const std::string& consumer_id,
                                         const identity::ScopeSet& scopes) {}
-
-    // Called on credentials and signin related changes.
-    virtual void NotifySigninValueChanged(
-        const signin_internals_util::TimedSigninStatusField& field,
-        const std::string& value) {}
   };
 
   IdentityManager(
@@ -372,6 +373,9 @@
       const std::vector<gaia::ListedAccount>& accounts,
       const std::vector<gaia::ListedAccount>& signed_out_accounts,
       const GoogleServiceAuthError& error) override;
+  void OnAddAccountToCookieCompleted(
+      const std::string& account_id,
+      const GoogleServiceAuthError& error) override;
 
   // OAuth2TokenService::DiagnosticsObserver:
   void OnAccessTokenRequested(
@@ -379,10 +383,6 @@
       const std::string& consumer_id,
       const OAuth2TokenService::ScopeSet& scopes) override;
 
-  void NotifySigninValueChanged(
-      const signin_internals_util::TimedSigninStatusField& field,
-      const std::string& value) override;
-
   // Backing signin classes. NOTE: We strive to limit synchronous access to
   // these classes in the IdentityManager implementation, as all such
   // synchronous access will become impossible when IdentityManager is
diff --git a/services/identity/public/cpp/identity_manager_unittest.cc b/services/identity/public/cpp/identity_manager_unittest.cc
index fa03267..38dff17b 100644
--- a/services/identity/public/cpp/identity_manager_unittest.cc
+++ b/services/identity/public/cpp/identity_manager_unittest.cc
@@ -246,6 +246,16 @@
     return accounts_from_cookie_change_callback_;
   }
 
+  const std::string& account_from_add_account_to_cookie_completed_callback()
+      const {
+    return account_from_add_account_to_cookie_completed_callback_;
+  }
+
+  const GoogleServiceAuthError&
+  error_from_add_account_to_cookie_completed_callback() const {
+    return error_from_add_account_to_cookie_completed_callback_;
+  }
+
   const GoogleServiceAuthError& error_from_signin_failed_callback() const {
     return google_signin_failed_error_;
   }
@@ -300,6 +310,13 @@
     if (on_accounts_in_cookie_updated_callback_)
       std::move(on_accounts_in_cookie_updated_callback_).Run();
   }
+  void OnAddAccountToCookieCompleted(
+      const std::string& account_id,
+      const GoogleServiceAuthError& error) override {
+    account_from_add_account_to_cookie_completed_callback_ = account_id;
+    error_from_add_account_to_cookie_completed_callback_ = error;
+  }
+
   void OnStartBatchOfRefreshTokenStateChanges() override {
     EXPECT_FALSE(is_inside_batch_);
     is_inside_batch_ = true;
@@ -326,6 +343,8 @@
   AccountInfo account_from_refresh_token_updated_callback_;
   std::string account_from_refresh_token_removed_callback_;
   std::vector<AccountInfo> accounts_from_cookie_change_callback_;
+  std::string account_from_add_account_to_cookie_completed_callback_;
+  GoogleServiceAuthError error_from_add_account_to_cookie_completed_callback_;
   GoogleServiceAuthError google_signin_failed_error_;
   bool is_inside_batch_ = false;
   std::vector<std::vector<std::string>> batch_change_records_;
@@ -489,6 +508,17 @@
         new TestIdentityManagerDiagnosticsObserver(identity_manager_.get()));
   }
 
+  void SimulateAdditionOfAccountToCookieSuccess(GaiaAuthConsumer* consumer,
+                                                const std::string& data) {
+    consumer->OnMergeSessionSuccess(data);
+  }
+
+  void SimulateAdditionOfAccountToCookieSuccessFailure(
+      GaiaAuthConsumer* consumer,
+      const GoogleServiceAuthError& error) {
+    consumer->OnMergeSessionFailure(error);
+  }
+
  private:
   base::MessageLoop message_loop_;
   sync_preferences::TestingPrefServiceSyncable pref_service_;
@@ -1756,6 +1786,36 @@
   EXPECT_EQ(kTestEmail2, account_info2.email);
 }
 
+TEST_F(IdentityManagerTest, CallbackSentOnSuccessfulAdditionOfAccountToCookie) {
+  const char kTestAccountId[] = "account_id";
+  gaia_cookie_manager_service()->AddAccountToCookie(kTestAccountId,
+                                                    gaia::GaiaSource::kChrome);
+  SimulateAdditionOfAccountToCookieSuccess(gaia_cookie_manager_service(),
+                                           "token");
+  EXPECT_EQ(identity_manager_observer()
+                ->account_from_add_account_to_cookie_completed_callback(),
+            kTestAccountId);
+  EXPECT_EQ(identity_manager_observer()
+                ->error_from_add_account_to_cookie_completed_callback(),
+            GoogleServiceAuthError::AuthErrorNone());
+}
+
+TEST_F(IdentityManagerTest, CallbackSentOnFailureAdditionOfAccountToCookie) {
+  const char kTestAccountId[] = "account_id";
+  gaia_cookie_manager_service()->AddAccountToCookie(kTestAccountId,
+                                                    gaia::GaiaSource::kChrome);
+
+  GoogleServiceAuthError error(GoogleServiceAuthError::SERVICE_ERROR);
+  SimulateAdditionOfAccountToCookieSuccessFailure(gaia_cookie_manager_service(),
+                                                  error);
+  EXPECT_EQ(identity_manager_observer()
+                ->account_from_add_account_to_cookie_completed_callback(),
+            kTestAccountId);
+  EXPECT_EQ(identity_manager_observer()
+                ->error_from_add_account_to_cookie_completed_callback(),
+            error);
+}
+
 TEST_F(IdentityManagerTest,
        BatchChangeObserversAreNotifiedOnCredentialsUpdate) {
   signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index bf1f2e3..196efbb 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -144,10 +144,6 @@
 #define SK_USE_LEGACY_DISTANCE_FIELDS
 #endif
 
-#ifndef SK_SUPPORT_LEGACY_FONTMETRICS_IN_PAINT
-#define SK_SUPPORT_LEGACY_FONTMETRICS_IN_PAINT
-#endif
-
 #ifndef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
 #define SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
 #endif
diff --git a/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc b/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
index f5b4ebe..8f8cd05 100644
--- a/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
+++ b/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
@@ -634,9 +634,8 @@
     {false, FILE_PATH_LITERAL("file 3"), 0},
   };
 
-  helper.VerifyTestCaseFiles(dest,
-                             kMoveDirResultCases,
-                             arraysize(kMoveDirResultCases));
+  helper.VerifyTestCaseFiles(dest, kMoveDirResultCases,
+                             base::size(kMoveDirResultCases));
 }
 
 TEST(LocalFileSystemCopyOrMoveOperationTest, CopySingleFileNoValidator) {
@@ -736,7 +735,7 @@
   base::FilePath dest_path = temp_dir.GetPath().AppendASCII("dest");
   const char kTestData[] = "abcdefghijklmnopqrstuvwxyz0123456789";
   base::WriteFile(source_path, kTestData,
-                  arraysize(kTestData) - 1);  // Exclude trailing '\0'.
+                  base::size(kTestData) - 1);  // Exclude trailing '\0'.
 
   base::MessageLoopForIO message_loop;
   base::Thread file_thread("file_thread");
@@ -792,8 +791,7 @@
   base::FilePath dest_path = temp_dir.GetPath().AppendASCII("dest");
   const char kTestData[] = "abcdefghijklmnopqrstuvwxyz0123456789";
   base::WriteFile(source_path, kTestData,
-                  arraysize(kTestData) - 1);  // Exclude trailing '\0'.
-
+                  base::size(kTestData) - 1);  // Exclude trailing '\0'.
 
   base::MessageLoopForIO message_loop;
   base::Thread file_thread("file_thread");
@@ -845,7 +843,7 @@
   base::FilePath dest_path = temp_dir.GetPath().AppendASCII("dest");
   const char kTestData[] = "abcdefghijklmnopqrstuvwxyz0123456789";
   base::WriteFile(source_path, kTestData,
-                  arraysize(kTestData) - 1);  // Exclude trailing '\0'.
+                  base::size(kTestData) - 1);  // Exclude trailing '\0'.
 
   base::MessageLoopForIO message_loop;
   base::Thread file_thread("file_thread");
diff --git a/storage/browser/fileapi/dragged_file_util_unittest.cc b/storage/browser/fileapi/dragged_file_util_unittest.cc
index 7503806..e004cf0 100644
--- a/storage/browser/fileapi/dragged_file_util_unittest.cc
+++ b/storage/browser/fileapi/dragged_file_util_unittest.cc
@@ -17,6 +17,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
+#include "base/stl_util.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "components/services/filesystem/public/interfaces/types.mojom.h"
@@ -268,7 +269,7 @@
       // to simulate a drop with multiple directories.
       if (toplevel_root_map_.find(toplevel) == toplevel_root_map_.end()) {
         base::FilePath root = root_path().Append(
-            kRootPaths[(root_path_index++) % arraysize(kRootPaths)]);
+            kRootPaths[(root_path_index++) % base::size(kRootPaths)]);
         toplevel_root_map_[toplevel] = root;
         toplevels.AddPath(root.Append(path), nullptr);
       }
@@ -325,7 +326,7 @@
     {false, FILE_PATH_LITERAL("bar"), 20},
   };
 
-  for (size_t i = 0; i < arraysize(kUnregisteredCases); ++i) {
+  for (size_t i = 0; i < base::size(kUnregisteredCases); ++i) {
     SCOPED_TRACE(testing::Message() << "Creating kUnregisteredCases " << i);
     const FileSystemTestCaseRecord& test_case = kUnregisteredCases[i];
 
@@ -340,7 +341,7 @@
     ASSERT_EQ(test_case.is_directory, info.is_directory);
   }
 
-  for (size_t i = 0; i < arraysize(kUnregisteredCases); ++i) {
+  for (size_t i = 0; i < base::size(kUnregisteredCases); ++i) {
     SCOPED_TRACE(testing::Message() << "Creating kUnregisteredCases " << i);
     const FileSystemTestCaseRecord& test_case = kUnregisteredCases[i];
     FileSystemURL url = GetFileSystemURL(base::FilePath(test_case.path));
diff --git a/storage/browser/fileapi/external_mount_points_unittest.cc b/storage/browser/fileapi/external_mount_points_unittest.cc
index 7e6007e..100c1ed 100644
--- a/storage/browser/fileapi/external_mount_points_unittest.cc
+++ b/storage/browser/fileapi/external_mount_points_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "base/files/file_path.h"
 #include "base/macros.h"
+#include "base/stl_util.h"
 #include "storage/browser/fileapi/file_system_url.h"
 #include "storage/common/fileapi/file_system_mount_option.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -110,19 +111,16 @@
   };
 
   // Test adding mount points.
-  for (size_t i = 0; i < arraysize(kTestCases); ++i) {
-    EXPECT_EQ(
-        kTestCases[i].success,
-        mount_points->RegisterFileSystem(kTestCases[i].name,
-                                         storage::kFileSystemTypeNativeLocal,
-                                         storage::FileSystemMountOption(),
-                                         base::FilePath(kTestCases[i].path)))
-        << "Adding mount point: " << kTestCases[i].name << " with path "
-        << kTestCases[i].path;
+  for (const auto& test : kTestCases) {
+    EXPECT_EQ(test.success,
+              mount_points->RegisterFileSystem(
+                  test.name, storage::kFileSystemTypeNativeLocal,
+                  storage::FileSystemMountOption(), base::FilePath(test.path)))
+        << "Adding mount point: " << test.name << " with path " << test.path;
   }
 
   // Test that final mount point presence state is as expected.
-  for (size_t i = 0; i < arraysize(kTestCases); ++i) {
+  for (size_t i = 0; i < base::size(kTestCases); ++i) {
     base::FilePath found_path;
     EXPECT_EQ(kTestCases[i].registered_path != nullptr,
               mount_points->GetRegisteredPath(kTestCases[i].name, &found_path))
@@ -218,22 +216,22 @@
 #endif
   };
 
-  for (size_t i = 0; i < arraysize(kTestCases); ++i) {
+  for (const auto& test_case : kTestCases) {
     // Initialize virtual path with a value.
     base::FilePath virtual_path(DRIVE FPL("/mount"));
-    base::FilePath local_path(kTestCases[i].local_path);
-    EXPECT_EQ(kTestCases[i].success,
+    base::FilePath local_path(test_case.local_path);
+    EXPECT_EQ(test_case.success,
               mount_points->GetVirtualPath(local_path, &virtual_path))
-        << "Resolving " << kTestCases[i].local_path;
+        << "Resolving " << test_case.local_path;
 
     // There are no guarantees for |virtual_path| value if |GetVirtualPath|
     // fails.
-    if (!kTestCases[i].success)
+    if (!test_case.success)
       continue;
 
-    base::FilePath expected_virtual_path(kTestCases[i].virtual_path);
+    base::FilePath expected_virtual_path(test_case.virtual_path);
     EXPECT_EQ(expected_virtual_path.NormalizePathSeparators(), virtual_path)
-        << "Resolving " << kTestCases[i].local_path;
+        << "Resolving " << test_case.local_path;
   }
 }
 
@@ -349,7 +347,7 @@
 #endif
   };
 
-  for (size_t i = 0; i < arraysize(kTestCases); ++i) {
+  for (size_t i = 0; i < base::size(kTestCases); ++i) {
     FileSystemURL cracked = mount_points->CreateCrackedFileSystemURL(
         kTestOrigin,
         storage::kFileSystemTypeExternal,
@@ -443,7 +441,7 @@
 #endif
   };
 
-  for (size_t i = 0; i < arraysize(kTestCases); ++i) {
+  for (size_t i = 0; i < base::size(kTestCases); ++i) {
     std::string cracked_name;
     storage::FileSystemType cracked_type;
     std::string cracked_id;
diff --git a/storage/browser/fileapi/file_system_context.cc b/storage/browser/fileapi/file_system_context.cc
index 35595d4..e9fde96 100644
--- a/storage/browser/fileapi/file_system_context.cc
+++ b/storage/browser/fileapi/file_system_context.cc
@@ -579,10 +579,10 @@
     kFileSystemTypeExternal,
   };
   // Register file system backends for public mount types.
-  for (size_t j = 0; j < arraysize(mount_types); ++j) {
-    if (backend->CanHandleType(mount_types[j])) {
-      const bool inserted = backend_map_.insert(
-          std::make_pair(mount_types[j], backend)).second;
+  for (const auto& mount_type : mount_types) {
+    if (backend->CanHandleType(mount_type)) {
+      const bool inserted =
+          backend_map_.insert(std::make_pair(mount_type, backend)).second;
       DCHECK(inserted);
     }
   }
diff --git a/storage/browser/fileapi/file_system_context_unittest.cc b/storage/browser/fileapi/file_system_context_unittest.cc
index 213db6e..555c8916 100644
--- a/storage/browser/fileapi/file_system_context_unittest.cc
+++ b/storage/browser/fileapi/file_system_context_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
+#include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -289,7 +290,7 @@
        FPL(""), std::string()},
   };
 
-  for (size_t i = 0; i < arraysize(kTestCases); ++i) {
+  for (size_t i = 0; i < base::size(kTestCases); ++i) {
     const base::FilePath virtual_path =
         base::FilePath::FromUTF8Unsafe(
             kTestCases[i].root).Append(kVirtualPathNoRoot);
diff --git a/storage/browser/fileapi/file_system_file_stream_reader_unittest.cc b/storage/browser/fileapi/file_system_file_stream_reader_unittest.cc
index e1f4e924..c545b3a 100644
--- a/storage/browser/fileapi/file_system_file_stream_reader_unittest.cc
+++ b/storage/browser/fileapi/file_system_file_stream_reader_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
 #include "net/base/test_completion_callback.h"
@@ -38,7 +39,7 @@
 const char kURLOrigin[] = "http://remote/";
 const char kTestFileName[] = "test.dat";
 const char kTestData[] = "0123456789";
-const int kTestDataSize = arraysize(kTestData) - 1;
+const int kTestDataSize = base::size(kTestData) - 1;
 
 void ReadFromReader(storage::FileSystemFileStreamReader* reader,
                     std::string* data,
diff --git a/storage/browser/fileapi/file_system_operation_impl_unittest.cc b/storage/browser/fileapi/file_system_operation_impl_unittest.cc
index ca94900..ec677ee 100644
--- a/storage/browser/fileapi/file_system_operation_impl_unittest.cc
+++ b/storage/browser/fileapi/file_system_operation_impl_unittest.cc
@@ -19,6 +19,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -823,7 +824,7 @@
   base::FilePath src_local_disk_file_path;
   base::CreateTemporaryFile(&src_local_disk_file_path);
   const char test_data[] = "foo";
-  int data_size = arraysize(test_data);
+  int data_size = base::size(test_data);
   base::WriteFile(src_local_disk_file_path, test_data, data_size);
 
   FileSystemURL dest_dir(CreateDirectory("dest"));
@@ -854,7 +855,7 @@
   base::FilePath src_local_disk_file_path;
   base::CreateTemporaryFile(&src_local_disk_file_path);
   const char test_data[] = "foo";
-  base::WriteFile(src_local_disk_file_path, test_data, arraysize(test_data));
+  base::WriteFile(src_local_disk_file_path, test_data, base::size(test_data));
 
   FileSystemURL dest_dir(CreateDirectory("dest"));
 
diff --git a/storage/browser/fileapi/file_system_quota_client_unittest.cc b/storage/browser/fileapi/file_system_quota_client_unittest.cc
index a6dc424..9125cc1 100644
--- a/storage/browser/fileapi/file_system_quota_client_unittest.cc
+++ b/storage/browser/fileapi/file_system_quota_client_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "base/test/scoped_task_environment.h"
 #include "storage/browser/fileapi/file_system_context.h"
 #include "storage/browser/fileapi/file_system_quota_client.h"
@@ -254,7 +255,7 @@
   const TestFile kFiles[] = {
       {true, nullptr, 0, kDummyURL1, kTemporary},
   };
-  InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
+  InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles));
 
   for (int i = 0; i < 2; i++) {
     EXPECT_EQ(0, GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
@@ -267,9 +268,9 @@
       {true, nullptr, 0, kDummyURL1, kTemporary},
       {false, "foo", 4921, kDummyURL1, kTemporary},
   };
-  InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
+  InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles));
   const int64_t file_paths_cost = ComputeFilePathsCostForOriginAndType(
-      kFiles, arraysize(kFiles), kDummyURL1, kTemporary);
+      kFiles, base::size(kFiles), kDummyURL1, kTemporary);
 
   for (int i = 0; i < 2; i++) {
     EXPECT_EQ(4921 + file_paths_cost,
@@ -284,9 +285,9 @@
       {false, "foo", 10310, kDummyURL1, kTemporary},
       {false, "bar", 41, kDummyURL1, kTemporary},
   };
-  InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
+  InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles));
   const int64_t file_paths_cost = ComputeFilePathsCostForOriginAndType(
-      kFiles, arraysize(kFiles), kDummyURL1, kTemporary);
+      kFiles, base::size(kFiles), kDummyURL1, kTemporary);
 
   for (int i = 0; i < 2; i++) {
     EXPECT_EQ(10310 + 41 + file_paths_cost,
@@ -302,9 +303,9 @@
       {false, "bar", 0, kDummyURL1, kTemporary},
       {false, "baz", 0, kDummyURL1, kTemporary},
   };
-  InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
+  InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles));
   const int64_t file_paths_cost = ComputeFilePathsCostForOriginAndType(
-      kFiles, arraysize(kFiles), kDummyURL1, kTemporary);
+      kFiles, base::size(kFiles), kDummyURL1, kTemporary);
 
   for (int i = 0; i < 2; i++) {
     EXPECT_EQ(file_paths_cost,
@@ -320,9 +321,9 @@
       {false, "dirtest/foo", 11921, kDummyURL1, kTemporary},
       {false, "bar", 4814, kDummyURL1, kTemporary},
   };
-  InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
+  InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles));
   const int64_t file_paths_cost = ComputeFilePathsCostForOriginAndType(
-      kFiles, arraysize(kFiles), kDummyURL1, kTemporary);
+      kFiles, base::size(kFiles), kDummyURL1, kTemporary);
 
   for (int i = 0; i < 2; i++) {
     EXPECT_EQ(11921 + 4814 + file_paths_cost,
@@ -342,12 +343,12 @@
       {false, "dirtest/foo", 193, kDummyURL1, kPersistent},
       {false, "bar", 9, kDummyURL1, kPersistent},
   };
-  InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
+  InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles));
   const int64_t file_paths_cost_temporary =
-      ComputeFilePathsCostForOriginAndType(kFiles, arraysize(kFiles),
+      ComputeFilePathsCostForOriginAndType(kFiles, base::size(kFiles),
                                            kDummyURL1, kTemporary);
   const int64_t file_paths_cost_persistent =
-      ComputeFilePathsCostForOriginAndType(kFiles, arraysize(kFiles),
+      ComputeFilePathsCostForOriginAndType(kFiles, base::size(kFiles),
                                            kDummyURL1, kTemporary);
 
   for (int i = 0; i < 2; i++) {
@@ -378,18 +379,18 @@
       {false, "dom/fan", 2013, kDummyURL2, kPersistent},
       {false, "baz", 18, kDummyURL2, kPersistent},
   };
-  InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
+  InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles));
   const int64_t file_paths_cost_temporary1 =
-      ComputeFilePathsCostForOriginAndType(kFiles, arraysize(kFiles),
+      ComputeFilePathsCostForOriginAndType(kFiles, base::size(kFiles),
                                            kDummyURL1, kTemporary);
   const int64_t file_paths_cost_persistent1 =
-      ComputeFilePathsCostForOriginAndType(kFiles, arraysize(kFiles),
+      ComputeFilePathsCostForOriginAndType(kFiles, base::size(kFiles),
                                            kDummyURL1, kPersistent);
   const int64_t file_paths_cost_temporary2 =
-      ComputeFilePathsCostForOriginAndType(kFiles, arraysize(kFiles),
+      ComputeFilePathsCostForOriginAndType(kFiles, base::size(kFiles),
                                            kDummyURL2, kTemporary);
   const int64_t file_paths_cost_persistent2 =
-      ComputeFilePathsCostForOriginAndType(kFiles, arraysize(kFiles),
+      ComputeFilePathsCostForOriginAndType(kFiles, base::size(kFiles),
                                            kDummyURL2, kPersistent);
 
   for (int i = 0; i < 2; i++) {
@@ -411,9 +412,9 @@
       {false, "foo", 11, kDummyURL1, kTemporary},
       {false, "bar", 22, kDummyURL1, kTemporary},
   };
-  InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
+  InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles));
   const int64_t file_paths_cost = ComputeFilePathsCostForOriginAndType(
-      kFiles, arraysize(kFiles), kDummyURL1, kTemporary);
+      kFiles, base::size(kFiles), kDummyURL1, kTemporary);
 
   // Dispatching three GetUsage tasks.
   set_additional_callback_count(0);
@@ -441,7 +442,7 @@
       {true, nullptr, 0, kDummyURL2, kTemporary},
       {true, nullptr, 0, kDummyURL3, kPersistent},
   };
-  InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
+  InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles));
 
   std::set<url::Origin> origins =
       GetOriginsForType(quota_client.get(), kTemporary);
@@ -468,7 +469,7 @@
       {true, nullptr, 0, kURL4, kTemporary},
       {true, nullptr, 0, kURL5, kPersistent},
   };
-  InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
+  InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles));
 
   std::set<url::Origin> origins =
       GetOriginsForHost(quota_client.get(), kTemporary, "foo.com");
@@ -488,7 +489,7 @@
       {true, nullptr, 0, kDummyURL1, kTemporary},
       {false, "foo", 10, kDummyURL1, kTemporary},
   };
-  InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
+  InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles));
 
   // Having files in the usual directory wouldn't affect the result
   // queried in incognito mode.
@@ -520,21 +521,21 @@
       {true, nullptr, 0, "https://bar.com/", kTemporary},
       {false, "g", 64, "https://bar.com/", kTemporary},
   };
-  InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
+  InitializeOriginFiles(quota_client.get(), kFiles, base::size(kFiles));
   const int64_t file_paths_cost_temporary_foo_https =
-      ComputeFilePathsCostForOriginAndType(kFiles, arraysize(kFiles),
+      ComputeFilePathsCostForOriginAndType(kFiles, base::size(kFiles),
                                            "https://foo.com/", kTemporary);
   const int64_t file_paths_cost_persistent_foo =
-      ComputeFilePathsCostForOriginAndType(kFiles, arraysize(kFiles),
+      ComputeFilePathsCostForOriginAndType(kFiles, base::size(kFiles),
                                            "http://foo.com/", kPersistent);
   const int64_t file_paths_cost_temporary_bar =
-      ComputeFilePathsCostForOriginAndType(kFiles, arraysize(kFiles),
+      ComputeFilePathsCostForOriginAndType(kFiles, base::size(kFiles),
                                            "http://bar.com/", kTemporary);
   const int64_t file_paths_cost_temporary_bar_https =
-      ComputeFilePathsCostForOriginAndType(kFiles, arraysize(kFiles),
+      ComputeFilePathsCostForOriginAndType(kFiles, base::size(kFiles),
                                            "https://bar.com/", kTemporary);
   const int64_t file_paths_cost_persistent_bar_https =
-      ComputeFilePathsCostForOriginAndType(kFiles, arraysize(kFiles),
+      ComputeFilePathsCostForOriginAndType(kFiles, base::size(kFiles),
                                            "https://bar.com/", kPersistent);
 
   DeleteOriginData(quota_client.get(), "http://foo.com/", kTemporary);
diff --git a/storage/browser/fileapi/file_system_url_request_job.cc b/storage/browser/fileapi/file_system_url_request_job.cc
index b5f1481..0edc3dd3 100644
--- a/storage/browser/fileapi/file_system_url_request_job.cc
+++ b/storage/browser/fileapi/file_system_url_request_job.cc
@@ -14,6 +14,7 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
@@ -42,7 +43,7 @@
 static net::HttpResponseHeaders* CreateHttpResponseHeaders() {
   // HttpResponseHeaders expects its input string to be terminated by two NULs.
   static const char kStatus[] = "HTTP/1.1 200 OK\0";
-  static const size_t kStatusLen = arraysize(kStatus);
+  static const size_t kStatusLen = base::size(kStatus);
 
   net::HttpResponseHeaders* headers =
       new net::HttpResponseHeaders(std::string(kStatus, kStatusLen));
diff --git a/storage/browser/fileapi/file_system_url_request_job_unittest.cc b/storage/browser/fileapi/file_system_url_request_job_unittest.cc
index 4e64cef..5c5a0c9c 100644
--- a/storage/browser/fileapi/file_system_url_request_job_unittest.cc
+++ b/storage/browser/fileapi/file_system_url_request_job_unittest.cc
@@ -19,6 +19,7 @@
 #include "base/rand_util.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
@@ -268,7 +269,7 @@
 namespace {
 
 TEST_F(FileSystemURLRequestJobTest, FileTest) {
-  WriteFile("file1.dat", kTestFileData, arraysize(kTestFileData) - 1);
+  WriteFile("file1.dat", kTestFileData, base::size(kTestFileData) - 1);
   TestRequest(CreateFileSystemURL("file1.dat"));
 
   ASSERT_FALSE(request_->is_pending());
@@ -328,7 +329,7 @@
 }
 
 TEST_F(FileSystemURLRequestJobTest, FileTestMultipleRangesNotSupported) {
-  WriteFile("file1.dat", kTestFileData, arraysize(kTestFileData) - 1);
+  WriteFile("file1.dat", kTestFileData, base::size(kTestFileData) - 1);
   net::HttpRequestHeaders headers;
   headers.SetHeader(net::HttpRequestHeaders::kRange,
                     "bytes=0-5,10-200,200-300");
@@ -339,7 +340,7 @@
 }
 
 TEST_F(FileSystemURLRequestJobTest, RangeOutOfBounds) {
-  WriteFile("file1.dat", kTestFileData, arraysize(kTestFileData) - 1);
+  WriteFile("file1.dat", kTestFileData, base::size(kTestFileData) - 1);
   net::HttpRequestHeaders headers;
   headers.SetHeader(
       net::HttpRequestHeaders::kRange,
@@ -387,7 +388,7 @@
 }
 
 TEST_F(FileSystemURLRequestJobTest, Cancel) {
-  WriteFile("file1.dat", kTestFileData, arraysize(kTestFileData) - 1);
+  WriteFile("file1.dat", kTestFileData, base::size(kTestFileData) - 1);
   TestRequestNoRun(CreateFileSystemURL("file1.dat"));
 
   // Run StartAsync() and only StartAsync().
@@ -416,7 +417,7 @@
 }
 
 TEST_F(FileSystemURLRequestJobTest, Incognito) {
-  WriteFile("file", kTestFileData, arraysize(kTestFileData) - 1);
+  WriteFile("file", kTestFileData, base::size(kTestFileData) - 1);
 
   // Creates a new filesystem context for incognito mode.
   scoped_refptr<FileSystemContext> file_system_context =
diff --git a/storage/browser/fileapi/file_system_url_unittest.cc b/storage/browser/fileapi/file_system_url_unittest.cc
index 71e0488c3..f016f4d1 100644
--- a/storage/browser/fileapi/file_system_url_unittest.cc
+++ b/storage/browser/fileapi/file_system_url_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "base/files/file_path.h"
 #include "base/macros.h"
+#include "base/stl_util.h"
 #include "storage/common/fileapi/file_system_types.h"
 #include "storage/common/fileapi/file_system_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -118,8 +119,8 @@
   };
 
   FileSystemURL::Comparator compare;
-  for (size_t i = 0; i < arraysize(urls); ++i) {
-    for (size_t j = 0; j < arraysize(urls); ++j) {
+  for (size_t i = 0; i < base::size(urls); ++i) {
+    for (size_t j = 0; j < base::size(urls); ++j) {
       SCOPED_TRACE(testing::Message() << i << " < " << j);
       EXPECT_EQ(urls[i] < urls[j],
                 compare(FileSystemURL::CreateForTest(urls[i]),
@@ -181,11 +182,8 @@
     "filesystem:http://chromium.org/test/plus%2B/space%20/colon%3A",
   };
 
-  for (size_t i = 0; i < arraysize(kTestURL); ++i) {
-    EXPECT_EQ(
-        kTestURL[i],
-        FileSystemURL::CreateForTest(GURL(kTestURL[i])).ToGURL().spec());
-  }
+  for (const char* url : kTestURL)
+    EXPECT_EQ(url, FileSystemURL::CreateForTest(GURL(url)).ToGURL().spec());
 }
 
 TEST(FileSystemURLTest, DebugString) {
diff --git a/storage/browser/fileapi/file_writer_delegate_unittest.cc b/storage/browser/fileapi/file_writer_delegate_unittest.cc
index eb78e5f..a40f98e 100644
--- a/storage/browser/fileapi/file_writer_delegate_unittest.cc
+++ b/storage/browser/fileapi/file_writer_delegate_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "net/base/io_buffer.h"
@@ -51,7 +52,7 @@
 const storage::FileSystemType kFileSystemType = storage::kFileSystemTypeTest;
 
 const char kData[] = "The quick brown fox jumps over the lazy dog.\n";
-const int kDataSize = arraysize(kData) - 1;
+const int kDataSize = base::size(kData) - 1;
 
 class Result {
  public:
diff --git a/storage/browser/fileapi/isolated_context_unittest.cc b/storage/browser/fileapi/isolated_context_unittest.cc
index 990a67c4..f453f17 100644
--- a/storage/browser/fileapi/isolated_context_unittest.cc
+++ b/storage/browser/fileapi/isolated_context_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/stl_util.h"
 #include "storage/browser/fileapi/file_system_url.h"
 #include "storage/browser/fileapi/isolated_context.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -53,16 +54,15 @@
 class IsolatedContextTest : public testing::Test {
  public:
   IsolatedContextTest() {
-    for (size_t i = 0; i < arraysize(kTestPaths); ++i)
-      fileset_.insert(kTestPaths[i].NormalizePathSeparators());
+    for (const auto& path : kTestPaths)
+      fileset_.insert(path.NormalizePathSeparators());
   }
 
   void SetUp() override {
     IsolatedContext::FileInfoSet files;
-    for (size_t i = 0; i < arraysize(kTestPaths); ++i) {
+    for (const auto& path : kTestPaths) {
       std::string name;
-      ASSERT_TRUE(
-          files.AddPath(kTestPaths[i].NormalizePathSeparators(), &name));
+      ASSERT_TRUE(files.AddPath(path.NormalizePathSeparators(), &name));
       names_.push_back(name);
     }
     id_ = IsolatedContext::GetInstance()->RegisterDraggedFileSystem(files);
@@ -99,7 +99,7 @@
   // See if the name of each registered kTestPaths (that is what we
   // register in SetUp() by RegisterDraggedFileSystem) is properly cracked as
   // a valid virtual path in the isolated filesystem.
-  for (size_t i = 0; i < arraysize(kTestPaths); ++i) {
+  for (size_t i = 0; i < base::size(kTestPaths); ++i) {
     base::FilePath virtual_path = isolated_context()->CreateVirtualRootPath(id_)
         .AppendASCII(names_[i]);
     std::string cracked_id;
@@ -196,8 +196,8 @@
     { FPL("foo/..\\baz"), SHOULD_FAIL_WITH_WIN_SEPARATORS },
   };
 
-  for (size_t i = 0; i < arraysize(kTestPaths); ++i) {
-    for (size_t j = 0; j < arraysize(relatives); ++j) {
+  for (size_t i = 0; i < base::size(kTestPaths); ++i) {
+    for (size_t j = 0; j < base::size(relatives); ++j) {
       SCOPED_TRACE(testing::Message() << "Testing "
                    << kTestPaths[i].value() << " " << relatives[j].path);
       base::FilePath virtual_path =
@@ -246,8 +246,8 @@
     { FPL("foo/..\\baz"), SHOULD_FAIL_WITH_WIN_SEPARATORS },
   };
 
-  for (size_t i = 0; i < arraysize(kTestPaths); ++i) {
-    for (size_t j = 0; j < arraysize(relatives); ++j) {
+  for (size_t i = 0; i < base::size(kTestPaths); ++i) {
+    for (size_t j = 0; j < base::size(relatives); ++j) {
       SCOPED_TRACE(testing::Message() << "Testing "
                    << kTestPaths[i].value() << " " << relatives[j].path);
       base::FilePath virtual_path =
diff --git a/storage/browser/fileapi/local_file_stream_reader_unittest.cc b/storage/browser/fileapi/local_file_stream_reader_unittest.cc
index 35d6aa0..3183386 100644
--- a/storage/browser/fileapi/local_file_stream_reader_unittest.cc
+++ b/storage/browser/fileapi/local_file_stream_reader_unittest.cc
@@ -20,6 +20,7 @@
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
 #include "base/threading/thread.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
@@ -33,7 +34,7 @@
 namespace {
 
 const char kTestData[] = "0123456789";
-const int kTestDataSize = arraysize(kTestData) - 1;
+const int kTestDataSize = base::size(kTestData) - 1;
 
 void ReadFromReader(LocalFileStreamReader* reader,
                     std::string* data, size_t size,
diff --git a/storage/browser/fileapi/obfuscated_file_util_unittest.cc b/storage/browser/fileapi/obfuscated_file_util_unittest.cc
index d6fe83a..ff117d9 100644
--- a/storage/browser/fileapi/obfuscated_file_util_unittest.cc
+++ b/storage/browser/fileapi/obfuscated_file_util_unittest.cc
@@ -19,6 +19,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
@@ -341,7 +342,7 @@
     EXPECT_EQ(0, GetSize(data_path));
 
     const char data[] = "test data";
-    const int length = arraysize(data) - 1;
+    const int length = base::size(data) - 1;
 
     if (!file.IsValid()) {
       file.Initialize(data_path,
@@ -1341,7 +1342,7 @@
   const int64_t kSourceLength = 5;
   const int64_t kDestLength = 50;
 
-  for (size_t i = 0; i < arraysize(kCopyMoveTestCases); ++i) {
+  for (size_t i = 0; i < base::size(kCopyMoveTestCases); ++i) {
     SCOPED_TRACE(testing::Message() << "kCopyMoveTestCase " << i);
     const CopyMoveTestCaseRecord& test_case = kCopyMoveTestCases[i];
     SCOPED_TRACE(testing::Message() << "\t is_copy_not_move " <<
@@ -1587,7 +1588,7 @@
   std::set<GURL> origins_expected;
   origins_expected.insert(origin());
 
-  for (size_t i = 0; i < arraysize(kOriginEnumerationTestRecords); ++i) {
+  for (size_t i = 0; i < base::size(kOriginEnumerationTestRecords); ++i) {
     SCOPED_TRACE(testing::Message() <<
         "Validating kOriginEnumerationTestRecords " << i);
     const OriginEnumerationTestRecord& record =
@@ -1629,10 +1630,7 @@
     origins_found.insert(origin_url);
     SCOPED_TRACE(testing::Message() << "Handling " << origin_url.spec());
     bool found = false;
-    for (size_t i = 0; !found && i < arraysize(kOriginEnumerationTestRecords);
-        ++i) {
-      const OriginEnumerationTestRecord& record =
-          kOriginEnumerationTestRecords[i];
+    for (const auto& record : kOriginEnumerationTestRecords) {
       if (origin_url != record.origin_url)
         continue;
       found = true;
@@ -1790,11 +1788,11 @@
   const FileSystemURL empty_path = CreateURL(base::FilePath());
   std::unique_ptr<FileSystemOperationContext> context;
 
-  for (size_t i = 0; i < arraysize(kPath); ++i) {
+  for (const auto& path : kPath) {
     bool created = false;
     context.reset(NewContext(nullptr));
     EXPECT_EQ(base::File::FILE_OK,
-              ofu()->EnsureFileExists(context.get(), kPath[i], &created));
+              ofu()->EnsureFileExists(context.get(), path, &created));
     EXPECT_TRUE(created);
   }
 
@@ -1813,7 +1811,7 @@
   EXPECT_EQ(base::File::FILE_OK,
             AsyncFileTestHelper::ReadDirectory(
                 file_system_context(), empty_path, &entries));
-  EXPECT_EQ(arraysize(kPath) - 1, entries.size());
+  EXPECT_EQ(base::size(kPath) - 1, entries.size());
 }
 
 TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) {
diff --git a/storage/browser/fileapi/sandbox_directory_database.cc b/storage/browser/fileapi/sandbox_directory_database.cc
index d516796..afb74cc 100644
--- a/storage/browser/fileapi/sandbox_directory_database.cc
+++ b/storage/browser/fileapi/sandbox_directory_database.cc
@@ -19,6 +19,7 @@
 #include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/pickle.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "storage/browser/fileapi/file_system_usage_cache.h"
@@ -309,8 +310,8 @@
       if (!path_.AppendRelativePath(absolute_file_path, &relative_file_path))
         return false;
 
-      if (std::find(kExcludes, kExcludes + arraysize(kExcludes),
-                    relative_file_path) != kExcludes + arraysize(kExcludes))
+      if (std::find(kExcludes, kExcludes + base::size(kExcludes),
+                    relative_file_path) != kExcludes + base::size(kExcludes))
         continue;
 
       if (find_info.IsDirectory()) {
@@ -402,8 +403,8 @@
       base::FilePath(kDirectoryDatabaseName),
       base::FilePath(storage::FileSystemUsageCache::kUsageFileName),
   };
-  for (size_t i = 0; i < arraysize(kExcludes); ++i) {
-    if (data_path == kExcludes[i] || kExcludes[i].IsParent(data_path))
+  for (const auto& exclude : kExcludes) {
+    if (data_path == exclude || exclude.IsParent(data_path))
       return false;
   }
   return true;
diff --git a/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc b/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc
index eb4239d..87ad7fc 100644
--- a/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc
+++ b/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc
@@ -211,7 +211,7 @@
       !file_task_runner_->RunsTasksInCurrentSequence()) {
     std::vector<std::string> types_to_prepopulate(
         &kPrepopulateTypes[0],
-        &kPrepopulateTypes[arraysize(kPrepopulateTypes)]);
+        &kPrepopulateTypes[base::size(kPrepopulateTypes)]);
     file_task_runner_->PostTask(
         FROM_HERE, base::BindOnce(&ObfuscatedFileUtil::MaybePrepopulateDatabase,
                                   base::Unretained(obfuscated_file_util()),
@@ -545,12 +545,12 @@
   // http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restrictions
   base::FilePath filename = VirtualPath::BaseName(url.path());
   // See if the name is allowed to create.
-  for (size_t i = 0; i < arraysize(kRestrictedNames); ++i) {
-    if (filename.value() == kRestrictedNames[i])
+  for (const auto* const restricted_name : kRestrictedNames) {
+    if (filename.value() == restricted_name)
       return false;
   }
-  for (size_t i = 0; i < arraysize(kRestrictedChars); ++i) {
-    if (filename.value().find(kRestrictedChars[i]) !=
+  for (const auto& restricted_char : kRestrictedChars) {
+    if (filename.value().find(restricted_char) !=
         base::FilePath::StringType::npos)
       return false;
   }
diff --git a/storage/browser/fileapi/sandbox_file_system_backend_unittest.cc b/storage/browser/fileapi/sandbox_file_system_backend_unittest.cc
index a5b3df8..2245c6ef 100644
--- a/storage/browser/fileapi/sandbox_file_system_backend_unittest.cc
+++ b/storage/browser/fileapi/sandbox_file_system_backend_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
+#include "base/stl_util.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "storage/browser/fileapi/file_system_backend.h"
@@ -154,8 +155,8 @@
     "http://www.foo.com:8080/",
     "http://www.foo.com:80/",
   };
-  size_t temporary_size = arraysize(temporary_origins);
-  size_t persistent_size = arraysize(persistent_origins);
+  size_t temporary_size = base::size(temporary_origins);
+  size_t persistent_size = base::size(persistent_origins);
   std::set<GURL> temporary_set, persistent_set;
   for (size_t i = 0; i < temporary_size; ++i) {
     CreateOriginTypeDirectory(GURL(temporary_origins[i]),
@@ -190,11 +191,12 @@
 }
 
 TEST_F(SandboxFileSystemBackendTest, GetRootPathCreateAndExamine) {
-  std::vector<base::FilePath> returned_root_path(arraysize(kRootPathTestCases));
+  std::vector<base::FilePath> returned_root_path(
+      base::size(kRootPathTestCases));
   SetUpNewBackend(CreateAllowFileAccessOptions());
 
   // Create a new root directory.
-  for (size_t i = 0; i < arraysize(kRootPathTestCases); ++i) {
+  for (size_t i = 0; i < base::size(kRootPathTestCases); ++i) {
     SCOPED_TRACE(testing::Message() << "RootPath (create) #" << i << " "
                  << kRootPathTestCases[i].expected_path);
 
@@ -214,7 +216,7 @@
 
   // Get the root directory with create=false and see if we get the
   // same directory.
-  for (size_t i = 0; i < arraysize(kRootPathTestCases); ++i) {
+  for (size_t i = 0; i < base::size(kRootPathTestCases); ++i) {
     SCOPED_TRACE(testing::Message() << "RootPath (get) #" << i << " "
                  << kRootPathTestCases[i].expected_path);
 
@@ -230,7 +232,8 @@
 
 TEST_F(SandboxFileSystemBackendTest,
        GetRootPathCreateAndExamineWithNewBackend) {
-  std::vector<base::FilePath> returned_root_path(arraysize(kRootPathTestCases));
+  std::vector<base::FilePath> returned_root_path(
+      base::size(kRootPathTestCases));
   SetUpNewBackend(CreateAllowFileAccessOptions());
 
   GURL origin_url("http://foo.com:1/");
@@ -255,7 +258,7 @@
   SetUpNewBackend(CreateDisallowFileAccessOptions());
 
   // Try to get a root directory without creating.
-  for (size_t i = 0; i < arraysize(kRootPathTestCases); ++i) {
+  for (size_t i = 0; i < base::size(kRootPathTestCases); ++i) {
     SCOPED_TRACE(testing::Message() << "RootPath (create=false) #" << i << " "
                  << kRootPathTestCases[i].expected_path);
     EXPECT_FALSE(GetRootPath(
@@ -268,7 +271,7 @@
   SetUpNewBackend(CreateIncognitoFileSystemOptions());
 
   // Try to get a root directory.
-  for (size_t i = 0; i < arraysize(kRootPathTestCases); ++i) {
+  for (size_t i = 0; i < base::size(kRootPathTestCases); ++i) {
     SCOPED_TRACE(testing::Message() << "RootPath (incognito) #" << i << " "
                  << kRootPathTestCases[i].expected_path);
     EXPECT_FALSE(GetRootPath(
@@ -279,7 +282,7 @@
 
 TEST_F(SandboxFileSystemBackendTest, GetRootPathFileURI) {
   SetUpNewBackend(CreateDisallowFileAccessOptions());
-  for (size_t i = 0; i < arraysize(kRootPathFileURITestCases); ++i) {
+  for (size_t i = 0; i < base::size(kRootPathFileURITestCases); ++i) {
     SCOPED_TRACE(testing::Message() << "RootPathFileURI (disallow) #"
                  << i << " " << kRootPathFileURITestCases[i].expected_path);
     EXPECT_FALSE(GetRootPath(GURL(kRootPathFileURITestCases[i].origin_url),
@@ -291,7 +294,7 @@
 
 TEST_F(SandboxFileSystemBackendTest, GetRootPathFileURIWithAllowFlag) {
   SetUpNewBackend(CreateAllowFileAccessOptions());
-  for (size_t i = 0; i < arraysize(kRootPathFileURITestCases); ++i) {
+  for (size_t i = 0; i < base::size(kRootPathFileURITestCases); ++i) {
     SCOPED_TRACE(testing::Message() << "RootPathFileURI (allow) #"
                  << i << " " << kRootPathFileURITestCases[i].expected_path);
     base::FilePath root_path;
diff --git a/storage/browser/fileapi/sandbox_origin_database_unittest.cc b/storage/browser/fileapi/sandbox_origin_database_unittest.cc
index d89ebb28..50aa92c9 100644
--- a/storage/browser/fileapi/sandbox_origin_database_unittest.cc
+++ b/storage/browser/fileapi/sandbox_origin_database_unittest.cc
@@ -215,7 +215,7 @@
 
   std::unique_ptr<SandboxOriginDatabase> database(
       new SandboxOriginDatabase(kFSDir, nullptr));
-  for (size_t i = 0; i < arraysize(kOrigins); ++i) {
+  for (size_t i = 0; i < base::size(kOrigins); ++i) {
     base::FilePath path;
     EXPECT_FALSE(database->HasOriginPath(kOrigins[i]));
     EXPECT_TRUE(database->GetPathForOrigin(kOrigins[i], &path));
@@ -249,7 +249,7 @@
 
   // Expect all but last added origin will be repaired back, and kOrigins[1]
   // should be dropped due to absence of backing directory.
-  EXPECT_EQ(arraysize(kOrigins) - 2, origins_in_db.size());
+  EXPECT_EQ(base::size(kOrigins) - 2, origins_in_db.size());
 
   const std::string kOrigin("piyo.example.org");
   EXPECT_FALSE(database->HasOriginPath(kOrigin));
@@ -272,7 +272,7 @@
     leveldb::kInfoLogFile,
   };
 
-  for (size_t i = 0; i < arraysize(kLevelDBFileTypes); ++i) {
+  for (const auto& file_type : kLevelDBFileTypes) {
     base::ScopedTempDir dir;
     ASSERT_TRUE(dir.CreateUniqueTempDir());
     const base::FilePath kFSDir = dir.GetPath().Append(kFileSystemDirName);
@@ -292,7 +292,7 @@
     EXPECT_TRUE(base::CreateDirectory(kFSDir.Append(path)));
     database.reset();
 
-    DeleteDatabaseFile(kDBDir, kLevelDBFileTypes[i]);
+    DeleteDatabaseFile(kDBDir, file_type);
 
     database.reset(new SandboxOriginDatabase(kFSDir, nullptr));
     std::vector<SandboxOriginDatabase::OriginRecord> origins_in_db;
diff --git a/storage/browser/test/fileapi_test_file_set.cc b/storage/browser/test/fileapi_test_file_set.cc
index 7b2b676..37917384 100644
--- a/storage/browser/test/fileapi_test_file_set.cc
+++ b/storage/browser/test/fileapi_test_file_set.cc
@@ -14,6 +14,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/rand_util.h"
+#include "base/stl_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace content {
@@ -40,7 +41,7 @@
 };
 
 const size_t kRegularFileSystemTestCaseSize =
-    arraysize(kRegularFileSystemTestCases);
+    base::size(kRegularFileSystemTestCases);
 
 void SetUpOneFileSystemTestCase(const base::FilePath& root_path,
                                 const FileSystemTestCaseRecord& test_case) {
@@ -62,7 +63,7 @@
 
 
 void SetUpRegularFileSystemTestCases(const base::FilePath& root_path) {
-  for (size_t i = 0; i < arraysize(kRegularFileSystemTestCases); ++i) {
+  for (size_t i = 0; i < base::size(kRegularFileSystemTestCases); ++i) {
     SCOPED_TRACE(testing::Message() << "Creating kRegularTestCases " << i);
     SetUpOneFileSystemTestCase(root_path, kRegularFileSystemTestCases[i]);
   }
diff --git a/storage/common/database/database_identifier.cc b/storage/common/database/database_identifier.cc
index c4983d3c..0625135f 100644
--- a/storage/common/database/database_identifier.cc
+++ b/storage/common/database/database_identifier.cc
@@ -7,6 +7,7 @@
 #include <stddef.h>
 
 #include "base/macros.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "url/url_canon.h"
@@ -117,8 +118,8 @@
   if (identifier.find("..") != std::string::npos)
     return DatabaseIdentifier();
   char forbidden[] = {'\\', '/', ':' ,'\0'};
-  if (identifier.find_first_of(forbidden, 0, arraysize(forbidden)) !=
-          std::string::npos) {
+  if (identifier.find_first_of(forbidden, 0, base::size(forbidden)) !=
+      std::string::npos) {
     return DatabaseIdentifier();
   }
 
diff --git a/storage/common/database/database_identifier_unittest.cc b/storage/common/database/database_identifier_unittest.cc
index af4ed79..18315f3 100644
--- a/storage/common/database/database_identifier_unittest.cc
+++ b/storage/common/database/database_identifier_unittest.cc
@@ -7,6 +7,7 @@
 #include <stddef.h>
 
 #include "base/macros.h"
+#include "base/stl_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 #include "url/origin.h"
@@ -41,19 +42,19 @@
     {"http://[::ffff:8190:3426]", "http_[__ffff_8190_3426]_0"},
   };
 
-  for (size_t i = 0; i < arraysize(cases); ++i) {
-    GURL origin_url(cases[i].origin);
+  for (const auto& test_case : cases) {
+    GURL origin_url(test_case.origin);
     url::Origin origin = url::Origin::Create(origin_url);
 
     DatabaseIdentifier identifier_from_url =
         DatabaseIdentifier::CreateFromOrigin(origin_url);
-    EXPECT_EQ(cases[i].expectedIdentifier, identifier_from_url.ToString())
-        << "test case " << cases[i].origin;
+    EXPECT_EQ(test_case.expectedIdentifier, identifier_from_url.ToString())
+        << "test case " << test_case.origin;
 
     DatabaseIdentifier identifier_from_origin =
         DatabaseIdentifier::CreateFromOrigin(origin_url);
-    EXPECT_EQ(cases[i].expectedIdentifier, identifier_from_origin.ToString())
-        << "test case " << cases[i].origin;
+    EXPECT_EQ(test_case.expectedIdentifier, identifier_from_origin.ToString())
+        << "test case " << test_case.origin;
   }
 }
 
@@ -165,7 +166,7 @@
     {"x\x80x", "__0", false},
   };
 
-  for (size_t i = 0; i < arraysize(cases); ++i) {
+  for (size_t i = 0; i < base::size(cases); ++i) {
     GURL origin_url("http://" + cases[i].hostname);
     url::Origin origin = url::Origin::Create(origin_url);
     DatabaseIdentifier identifier_from_url =
@@ -238,19 +239,18 @@
      "http", "[::ffff:8190:3426]", 0, GURL("http://[::ffff:8190:3426]"), false},
   };
 
-  for (size_t i = 0; i < arraysize(valid_cases); ++i) {
-    DatabaseIdentifier identifier =
-        DatabaseIdentifier::Parse(valid_cases[i].str);
-    EXPECT_EQ(valid_cases[i].expected_scheme, identifier.scheme())
-        << "test case " << valid_cases[i].str;
-    EXPECT_EQ(valid_cases[i].expected_host, identifier.hostname())
-        << "test case " << valid_cases[i].str;
-    EXPECT_EQ(valid_cases[i].expected_port, identifier.port())
-        << "test case " << valid_cases[i].str;
-    EXPECT_EQ(valid_cases[i].expected_origin, identifier.ToOrigin())
-        << "test case " << valid_cases[i].str;
-    EXPECT_EQ(valid_cases[i].expected_unique, identifier.is_unique())
-        << "test case " << valid_cases[i].str;
+  for (const auto& valid_case : valid_cases) {
+    DatabaseIdentifier identifier = DatabaseIdentifier::Parse(valid_case.str);
+    EXPECT_EQ(valid_case.expected_scheme, identifier.scheme())
+        << "test case " << valid_case.str;
+    EXPECT_EQ(valid_case.expected_host, identifier.hostname())
+        << "test case " << valid_case.str;
+    EXPECT_EQ(valid_case.expected_port, identifier.port())
+        << "test case " << valid_case.str;
+    EXPECT_EQ(valid_case.expected_origin, identifier.ToOrigin())
+        << "test case " << valid_case.str;
+    EXPECT_EQ(valid_case.expected_unique, identifier.is_unique())
+        << "test case " << valid_case.str;
   }
 
   std::string bogus_components[] = {
@@ -266,15 +266,12 @@
     "http_bytes_after_port_0abcd",
   };
 
-  for (size_t i = 0; i < arraysize(bogus_components); ++i) {
-    DatabaseIdentifier identifier =
-        DatabaseIdentifier::Parse(bogus_components[i]);
-    EXPECT_EQ("__0", identifier.ToString())
-        << "test case " << bogus_components[i];
+  for (const auto& bogus_component : bogus_components) {
+    DatabaseIdentifier identifier = DatabaseIdentifier::Parse(bogus_component);
+    EXPECT_EQ("__0", identifier.ToString()) << "test case " << bogus_component;
     EXPECT_EQ(GURL("null"), identifier.ToOrigin())
-        << "test case " << bogus_components[i];
-    EXPECT_EQ(true, identifier.is_unique())
-        << "test case " << bogus_components[i];
+        << "test case " << bogus_component;
+    EXPECT_EQ(true, identifier.is_unique()) << "test case " << bogus_component;
   }
 }
 
diff --git a/storage/common/fileapi/file_system_util.cc b/storage/common/fileapi/file_system_util.cc
index 92e0214c..9f59377 100644
--- a/storage/common/fileapi/file_system_util.cc
+++ b/storage/common/fileapi/file_system_util.cc
@@ -10,6 +10,7 @@
 
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
@@ -165,9 +166,9 @@
   // A path of the inner_url contains only mount type part (e.g. "/temporary").
   DCHECK(url.inner_url());
   std::string inner_path = url.inner_url()->path();
-  for (size_t i = 0; i < arraysize(kValidTypes); ++i) {
-    if (inner_path == kValidTypes[i].dir) {
-      file_system_type = kValidTypes[i].type;
+  for (const auto& valid_type : kValidTypes) {
+    if (inner_path == valid_type.dir) {
+      file_system_type = valid_type.type;
       break;
     }
   }
diff --git a/storage/common/fileapi/file_system_util_unittest.cc b/storage/common/fileapi/file_system_util_unittest.cc
index f7697b6..efa8567 100644
--- a/storage/common/fileapi/file_system_util_unittest.cc
+++ b/storage/common/fileapi/file_system_util_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/files/file_path.h"
 #include "base/macros.h"
+#include "base/stl_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
@@ -72,10 +73,10 @@
     { FILE_PATH_LITERAL("////bar"), FILE_PATH_LITERAL("bar") },
     { FILE_PATH_LITERAL("bar"), FILE_PATH_LITERAL("bar") }
   };
-  for (size_t i = 0; i < arraysize(test_cases); ++i) {
-    base::FilePath input = base::FilePath(test_cases[i].path);
+  for (const auto& test_case : test_cases) {
+    base::FilePath input = base::FilePath(test_case.path);
     base::FilePath base_name = VirtualPath::BaseName(input);
-    EXPECT_EQ(test_cases[i].base_name, base_name.value());
+    EXPECT_EQ(test_case.base_name, base_name.value());
   }
 }
 
@@ -112,10 +113,10 @@
     { FILE_PATH_LITERAL("\\\\\\\\bar"), FILE_PATH_LITERAL("\\") },
 #endif
   };
-  for (size_t i = 0; i < arraysize(test_cases); ++i) {
-    base::FilePath input = base::FilePath(test_cases[i].path);
+  for (const auto& test_case : test_cases) {
+    base::FilePath input = base::FilePath(test_case.path);
     base::FilePath dir_name = VirtualPath::DirName(input);
-    EXPECT_EQ(test_cases[i].dir_name, dir_name.value());
+    EXPECT_EQ(test_case.dir_name, dir_name.value());
   }
 }
 
@@ -132,11 +133,11 @@
     { FILE_PATH_LITERAL("\\foo"), FILE_PATH_LITERAL("/foo") },
 #endif
   };
-  for (size_t i = 0; i < arraysize(test_cases); ++i) {
-    base::FilePath input = base::FilePath(test_cases[i].path);
+  for (const auto& test_case : test_cases) {
+    base::FilePath input = base::FilePath(test_case.path);
     base::FilePath::StringType normalized_path_string =
         VirtualPath::GetNormalizedFilePath(input);
-    EXPECT_EQ(test_cases[i].normalized_path, normalized_path_string);
+    EXPECT_EQ(test_case.normalized_path, normalized_path_string);
   }
 }
 
@@ -197,21 +198,21 @@
       { FILE_PATH_LITERAL("c:"), FILE_PATH_LITERAL("bar") } },
 #endif
   };
-  for (size_t i = 0; i < arraysize(test_cases); ++i) {
-    base::FilePath input = base::FilePath(test_cases[i].path);
+  for (const auto& test_case : test_cases) {
+    base::FilePath input = base::FilePath(test_case.path);
     std::vector<base::FilePath::StringType> components =
         VirtualPath::GetComponents(input);
-    EXPECT_EQ(test_cases[i].count, components.size());
+    EXPECT_EQ(test_case.count, components.size());
     for (size_t j = 0; j < components.size(); ++j)
-      EXPECT_EQ(test_cases[i].components[j], components[j]);
+      EXPECT_EQ(test_case.components[j], components[j]);
   }
-  for (size_t i = 0; i < arraysize(test_cases); ++i) {
-    base::FilePath input = base::FilePath(test_cases[i].path);
+  for (const auto& test_case : test_cases) {
+    base::FilePath input = base::FilePath(test_case.path);
     std::vector<std::string> components =
         VirtualPath::GetComponentsUTF8Unsafe(input);
-    EXPECT_EQ(test_cases[i].count, components.size());
+    EXPECT_EQ(test_case.count, components.size());
     for (size_t j = 0; j < components.size(); ++j) {
-      EXPECT_EQ(base::FilePath(test_cases[i].components[j]).AsUTF8Unsafe(),
+      EXPECT_EQ(base::FilePath(test_case.components[j]).AsUTF8Unsafe(),
                 components[j]);
     }
   }
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json
index 3d5ba12..d40d195 100644
--- a/testing/buildbot/chromium.clang.json
+++ b/testing/buildbot/chromium.clang.json
@@ -11459,25 +11459,6 @@
         "test": "boringssl_ssl_tests"
       },
       {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "args": [
-          "--enable-features=NetworkService",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_browser_tests.filter"
-        ],
-        "name": "network_service_browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 15
-        },
-        "test": "browser_tests"
-      },
-      {
         "args": [
           "--enable-features=WebUIPolymer2",
           "--test-launcher-filter-file=../../testing/buildbot/filters/webui_polymer2_browser_tests.filter"
@@ -11558,7 +11539,8 @@
       },
       {
         "swarming": {
-          "can_use_on_swarming_builders": true
+          "can_use_on_swarming_builders": true,
+          "shards": 5
         },
         "test": "content_browsertests"
       },
@@ -11695,18 +11677,12 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "headless_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "headless_unittests"
       },
       {
         "swarming": {
           "can_use_on_swarming_builders": true,
-          "shards": 3
+          "shards": 6
         },
         "test": "interactive_ui_tests"
       },
@@ -11824,7 +11800,8 @@
       },
       {
         "swarming": {
-          "can_use_on_swarming_builders": true
+          "can_use_on_swarming_builders": true,
+          "shards": 4
         },
         "test": "net_unittests"
       },
@@ -11902,7 +11879,8 @@
       },
       {
         "swarming": {
-          "can_use_on_swarming_builders": true
+          "can_use_on_swarming_builders": true,
+          "shards": 6
         },
         "test": "sync_integration_tests"
       },
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index b79d871..a054b01 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -8152,6 +8152,15 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "blink_heap_unittests"
+      },
+      {
+        "args": [
+          "--test-launcher-print-test-stdio=always"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "blink_platform_unittests"
       },
       {
@@ -8732,6 +8741,16 @@
           "--test-launcher-print-test-stdio=always"
         ],
         "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 6
+        },
+        "test": "sync_integration_tests"
+      },
+      {
+        "args": [
+          "--test-launcher-print-test-stdio=always"
+        ],
+        "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "traffic_annotation_auditor_unittests"
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index eda069c..63ee6a2 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -56,17 +56,12 @@
       },
     },
   },
-  'blink_heap_unittests': {
-    'remove_from': [
-      # chromium.memory
-      'Linux TSan Tests',  # https://crbug.com/831674
-    ],
-  },
   'browser_tests': {
     'remove_from': [
       # chromium.clang
       'CrWinAsanCov',
       'linux-win_cross-rel',
+      'ToTLinuxTSan',  # https://crbug.com/368525
       'ToTMac', # https://crbug.com/828031
       'ToTMacASan', # https://crbug.com/828031
       # chromium.fyi
@@ -324,6 +319,11 @@
         },
       },
       # chromium.clang
+      'ToTLinuxTSan': {
+        'swarming': {
+          'shards': 5,
+        },
+      },
       'ToTLinuxUBSanVptr': {
         'swarming': {
           'shards': 5,
@@ -595,6 +595,7 @@
     'remove_from': [
       # chromium.clang
       'ToTLinuxASan',  # https://crbug.com/843732
+      'ToTLinuxTSan',  # https://crbug.com/843734
       # chromium.memory
       'Linux ASan LSan Tests (1)',  # https://crbug.com/843732
       'Linux TSan Tests',  # https://crbug.com/843734
@@ -624,6 +625,13 @@
   },
   'interactive_ui_tests': {
     'modifications': {
+      # chromium.clang
+      'ToTLinuxTSan': {
+        # These are slow on the TSan bots for some reason, crbug.com/794372
+        'swarming': {
+          'shards': 6,
+        },
+      },
       # chromium.win
       'Win7 Tests (dbg)(1)': {
         'swarming': {
@@ -638,7 +646,7 @@
         },
       },
       'Linux TSan Tests': {
-        # These are slow on the TSan trybot for some reason, crbug.com/794372
+        # These are slow on the TSan bots for some reason, crbug.com/794372
         'swarming': {
           'shards': 6,
         },
@@ -694,6 +702,11 @@
           'shards': 16,
         },
       },
+      'ToTLinuxTSan': {
+        'swarming': {
+          'shards': 4,
+        }
+      },
       # chromium.memory
       'Linux ASan LSan Tests (1)': {
         # These are very slow on the ASAN trybot for some reason.
@@ -741,6 +754,8 @@
   },
   'network_service_browser_tests': {
     'remove_from': [
+      # chromium.clang
+      'ToTLinuxTSan',  # https://crbug.com/368525
       # chromium.memory
       'Linux ASan LSan Tests (1)',  # No capacity, https://crbug.com/852442
       'Linux TSan Tests',  # No capacity, https://crbug.com/852442
@@ -1027,6 +1042,19 @@
   },
   'sync_integration_tests': {
     'modifications': {
+      # chromium.clang
+      'ToTLinuxTSan': {
+        'swarming': {
+          'shards': 6,
+        },
+      },
+      # chromium.memory
+      'Linux TSan Tests': {
+        'swarming': {
+          'shards': 6,
+        },
+      },
+      # chromium.win
       'Win7 Tests (dbg)(1)': {
         'swarming': {
           'shards': 2,
@@ -1036,10 +1064,6 @@
         'experiment_percentage': 100, # https://crbug.com/840369
       },
     },
-    'remove_from': [
-      # chromium.memory
-      'Linux TSan Tests',  # https://crbug.com/852002
-    ],
   },
   'tab_capture_end2end_tests': {
     # Run these only on Release bots.
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn
index 81b6fb93..771b3c8 100644
--- a/third_party/blink/public/BUILD.gn
+++ b/third_party/blink/public/BUILD.gn
@@ -167,8 +167,6 @@
     "platform/modules/service_worker/web_service_worker_request.h",
     "platform/modules/service_worker/web_service_worker_response.h",
     "platform/modules/service_worker/web_service_worker_stream_handle.h",
-    "platform/modules/webmidi/web_midi_accessor.h",
-    "platform/modules/webmidi/web_midi_accessor_client.h",
     "platform/platform.h",
     "platform/pointer_properties.h",
     "platform/scheduler/web_rail_mode_observer.h",
@@ -537,7 +535,6 @@
     "//cc:cc",
     "//cc/paint:paint",
     "//components/viz/common",
-    "//media/midi:mojo_shared_cpp_sources",
     "//mojo/public/cpp/bindings:bindings",
     "//mojo/public/cpp/system:system",
     "//services/device/public/mojom:mojom_shared_cpp_sources",
diff --git a/third_party/blink/public/blink_typemaps.gni b/third_party/blink/public/blink_typemaps.gni
index 97e2b6d..283c715 100644
--- a/third_party/blink/public/blink_typemaps.gni
+++ b/third_party/blink/public/blink_typemaps.gni
@@ -6,6 +6,7 @@
   "//gpu/ipc/common/mailbox_holder_for_blink.typemap",
   "//gpu/ipc/common/sync_token.typemap",
   "//mojo/public/cpp/base/file_error.typemap",
+  "//mojo/public/cpp/base/time.typemap",
   "//services/viz/public/cpp/compositing/begin_frame_args_for_blink.typemap",
   "//services/viz/public/cpp/compositing/compositor_frame_for_blink.typemap",
   "//services/viz/public/cpp/compositing/frame_sink_id.typemap",
diff --git a/third_party/blink/public/platform/modules/webmidi/DEPS b/third_party/blink/public/platform/modules/webmidi/DEPS
deleted file mode 100644
index dcd5e5b..0000000
--- a/third_party/blink/public/platform/modules/webmidi/DEPS
+++ /dev/null
@@ -1,6 +0,0 @@
-include_rules = [
-    # TODO(toyoshim): Remove following media/midi direct dependency in public
-    # interface once Web MIDI starts calling the Mojo service inside Blink.
-    # http://crbug.com/582327
-    "+media/midi/midi_service.mojom-shared.h",
-]
diff --git a/third_party/blink/public/platform/modules/webmidi/OWNERS b/third_party/blink/public/platform/modules/webmidi/OWNERS
deleted file mode 100644
index 1a8a48d..0000000
--- a/third_party/blink/public/platform/modules/webmidi/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-kouhei@chromium.org
-toyoshim@chromium.org
-yhirano@chromium.org
-
-# TEAM: midi-dev@chromium.org
-# COMPONENT: Blink>WebMIDI
diff --git a/third_party/blink/public/platform/modules/webmidi/web_midi_accessor.h b/third_party/blink/public/platform/modules/webmidi/web_midi_accessor.h
deleted file mode 100644
index 9707b78a..0000000
--- a/third_party/blink/public/platform/modules/webmidi/web_midi_accessor.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_WEBMIDI_WEB_MIDI_ACCESSOR_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_WEBMIDI_WEB_MIDI_ACCESSOR_H_
-
-#include "base/time/time.h"
-#include "third_party/blink/public/platform/web_string.h"
-
-namespace blink {
-
-class WebMIDIAccessor {
- public:
-  virtual ~WebMIDIAccessor() = default;
-
-  virtual void StartSession() {}
-  virtual void Open(unsigned port_index) {}
-  // |timeStamp| is measured in milliseconds as Web MIDI spec defines.
-  virtual void SendMIDIData(unsigned port_index,
-                            const unsigned char* data,
-                            size_t length,
-                            base::TimeTicks time_stamp) {}
-  virtual void Clear(unsigned port_index) {}
-  virtual void Close(unsigned port_index) {}
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_WEBMIDI_WEB_MIDI_ACCESSOR_H_
diff --git a/third_party/blink/public/platform/modules/webmidi/web_midi_accessor_client.h b/third_party/blink/public/platform/modules/webmidi/web_midi_accessor_client.h
deleted file mode 100644
index 967969f..0000000
--- a/third_party/blink/public/platform/modules/webmidi/web_midi_accessor_client.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_WEBMIDI_WEB_MIDI_ACCESSOR_CLIENT_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_WEBMIDI_WEB_MIDI_ACCESSOR_CLIENT_H_
-
-#include "media/midi/midi_service.mojom-shared.h"
-#include "third_party/blink/public/platform/web_string.h"
-
-namespace blink {
-
-class WebMIDIAccessorClient {
- public:
-  // didAddInputPort() and didAddOutputPort() can be called before and after
-  // didStartSession() is called. But |id| should be unique in each function.
-  virtual void DidAddInputPort(const WebString& id,
-                               const WebString& manufacturer,
-                               const WebString& name,
-                               const WebString& version,
-                               midi::mojom::PortState) = 0;
-  virtual void DidAddOutputPort(const WebString& id,
-                                const WebString& manufacturer,
-                                const WebString& name,
-                                const WebString& version,
-                                midi::mojom::PortState) = 0;
-  // didSetInputPortState() and didSetOutputPortState() should not be called
-  // until didStartSession() is called.
-  virtual void DidSetInputPortState(unsigned port_index,
-                                    midi::mojom::PortState) = 0;
-  virtual void DidSetOutputPortState(unsigned port_index,
-                                     midi::mojom::PortState) = 0;
-
-  virtual void DidStartSession(midi::mojom::Result) = 0;
-
-  // |timeStamp| is in milliseconds according to the Web MIDI API.
-  virtual void DidReceiveMIDIData(unsigned port_index,
-                                  const unsigned char* data,
-                                  size_t length,
-                                  base::TimeTicks time_stamp) = 0;
-
- protected:
-  virtual ~WebMIDIAccessorClient() = default;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_WEBMIDI_WEB_MIDI_ACCESSOR_CLIENT_H_
diff --git a/third_party/blink/public/platform/platform.h b/third_party/blink/public/platform/platform.h
index e3f1a221..adf0713 100644
--- a/third_party/blink/public/platform/platform.h
+++ b/third_party/blink/public/platform/platform.h
@@ -111,8 +111,6 @@
 class WebGraphicsContext3DProvider;
 class WebImageCaptureFrameGrabber;
 class WebLocalFrame;
-class WebMIDIAccessor;
-class WebMIDIAccessorClient;
 class WebMediaCapabilitiesClient;
 class WebMediaPlayer;
 class WebMediaRecorderHandler;
@@ -222,13 +220,6 @@
     return nullptr;
   }
 
-  // MIDI ----------------------------------------------------------------
-
-  // Creates a platform dependent WebMIDIAccessor. MIDIAccessor under platform
-  // creates and owns it.
-  virtual std::unique_ptr<WebMIDIAccessor> CreateMIDIAccessor(
-      WebMIDIAccessorClient*);
-
   // Blob ----------------------------------------------------------------
 
   // Must return non-null.
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 072a710d..69e8a77 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1796,6 +1796,7 @@
     "css/threaded/filter_operation_resolver_threaded_test.cc",
     "css/threaded/font_object_threaded_test.cc",
     "css/threaded/text_renderer_threaded_test.cc",
+    "display_lock/display_lock_budget_test.cc",
     "display_lock/display_lock_context_test.cc",
     "dom/attr_test.cc",
     "dom/document_statistics_collector_test.cc",
diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5
index 9a6fcd2c..8bab7d7d 100644
--- a/third_party/blink/renderer/core/css/css_properties.json5
+++ b/third_party/blink/renderer/core/css/css_properties.json5
@@ -2884,7 +2884,7 @@
       property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal", "ColorIncludingFallback"],
       interpolable: true,
       svg: true,
-      converter: "ConvertColor",
+      converter: "ConvertStyleColor",
       keywords: ["currentcolor"],
       typedom_types: ["Keyword"],
     },
@@ -4476,9 +4476,9 @@
     {
       name: "animation",
       longhands: [
-        "animation-name", "animation-duration", "animation-timing-function",
-        "animation-delay", "animation-iteration-count", "animation-direction",
-        "animation-fill-mode", "animation-play-state"
+        "animation-duration", "animation-timing-function", "animation-delay",
+        "animation-iteration-count", "animation-direction",
+        "animation-fill-mode", "animation-play-state", "animation-name"
       ],
       property_methods: ["ParseShorthand", "CSSValueFromComputedStyleInternal"],
     },
diff --git a/third_party/blink/renderer/core/css/document_style_sheet_collection.cc b/third_party/blink/renderer/core/css/document_style_sheet_collection.cc
index 81d15d5..fcc8b24 100644
--- a/third_party/blink/renderer/core/css/document_style_sheet_collection.cc
+++ b/third_party/blink/renderer/core/css/document_style_sheet_collection.cc
@@ -94,7 +94,8 @@
   for (CSSStyleSheet* sheet : GetTreeScope().AdoptedStyleSheets()) {
     if (!sheet ||
         !sheet->CanBeActivated(
-            GetDocument().GetStyleEngine().PreferredStylesheetSetName()))
+            GetDocument().GetStyleEngine().PreferredStylesheetSetName()) ||
+        sheet->AssociatedDocument() != GetDocument())
       continue;
     collector.AppendSheetForList(sheet);
     collector.AppendActiveStyleSheet(
diff --git a/third_party/blink/renderer/core/css/properties/shorthands/animation_custom.cc b/third_party/blink/renderer/core/css/properties/shorthands/animation_custom.cc
index eb60bd5..4f27aa4 100644
--- a/third_party/blink/renderer/core/css/properties/shorthands/animation_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/shorthands/animation_custom.cc
@@ -92,7 +92,6 @@
     CSSValueList* animations_list = CSSValueList::CreateCommaSeparated();
     for (wtf_size_t i = 0; i < animation_data->NameList().size(); ++i) {
       CSSValueList* list = CSSValueList::CreateSpaceSeparated();
-      list->Append(*CSSCustomIdentValue::Create(animation_data->NameList()[i]));
       list->Append(*CSSPrimitiveValue::Create(
           CSSTimingData::GetRepeated(animation_data->DurationList(), i),
           CSSPrimitiveValue::UnitType::kSeconds));
@@ -110,6 +109,7 @@
           CSSTimingData::GetRepeated(animation_data->FillModeList(), i)));
       list->Append(*ComputedStyleUtils::ValueForAnimationPlayState(
           CSSTimingData::GetRepeated(animation_data->PlayStateList(), i)));
+      list->Append(*CSSCustomIdentValue::Create(animation_data->NameList()[i]));
       animations_list->Append(*list);
     }
     return animations_list;
diff --git a/third_party/blink/renderer/core/css/shadow_tree_style_sheet_collection.cc b/third_party/blink/renderer/core/css/shadow_tree_style_sheet_collection.cc
index ffb4d59..066cfca 100644
--- a/third_party/blink/renderer/core/css/shadow_tree_style_sheet_collection.cc
+++ b/third_party/blink/renderer/core/css/shadow_tree_style_sheet_collection.cc
@@ -66,7 +66,8 @@
     return;
 
   for (CSSStyleSheet* sheet : GetTreeScope().AdoptedStyleSheets()) {
-    if (!sheet || !sheet->CanBeActivated(g_null_atom))
+    if (!sheet || !sheet->CanBeActivated(g_null_atom) ||
+        sheet->AssociatedDocument() != GetTreeScope().GetDocument())
       continue;
     collection.AppendActiveStyleSheet(
         std::make_pair(sheet, master_engine.RuleSetForSheet(*sheet)));
diff --git a/third_party/blink/renderer/core/display_lock/BUILD.gn b/third_party/blink/renderer/core/display_lock/BUILD.gn
index d6cce9b..7a6b0bc 100644
--- a/third_party/blink/renderer/core/display_lock/BUILD.gn
+++ b/third_party/blink/renderer/core/display_lock/BUILD.gn
@@ -6,10 +6,16 @@
 
 blink_core_sources("display_lock") {
   sources = [
+    "display_lock_budget.cc",
+    "display_lock_budget.h",
     "display_lock_context.cc",
     "display_lock_context.h",
     "display_lock_suspended_handle.cc",
     "display_lock_suspended_handle.h",
+    "strict_yielding_display_lock_budget.cc",
+    "strict_yielding_display_lock_budget.h",
+    "unyielding_display_lock_budget.cc",
+    "unyielding_display_lock_budget.h",
   ]
 
   public_deps = [
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_budget.cc b/third_party/blink/renderer/core/display_lock/display_lock_budget.cc
new file mode 100644
index 0000000..3a0ec4d
--- /dev/null
+++ b/third_party/blink/renderer/core/display_lock/display_lock_budget.cc
@@ -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.
+
+#include "third_party/blink/renderer/core/display_lock/display_lock_budget.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_context.h"
+
+namespace blink {
+
+DisplayLockBudget::DisplayLockBudget(DisplayLockContext* context)
+    : context_(context) {}
+
+bool DisplayLockBudget::MarkAncestorsDirtyForPhaseIfNeeded(Phase phase) {
+  switch (phase) {
+    case Phase::kStyle:
+      return context_->MarkAncestorsForStyleRecalcIfNeeded();
+    case Phase::kLayout:
+      return context_->MarkAncestorsForLayoutIfNeeded();
+    case Phase::kPrePaint:
+      return context_->MarkAncestorsForPaintInvalidationCheckIfNeeded();
+    case Phase::kPaint:
+      return context_->MarkPaintLayerNeedsRepaint();
+  }
+  NOTREACHED();
+  return false;
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_budget.h b/third_party/blink/renderer/core/display_lock/display_lock_budget.h
new file mode 100644
index 0000000..edec9b3
--- /dev/null
+++ b/third_party/blink/renderer/core/display_lock/display_lock_budget.h
@@ -0,0 +1,55 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_CORE_DISPLAY_LOCK_DISPLAY_LOCK_BUDGET_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_DISPLAY_LOCK_DISPLAY_LOCK_BUDGET_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/heap/member.h"
+
+namespace blink {
+
+class DisplayLockContext;
+class CORE_EXPORT DisplayLockBudget {
+ public:
+  enum class Phase : unsigned {
+    kStyle,
+    kLayout,
+    kPrePaint,
+    kPaint,
+    kFirst = kStyle,
+    kLast = kPaint
+  };
+
+  DisplayLockBudget(DisplayLockContext*);
+  virtual ~DisplayLockBudget() = default;
+
+  // Returns true if the given phase is allowed to proceed under the current
+  // budget.
+  virtual bool ShouldPerformPhase(Phase) const = 0;
+
+  // Notifies the budget that the given phase was completed.
+  virtual void DidPerformPhase(Phase) = 0;
+
+  // Notifies the budget that a new lifecycle update phase is going to start.
+  virtual void WillStartLifecycleUpdate() = 0;
+
+  // Notifies the budget that a lifecycle update phase finished. This returns
+  // true if another update cycle is needed in order to process more phases.
+  virtual bool DidFinishLifecycleUpdate() = 0;
+
+ protected:
+  // Marks the ancestor chain dirty for the given phase if it's needed. Returns
+  // true if the ancestors were marked dirty and false otherwise.
+  bool MarkAncestorsDirtyForPhaseIfNeeded(Phase);
+
+ private:
+  // This is a backpointer to the context, which should always outlive this
+  // budget, so it's untraced.
+  UntracedMember<DisplayLockContext> context_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_DISPLAY_LOCK_DISPLAY_LOCK_BUDGET_H_
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc b/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc
new file mode 100644
index 0000000..b2032ff4
--- /dev/null
+++ b/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc
@@ -0,0 +1,217 @@
+// 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 "third_party/blink/renderer/core/display_lock/display_lock_budget.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_display_lock_callback.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_context.h"
+#include "third_party/blink/renderer/core/display_lock/strict_yielding_display_lock_budget.h"
+#include "third_party/blink/renderer/core/display_lock/unyielding_display_lock_budget.h"
+#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+
+namespace blink {
+
+class DisplayLockBudgetTest : public RenderingTest {
+  void SetUp() override {
+    RenderingTest::SetUp();
+    features_backup_.emplace();
+    RuntimeEnabledFeatures::SetDisplayLockingEnabled(true);
+  }
+
+  void TearDown() override {
+    if (features_backup_) {
+      features_backup_->Restore();
+      features_backup_.reset();
+    }
+  }
+
+ private:
+  base::Optional<RuntimeEnabledFeatures::Backup> features_backup_;
+};
+
+class BudgetTestEmptyFunction : public ScriptFunction {
+ public:
+  static v8::Local<v8::Function> Create(ScriptState* script_state) {
+    auto* callback =
+        MakeGarbageCollected<BudgetTestEmptyFunction>(script_state);
+    return callback->BindToV8Function();
+  }
+
+  BudgetTestEmptyFunction(ScriptState* script_state)
+      : ScriptFunction(script_state) {}
+
+  ScriptValue Call(ScriptValue value) final { return value; }
+};
+
+TEST_F(DisplayLockBudgetTest, UnyieldingBudget) {
+  WeakPersistent<Element> element =
+      GetDocument().CreateRawElement(html_names::kDivTag);
+  {
+    auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
+    ScriptState::Scope scope(script_state);
+    element->acquireDisplayLock(
+        script_state, V8DisplayLockCallback::Create(
+                          BudgetTestEmptyFunction::Create(script_state)));
+  }
+
+  ASSERT_TRUE(element->GetDisplayLockContext());
+  UnyieldingDisplayLockBudget budget(element->GetDisplayLockContext());
+  // Check everything twice since it shouldn't matter how many times we ask the
+  // unyielding budget, the results should always be the same.
+  for (int i = 0; i < 2; ++i) {
+    budget.WillStartLifecycleUpdate();
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPaint));
+    budget.DidPerformPhase(DisplayLockBudget::Phase::kStyle);
+    budget.DidPerformPhase(DisplayLockBudget::Phase::kLayout);
+    budget.DidPerformPhase(DisplayLockBudget::Phase::kPrePaint);
+    budget.DidPerformPhase(DisplayLockBudget::Phase::kPaint);
+    EXPECT_FALSE(budget.DidFinishLifecycleUpdate());
+  }
+}
+
+TEST_F(DisplayLockBudgetTest, StrictYieldingBudget) {
+  WeakPersistent<Element> element =
+      GetDocument().CreateRawElement(html_names::kDivTag);
+  {
+    auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
+    ScriptState::Scope scope(script_state);
+    element->acquireDisplayLock(
+        script_state, V8DisplayLockCallback::Create(
+                          BudgetTestEmptyFunction::Create(script_state)));
+  }
+
+  ASSERT_TRUE(element->GetDisplayLockContext());
+  StrictYieldingDisplayLockBudget budget(element->GetDisplayLockContext());
+  {
+    budget.WillStartLifecycleUpdate();
+    // Initially all of the phase checks should return true, since we don't know
+    // which phase the system wants to process next.
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPaint));
+
+    // Not doing anything should ensure that we schedule another animation by
+    // returning true here.
+    EXPECT_TRUE(budget.DidFinishLifecycleUpdate());
+  }
+  {
+    budget.WillStartLifecycleUpdate();
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPaint));
+
+    // Once we perform a phase, its check should remain true, but the rest
+    // will be false for this cycle.
+    budget.DidPerformPhase(DisplayLockBudget::Phase::kStyle);
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle));
+    EXPECT_FALSE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout));
+    EXPECT_FALSE(
+        budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint));
+    EXPECT_FALSE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPaint));
+
+    // We would need at least one more run to finish everything.
+    EXPECT_TRUE(budget.DidFinishLifecycleUpdate());
+  }
+  {
+    budget.WillStartLifecycleUpdate();
+    // Run the previous block again, now everything will always return true
+    // since the phase we complete here (style) has already been completed
+    // before, and we are open to complete a new phase.
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPaint));
+
+    // Since we already befored style before, no new phase has been processed
+    // and all phases are allowed to finish.
+    budget.DidPerformPhase(DisplayLockBudget::Phase::kStyle);
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPaint));
+
+    // We would need at least one more run to finish everything.
+    EXPECT_TRUE(budget.DidFinishLifecycleUpdate());
+  }
+  {
+    budget.WillStartLifecycleUpdate();
+    // On the next run, the checks for phases completed before should always
+    // return true, and as before since we haven't completed a new phase, the
+    // remainder of the phases should return true for now.
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPaint));
+
+    // This check is the same as in the previous block, but is here to verify
+    // that going through DidFinishLifecycleUpdate() and then
+    // WillStartLifecycleUpdate() again doesn't change the fact that we should
+    // still perform all of the phases at this point.
+    budget.DidPerformPhase(DisplayLockBudget::Phase::kStyle);
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPaint));
+
+    // Let's say layout was clean and we jumped and did prepaint instead, now
+    // every phase before and including prepaint should be true, the rest are
+    // locked from completing.
+    budget.DidPerformPhase(DisplayLockBudget::Phase::kPrePaint);
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint));
+    EXPECT_FALSE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPaint));
+
+    // We would need at least one more run to finish everything.
+    EXPECT_TRUE(budget.DidFinishLifecycleUpdate());
+  }
+  {
+    budget.WillStartLifecycleUpdate();
+    // On the last run, we'll complete all phases. Since there is only one
+    // remaining phase we haven't done, all of the checks should always return
+    // true (it's either an old phase or a first uncompleted phase).
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPaint));
+
+    budget.DidPerformPhase(DisplayLockBudget::Phase::kStyle);
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPaint));
+
+    budget.DidPerformPhase(DisplayLockBudget::Phase::kLayout);
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPaint));
+
+    budget.DidPerformPhase(DisplayLockBudget::Phase::kPrePaint);
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPaint));
+
+    budget.DidPerformPhase(DisplayLockBudget::Phase::kPaint);
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kStyle));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kLayout));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint));
+    EXPECT_TRUE(budget.ShouldPerformPhase(DisplayLockBudget::Phase::kPaint));
+
+    // Since we completed everything, we should now be returning false here (no
+    // more updates needed).
+    EXPECT_FALSE(budget.DidFinishLifecycleUpdate());
+  }
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.cc b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
index da44159..4d0c542 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
@@ -6,6 +6,8 @@
 
 #include "third_party/blink/renderer/bindings/core/v8/v8_display_lock_callback.h"
 #include "third_party/blink/renderer/core/display_lock/display_lock_suspended_handle.h"
+#include "third_party/blink/renderer/core/display_lock/strict_yielding_display_lock_budget.h"
+#include "third_party/blink/renderer/core/display_lock/unyielding_display_lock_budget.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/dom/node_computed_style.h"
@@ -14,104 +16,29 @@
 #include "third_party/blink/renderer/core/layout/layout_box.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
 #include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/core/paint/paint_layer.h"
 #include "third_party/blink/renderer/platform/bindings/microtask.h"
 
 namespace blink {
 
-// Change this to 1 to enable each function stderr logging.
-// TODO(vmpstr): Remove this after debugging is all done.
-#if 0
-class CORE_EXPORT DisplayLockScopedLogger {
- public:
-  DisplayLockScopedLogger(const char* function,
-                          const DisplayLockContext::State* state,
-                          const DisplayLockContext::LifecycleUpdateState* lifecycle_update_state)
-      : function_(function), state_(state), lifecycle_update_state_(lifecycle_update_state) {
-    for (int i = 0; i < s_indent_; ++i)
-      fprintf(stderr, " ");
-    fprintf(stderr, "entering %s: state %s lifecycle_update_state %s\n",
-            function, StateToString(*state),
-            LifecycleUpdateStateToString(*lifecycle_update_state));
-    ++s_indent_;
-  }
-
-  ~DisplayLockScopedLogger() {
-    --s_indent_;
-    for (int i = 0; i < s_indent_; ++i)
-      fprintf(stderr, " ");
-    fprintf(stderr, "exiting %s: state %s lifecycle_update_state %s\n",
-            function_, StateToString(*state_),
-            LifecycleUpdateStateToString(*lifecycle_update_state_));
-  }
-
- private:
-  const char* StateToString(DisplayLockContext::State state) {
-    switch (state) {
-      case DisplayLockContext::kUninitialized:
-        return "kUninitialized";
-      case DisplayLockContext::kSuspended:
-        return "kSuspended";
-      case DisplayLockContext::kCallbacksPending:
-        return "kCallbacksPending";
-      case DisplayLockContext::kDisconnected:
-        return "kDisconnected";
-      case DisplayLockContext::kCommitting:
-        return "kCommitting";
-      case DisplayLockContext::kResolving:
-        return "kResolving";
-      case DisplayLockContext::kResolved:
-        return "kResolved";
-    }
-    return "<unknown>";
-  };
-
-  const char* LifecycleUpdateStateToString(
-      DisplayLockContext::LifecycleUpdateState state) {
-    switch (state) {
-      case DisplayLockContext::kNeedsStyle:
-        return "kNeedsStyle";
-      case DisplayLockContext::kNeedsLayout:
-        return "kNeedsLayout";
-      case DisplayLockContext::kNeedsPrePaint:
-        return "kNeedsPrePaint";
-      case DisplayLockContext::kNeedsPaint:
-        return "kNeedsPaint";
-      case DisplayLockContext::kDone:
-        return "kDone";
-    }
-    return "<unknown>";
-  }
-
-  const char* function_;
-  const DisplayLockContext::State* state_;
-  const DisplayLockContext::LifecycleUpdateState* lifecycle_update_state_;
-  static int s_indent_;
-};
-
-int DisplayLockScopedLogger::s_indent_ = 0;
-
-#define SCOPED_LOGGER(func) \
-  DisplayLockScopedLogger logger(func, &state_, &lifecycle_update_state_)
-#else
-#define SCOPED_LOGGER(func)
-#endif  // #if 0
+DisplayLockContext::BudgetType DisplayLockContext::s_budget_type_ =
+    DisplayLockContext::BudgetType::kDefault;
 
 DisplayLockContext::DisplayLockContext(Element* element,
                                        ExecutionContext* context)
     : ContextLifecycleObserver(context),
       element_(element),
       weak_element_handle_(element) {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
+  DCHECK(element_->GetDocument().View());
+  element_->GetDocument().View()->RegisterForLifecycleNotifications(this);
 }
 
 DisplayLockContext::~DisplayLockContext() {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   DCHECK(state_ == kResolved || state_ == kSuspended) << state_;
   DCHECK(callbacks_.IsEmpty());
 }
 
 void DisplayLockContext::Trace(blink::Visitor* visitor) {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   visitor->Trace(callbacks_);
   visitor->Trace(resolver_);
   visitor->Trace(element_);
@@ -122,7 +49,6 @@
 }
 
 void DisplayLockContext::Dispose() {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   // Note that if we have a resolver_ at dispose time, then it's too late to
   // reject the promise, since we are not allowed to create new strong
   // references to objects already set for destruction (and rejecting would do
@@ -135,22 +61,21 @@
     state_ = kResolved;
   }
   RejectAndCleanUp();
+  if (element_ && element_->GetDocument().View())
+    element_->GetDocument().View()->UnregisterFromLifecycleNotifications(this);
 }
 
 void DisplayLockContext::ContextDestroyed(ExecutionContext*) {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   RejectAndCleanUp();
 }
 
 bool DisplayLockContext::HasPendingActivity() const {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   // If we haven't resolved it, we should stick around.
   // Note that if the element we're locking is gone, then we can also be GCed.
   return !IsResolved() && weak_element_handle_;
 }
 
 void DisplayLockContext::ScheduleCallback(V8DisplayLockCallback* callback) {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   callbacks_.push_back(callback);
 
   // Suspended state supercedes any new lock requests.
@@ -163,23 +88,21 @@
 
 void DisplayLockContext::RequestLock(V8DisplayLockCallback* callback,
                                      ScriptState* script_state) {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   if (!resolver_) {
     DCHECK(script_state);
     resolver_ = ScriptPromiseResolver::Create(script_state);
+    budget_.reset();
   }
   ScheduleCallback(callback);
 }
 
 void DisplayLockContext::schedule(V8DisplayLockCallback* callback) {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   DCHECK(state_ == kSuspended || state_ == kCallbacksPending);
 
   ScheduleCallback(callback);
 }
 
 DisplayLockSuspendedHandle* DisplayLockContext::suspend() {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   ++suspended_count_;
   state_ = kSuspended;
   return MakeGarbageCollected<DisplayLockSuspendedHandle>(this);
@@ -190,7 +113,6 @@
 }
 
 void DisplayLockContext::ProcessQueue() {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   // It's important to clear this before running the tasks, since the tasks can
   // call ScheduleCallback() which will re-schedule a PostTask() for us to
   // continue the work.
@@ -253,27 +175,27 @@
 }
 
 void DisplayLockContext::RejectAndCleanUp() {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   if (resolver_) {
     state_ = kResolved;
     resolver_->Reject();
     resolver_ = nullptr;
+    budget_.reset();
   }
   callbacks_.clear();
   locked_frame_rect_.reset();
 
   // We may have a dirty subtree and have not propagated the dirty bit up the
   // ancestor tree. Since we're now rejecting the promise and unlocking the
-  // element, ensure that we can reach both style and layout subtrees if they
-  // are dirty by propagating the bit.
+  // element, ensure that we can reach the element in all of the phases.
   if (weak_element_handle_) {
     MarkAncestorsForStyleRecalcIfNeeded();
     MarkAncestorsForLayoutIfNeeded();
+    MarkAncestorsForPaintInvalidationCheckIfNeeded();
+    MarkPaintLayerNeedsRepaint();
   }
 }
 
 void DisplayLockContext::Resume() {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   DCHECK_GT(suspended_count_, 0u);
   DCHECK_EQ(state_, kSuspended);
   if (--suspended_count_ == 0) {
@@ -293,7 +215,6 @@
 }
 
 void DisplayLockContext::NotifyWillNotResume() {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   DCHECK_GT(suspended_count_, 0u);
   // The promise will never reject or resolve since we're now indefinitely
   // suspended.
@@ -306,7 +227,6 @@
 }
 
 void DisplayLockContext::ScheduleTaskIfNeeded() {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   if (state_ != kCallbacksPending || process_queue_task_scheduled_)
     return;
 
@@ -320,7 +240,6 @@
 }
 
 void DisplayLockContext::NotifyConnectedMayHaveChanged() {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   if (GetElement()->isConnected()) {
     if (state_ == kDisconnected)
       StartCommit();
@@ -337,12 +256,12 @@
 }
 
 bool DisplayLockContext::ShouldStyle() const {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
-  return update_forced_ || state_ >= kCommitting;
+  return update_forced_ || state_ > kCommitting ||
+         (state_ == kCommitting &&
+          budget_->ShouldPerformPhase(DisplayLockBudget::Phase::kStyle));
 }
 
 void DisplayLockContext::DidStyle() {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   if (state_ != kCommitting && !update_forced_)
     return;
 
@@ -360,72 +279,59 @@
   if (state_ != kCommitting)
     return;
 
-  if (lifecycle_update_state_ <= kNeedsStyle) {
-    // Normally we need to do layout next, but if it's not dirty then we can
-    // skip ahead to pre-paint.
-    if (MarkAncestorsForLayoutIfNeeded())
-      lifecycle_update_state_ = kNeedsLayout;
-    else
-      lifecycle_update_state_ = kNeedsPrePaint;
-  }
+  budget_->DidPerformPhase(DisplayLockBudget::Phase::kStyle);
 }
 
 bool DisplayLockContext::ShouldLayout() const {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
-  return update_forced_ ||
-         std::tie(state_, lifecycle_update_state_) >=
-             std::tuple<State, LifecycleUpdateState>{kCommitting, kNeedsLayout};
+  return update_forced_ || state_ > kCommitting ||
+         (state_ == kCommitting &&
+          budget_->ShouldPerformPhase(DisplayLockBudget::Phase::kLayout));
 }
 
 void DisplayLockContext::DidLayout() {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   if (state_ != kCommitting)
     return;
 
-  if (lifecycle_update_state_ <= kNeedsLayout)
-    lifecycle_update_state_ = kNeedsPrePaint;
+  budget_->DidPerformPhase(DisplayLockBudget::Phase::kLayout);
 }
 
 bool DisplayLockContext::ShouldPrePaint() const {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
-  return update_forced_ || std::tie(state_, lifecycle_update_state_) >=
-                               std::tuple<State, LifecycleUpdateState>{
-                                   kCommitting, kNeedsPrePaint};
+  return update_forced_ || state_ > kCommitting ||
+         (state_ == kCommitting &&
+          budget_->ShouldPerformPhase(DisplayLockBudget::Phase::kPrePaint));
 }
 
 void DisplayLockContext::DidPrePaint() {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   if (state_ != kCommitting)
     return;
 
+  budget_->DidPerformPhase(DisplayLockBudget::Phase::kPrePaint);
+
   // Since we should be under containment, we should have a layer. If we don't,
   // then paint might not happen and we'll never resolve.
   DCHECK(GetElement()->GetLayoutObject()->HasLayer());
-  if (lifecycle_update_state_ <= kNeedsPrePaint)
-    lifecycle_update_state_ = kNeedsPaint;
 }
 
 bool DisplayLockContext::ShouldPaint() const {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   // Note that forced updates should never require us to paint, so we don't
   // check |update_forced_| here. In other words, although |update_forced_|
   // could be true here, we still should not paint.
-  return std::tie(state_, lifecycle_update_state_) >=
-         std::tuple<State, LifecycleUpdateState>{kCommitting, kNeedsPaint};
+  return state_ > kCommitting ||
+         (state_ == kCommitting &&
+          budget_->ShouldPerformPhase(DisplayLockBudget::Phase::kPaint));
 }
 
 void DisplayLockContext::DidPaint() {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   if (state_ != kCommitting)
     return;
 
-  if (lifecycle_update_state_ <= kNeedsPaint)
-    lifecycle_update_state_ = kDone;
+  budget_->DidPerformPhase(DisplayLockBudget::Phase::kPaint);
 
   DCHECK(resolver_);
   state_ = kResolving;
   resolver_->Resolve();
   resolver_ = nullptr;
+  budget_.reset();
 
   // After the above resolution callback runs (in a microtask), we should
   // finish resolving if the lock was not re-acquired.
@@ -434,7 +340,6 @@
 }
 
 void DisplayLockContext::DidAttachLayoutTree() {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
 
   // Note that although we checked at style recalc time that the element has
   // "contain: content", it might not actually apply the containment (e.g. see
@@ -447,7 +352,6 @@
 
 DisplayLockContext::ScopedPendingFrameRect
 DisplayLockContext::GetScopedPendingFrameRect() {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   if (IsResolved())
     return ScopedPendingFrameRect(nullptr);
   DCHECK(GetElement()->GetLayoutObject() && GetElement()->GetLayoutBox());
@@ -456,7 +360,6 @@
 }
 
 void DisplayLockContext::NotifyPendingFrameRectScopeEnded() {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   DCHECK(GetElement()->GetLayoutObject() && GetElement()->GetLayoutBox());
   DCHECK(locked_frame_rect_);
   pending_frame_rect_ = GetElement()->GetLayoutBox()->FrameRect();
@@ -465,26 +368,29 @@
 
 DisplayLockContext::ScopedForcedUpdate
 DisplayLockContext::GetScopedForcedUpdate() {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   DCHECK(!update_forced_);
   update_forced_ = true;
-  // Now that the update is forced, we should ensure that style and layout code
-  // can reach it via dirty bits.
+  // Now that the update is forced, we should ensure that style layout, and
+  // prepaint code can reach it via dirty bits. Note that paint isn't a part of
+  // this, since |update_forced_| doesn't force paint to happen. See
+  // ShouldPaint().
   MarkAncestorsForStyleRecalcIfNeeded();
   MarkAncestorsForLayoutIfNeeded();
+  MarkAncestorsForPaintInvalidationCheckIfNeeded();
   return ScopedForcedUpdate(this);
 }
 
 void DisplayLockContext::NotifyForcedUpdateScopeEnded() {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   DCHECK(update_forced_);
   update_forced_ = false;
 }
 
 void DisplayLockContext::FinishResolution() {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
-  if (state_ == kResolving)
-    state_ = kResolved;
+  // If we're not resolving, then something in the promise resolution prevented
+  // us from proceeding (we could have been suspended or relocked).
+  if (state_ != kResolving)
+    return;
+  state_ = kResolved;
   locked_frame_rect_.reset();
 
   // Update the pending frame rect if we still have a layout object.
@@ -512,27 +418,13 @@
   ToLayoutBox(layout_object)->SetFrameRect(pending_frame_rect_);
   layout_object->SetNeedsLayout(
       layout_invalidation_reason::kDisplayLockCommitting);
-  // Schedule an animation to perform the lifecycle phases.
-  GetElement()->GetDocument().GetPage()->Animator().ScheduleVisualUpdate(
-      GetElement()->GetDocument().GetFrame());
+  ScheduleAnimation();
 }
 
 void DisplayLockContext::StartCommit() {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   state_ = kCommitting;
-  lifecycle_update_state_ = kNeedsStyle;
-
-  if (!MarkAncestorsForStyleRecalcIfNeeded())
-    DidStyle();
-
-  // The above DidStyle() may reject the promise since it checks that we have
-  // containment before proceeding.
-  if (state_ != kCommitting)
-    return;
-
-  // Schedule an animation to perform the lifecycle phases.
-  GetElement()->GetDocument().GetPage()->Animator().ScheduleVisualUpdate(
-      GetElement()->GetDocument().GetFrame());
+  ResetNewBudget();
+  ScheduleAnimation();
 }
 
 bool DisplayLockContext::MarkAncestorsForStyleRecalcIfNeeded() {
@@ -554,14 +446,83 @@
   return false;
 }
 
+bool DisplayLockContext::MarkAncestorsForPaintInvalidationCheckIfNeeded() {
+  if (auto* layout_object = GetElement()->GetLayoutObject()) {
+    if (layout_object->Parent() &&
+        (layout_object->ShouldCheckForPaintInvalidation() ||
+         layout_object->SubtreeShouldCheckForPaintInvalidation())) {
+      layout_object->Parent()->SetSubtreeShouldCheckForPaintInvalidation();
+      return true;
+    }
+  }
+  return false;
+}
+
+bool DisplayLockContext::MarkPaintLayerNeedsRepaint() {
+  if (auto* layout_object = GetElement()->GetLayoutObject()) {
+    layout_object->PaintingLayer()->SetNeedsRepaint();
+    return true;
+  }
+  return false;
+}
+
 void DisplayLockContext::MarkAsDisconnected() {
-  SCOPED_LOGGER(__PRETTY_FUNCTION__);
   state_ = kDisconnected;
   // Let go of the strong reference to the element, allowing it to be GCed. See
   // the comment on |element_| in the header.
   element_ = nullptr;
 }
 
+void DisplayLockContext::ResetNewBudget() {
+  switch (s_budget_type_) {
+    case BudgetType::kDoNotYield:
+      budget_.reset(new UnyieldingDisplayLockBudget(this));
+      return;
+    case BudgetType::kStrictYieldBetweenLifecyclePhases:
+      budget_.reset(new StrictYieldingDisplayLockBudget(this));
+      return;
+    case BudgetType::kYieldBetweenLifecyclePhases:
+      NOTIMPLEMENTED();
+      return;
+  }
+  NOTREACHED();
+}
+
+void DisplayLockContext::DidMoveToNewDocument(Document& old_document) {
+  if (old_document.View())
+    old_document.View()->UnregisterFromLifecycleNotifications(this);
+  if (element_ && element_->GetDocument().View())
+    element_->GetDocument().View()->RegisterForLifecycleNotifications(this);
+}
+
+void DisplayLockContext::WillStartLifecycleUpdate() {
+  if (state_ != kCommitting)
+    return;
+  budget_->WillStartLifecycleUpdate();
+}
+
+void DisplayLockContext::DidFinishLifecycleUpdate() {
+  if (state_ != kCommitting)
+    return;
+  bool needs_animation = budget_->DidFinishLifecycleUpdate();
+  if (needs_animation) {
+    // Note that we post a task to schedule an animation, since rAF requests can
+    // be ignored if they happen from within a lifecycle update.
+    GetExecutionContext()
+        ->GetTaskRunner(TaskType::kMiscPlatformAPI)
+        ->PostTask(FROM_HERE, WTF::Bind(&DisplayLockContext::ScheduleAnimation,
+                                        WrapWeakPersistent(this)));
+  }
+}
+
+void DisplayLockContext::ScheduleAnimation() {
+  // Schedule an animation to perform the lifecycle phases.
+  GetElement()->GetDocument().GetPage()->Animator().ScheduleVisualUpdate(
+      GetElement()->GetDocument().GetFrame());
+}
+
+// Scoped objects implementation -----------------------------------------------
+
 DisplayLockContext::ScopedPendingFrameRect::ScopedPendingFrameRect(
     DisplayLockContext* context)
     : context_(context) {}
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.h b/third_party/blink/renderer/core/display_lock/display_lock_context.h
index d1fcb9dc..55511fd4 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context.h
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context.h
@@ -8,6 +8,8 @@
 #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_budget.h"
+#include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/wtf/compiler.h"
 
@@ -20,14 +22,34 @@
 class CORE_EXPORT DisplayLockContext final
     : public ScriptWrappable,
       public ActiveScriptWrappable<DisplayLockContext>,
-      public ContextLifecycleObserver {
+      public ContextLifecycleObserver,
+      public LocalFrameView::LifecycleNotificationObserver {
   DEFINE_WRAPPERTYPEINFO();
   USING_GARBAGE_COLLECTED_MIXIN(DisplayLockContext);
   USING_PRE_FINALIZER(DisplayLockContext, Dispose);
 
  public:
-  // Conceptually the states are private, but made public for debugging /
-  // logging.
+  // Determines what type of budget to use. This can be overridden via
+  // DisplayLockContext::SetBudgetType().
+  // - kDoNotYield:
+  //     This will effectively do all of the lifecycle phases when we're
+  //     committing. That is, this is the "no budget" option.
+  // - kStrictYieldBetweenLifecyclePhases:
+  //     This type always yields between each lifecycle phase, even if that
+  //     phase was quick.
+  // - kYieldBetweenLifecyclePhases:
+  //     This type will only yield between lifecycle phases (not in the middle
+  //     of one). However, if there is sufficient time left (TODO(vmpstr):
+  //     define this), then it will continue on to the next lifecycle phase.
+  enum class BudgetType {
+    kDoNotYield,
+    kStrictYieldBetweenLifecyclePhases,
+    kYieldBetweenLifecyclePhases,
+    kDefault = kStrictYieldBetweenLifecyclePhases
+  };
+
+  // Conceptually the states are private, but made public for testing.
+  // TODO(vmpstr): Make this private and update the tests.
   enum State {
     kUninitialized,
     kSuspended,
@@ -38,14 +60,7 @@
     kResolved
   };
 
-  enum LifecycleUpdateState {
-    kNeedsStyle,
-    kNeedsLayout,
-    kNeedsPrePaint,
-    kNeedsPaint,
-    kDone
-  };
-
+  // See GetScopedPendingFrameRect() for description.
   class ScopedPendingFrameRect {
    public:
     ScopedPendingFrameRect(ScopedPendingFrameRect&&);
@@ -59,6 +74,7 @@
     UntracedMember<DisplayLockContext> context_ = nullptr;
   };
 
+  // See GetScopedForcedUpdate() for description.
   class ScopedForcedUpdate {
    public:
     ScopedForcedUpdate(ScopedForcedUpdate&&);
@@ -142,9 +158,31 @@
   // time.
   ScopedForcedUpdate GetScopedForcedUpdate();
 
+  // This is called when the element with which this context is associated is
+  // moved to a new document.
+  void DidMoveToNewDocument(Document& old_document);
+
+  // LifecycleNotificationObserver overrides.
+  void WillStartLifecycleUpdate() override;
+  void DidFinishLifecycleUpdate() override;
+
  private:
   friend class DisplayLockContextTest;
   friend class DisplayLockSuspendedHandle;
+  friend class DisplayLockBudget;
+
+  // Sets a new budget type. Note that since this is static, all of the existing
+  // locks will be affected as well (unless they already have a budget). This is
+  // meant to be used to set the budget type once (such as in a test), but
+  // technically could be used outside of tests as well to force a certain
+  // budget type. Use with caution. Note that if a budget already exists on the
+  // lock, then it will continue to use the existing budget until a new budget
+  // is requested.
+  static void SetBudgetType(BudgetType type) {
+    if (s_budget_type_ == type)
+      return;
+    s_budget_type_ = type;
+  }
 
   // Schedules a new callback. If this is the first callback to be scheduled,
   // then a valid ScriptState must be provided, which will be used to create a
@@ -181,6 +219,8 @@
   // its subtree were dirty, and false otherwise.
   bool MarkAncestorsForStyleRecalcIfNeeded();
   bool MarkAncestorsForLayoutIfNeeded();
+  bool MarkAncestorsForPaintInvalidationCheckIfNeeded();
+  bool MarkPaintLayerNeedsRepaint();
 
   // Marks the display lock as being disconnected. Note that this removes the
   // strong reference to the element in case the element is deleted. Once we're
@@ -202,6 +242,17 @@
   // GetScopedForcedUpdate() for more information.
   void NotifyForcedUpdateScopeEnded();
 
+  // This resets the existing budget (if any) and establishes a new budget
+  // starting "now".
+  void ResetNewBudget();
+
+  // Helper to schedule an animation to delay lifecycle updates for the next
+  // frame.
+  void ScheduleAnimation();
+
+  static BudgetType s_budget_type_;
+  std::unique_ptr<DisplayLockBudget> budget_;
+
   HeapVector<Member<V8DisplayLockCallback>> callbacks_;
   Member<ScriptPromiseResolver> resolver_;
 
@@ -232,7 +283,6 @@
 
   unsigned suspended_count_ = 0;
   State state_ = kUninitialized;
-  LifecycleUpdateState lifecycle_update_state_ = kNeedsStyle;
   LayoutRect pending_frame_rect_;
   base::Optional<LayoutRect> locked_frame_rect_;
 
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc b/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc
index ae458dbe..be55e698 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc
@@ -44,14 +44,16 @@
   base::Optional<RuntimeEnabledFeatures::Backup> features_backup_;
 };
 
-class EmptyFunction : public ScriptFunction {
+class ContextTestEmptyFunction : public ScriptFunction {
  public:
   static v8::Local<v8::Function> Create(ScriptState* script_state) {
-    auto* callback = MakeGarbageCollected<EmptyFunction>(script_state);
+    auto* callback =
+        MakeGarbageCollected<ContextTestEmptyFunction>(script_state);
     return callback->BindToV8Function();
   }
 
-  EmptyFunction(ScriptState* script_state) : ScriptFunction(script_state) {}
+  ContextTestEmptyFunction(ScriptState* script_state)
+      : ScriptFunction(script_state) {}
 
   ScriptValue Call(ScriptValue value) final { return value; }
 };
@@ -67,8 +69,8 @@
     auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
     ScriptState::Scope scope(script_state);
     script_promise = element->acquireDisplayLock(
-        script_state,
-        V8DisplayLockCallback::Create(EmptyFunction::Create(script_state)));
+        script_state, V8DisplayLockCallback::Create(
+                          ContextTestEmptyFunction::Create(script_state)));
   }
   WeakPersistent<DisplayLockContext> context = element->GetDisplayLockContext();
   ASSERT_TRUE(context);
diff --git a/third_party/blink/renderer/core/display_lock/strict_yielding_display_lock_budget.cc b/third_party/blink/renderer/core/display_lock/strict_yielding_display_lock_budget.cc
new file mode 100644
index 0000000..2485aba6
--- /dev/null
+++ b/third_party/blink/renderer/core/display_lock/strict_yielding_display_lock_budget.cc
@@ -0,0 +1,65 @@
+// 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 "third_party/blink/renderer/core/display_lock/strict_yielding_display_lock_budget.h"
+
+#include <algorithm>
+
+namespace blink {
+
+StrictYieldingDisplayLockBudget::StrictYieldingDisplayLockBudget(
+    DisplayLockContext* context)
+    : DisplayLockBudget(context) {}
+
+bool StrictYieldingDisplayLockBudget::ShouldPerformPhase(Phase phase) const {
+  // We should perform any phase earlier than the one we already completed.
+  // Also, we should complete a new phase once per cycle.
+  return (last_completed_phase_ && phase <= *last_completed_phase_) ||
+         !completed_new_phase_this_cycle_;
+}
+
+void StrictYieldingDisplayLockBudget::DidPerformPhase(Phase phase) {
+  if (!completed_new_phase_this_cycle_ &&
+      (!last_completed_phase_ || phase > *last_completed_phase_)) {
+    last_completed_phase_ = phase;
+    completed_new_phase_this_cycle_ = true;
+  }
+
+#if DCHECK_IS_ON()
+  // If we completed a new phase this cycle, then we should not complete any
+  // later phases in the same cycle.
+  if (completed_new_phase_this_cycle_) {
+    DCHECK(last_completed_phase_);
+    DCHECK(phase <= *last_completed_phase_);
+  }
+#endif
+}
+
+void StrictYieldingDisplayLockBudget::WillStartLifecycleUpdate() {
+  // Figure out the next phase we would run. If we had completed a phase before,
+  // then we should try to complete the next one, otherwise we'll start with the
+  // first phase.
+  Phase next_phase =
+      last_completed_phase_
+          ? static_cast<Phase>(
+                std::min(static_cast<unsigned>(*last_completed_phase_) + 1,
+                         static_cast<unsigned>(Phase::kLast)))
+          : Phase::kFirst;
+
+  // Mark the next phase we're scheduled to run.
+  for (auto phase = static_cast<unsigned>(next_phase);
+       phase <= static_cast<unsigned>(Phase::kLast); ++phase) {
+    if (MarkAncestorsDirtyForPhaseIfNeeded(static_cast<Phase>(phase)))
+      break;
+  }
+
+  completed_new_phase_this_cycle_ = false;
+}
+
+bool StrictYieldingDisplayLockBudget::DidFinishLifecycleUpdate() {
+  return !completed_new_phase_this_cycle_ || !last_completed_phase_ ||
+         *last_completed_phase_ != Phase::kLast;
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/display_lock/strict_yielding_display_lock_budget.h b/third_party/blink/renderer/core/display_lock/strict_yielding_display_lock_budget.h
new file mode 100644
index 0000000..1824e63
--- /dev/null
+++ b/third_party/blink/renderer/core/display_lock/strict_yielding_display_lock_budget.h
@@ -0,0 +1,36 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_CORE_DISPLAY_LOCK_STRICT_YIELDING_DISPLAY_LOCK_BUDGET_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_DISPLAY_LOCK_STRICT_YIELDING_DISPLAY_LOCK_BUDGET_H_
+
+#include "base/optional.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_budget.h"
+
+namespace blink {
+
+// This budget yields between lifecycle phases even if that phase is quick. In
+// other words, it will only do one new lifecycle phase at a time, and block the
+// future ones. Any lifecycle phases that have already been allowed by this
+// budget in the past are not blocked.
+class CORE_EXPORT StrictYieldingDisplayLockBudget final
+    : public DisplayLockBudget {
+ public:
+  StrictYieldingDisplayLockBudget(DisplayLockContext*);
+  ~StrictYieldingDisplayLockBudget() override = default;
+
+  bool ShouldPerformPhase(Phase) const override;
+  void DidPerformPhase(Phase) override;
+  void WillStartLifecycleUpdate() override;
+  bool DidFinishLifecycleUpdate() override;
+
+ protected:
+  base::Optional<Phase> last_completed_phase_;
+  bool completed_new_phase_this_cycle_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_DISPLAY_LOCK_STRICT_YIELDING_DISPLAY_LOCK_BUDGET_H_
diff --git a/third_party/blink/renderer/core/display_lock/unyielding_display_lock_budget.cc b/third_party/blink/renderer/core/display_lock/unyielding_display_lock_budget.cc
new file mode 100644
index 0000000..6e0c4d3
--- /dev/null
+++ b/third_party/blink/renderer/core/display_lock/unyielding_display_lock_budget.cc
@@ -0,0 +1,31 @@
+// 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 "third_party/blink/renderer/core/display_lock/unyielding_display_lock_budget.h"
+
+namespace blink {
+
+UnyieldingDisplayLockBudget::UnyieldingDisplayLockBudget(
+    DisplayLockContext* context)
+    : DisplayLockBudget(context) {}
+
+bool UnyieldingDisplayLockBudget::ShouldPerformPhase(Phase) const {
+  return true;
+}
+
+void UnyieldingDisplayLockBudget::DidPerformPhase(Phase) {}
+
+void UnyieldingDisplayLockBudget::WillStartLifecycleUpdate() {
+  // Mark all the phases dirty since we have no intention of yielding.
+  for (auto phase = static_cast<unsigned>(Phase::kFirst);
+       phase <= static_cast<unsigned>(Phase::kLast); ++phase) {
+    MarkAncestorsDirtyForPhaseIfNeeded(static_cast<Phase>(phase));
+  }
+}
+
+bool UnyieldingDisplayLockBudget::DidFinishLifecycleUpdate() {
+  return false;
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/display_lock/unyielding_display_lock_budget.h b/third_party/blink/renderer/core/display_lock/unyielding_display_lock_budget.h
new file mode 100644
index 0000000..9c60602
--- /dev/null
+++ b/third_party/blink/renderer/core/display_lock/unyielding_display_lock_budget.h
@@ -0,0 +1,29 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_CORE_DISPLAY_LOCK_UNYIELDING_DISPLAY_LOCK_BUDGET_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_DISPLAY_LOCK_UNYIELDING_DISPLAY_LOCK_BUDGET_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_budget.h"
+
+namespace blink {
+
+// This budget never yields. That is, this is essentially infinite budget that
+// will finish all of the lifecycle phases for the locked subtree if given the
+// chance.
+class CORE_EXPORT UnyieldingDisplayLockBudget final : public DisplayLockBudget {
+ public:
+  UnyieldingDisplayLockBudget(DisplayLockContext*);
+  ~UnyieldingDisplayLockBudget() override = default;
+
+  bool ShouldPerformPhase(Phase) const override;
+  void DidPerformPhase(Phase) override;
+  void WillStartLifecycleUpdate() override;
+  bool DidFinishLifecycleUpdate() override;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_DISPLAY_LOCK_UNYIELDING_DISPLAY_LOCK_BUDGET_H_
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index d6005c1..dd22788d 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -4571,6 +4571,9 @@
 
   if (NeedsURLResolutionForInlineStyle(*this, old_document, GetDocument()))
     ReResolveURLsInInlineStyle(GetDocument(), EnsureMutableInlineStyle());
+
+  if (auto* context = GetDisplayLockContext())
+    context->DidMoveToNewDocument(old_document);
 }
 
 void Element::UpdateNamedItemRegistration(NamedItemType type,
diff --git a/third_party/blink/renderer/core/editing/BUILD.gn b/third_party/blink/renderer/core/editing/BUILD.gn
index 878a314..faa763c 100644
--- a/third_party/blink/renderer/core/editing/BUILD.gn
+++ b/third_party/blink/renderer/core/editing/BUILD.gn
@@ -130,6 +130,8 @@
     "element_inner_text.cc",
     "ephemeral_range.cc",
     "ephemeral_range.h",
+    "finder/find_buffer.cc",
+    "finder/find_buffer.h",
     "finder/find_in_page_coordinates.cc",
     "finder/find_in_page_coordinates.h",
     "finder/find_task_controller.cc",
@@ -361,6 +363,7 @@
     "editor_test.cc",
     "element_inner_text_test.cc",
     "ephemeral_range_test.cc",
+    "finder/find_buffer_test.cc",
     "frame_caret_test.cc",
     "frame_selection_test.cc",
     "granularity_strategy_test.cc",
diff --git a/third_party/blink/renderer/core/editing/finder/find_buffer.cc b/third_party/blink/renderer/core/editing/finder/find_buffer.cc
new file mode 100644
index 0000000..e7d5433
--- /dev/null
+++ b/third_party/blink/renderer/core/editing/finder/find_buffer.cc
@@ -0,0 +1,316 @@
+// 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 "third_party/blink/renderer/core/editing/finder/find_buffer.h"
+
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/dom/range.h"
+#include "third_party/blink/renderer/core/dom/text.h"
+#include "third_party/blink/renderer/core/editing/editing_utilities.h"
+#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
+#include "third_party/blink/renderer/core/editing/iterators/text_searcher_icu.h"
+#include "third_party/blink/renderer/core/html/forms/html_form_control_element.h"
+#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
+#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/style/computed_style.h"
+#include "third_party/blink/renderer/platform/text/unicode_utilities.h"
+#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
+#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+
+namespace blink {
+
+FindBuffer::FindBuffer(const PositionInFlatTree& start_position) {
+  DCHECK(start_position.ComputeContainerNode());
+  DCHECK(start_position == PositionInFlatTree::FirstPositionInNode(
+                               *start_position.ComputeContainerNode()));
+  CollectTextUntilBlockBoundary(*start_position.ComputeContainerNode());
+}
+
+FindBuffer::Results::Results() {
+  empty_result_ = true;
+}
+
+FindBuffer::Results::Results(const Vector<UChar>& buffer,
+                             String search_text,
+                             const mojom::blink::FindOptions& options) {
+  // We need to own the |search_text| because |text_searcher_| only has a
+  // StringView (doesn't own the search text).
+  search_text_ = search_text;
+  text_searcher_.SetPattern(search_text_, options.match_case);
+  text_searcher_.SetText(buffer.data(), buffer.size());
+  text_searcher_.SetOffset(0);
+}
+
+FindBuffer::Results::Iterator::Iterator(TextSearcherICU* text_searcher)
+    : text_searcher_(text_searcher), has_match_(true) {
+  operator++();
+}
+
+const FindBuffer::BufferMatchResult FindBuffer::Results::Iterator::operator*()
+    const {
+  DCHECK(has_match_);
+  return FindBuffer::BufferMatchResult({match_.start, match_.length});
+}
+
+void FindBuffer::Results::Iterator::operator++() {
+  DCHECK(has_match_);
+  has_match_ = text_searcher_->NextMatchResult(match_);
+}
+
+FindBuffer::Results::Iterator FindBuffer::Results::begin() {
+  if (empty_result_)
+    return end();
+  text_searcher_.SetOffset(0);
+  return Iterator(&text_searcher_);
+}
+
+FindBuffer::Results::Iterator FindBuffer::Results::end() const {
+  return Iterator();
+}
+
+unsigned FindBuffer::Results::CountForTesting() {
+  unsigned result = 0;
+  for (Iterator it = begin(); it != end(); ++it) {
+    ++result;
+  }
+  return result;
+}
+
+bool ShouldIgnoreContents(const Node& node) {
+  if (!node.IsHTMLElement())
+    return false;
+  const HTMLElement& element = ToHTMLElement(node);
+  return (!element.ShouldSerializeEndTag() && !IsHTMLInputElement(element)) ||
+         IsHTMLIFrameElement(element) || IsHTMLImageElement(element) ||
+         IsHTMLLegendElement(element) || IsHTMLMeterElement(element) ||
+         IsHTMLObjectElement(element) || IsHTMLProgressElement(element) ||
+         IsHTMLSelectElement(element) || IsHTMLStyleElement(element) ||
+         IsHTMLScriptElement(element) || IsHTMLVideoElement(element) ||
+         IsHTMLAudioElement(element);
+}
+
+Node* GetDisplayNoneAncestor(const Node& node) {
+  for (Node& ancestor : FlatTreeTraversal::InclusiveAncestorsOf(node)) {
+    const ComputedStyle* style = ancestor.EnsureComputedStyle();
+    if (style && style->Display() == EDisplay::kNone)
+      return &ancestor;
+    if (ancestor.IsDocumentNode())
+      return nullptr;
+  }
+  return nullptr;
+}
+
+bool IsBlock(EDisplay display) {
+  return display == EDisplay::kBlock || display == EDisplay::kTable ||
+         display == EDisplay::kFlowRoot || display == EDisplay::kGrid ||
+         display == EDisplay::kFlex || display == EDisplay::kListItem;
+}
+
+Node* GetVisibleTextNode(Node& start_node) {
+  Node* node = &start_node;
+  // Move to outside display none subtree if we're inside one.
+  while (Node* ancestor = GetDisplayNoneAncestor(*node)) {
+    if (ancestor->IsDocumentNode())
+      return nullptr;
+    node = FlatTreeTraversal::NextSkippingChildren(*ancestor);
+    if (!node)
+      return nullptr;
+  }
+  // Move to first text node that's visible.
+  while (node) {
+    const ComputedStyle* style = node->EnsureComputedStyle();
+    if (ShouldIgnoreContents(*node) ||
+        (style && style->Display() == EDisplay::kNone)) {
+      // This element and its descendants are not visible, skip it.
+      node = FlatTreeTraversal::NextSkippingChildren(*node);
+      continue;
+    }
+    if (style && style->Visibility() == EVisibility::kVisible &&
+        node->IsTextNode()) {
+      return node;
+    }
+    // This element is hidden, but node might be visible,
+    // or this is not a text node, so we move on.
+    node = FlatTreeTraversal::Next(*node);
+  }
+  return nullptr;
+}
+
+const Node& GetLowestDisplayBlockInclusiveAncestor(const Node& start_node) {
+  // Gets lowest inclusive ancestor that has block display value.
+  // <div id=outer>a<div id=inner>b</div>c</div>
+  // If we run this on "a" or "c" text node in we will get the outer div.
+  // If we run it on the "b" text node we will get the inner div.
+  for (Node& ancestor : FlatTreeTraversal::InclusiveAncestorsOf(start_node)) {
+    const ComputedStyle* style = ancestor.EnsureComputedStyle();
+    if (style && !ancestor.IsTextNode() && IsBlock(style->Display()))
+      return ancestor;
+  }
+  return *start_node.GetDocument().documentElement();
+}
+
+// Note: LayoutFlowThread, used for multicol, can't provide offset mapping.
+bool CanUseNGOffsetMapping(const LayoutObject& object) {
+  return object.IsLayoutBlockFlow() && !object.IsLayoutFlowThread();
+}
+
+LayoutBlockFlow* ContainingLayoutBlockFlowFor(const LayoutText& object) {
+  for (LayoutObject* runner = object.Parent(); runner;
+       runner = runner->Parent()) {
+    if (!CanUseNGOffsetMapping(*runner))
+      continue;
+    return ToLayoutBlockFlow(runner);
+  }
+  return nullptr;
+}
+
+std::unique_ptr<FindBuffer::Results> FindBuffer::FindMatches(
+    const WebString& search_text,
+    const mojom::blink::FindOptions& options) const {
+  if (buffer_.IsEmpty() || search_text.length() > buffer_.size())
+    return std::make_unique<Results>();
+  String search_text_16_bit = search_text;
+  search_text_16_bit.Ensure16Bit();
+  FoldQuoteMarksAndSoftHyphens(search_text_16_bit);
+  return std::make_unique<Results>(buffer_, search_text_16_bit, options);
+}
+
+EphemeralRangeInFlatTree FindBuffer::RangeFromBufferIndex(
+    unsigned start_index,
+    unsigned end_index) const {
+  PositionInFlatTree start_position =
+      PositionAtStartOfCharacterAtIndex(start_index);
+  PositionInFlatTree end_position =
+      PositionAtEndOfCharacterAtIndex(end_index - 1);
+  return EphemeralRangeInFlatTree(start_position, end_position);
+}
+
+// Collects text until block boundary located at or after |start_node|
+// to |buffer_|. Saves the next starting node after the block to
+// |node_after_block_|.
+void FindBuffer::CollectTextUntilBlockBoundary(Node& start_node) {
+  // Get first visible text node from |start_node|.
+  Node* node = GetVisibleTextNode(start_node);
+  if (!node || !node->isConnected()) {
+    node_after_block_ = nullptr;
+    return;
+  }
+
+  const Node& block_ancestor = GetLowestDisplayBlockInclusiveAncestor(*node);
+  const Node* just_after_block = FlatTreeTraversal::Next(
+      FlatTreeTraversal::LastWithinOrSelf(block_ancestor));
+  const LayoutBlockFlow* last_block_flow = nullptr;
+
+  // Collect all text under |block_ancestor| to |buffer_|,
+  // unless we meet another block on the way. If so, we should split.
+  // Example: <div id="outer">a<span>b</span>c<div>d</div></div>
+  // Will try to collect all text in outer div but will actually
+  // stop when it encounters the inner div. So buffer will be "abc".
+  const Node* first_traversed_node = node;
+  while (node && node != just_after_block) {
+    if (ShouldIgnoreContents(*node)) {
+      // Move the node so we wouldn't encounter this node or its descendants
+      // later.
+      buffer_.push_back(kObjectReplacementCharacter);
+      node = FlatTreeTraversal::NextSkippingChildren(*node);
+      continue;
+    }
+    const ComputedStyle* style = node->EnsureComputedStyle();
+    if (style->Display() == EDisplay::kNone) {
+      // This element and its descendants are not visible, skip it.
+      // We can safely just check the computed style of this node since
+      // we guarantee |block_ancestor| is visible.
+      node = FlatTreeTraversal::NextSkippingChildren(*node);
+      if (node && !FlatTreeTraversal::IsDescendantOf(*node, block_ancestor))
+        break;
+      continue;
+    }
+    // This node is in its own sub-block separate from our starting position.
+    if (first_traversed_node != node && !node->IsTextNode() &&
+        IsBlock(style->Display())) {
+      break;
+    }
+
+    if (style->Visibility() == EVisibility::kVisible && node->IsTextNode() &&
+        node->GetLayoutObject()) {
+      const Text& text_node = ToText(*node);
+      LayoutBlockFlow& block_flow =
+          *ContainingLayoutBlockFlowFor(*text_node.GetLayoutObject());
+      if (last_block_flow && last_block_flow != block_flow) {
+        // We enter another block flow.
+        break;
+      }
+      if (!last_block_flow) {
+        DCHECK(!offset_mapping_storage_);
+        last_block_flow = &block_flow;
+      }
+      AddTextToBuffer(text_node, block_flow);
+    }
+    node = FlatTreeTraversal::Next(*node);
+  }
+  node_after_block_ = node;
+  FoldQuoteMarksAndSoftHyphens(buffer_.data(), buffer_.size());
+}
+
+FindBuffer::BufferNodeMapping FindBuffer::MappingForIndex(
+    unsigned index) const {
+  // Get the first entry that starts at a position higher than offset, and
+  // move back one entry.
+  auto* it = std::upper_bound(
+      buffer_node_mappings_.begin(), buffer_node_mappings_.end(), index,
+      [](const unsigned offset, const BufferNodeMapping& entry) {
+        return offset < entry.offset_in_buffer;
+      });
+  DCHECK_NE(it, buffer_node_mappings_.begin());
+  auto* const entry = std::prev(it);
+  return *entry;
+}
+
+PositionInFlatTree FindBuffer::PositionAtStartOfCharacterAtIndex(
+    unsigned index) const {
+  DCHECK_LT(index, buffer_.size());
+  BufferNodeMapping entry = MappingForIndex(index);
+  return ToPositionInFlatTree(offset_mapping_->GetLastPosition(
+      index - entry.offset_in_buffer + entry.offset_in_mapping));
+}
+
+PositionInFlatTree FindBuffer::PositionAtEndOfCharacterAtIndex(
+    unsigned index) const {
+  DCHECK_LT(index, buffer_.size());
+  BufferNodeMapping entry = MappingForIndex(index);
+  return ToPositionInFlatTree(offset_mapping_->GetFirstPosition(
+      index - entry.offset_in_buffer + entry.offset_in_mapping + 1));
+}
+
+void FindBuffer::AddTextToBuffer(const Text& text_node,
+                                 LayoutBlockFlow& block_flow) {
+  if (!offset_mapping_storage_) {
+    offset_mapping_ =
+        NGInlineNode::GetOffsetMapping(&block_flow, &offset_mapping_storage_);
+  }
+  const String mapped_text = offset_mapping_->GetText();
+  const NGMappingUnitRange range =
+      offset_mapping_->GetMappingUnitsForNode(text_node);
+  unsigned last_unit_end = 0;
+  bool first_unit = true;
+  for (const NGOffsetMappingUnit& unit : range) {
+    String text_for_unit =
+        mapped_text.Substring(unit.TextContentStart(),
+                              unit.TextContentEnd() - unit.TextContentStart());
+    text_for_unit.Ensure16Bit();
+    text_for_unit.Replace('\n', kObjectReplacementCharacter);
+    if (first_unit || last_unit_end != unit.TextContentStart()) {
+      // This is the first unit, or the units are not consecutive, so we need to
+      // insert a new BufferNodeMapping.
+      buffer_node_mappings_.push_back(
+          BufferNodeMapping({buffer_.size(), unit.TextContentStart()}));
+      first_unit = false;
+    }
+    buffer_.Append(text_for_unit.Characters16(), text_for_unit.length());
+    last_unit_end = unit.TextContentEnd();
+  }
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/editing/finder/find_buffer.h b/third_party/blink/renderer/core/editing/finder/find_buffer.h
new file mode 100644
index 0000000..ef12f4e
--- /dev/null
+++ b/third_party/blink/renderer/core/editing/finder/find_buffer.h
@@ -0,0 +1,156 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_FINDER_FIND_BUFFER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_FINDER_FIND_BUFFER_H_
+
+#include "third_party/blink/public/mojom/frame/find_in_page.mojom-blink.h"
+#include "third_party/blink/renderer/core/editing/finder/find_buffer.h"
+#include "third_party/blink/renderer/core/editing/iterators/text_searcher_icu.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
+
+namespace blink {
+
+class LayoutBlockFlow;
+class Node;
+class WebString;
+
+// Buffer for find-in-page, collects text until it meets a block/other
+// delimiters. Uses TextSearcherICU to find match in buffer.
+// See doc at https://goo.gl/rnXjBu
+class CORE_EXPORT FindBuffer {
+  STACK_ALLOCATED();
+
+ public:
+  FindBuffer(const PositionInFlatTree& start_position);
+
+  // A match result, containing the starting position of the match and
+  // the length of the match.
+  struct BufferMatchResult {
+    const unsigned start;
+    const unsigned length;
+  };
+
+  // All match results for this buffer. We can iterate through the
+  // BufferMatchResults one by one using the Iterator.
+  class CORE_EXPORT Results {
+   public:
+    Results();
+
+    Results(const Vector<UChar>& buffer,
+            String search_text,
+            const mojom::blink::FindOptions& options);
+
+    class CORE_EXPORT Iterator
+        : public std::iterator<std::forward_iterator_tag, BufferMatchResult> {
+     public:
+      Iterator() = default;
+      Iterator(TextSearcherICU* text_searcher);
+
+      bool operator==(const Iterator& other) {
+        return has_match_ == other.has_match_;
+      }
+
+      bool operator!=(const Iterator& other) {
+        return has_match_ != other.has_match_;
+      }
+
+      const BufferMatchResult operator*() const;
+
+      void operator++();
+
+     private:
+      TextSearcherICU* text_searcher_;
+      MatchResultICU match_;
+      bool has_match_ = false;
+    };
+
+    Iterator begin();
+
+    Iterator end() const;
+
+    unsigned CountForTesting();
+
+   private:
+    bool empty_result_ = false;
+    String search_text_;
+    TextSearcherICU text_searcher_;
+  };
+
+  // Finds all the match for |search_text| in |buffer_|.
+  std::unique_ptr<Results> FindMatches(
+      const WebString& search_text,
+      const mojom::blink::FindOptions& options) const;
+
+  // Gets a flat tree range corresponding to text in the [start_index,
+  // end_index) of |buffer|.
+  EphemeralRangeInFlatTree RangeFromBufferIndex(unsigned start_index,
+                                                unsigned end_index) const;
+
+  PositionInFlatTree PositionAfterBlock() const {
+    if (!node_after_block_)
+      return PositionInFlatTree();
+    return PositionInFlatTree::FirstPositionInNode(*node_after_block_);
+  }
+
+ private:
+  // Collects text for one LayoutBlockFlow located at or after |start_node|
+  // to |buffer_|, might be stopped without finishing one full LayoutBlockFlow
+  // if we encountered another LayoutBLockFlow. Saves the next starting node
+  // after the block (first node in another LayoutBlockFlow) to
+  // |node_after_block_|.
+  void CollectTextUntilBlockBoundary(Node& start_node);
+
+  // Mapping for position in buffer -> actual node where the text came from,
+  // along with the offset in the NGOffsetMapping of this find_buffer.
+  // This is needed because when we find a match in the buffer, we want to know
+  // where it's located in the NGOffsetMapping for this FindBuffer.
+  // Example: (assume there are no whitespace)
+  // <div>
+  //  aaa
+  //  <span style="float:right;">bbb<span>ccc</span></span>
+  //  ddd
+  // </div>
+  // We can finish FIP with three FindBuffer runs:
+  // Run #1, 1 BufferNodeMapping with mapping text = "aaa\uFFFCddd",
+  // The "\uFFFC" is the object replacement character created by the float.
+  // For text node "aaa", oib = 0, oim = 0.
+  // Content of |buffer_| = "aaa".
+  // Run #2, 2 BufferNodeMappings, with mapping text = "bbbccc",
+  //  1. For text node "bbb", oib = 0, oim = 0.
+  //  2. For text node "ccc", oib = 3, oim = 3.
+  // Content of |buffer_| = "bbbccc".
+  // Run #3, 1 BufferNodeMapping with mapping text = "aaa\uFFFCddd",
+  // For text node "ddd", oib = 0, oim = 4.
+  // Content of |buffer_| = "ddd".
+  // Since the LayoutBlockFlow for "aaa" and "ddd" is the same, they have the
+  // same NGOffsetMapping, the |offset_in_mapping_| for the BufferNodeMapping in
+  // run #3 is 4 (the index of first "d" character in the mapping text).
+  struct BufferNodeMapping {
+    const unsigned offset_in_buffer;
+    const unsigned offset_in_mapping;
+  };
+
+  BufferNodeMapping MappingForIndex(unsigned index) const;
+
+  PositionInFlatTree PositionAtStartOfCharacterAtIndex(unsigned index) const;
+
+  PositionInFlatTree PositionAtEndOfCharacterAtIndex(unsigned index) const;
+
+  void AddTextToBuffer(const Text& text_node, LayoutBlockFlow& block_flow);
+
+  Member<Node> node_after_block_;
+  Vector<UChar> buffer_;
+  Vector<BufferNodeMapping> buffer_node_mappings_;
+
+  // For legacy layout, we need to save a unique_ptr of the NGOffsetMapping
+  // because nobody owns it. In LayoutNG, the NGOffsetMapping is owned by
+  // the corresponding LayoutBlockFlow, so we don't need to save it.
+  std::unique_ptr<NGOffsetMapping> offset_mapping_storage_;
+  const NGOffsetMapping* offset_mapping_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_FINDER_FIND_BUFFER_H_
diff --git a/third_party/blink/renderer/core/editing/finder/find_buffer_test.cc b/third_party/blink/renderer/core/editing/finder/find_buffer_test.cc
new file mode 100644
index 0000000..71cb1338
--- /dev/null
+++ b/third_party/blink/renderer/core/editing/finder/find_buffer_test.cc
@@ -0,0 +1,280 @@
+// 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 "third_party/blink/renderer/core/editing/finder/find_buffer.h"
+
+#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
+#include "third_party/blink/renderer/core/editing/selection_template.h"
+#include "third_party/blink/renderer/core/editing/testing/editing_test_base.h"
+
+namespace blink {
+
+class FindBufferTest : public EditingTestBase {
+ protected:
+  PositionInFlatTree FirstPosition() {
+    return PositionInFlatTree::FirstPositionInNode(
+        *GetDocument().documentElement());
+  }
+
+  PositionInFlatTree PositionFromParentId(const char* id, unsigned offset) {
+    return PositionInFlatTree(GetElementById(id)->firstChild(), offset);
+  }
+
+  std::string SerializeRange(const EphemeralRangeInFlatTree& range) {
+    return GetSelectionTextInFlatTreeFromBody(
+        SelectionInFlatTree::Builder().SetAsForwardSelection(range).Build());
+  }
+};
+
+TEST_F(FindBufferTest, FindInline) {
+  SetBodyContent(
+      "<div id='container'>a<span id='span'>b</span><b id='b'>c</b><div "
+      "id='none' style='display:none'>d</div><div id='inline-div' "
+      "style='display: inline;'>e</div></div>");
+  FindBuffer buffer(FirstPosition());
+  EXPECT_TRUE(buffer.PositionAfterBlock().IsNull());
+  std::unique_ptr<FindBuffer::Results> results =
+      buffer.FindMatches("abce", *mojom::blink::FindOptions::New());
+  EXPECT_EQ(1u, results->CountForTesting());
+  FindBuffer::BufferMatchResult match = *results->begin();
+  EXPECT_EQ(0u, match.start);
+  EXPECT_EQ(4u, match.length);
+  EXPECT_EQ(
+      EphemeralRangeInFlatTree(PositionFromParentId("container", 0),
+                               PositionFromParentId("inline-div", 1)),
+      buffer.RangeFromBufferIndex(match.start, match.start + match.length));
+}
+
+TEST_F(FindBufferTest, RangeFromBufferIndex) {
+  SetBodyContent(
+      "<div id='container'>a <span id='span'> b</span><b id='b'>cc</b><div "
+      "id='none' style='display:none'>d</div><div id='inline-div' "
+      "style='display: inline;'>e</div></div>");
+  FindBuffer buffer(FirstPosition());
+  // Range for "a"
+  EXPECT_EQ(EphemeralRangeInFlatTree(PositionFromParentId("container", 0),
+                                     PositionFromParentId("container", 1)),
+            buffer.RangeFromBufferIndex(0, 1));
+  EXPECT_EQ(
+      "<div id=\"container\">^a| <span id=\"span\"> b</span><b "
+      "id=\"b\">cc</b><div id=\"none\" style=\"display:none\">d</div><div "
+      "id=\"inline-div\" style=\"display: inline;\">e</div></div>",
+      SerializeRange(buffer.RangeFromBufferIndex(0, 1)));
+  // Range for "a "
+  EXPECT_EQ(EphemeralRangeInFlatTree(PositionFromParentId("container", 0),
+                                     PositionFromParentId("container", 2)),
+            buffer.RangeFromBufferIndex(0, 2));
+  EXPECT_EQ(
+      "<div id=\"container\">^a |<span id=\"span\"> b</span><b "
+      "id=\"b\">cc</b><div id=\"none\" style=\"display:none\">d</div><div "
+      "id=\"inline-div\" style=\"display: inline;\">e</div></div>",
+      SerializeRange(buffer.RangeFromBufferIndex(0, 2)));
+  // Range for "a b"
+  EXPECT_EQ(EphemeralRangeInFlatTree(PositionFromParentId("container", 0),
+                                     PositionFromParentId("span", 2)),
+            buffer.RangeFromBufferIndex(0, 3));
+  EXPECT_EQ(
+      "<div id=\"container\">^a <span id=\"span\"> b|</span><b "
+      "id=\"b\">cc</b><div id=\"none\" style=\"display:none\">d</div><div "
+      "id=\"inline-div\" style=\"display: inline;\">e</div></div>",
+      SerializeRange(buffer.RangeFromBufferIndex(0, 3)));
+  // Range for "a bc"
+  EXPECT_EQ(EphemeralRangeInFlatTree(PositionFromParentId("container", 0),
+                                     PositionFromParentId("b", 1)),
+            buffer.RangeFromBufferIndex(0, 4));
+  EXPECT_EQ(
+      "<div id=\"container\">^a <span id=\"span\"> b</span><b "
+      "id=\"b\">c|c</b><div id=\"none\" style=\"display:none\">d</div><div "
+      "id=\"inline-div\" style=\"display: inline;\">e</div></div>",
+      SerializeRange(buffer.RangeFromBufferIndex(0, 4)));
+  // Range for "a bcc"
+  EXPECT_EQ(EphemeralRangeInFlatTree(PositionFromParentId("container", 0),
+                                     PositionFromParentId("b", 2)),
+            buffer.RangeFromBufferIndex(0, 5));
+  EXPECT_EQ(
+      "<div id=\"container\">^a <span id=\"span\"> b</span><b "
+      "id=\"b\">cc|</b><div id=\"none\" style=\"display:none\">d</div><div "
+      "id=\"inline-div\" style=\"display: inline;\">e</div></div>",
+      SerializeRange(buffer.RangeFromBufferIndex(0, 5)));
+  // Range for "a bcce"
+  EXPECT_EQ(EphemeralRangeInFlatTree(PositionFromParentId("container", 0),
+                                     PositionFromParentId("inline-div", 1)),
+            buffer.RangeFromBufferIndex(0, 6));
+  EXPECT_EQ(
+      "<div id=\"container\">^a <span id=\"span\"> b</span><b "
+      "id=\"b\">cc</b><div id=\"none\" style=\"display:none\">d</div><div "
+      "id=\"inline-div\" style=\"display: inline;\">e|</div></div>",
+      SerializeRange(buffer.RangeFromBufferIndex(0, 6)));
+  // Range for " b"
+  EXPECT_EQ(EphemeralRangeInFlatTree(PositionFromParentId("container", 1),
+                                     PositionFromParentId("span", 2)),
+            buffer.RangeFromBufferIndex(1, 3));
+  EXPECT_EQ(
+      "<div id=\"container\">a^ <span id=\"span\"> b|</span><b "
+      "id=\"b\">cc</b><div id=\"none\" style=\"display:none\">d</div><div "
+      "id=\"inline-div\" style=\"display: inline;\">e</div></div>",
+      SerializeRange(buffer.RangeFromBufferIndex(1, 3)));
+  // Range for " bc"
+  EXPECT_EQ(EphemeralRangeInFlatTree(PositionFromParentId("container", 1),
+                                     PositionFromParentId("b", 1)),
+            buffer.RangeFromBufferIndex(1, 4));
+  EXPECT_EQ(
+      "<div id=\"container\">a^ <span id=\"span\"> b</span><b "
+      "id=\"b\">c|c</b><div id=\"none\" style=\"display:none\">d</div><div "
+      "id=\"inline-div\" style=\"display: inline;\">e</div></div>",
+      SerializeRange(buffer.RangeFromBufferIndex(1, 4)));
+}
+
+class FindBufferBlockTest : public FindBufferTest,
+                            public testing::WithParamInterface<std::string> {};
+
+INSTANTIATE_TEST_CASE_P(Blocks,
+                        FindBufferBlockTest,
+                        testing::Values("block",
+                                        "table",
+                                        "flow-root",
+                                        "grid",
+                                        "flex",
+                                        "list-item"));
+
+TEST_P(FindBufferBlockTest, FindBlock) {
+  SetBodyContent("text<div id='block' style='display: " + GetParam() +
+                 ";'>block</div><span id='span'>span</span>");
+  FindBuffer text_buffer(FirstPosition());
+  EXPECT_EQ(GetElementById("block"),
+            *text_buffer.PositionAfterBlock().ComputeContainerNode());
+  EXPECT_EQ(1u,
+            text_buffer.FindMatches("text", *mojom::blink::FindOptions::New())
+                ->CountForTesting());
+  EXPECT_EQ(0u, text_buffer
+                    .FindMatches("textblock", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+  EXPECT_EQ(
+      0u,
+      text_buffer.FindMatches("text block", *mojom::blink::FindOptions::New())
+          ->CountForTesting());
+
+  FindBuffer block_buffer(text_buffer.PositionAfterBlock());
+  EXPECT_EQ(GetElementById("span"),
+            *block_buffer.PositionAfterBlock().ComputeContainerNode());
+  EXPECT_EQ(
+      1u, block_buffer.FindMatches("block", *mojom::blink::FindOptions::New())
+              ->CountForTesting());
+  EXPECT_EQ(0u, block_buffer
+                    .FindMatches("textblock", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+  EXPECT_EQ(
+      0u,
+      block_buffer.FindMatches("text block", *mojom::blink::FindOptions::New())
+          ->CountForTesting());
+  EXPECT_EQ(0u, block_buffer
+                    .FindMatches("blockspan", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+  EXPECT_EQ(
+      0u,
+      block_buffer.FindMatches("block span", *mojom::blink::FindOptions::New())
+          ->CountForTesting());
+
+  FindBuffer span_buffer(block_buffer.PositionAfterBlock());
+  EXPECT_TRUE(span_buffer.PositionAfterBlock().IsNull());
+  EXPECT_EQ(1u,
+            span_buffer.FindMatches("span", *mojom::blink::FindOptions::New())
+                ->CountForTesting());
+  EXPECT_EQ(0u, span_buffer
+                    .FindMatches("blockspan", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+  EXPECT_EQ(
+      0u,
+      span_buffer.FindMatches("block span", *mojom::blink::FindOptions::New())
+          ->CountForTesting());
+}
+
+class FindBufferSeparatorTest
+    : public FindBufferTest,
+      public testing::WithParamInterface<std::string> {};
+
+INSTANTIATE_TEST_CASE_P(Separators,
+                        FindBufferSeparatorTest,
+                        testing::Values("br",
+                                        "hr",
+                                        "legend",
+                                        "meter",
+                                        "object",
+                                        "progress",
+                                        "select",
+                                        "video"));
+
+TEST_P(FindBufferSeparatorTest, FindSeparatedElements) {
+  SetBodyContent("a<" + GetParam() + ">a</" + GetParam() + ">a");
+  FindBuffer buffer(FirstPosition());
+  EXPECT_EQ(0u, buffer.FindMatches("aa", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+}
+
+TEST_F(FindBufferTest, WhiteSpaceCollapsingPreWrap) {
+  SetBodyContent(
+      " a  \n   b  <b> c </b> d  <span style='white-space: pre-wrap'> e  "
+      "</span>");
+  FindBuffer buffer(FirstPosition());
+  EXPECT_EQ(
+      1u, buffer.FindMatches("a b c d  e  ", *mojom::blink::FindOptions::New())
+              ->CountForTesting());
+};
+
+TEST_F(FindBufferTest, WhiteSpaceCollapsingPre) {
+  SetBodyContent("<div style='white-space: pre;'>a \n b</div>");
+  FindBuffer buffer(FirstPosition());
+  EXPECT_EQ(1u, buffer.FindMatches("a", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+  EXPECT_EQ(1u, buffer.FindMatches("b", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+  EXPECT_EQ(0u, buffer.FindMatches("ab", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+  EXPECT_EQ(0u, buffer.FindMatches("a b", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+  EXPECT_EQ(0u, buffer.FindMatches("a  b", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+  EXPECT_EQ(0u, buffer.FindMatches("a   b", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+  EXPECT_EQ(0u, buffer.FindMatches("a\n b", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+  EXPECT_EQ(0u, buffer.FindMatches("a \nb", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+  EXPECT_EQ(0u, buffer.FindMatches("a \n b", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+}
+
+TEST_F(FindBufferTest, WhiteSpaceCollapsingPreLine) {
+  SetBodyContent("<div style='white-space: pre-line;'>a \n b</div>");
+  FindBuffer buffer(FirstPosition());
+  EXPECT_EQ(1u, buffer.FindMatches("a", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+  EXPECT_EQ(1u, buffer.FindMatches("b", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+  EXPECT_EQ(0u, buffer.FindMatches("ab", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+  EXPECT_EQ(0u, buffer.FindMatches("a b", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+  EXPECT_EQ(0u, buffer.FindMatches("a  b", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+  EXPECT_EQ(0u, buffer.FindMatches("a   b", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+  EXPECT_EQ(0u, buffer.FindMatches("a \n b", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+  EXPECT_EQ(0u, buffer.FindMatches("a\n b", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+  EXPECT_EQ(0u, buffer.FindMatches("a \nb", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+  EXPECT_EQ(0u, buffer.FindMatches("a\nb", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+}
+
+TEST_F(FindBufferTest, BidiTest) {
+  SetBodyContent("<bdo dir=rtl id=bdo>foo<span>bar</span></bdo>");
+  FindBuffer buffer(FirstPosition());
+  EXPECT_EQ(1u, buffer.FindMatches("foobar", *mojom::blink::FindOptions::New())
+                    ->CountForTesting());
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/editing/finder/find_task_controller.cc b/third_party/blink/renderer/core/editing/finder/find_task_controller.cc
index 5df794ea..cfe1d10 100644
--- a/third_party/blink/renderer/core/editing/finder/find_task_controller.cc
+++ b/third_party/blink/renderer/core/editing/finder/find_task_controller.cc
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/core/dom/range.h"
 #include "third_party/blink/renderer/core/dom/scripted_idle_task_controller.h"
 #include "third_party/blink/renderer/core/editing/ephemeral_range.h"
+#include "third_party/blink/renderer/core/editing/finder/find_buffer.h"
 #include "third_party/blink/renderer/core/editing/finder/find_options.h"
 #include "third_party/blink/renderer/core/editing/finder/text_finder.h"
 #include "third_party/blink/renderer/core/editing/iterators/search_buffer.h"
@@ -106,41 +107,38 @@
 
     int match_count = 0;
     bool full_range_searched = false;
-    PositionInFlatTree next_scoping_start;
+    PositionInFlatTree next_task_start_position;
     do {
-      // Find next occurrence of the search string.
-      // FIXME: (http://crbug.com/6818) This WebKit operation may run for longer
-      // than the timeout value, and is not interruptible as it is currently
-      // written. We may need to rewrite it with interruptibility in mind, or
-      // find an alternative.
-      const EphemeralRangeInFlatTree result = FindPlainText(
-          EphemeralRangeInFlatTree(search_start, search_end), search_text_,
-          options_->match_case ? 0 : kCaseInsensitive);
-      if (result.IsCollapsed()) {
-        // Not found.
+      // Find in the whole block.
+      FindBuffer buffer(search_start);
+      std::unique_ptr<FindBuffer::Results> match_results =
+          buffer.FindMatches(search_text_, *options_);
+      for (FindBuffer::BufferMatchResult match : *match_results) {
+        const EphemeralRangeInFlatTree ephemeral_match_range =
+            buffer.RangeFromBufferIndex(match.start,
+                                        match.start + match.length);
+        Range* const match_range = Range::Create(
+            ephemeral_match_range.GetDocument(),
+            ToPositionInDOMTree(ephemeral_match_range.StartPosition()),
+            ToPositionInDOMTree(ephemeral_match_range.EndPosition()));
+        if (match_range->collapsed()) {
+          // resultRange will be collapsed if the matched text spans over
+          // multiple TreeScopes.  TODO(rakina): Show such matches to users.
+          next_task_start_position = ephemeral_match_range.EndPosition();
+          continue;
+        }
+        ++match_count;
+        controller_->DidFindMatch(identifier_, match_range);
+      }
+      // At this point, all text in the block collected above has been
+      // processed. Now we move to the next block if there's any,
+      // otherwise we should stop.
+      search_start = buffer.PositionAfterBlock();
+      if (search_start.IsNull()) {
         full_range_searched = true;
         break;
       }
-      Range* result_range = Range::Create(
-          result.GetDocument(), ToPositionInDOMTree(result.StartPosition()),
-          ToPositionInDOMTree(result.EndPosition()));
-      if (result_range->collapsed()) {
-        // resultRange will be collapsed if the matched text spans over multiple
-        // TreeScopes.  FIXME: Show such matches to users.
-        search_start = result.EndPosition();
-        if (deadline->timeRemaining() > 0)
-          continue;
-        break;
-      }
-      ++match_count;
-      controller_->DidFindMatch(identifier_, result_range);
-
-      // Set the new start for the search range to be the end of the previous
-      // result range. There is no need to use a VisiblePosition here,
-      // since findPlainText will use a TextIterator to go over the visible
-      // text nodes.
-      search_start = result.EndPosition();
-      next_scoping_start = search_start;
+      next_task_start_position = search_start;
     } while (deadline->timeRemaining() > 0);
 
     const TimeDelta time_spent = CurrentTimeTicks() - start_time;
@@ -148,7 +146,7 @@
                         time_spent - time_available);
 
     controller_->DidFinishTask(identifier_, search_text_, *options_,
-                               full_range_searched, next_scoping_start,
+                               full_range_searched, next_task_start_position,
                                match_count);
   }
 
diff --git a/third_party/blink/renderer/core/frame/document_loading_rendering_test.cc b/third_party/blink/renderer/core/frame/document_loading_rendering_test.cc
index e2ad997..fa4bf503 100644
--- a/third_party/blink/renderer/core/frame/document_loading_rendering_test.cc
+++ b/third_party/blink/renderer/core/frame/document_loading_rendering_test.cc
@@ -461,8 +461,9 @@
 
     Element* element = GetDocument().getElementById("test");
     ASSERT_NE(nullptr, element);
-    EXPECT_EQ(0xff008000, element->ComputedStyleRef().SvgStyle().StopColor());
-    EXPECT_EQ(.5f, element->ComputedStyleRef().SvgStyle().StopOpacity());
+    const SVGComputedStyle& svg_style = element->ComputedStyleRef().SvgStyle();
+    EXPECT_EQ(0xff008000, svg_style.StopColor().GetColor());
+    EXPECT_EQ(.5f, svg_style.StopOpacity());
   };
 
   EXPECT_TRUE(GetDocument().IsRenderingReady());
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc
index b7e3d7d..e91013a 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -293,6 +293,7 @@
   visitor->Trace(anchoring_adjustment_queue_);
   visitor->Trace(print_context_);
   visitor->Trace(paint_timing_detector_);
+  visitor->Trace(lifecycle_observers_);
 }
 
 template <typename Function>
@@ -2329,6 +2330,9 @@
   if (reason == DocumentLifecycle::LifecycleUpdateReason::kBeginMainFrame)
     EnsureUkmAggregator().BeginMainFrame();
 
+  for (auto& observer : lifecycle_observers_)
+    observer->WillStartLifecycleUpdate();
+
   // If we're in PrintBrowser mode, setup a print context.
   // TODO(vmpstr): It doesn't seem like we need to do this every lifecycle
   // update, but rather once somewhere at creation time.
@@ -2351,6 +2355,9 @@
 
   UpdateThrottlingStatusForSubtree();
 
+  for (auto& observer : lifecycle_observers_)
+    observer->DidFinishLifecycleUpdate();
+
   return Lifecycle().GetState() == target_state;
 }
 
@@ -4379,4 +4386,14 @@
   return *ukm_aggregator_;
 }
 
+void LocalFrameView::RegisterForLifecycleNotifications(
+    LifecycleNotificationObserver* observer) {
+  lifecycle_observers_.insert(observer);
+}
+
+void LocalFrameView::UnregisterFromLifecycleNotifications(
+    LifecycleNotificationObserver* observer) {
+  lifecycle_observers_.erase(observer);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.h b/third_party/blink/renderer/core/frame/local_frame_view.h
index 7f38b9c..b957bd72 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.h
+++ b/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -108,6 +108,14 @@
   friend class Internals;
 
  public:
+  class CORE_EXPORT LifecycleNotificationObserver
+      : public GarbageCollectedMixin {
+   public:
+    // These are called when the lifecycle updates start/finish.
+    virtual void WillStartLifecycleUpdate() = 0;
+    virtual void DidFinishLifecycleUpdate() = 0;
+  };
+
   static LocalFrameView* Create(LocalFrame&);
   static LocalFrameView* Create(LocalFrame&, const IntSize& initial_size);
 
@@ -699,6 +707,9 @@
   // Return the UKM aggregator for this frame, creating it if necessary.
   LocalFrameUkmAggregator& EnsureUkmAggregator();
 
+  void RegisterForLifecycleNotifications(LifecycleNotificationObserver*);
+  void UnregisterFromLifecycleNotifications(LifecycleNotificationObserver*);
+
  protected:
   void NotifyFrameRectsChangedIfNeeded();
 
@@ -991,6 +1002,8 @@
   std::unique_ptr<JankTracker> jank_tracker_;
   Member<PaintTimingDetector> paint_timing_detector_;
 
+  HeapHashSet<WeakMember<LifecycleNotificationObserver>> lifecycle_observers_;
+
   FRIEND_TEST_ALL_PREFIXES(WebViewTest, DeviceEmulationResetScrollbars);
 };
 
diff --git a/third_party/blink/renderer/core/html/shadow/progress_shadow_element.cc b/third_party/blink/renderer/core/html/shadow/progress_shadow_element.cc
index 0532db1..09230015 100644
--- a/third_party/blink/renderer/core/html/shadow/progress_shadow_element.cc
+++ b/third_party/blink/renderer/core/html/shadow/progress_shadow_element.cc
@@ -36,7 +36,9 @@
 namespace blink {
 
 ProgressShadowElement::ProgressShadowElement(Document& document)
-    : HTMLDivElement(document) {}
+    : HTMLDivElement(document) {
+  SetHasCustomStyleCallbacks();
+}
 
 DEFINE_NODE_FACTORY(ProgressShadowElement)
 
@@ -44,11 +46,14 @@
   return ToHTMLProgressElement(OwnerShadowHost());
 }
 
-bool ProgressShadowElement::LayoutObjectIsNeeded(
-    const ComputedStyle& style) const {
+scoped_refptr<ComputedStyle>
+ProgressShadowElement::CustomStyleForLayoutObject() {
+  scoped_refptr<ComputedStyle> style = OriginalStyleForLayoutObject();
   const ComputedStyle* progress_style = ProgressElement()->GetComputedStyle();
-  return progress_style && !progress_style->HasAppearance() &&
-         HTMLDivElement::LayoutObjectIsNeeded(style);
+  DCHECK(progress_style);
+  if (progress_style->HasAppearance())
+    style->SetDisplay(EDisplay::kNone);
+  return style;
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/shadow/progress_shadow_element.h b/third_party/blink/renderer/core/html/shadow/progress_shadow_element.h
index d14d83c2..f8d63f94 100644
--- a/third_party/blink/renderer/core/html/shadow/progress_shadow_element.h
+++ b/third_party/blink/renderer/core/html/shadow/progress_shadow_element.h
@@ -47,7 +47,7 @@
 
  private:
   HTMLProgressElement* ProgressElement() const;
-  bool LayoutObjectIsNeeded(const ComputedStyle&) const override;
+  scoped_refptr<ComputedStyle> CustomStyleForLayoutObject() override;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_image.cc b/third_party/blink/renderer/core/layout/layout_image.cc
index 44a4204..769df9a 100644
--- a/third_party/blink/renderer/core/layout/layout_image.cc
+++ b/third_party/blink/renderer/core/layout/layout_image.cc
@@ -210,6 +210,21 @@
   SetIntrinsicSize(new_size);
 }
 
+bool LayoutImage::NeedsLayoutOnIntrinsicSizeChange() const {
+  // If the actual area occupied by the image has changed and it is not
+  // constrained by style then a layout is required.
+  bool image_size_is_constrained = StyleRef().LogicalWidth().IsSpecified() &&
+                                   StyleRef().LogicalHeight().IsSpecified();
+  if (!image_size_is_constrained)
+    return true;
+
+  // FIXME: We only need to recompute the containing block's preferred size if
+  // the containing block's size depends on the image's size (i.e., the
+  // container uses shrink-to-fit sizing). There's no easy way to detect that
+  // shrink-to-fit is needed, always force a layout.
+  return HasRelativeLogicalWidth();
+}
+
 void LayoutImage::InvalidatePaintAndMarkForLayoutIfNeeded(
     CanDeferInvalidation defer) {
   LayoutSize old_intrinsic_size = IntrinsicSize();
@@ -225,30 +240,14 @@
   if (!ContainingBlock())
     return;
 
-  bool image_source_has_changed_size = old_intrinsic_size != new_intrinsic_size;
-  if (image_source_has_changed_size)
+  if (old_intrinsic_size != new_intrinsic_size) {
     SetPreferredLogicalWidthsDirty();
 
-  // If the actual area occupied by the image has changed and it is not
-  // constrained by style then a layout is required.
-  bool image_size_is_constrained = StyleRef().LogicalWidth().IsSpecified() &&
-                                   StyleRef().LogicalHeight().IsSpecified();
-
-  // FIXME: We only need to recompute the containing block's preferred size if
-  // the containing block's size depends on the image's size (i.e., the
-  // container uses shrink-to-fit sizing). There's no easy way to detect that
-  // shrink-to-fit is needed, always force a layout.
-  bool containing_block_needs_to_recompute_preferred_size =
-      StyleRef().LogicalWidth().IsPercentOrCalc() ||
-      StyleRef().LogicalMaxWidth().IsPercentOrCalc() ||
-      StyleRef().LogicalMinWidth().IsPercentOrCalc();
-
-  if (image_source_has_changed_size &&
-      (!image_size_is_constrained ||
-       containing_block_needs_to_recompute_preferred_size)) {
-    SetNeedsLayoutAndFullPaintInvalidation(
-        layout_invalidation_reason::kSizeChanged);
-    return;
+    if (NeedsLayoutOnIntrinsicSizeChange()) {
+      SetNeedsLayoutAndFullPaintInvalidation(
+          layout_invalidation_reason::kSizeChanged);
+      return;
+    }
   }
 
   SetShouldDoFullPaintInvalidationWithoutGeometryChange(
diff --git a/third_party/blink/renderer/core/layout/layout_image.h b/third_party/blink/renderer/core/layout/layout_image.h
index 7db612e..a1827913 100644
--- a/third_party/blink/renderer/core/layout/layout_image.h
+++ b/third_party/blink/renderer/core/layout/layout_image.h
@@ -136,6 +136,7 @@
 
   void InvalidatePaintAndMarkForLayoutIfNeeded(CanDeferInvalidation);
   void UpdateIntrinsicSizeIfNeeded(const LayoutSize&);
+  bool NeedsLayoutOnIntrinsicSizeChange() const;
   // Override intrinsic sizing info by HTMLImageElement "intrinsicsize"
   // attribute if enabled and exists.
   bool OverrideIntrinsicSizingInfo(IntrinsicSizingInfo&) const;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.cc
index 5cdf5a9e..776dbe0 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.cc
@@ -49,6 +49,78 @@
 }
 #endif
 
+LayoutUnit NGLineInfo::ComputeTrailingSpaceWidth(
+    unsigned* end_offset_out) const {
+  // TODO(kojii): Consider adding a flag to skip this function when not needed.
+  // In many common cases, NGLineBreaker knows that there are no trailing
+  // spaces, so we can leverage the knowledge without adding the cost to compute
+  // the flag. We use this function only for 'text-align: justify', so the cost
+  // to compute the flag should not be more expensive than it benefits.
+  const NGInlineItemResults& item_results = Results();
+  LayoutUnit trailing_spaces_width;
+  for (auto it = item_results.rbegin(); it != item_results.rend(); ++it) {
+    const NGInlineItemResult& item_result = *it;
+    DCHECK(item_result.item);
+    const NGInlineItem& item = *item_result.item;
+
+    // If this item is opaque to whitespace collapsing, whitespace before this
+    // item maybe collapsed. Keep looking for previous items.
+    if (item.EndCollapseType() == NGInlineItem::kOpaqueToCollapsing) {
+      continue;
+    }
+    // These items should be opaque-to-collapsing.
+    DCHECK(item.Type() != NGInlineItem::kFloating &&
+           item.Type() != NGInlineItem::kOutOfFlowPositioned &&
+           item.Type() != NGInlineItem::kBidiControl);
+
+    if (item.Type() == NGInlineItem::kControl ||
+        item_result.has_only_trailing_spaces) {
+      trailing_spaces_width += item_result.inline_size;
+      continue;
+    }
+
+    // The last text item may contain trailing spaces if this is a last line,
+    // has a forced break, or is 'white-space: pre'.
+    unsigned end_offset = item_result.end_offset;
+    DCHECK(end_offset);
+    if (item.Type() == NGInlineItem::kText) {
+      const String& text = items_data_->text_content;
+      if (end_offset && text[end_offset - 1] == kSpaceCharacter) {
+        do {
+          --end_offset;
+        } while (end_offset > item_result.start_offset &&
+                 text[end_offset - 1] == kSpaceCharacter);
+
+        // If all characters in this item_result are spaces, check next item.
+        if (end_offset == item_result.start_offset) {
+          trailing_spaces_width += item_result.inline_size;
+          continue;
+        }
+
+        // To compute the accurate width, we need to reshape if |end_offset| is
+        // not safe-to-break. We avoid reshaping in this case because the cost
+        // is high and the difference is subtle for the purpose of this
+        // function.
+        // TODO(kojii): Compute this without |CreateShapeResult|.
+        scoped_refptr<ShapeResult> shape_result =
+            item_result.shape_result->CreateShapeResult();
+        float end_position = shape_result->PositionForOffset(
+            end_offset - shape_result->StartIndex());
+        trailing_spaces_width += shape_result->Width() - end_position;
+      }
+    }
+
+    if (end_offset_out)
+      *end_offset_out = end_offset;
+    return trailing_spaces_width;
+  }
+
+  // An empty line, or only trailing spaces.
+  if (end_offset_out)
+    *end_offset_out = StartOffset();
+  return trailing_spaces_width;
+}
+
 LayoutUnit NGLineInfo::ComputeWidth() const {
   LayoutUnit inline_size = TextIndent();
   for (const NGInlineItemResult& item_result : Results())
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h
index 05167d9..2ce6795 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h
@@ -166,8 +166,18 @@
 
   NGBfcOffset BfcOffset() const { return bfc_offset_; }
   LayoutUnit AvailableWidth() const { return available_width_; }
+
+  // The width of this line. Includes trailing spaces if they were preserved.
+  // Negative width created by negative 'text-indent' is clamped to zero.
   LayoutUnit Width() const { return width_.ClampNegativeToZero(); }
+  // Same as |Width()| but returns negative value as is.
   LayoutUnit WidthForAlignment() const { return width_; }
+  // The width of preserved trailing spaces.
+  LayoutUnit ComputeTrailingSpaceWidth(
+      unsigned* end_offset_out = nullptr) const;
+  // Compute |Width()| from |Results()|. Used during line breaking, before
+  // |Width()| is set. After line breaking, this should match to |Width()|
+  // without clamping.
   LayoutUnit ComputeWidth() const;
 
   // True if this line has overflow, excluding preserved trailing spaces.
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
index 58d4210ac..96dd4b5 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
@@ -35,60 +35,6 @@
 #include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h"
 
 namespace blink {
-namespace {
-
-// Represents a data struct that are needed for 'text-align' and justifications.
-struct NGLineAlign {
-  STACK_ALLOCATED();
-
- public:
-  NGLineAlign(const NGLineInfo&);
-  NGLineAlign() = delete;
-
-  // The space to align or justify. This includes trailing spaces if exists.
-  LayoutUnit space;
-
-  // The end offset with trailing spaces excluded.
-  unsigned end_offset;
-  LayoutUnit trailing_spaces_width;
-};
-
-NGLineAlign::NGLineAlign(const NGLineInfo& line_info) {
-  // NGLineInfo::WidthForAlignment may return a negative value, as text-indent
-  // can accept negative values. We need to use this un-clamped value for
-  // alginment, instead of just NGLineInfo::Width.
-  space = line_info.AvailableWidth() - line_info.WidthForAlignment();
-
-  // Compute the end text offset of this line for the alignment purpose.
-  // Trailing spaces are not part of the alignment space even when they are
-  // preserved.
-  const NGInlineItemResults& item_results = line_info.Results();
-  for (auto it = item_results.rbegin(); it != item_results.rend(); ++it) {
-    const NGInlineItemResult& item_result = *it;
-
-    // If this item is opaque to whitespace collapsing, whitespace before this
-    // item maybe collapsed. Keep looking for previous items.
-    if (item_result.item && item_result.item->EndCollapseType() ==
-                                NGInlineItem::kOpaqueToCollapsing) {
-      continue;
-    }
-
-    if (item_result.has_only_trailing_spaces) {
-      trailing_spaces_width += item_result.inline_size;
-      continue;
-    }
-
-    end_offset = item_result.end_offset;
-    space += trailing_spaces_width;
-    return;
-  }
-
-  // An empty line, or only trailing spaces.
-  end_offset = line_info.StartOffset();
-  space += trailing_spaces_width;
-}
-
-}  // namespace
 
 NGInlineLayoutAlgorithm::NGInlineLayoutAlgorithm(
     NGInlineNode inline_node,
@@ -223,13 +169,9 @@
 
   // Apply justification before placing items, because it affects size/position
   // of items, which are needed to compute inline static positions.
-  const ComputedStyle& line_style = line_info->LineStyle();
-  ETextAlign text_align = line_style.GetTextAlign(line_info->IsLastLine());
-  if (text_align == ETextAlign::kJustify) {
-    if (!ApplyJustify(line_info))
-      text_align = ETextAlign::kStart;
-  }
+  LayoutUnit line_offset_for_text_align = ApplyTextAlign(line_info);
 
+  const ComputedStyle& line_style = line_info->LineStyle();
   NGLineHeightMetrics line_metrics(line_style, baseline_type_);
   NGLineHeightMetrics line_metrics_with_leading = line_metrics;
   line_metrics_with_leading.AddLeading(line_style.ComputedLineHeightAsFixed());
@@ -339,9 +281,8 @@
 
   // Other 'text-align' values than 'justify' move line boxes as a whole, but
   // indivisual items do not change their relative position to the line box.
-  LayoutUnit bfc_line_offset = line_info->BfcOffset().line_offset;
-  if (text_align != ETextAlign::kJustify)
-    bfc_line_offset += OffsetForTextAlign(*line_info, text_align);
+  LayoutUnit bfc_line_offset =
+      line_info->BfcOffset().line_offset + line_offset_for_text_align;
 
   if (IsLtr(line_info->BaseDirection()))
     bfc_line_offset += line_info->TextIndent();
@@ -582,19 +523,26 @@
 
 // Justify the line. This changes the size of items by adding spacing.
 // Returns false if justification failed and should fall back to start-aligned.
-bool NGInlineLayoutAlgorithm::ApplyJustify(NGLineInfo* line_info) {
+bool NGInlineLayoutAlgorithm::ApplyJustify(LayoutUnit space,
+                                           NGLineInfo* line_info) {
   // Empty lines should align to start.
   if (line_info->IsEmptyLine())
     return false;
 
-  NGLineAlign align(*line_info);
-  if (align.space <= 0)
-    return false;  // no expansion is needed.
+  // Justify the end of visible text, ignoring preserved trailing spaces.
+  unsigned end_offset;
+  LayoutUnit trailing_spaces_width =
+      line_info->ComputeTrailingSpaceWidth(&end_offset);
+  space += trailing_spaces_width;
+
+  // If this line overflows, fallback to 'text-align: start'.
+  if (space <= 0)
+    return false;
 
   // Construct the line text to compute spacing for.
   String line_text =
       StringView(line_info->ItemsData().text_content, line_info->StartOffset(),
-                 align.end_offset - line_info->StartOffset())
+                 end_offset - line_info->StartOffset())
           .ToString();
 
   // Append a hyphen if the last word is hyphenated. The hyphen is in
@@ -607,7 +555,7 @@
 
   // Compute the spacing to justify.
   ShapeResultSpacing<String> spacing(line_text);
-  spacing.SetExpansion(align.space, line_info->BaseDirection(),
+  spacing.SetExpansion(space, line_info->BaseDirection(),
                        line_info->LineStyle().GetTextJustify());
   if (!spacing.HasExpansion())
     return false;  // no expansion opportunities exist.
@@ -643,16 +591,28 @@
   return true;
 }
 
-// Compute the offset to shift the line box for the 'text-align' property.
-LayoutUnit NGInlineLayoutAlgorithm::OffsetForTextAlign(
-    const NGLineInfo& line_info,
-    ETextAlign text_align) const {
-  // Justification is applied in earlier phase, see PlaceItems().
-  DCHECK_NE(text_align, ETextAlign::kJustify);
+// Apply the 'text-align' property to |line_info|. Returns the amount to move
+// the line in the inline direction.
+LayoutUnit NGInlineLayoutAlgorithm::ApplyTextAlign(NGLineInfo* line_info) {
+  // NGLineInfo::WidthForAlignment may return a negative value, as text-indent
+  // can accept negative values. We need to use this un-clamped value for
+  // alginment, instead of just NGLineInfo::Width.
+  LayoutUnit space =
+      line_info->AvailableWidth() - line_info->WidthForAlignment();
 
-  NGLineAlign align(line_info);
-  return LineOffsetForTextAlign(text_align, line_info.BaseDirection(),
-                                align.space, align.trailing_spaces_width);
+  const ComputedStyle& line_style = line_info->LineStyle();
+  ETextAlign text_align = line_style.GetTextAlign(line_info->IsLastLine());
+  if (text_align == ETextAlign::kJustify) {
+    // If justification succeeds, no offset is needed. Expansions are set to
+    // each |NGInlineItemResult| in |line_info|.
+    if (ApplyJustify(space, line_info))
+      return LayoutUnit();
+
+    // If justification fails, fallback to 'text-align: start'.
+    text_align = ETextAlign::kStart;
+  }
+
+  return LineOffsetForTextAlign(text_align, line_info->BaseDirection(), space);
 }
 
 LayoutUnit NGInlineLayoutAlgorithm::ComputeContentSize(
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h
index f3d878a..5d8049b2 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h
@@ -93,8 +93,8 @@
                        NGInlineItemResult*,
                        const NGLineInfo&);
 
-  LayoutUnit OffsetForTextAlign(const NGLineInfo&, ETextAlign) const;
-  bool ApplyJustify(NGLineInfo*);
+  LayoutUnit ApplyTextAlign(NGLineInfo*);
+  bool ApplyJustify(LayoutUnit space, NGLineInfo*);
 
   LayoutUnit ComputeContentSize(const NGLineInfo&,
                                 const NGExclusionSpace&,
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc
index 53f11d1..50e4672 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc
@@ -17,7 +17,7 @@
 
 namespace blink {
 
-class NGLineBreakerTest : public NGBaseLayoutAlgorithmTest {
+class NGLineBreakerTest : public NGLayoutTest {
  protected:
   NGInlineNode CreateInlineNode(const String& html_content) {
     SetBodyInnerHTML(html_content);
@@ -28,8 +28,8 @@
   }
 
   // Break lines using the specified available width.
-  Vector<NGInlineItemResults> BreakLines(NGInlineNode node,
-                                         LayoutUnit available_width) {
+  Vector<NGLineInfo> BreakToLineInfo(NGInlineNode node,
+                                     LayoutUnit available_width) {
     DCHECK(node);
 
     node.PrepareLayoutIfNeeded();
@@ -46,11 +46,11 @@
 
     scoped_refptr<NGInlineBreakToken> break_token;
 
-    Vector<NGInlineItemResults> lines;
+    Vector<NGLineInfo> line_infos;
     NGExclusionSpace exclusion_space;
     NGLineLayoutOpportunity line_opportunity(available_width);
     while (!break_token || !break_token->IsFinished()) {
-      NGLineInfo line_info;
+      NGLineInfo& line_info = line_infos.emplace_back();
       NGLineBreaker line_breaker(node, NGLineBreakerMode::kContent, space,
                                  &positioned_floats, &unpositioned_floats,
                                  /* container_builder */ nullptr,
@@ -62,9 +62,17 @@
         break;
 
       break_token = line_breaker.CreateBreakToken(line_info);
-      lines.push_back(std::move(line_info.Results()));
     }
 
+    return line_infos;
+  }
+
+  Vector<NGInlineItemResults> BreakLines(NGInlineNode node,
+                                         LayoutUnit available_width) {
+    Vector<NGLineInfo> line_infos = BreakToLineInfo(node, available_width);
+    Vector<NGInlineItemResults> lines;
+    for (NGLineInfo& line_info : line_infos)
+      lines.push_back(std::move(line_info.Results()));
     return lines;
   }
 };
@@ -312,6 +320,68 @@
   EXPECT_EQ("789", ToString(lines[1], node));
 }
 
+struct TrailingSpaceWidthTestData {
+  const char* html;
+  const char* white_space;
+  unsigned trailing_space_width;
+} trailing_space_width_test_data[] = {
+    {" ", "pre", 1},
+    {"   ", "pre", 3},
+    {"1 ", "pre", 1},
+    {"1  ", "pre", 2},
+    {"1<span> </span>", "pre", 1},
+    {"<span>1 </span> ", "pre", 2},
+    {"1<span> </span> ", "pre", 2},
+    {"1 <span> </span> ", "pre", 3},
+    {"1 \t", "pre", 3},
+    {"1  \n", "pre", 2},
+    {"1  <br>", "pre", 2},
+
+    {" ", "pre-wrap", 1},
+    {"   ", "pre-wrap", 3},
+    {"1 ", "pre-wrap", 1},
+    {"1  ", "pre-wrap", 2},
+    {"1<span> </span>", "pre-wrap", 1},
+    {"<span>1 </span> ", "pre-wrap", 2},
+    {"1<span> </span> ", "pre-wrap", 2},
+    {"1 <span> </span> ", "pre-wrap", 3},
+    {"1 \t", "pre-wrap", 3},
+    {"1  <br>", "pre-wrap", 2},
+    {"12 1234", "pre-wrap", 1},
+    {"12  1234", "pre-wrap", 2},
+};
+
+class NGTrailingSpaceWidthTest
+    : public NGLineBreakerTest,
+      public testing::WithParamInterface<TrailingSpaceWidthTestData> {};
+
+INSTANTIATE_TEST_CASE_P(NGLineBreakerTest,
+                        NGTrailingSpaceWidthTest,
+                        testing::ValuesIn(trailing_space_width_test_data));
+
+TEST_P(NGTrailingSpaceWidthTest, TrailingSpaceWidth) {
+  const auto& data = GetParam();
+  LoadAhem();
+  NGInlineNode node = CreateInlineNode(String(R"HTML(
+    <!DOCTYPE html>
+    <style>
+    #container {
+      font: 10px/1 Ahem;
+      width: 50px;
+      tab-size: 2;
+      white-space: )HTML") + data.white_space +
+                                       R"HTML(;
+    }
+    </style>
+    <div id=container>)HTML" + data.html +
+                                       R"HTML(</div>
+  )HTML");
+
+  Vector<NGLineInfo> line_infos = BreakToLineInfo(node, LayoutUnit(50));
+  EXPECT_EQ(line_infos[0].ComputeTrailingSpaceWidth(),
+            LayoutUnit(10) * data.trailing_space_width);
+}
+
 #undef MAYBE_OverflowAtomicInline
 }  // namespace
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
index b66b82f..e2fbc16 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
@@ -921,8 +921,7 @@
 
 LayoutUnit LineOffsetForTextAlign(ETextAlign text_align,
                                   TextDirection direction,
-                                  LayoutUnit space_left,
-                                  LayoutUnit trailing_spaces_width) {
+                                  LayoutUnit space_left) {
   bool is_ltr = IsLtr(direction);
   if (text_align == ETextAlign::kStart || text_align == ETextAlign::kJustify)
     text_align = is_ltr ? ETextAlign::kLeft : ETextAlign::kRight;
@@ -943,7 +942,7 @@
     case ETextAlign::kWebkitRight: {
       // In RTL, trailing spaces appear on the left of the line.
       if (UNLIKELY(!is_ltr))
-        return space_left - trailing_spaces_width;
+        return space_left;
       // Wide lines spill out of the block based off direction.
       // So even if text-align is right, if direction is LTR, wide lines
       // should overflow out of the right side of the block.
@@ -957,9 +956,9 @@
         return (space_left / 2).ClampNegativeToZero();
       // In RTL, trailing spaces appear on the left of the line.
       if (space_left > LayoutUnit())
-        return (space_left / 2).ClampNegativeToZero() - trailing_spaces_width;
+        return (space_left / 2).ClampNegativeToZero();
       // In RTL, wide lines should spill out to the left, same as kRight.
-      return space_left - trailing_spaces_width;
+      return space_left;
     }
     default:
       NOTREACHED();
@@ -971,7 +970,7 @@
                                     LayoutUnit space_left) {
   TextDirection direction = container_style.Direction();
   LayoutUnit line_offset = LineOffsetForTextAlign(
-      container_style.GetTextAlign(), direction, space_left, LayoutUnit());
+      container_style.GetTextAlign(), direction, space_left);
   return IsLtr(direction) ? line_offset : space_left - line_offset;
 }
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_length_utils.h b/third_party/blink/renderer/core/layout/ng/ng_length_utils.h
index 6127283b..28581eb 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_length_utils.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_length_utils.h
@@ -306,8 +306,7 @@
 // text-align, direction and amount of unused space.
 CORE_EXPORT LayoutUnit LineOffsetForTextAlign(ETextAlign,
                                               TextDirection,
-                                              LayoutUnit space_left,
-                                              LayoutUnit trailing_spaces_width);
+                                              LayoutUnit space_left);
 
 // Same as |LineOffsetForTextAlign| but returns the logical inline offset
 // instead of line-left offset.
diff --git a/third_party/blink/renderer/core/loader/mixed_content_checker.cc b/third_party/blink/renderer/core/loader/mixed_content_checker.cc
index 43a77bb..1c148e0d 100644
--- a/third_party/blink/renderer/core/loader/mixed_content_checker.cc
+++ b/third_party/blink/renderer/core/loader/mixed_content_checker.cc
@@ -725,21 +725,6 @@
       !effective_frame)
     return;
 
-  // There should not be certificate errors for non-HTTPS responses.
-  DCHECK(response.CurrentRequestUrl().ProtocolIs("https"));
-
-  // Avoid logging in cases where the page URL is HTTP and the response
-  // URL is HTTPS.
-  if (MainResourceUrlForFrame(effective_frame).ProtocolIs("https")) {
-    String message = String::Format(
-        "Mixed Content: The page at '%s' attempted to load subresource "
-        "at '%s' over broken HTTPS.",
-        MainResourceUrlForFrame(effective_frame).ElidedString().Utf8().data(),
-        response.CurrentRequestUrl().ElidedString().Utf8().data());
-    frame->GetDocument()->AddConsoleMessage(ConsoleMessage::Create(
-        kSecurityMessageSource, kErrorMessageLevel, message));
-  }
-
   // Use the current local frame's client; the embedder doesn't distinguish
   // mixed content signals from different frames on the same page.
   LocalFrameClient* client = frame->Client();
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h
index 63263e8..4b28646 100644
--- a/third_party/blink/renderer/core/style/computed_style.h
+++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -2488,7 +2488,7 @@
 
   StyleColor DecorationColorIncludingFallback(bool visited_link) const;
 
-  Color StopColor() const { return SvgStyle().StopColor(); }
+  const StyleColor& StopColor() const { return SvgStyle().StopColor(); }
   StyleColor FloodColor() const { return SvgStyle().FloodColor(); }
   StyleColor LightingColor() const { return SvgStyle().LightingColor(); }
 
diff --git a/third_party/blink/renderer/core/style/svg_computed_style.h b/third_party/blink/renderer/core/style/svg_computed_style.h
index 3eb4bc6a..c0d4aac 100644
--- a/third_party/blink/renderer/core/style/svg_computed_style.h
+++ b/third_party/blink/renderer/core/style/svg_computed_style.h
@@ -232,7 +232,7 @@
       stops.Access()->opacity = obj;
   }
 
-  void SetStopColor(const Color& obj) {
+  void SetStopColor(const StyleColor& obj) {
     if (!(stops->color == obj))
       stops.Access()->color = obj;
   }
@@ -320,7 +320,7 @@
   const UnzoomedLength& StrokeWidth() const { return stroke->width; }
   const Length& StrokeDashOffset() const { return stroke->dash_offset; }
   float StopOpacity() const { return stops->opacity; }
-  const Color& StopColor() const { return stops->color; }
+  const StyleColor& StopColor() const { return stops->color; }
   float FloodOpacity() const { return misc->flood_opacity; }
   StyleColor FloodColor() const {
     return misc->flood_color_is_current_color ? StyleColor::CurrentColor()
diff --git a/third_party/blink/renderer/core/style/svg_computed_style_defs.cc b/third_party/blink/renderer/core/style/svg_computed_style_defs.cc
index 95d40a0..c6d8ee1e 100644
--- a/third_party/blink/renderer/core/style/svg_computed_style_defs.cc
+++ b/third_party/blink/renderer/core/style/svg_computed_style_defs.cc
@@ -93,11 +93,11 @@
 }
 
 StyleStopData::StyleStopData()
-    : opacity(SVGComputedStyle::InitialStopOpacity()),
-      color(SVGComputedStyle::InitialStopColor()) {}
+    : color(SVGComputedStyle::InitialStopColor()),
+      opacity(SVGComputedStyle::InitialStopOpacity()) {}
 
 StyleStopData::StyleStopData(const StyleStopData& other)
-    : RefCounted<StyleStopData>(), opacity(other.opacity), color(other.color) {}
+    : RefCounted<StyleStopData>(), color(other.color), opacity(other.opacity) {}
 
 bool StyleStopData::operator==(const StyleStopData& other) const {
   return color == other.color && opacity == other.opacity;
diff --git a/third_party/blink/renderer/core/style/svg_computed_style_defs.h b/third_party/blink/renderer/core/style/svg_computed_style_defs.h
index 5920c75..915d9bc 100644
--- a/third_party/blink/renderer/core/style/svg_computed_style_defs.h
+++ b/third_party/blink/renderer/core/style/svg_computed_style_defs.h
@@ -30,6 +30,7 @@
 
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/css/style_color.h"
 #include "third_party/blink/renderer/core/style/style_path.h"
 #include "third_party/blink/renderer/platform/geometry/length.h"
 #include "third_party/blink/renderer/platform/graphics/color.h"
@@ -249,8 +250,8 @@
     return !(*this == other);
   }
 
+  StyleColor color;
   float opacity;
-  Color color;
 
  private:
   StyleStopData();
diff --git a/third_party/blink/renderer/core/svg/svg_stop_element.cc b/third_party/blink/renderer/core/svg/svg_stop_element.cc
index 03ecf0e..18bf829 100644
--- a/third_party/blink/renderer/core/svg/svg_stop_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_stop_element.cc
@@ -80,8 +80,8 @@
   if (!style)
     return Color::kBlack;
 
-  const SVGComputedStyle& svg_style = style->SvgStyle();
-  return svg_style.StopColor().CombineWithAlpha(svg_style.StopOpacity());
+  Color base_color = style->VisitedDependentColor(GetCSSPropertyStopColor());
+  return base_color.CombineWithAlpha(style->SvgStyle().StopOpacity());
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/testing/internals.cc b/third_party/blink/renderer/core/testing/internals.cc
index 0749569..59d5b156 100644
--- a/third_party/blink/renderer/core/testing/internals.cc
+++ b/third_party/blink/renderer/core/testing/internals.cc
@@ -3437,6 +3437,10 @@
       .InSecondsF();
 }
 
+int64_t Internals::currentTimeTicks() {
+  return base::TimeTicks::Now().since_origin().InMicroseconds();
+}
+
 String Internals::getScrollAnimationState(Node* node) const {
   if (ScrollableArea* scrollable_area = ScrollableAreaForNode(node))
     return scrollable_area->GetScrollAnimator().RunStateAsText();
diff --git a/third_party/blink/renderer/core/testing/internals.h b/third_party/blink/renderer/core/testing/internals.h
index c66407f..3ecbc535 100644
--- a/third_party/blink/renderer/core/testing/internals.h
+++ b/third_party/blink/renderer/core/testing/internals.h
@@ -556,6 +556,9 @@
   // document time in seconds
   double monotonicTimeToZeroBasedDocumentTime(double, ExceptionState&);
 
+  // Returns the current time ticks (in microseconds).
+  int64_t currentTimeTicks();
+
   // Returns the run state of the node's scroll animator (see
   // ScrollAnimatorCompositorCoordinater::RunState), or -1 if the node does not
   // have a scrollable area.
diff --git a/third_party/blink/renderer/core/testing/internals.idl b/third_party/blink/renderer/core/testing/internals.idl
index 36183a035..96ec876 100644
--- a/third_party/blink/renderer/core/testing/internals.idl
+++ b/third_party/blink/renderer/core/testing/internals.idl
@@ -380,6 +380,7 @@
     boolean setScrollbarVisibilityInScrollableArea(Node node, boolean visible);
 
     [RaisesException] double monotonicTimeToZeroBasedDocumentTime(double platformTime);
+    long long currentTimeTicks();
 
     DOMString getScrollAnimationState(Node node);
 
diff --git a/third_party/blink/renderer/core/timing/performance.idl b/third_party/blink/renderer/core/timing/performance.idl
index ae021aaa..533673e 100644
--- a/third_party/blink/renderer/core/timing/performance.idl
+++ b/third_party/blink/renderer/core/timing/performance.idl
@@ -65,7 +65,7 @@
     // User Timing
     // https://w3c.github.io/user-timing/#extensions-performance-interface
     // We use the returned value for feature detection:
-    // * L2 API returns null.
+    // * L2 API returns null but this is a bug: crbug.com/914441.
     // * L3 API returns the created entry.
     [MeasureAs=UserTiming, CallWith=ScriptState, RaisesException] PerformanceMark? mark(DOMString markName);
     [MeasureAs=UserTiming, CallWith=ScriptState, RuntimeEnabled=CustomUserTiming, RaisesException] PerformanceMark? mark(DOMString markName, (DOMHighResTimeStamp or PerformanceMarkOptions) startTimeOrPerformanceMarkOptions);
@@ -75,7 +75,7 @@
     // * passing PerformanceMeasureOptions to |startOrOptions|
     // * passing timestamps to |startOrOptions| or |end|
     // We use the returned value for feature detection:
-    // * L2 API returns null.
+    // * L2 API returns null but this is a bug: crbug.com/914441.
     // * L3 API returns the created entry.
     // Custom User Timing (or User Timing L3) explainer:
     // https://docs.google.com/document/d/1hltt8z9C4PaI5Qu1YMIp1wOGdbJPJPoJwBarEeCY6xQ/edit#heading=h.ejti6qhmjv0b
diff --git a/third_party/blink/renderer/modules/webmidi/BUILD.gn b/third_party/blink/renderer/modules/webmidi/BUILD.gn
index 65b0f4c..1d56cbd 100644
--- a/third_party/blink/renderer/modules/webmidi/BUILD.gn
+++ b/third_party/blink/renderer/modules/webmidi/BUILD.gn
@@ -15,6 +15,8 @@
     "midi_accessor_client.h",
     "midi_connection_event.cc",
     "midi_connection_event.h",
+    "midi_dispatcher.cc",
+    "midi_dispatcher.h",
     "midi_input.cc",
     "midi_input.h",
     "midi_input_map.cc",
diff --git a/third_party/blink/renderer/modules/webmidi/midi_accessor.cc b/third_party/blink/renderer/modules/webmidi/midi_accessor.cc
index c27ead34..6678254a 100644
--- a/third_party/blink/renderer/modules/webmidi/midi_accessor.cc
+++ b/third_party/blink/renderer/modules/webmidi/midi_accessor.cc
@@ -33,14 +33,13 @@
 #include <memory>
 
 #include "base/memory/ptr_util.h"
-#include "third_party/blink/public/platform/modules/webmidi/web_midi_accessor.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/renderer/modules/webmidi/midi_accessor_client.h"
+#include "third_party/blink/renderer/modules/webmidi/midi_dispatcher.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
-using blink::WebString;
-using midi::mojom::PortState;
-using midi::mojom::Result;
+using midi::mojom::blink::PortState;
+using midi::mojom::blink::Result;
 
 namespace blink {
 
@@ -51,35 +50,37 @@
 
 MIDIAccessor::MIDIAccessor(MIDIAccessorClient* client) : client_(client) {
   DCHECK(client);
+}
 
-  accessor_ = Platform::Current()->CreateMIDIAccessor(this);
-
-  DCHECK(accessor_);
+MIDIAccessor::~MIDIAccessor() {
+  if (called_start_session_)
+    MIDIDispatcher::Instance().RemoveAccessor(this);
 }
 
 void MIDIAccessor::StartSession() {
-  accessor_->StartSession();
+  MIDIDispatcher::Instance().AddAccessor(this);
+  called_start_session_ = true;
 }
 
 void MIDIAccessor::SendMIDIData(unsigned port_index,
                                 const unsigned char* data,
                                 size_t length,
                                 base::TimeTicks time_stamp) {
-  accessor_->SendMIDIData(port_index, data, length, time_stamp);
+  MIDIDispatcher::Instance().SendMidiData(port_index, data, length, time_stamp);
 }
 
-void MIDIAccessor::DidAddInputPort(const WebString& id,
-                                   const WebString& manufacturer,
-                                   const WebString& name,
-                                   const WebString& version,
+void MIDIAccessor::DidAddInputPort(const String& id,
+                                   const String& manufacturer,
+                                   const String& name,
+                                   const String& version,
                                    PortState state) {
   client_->DidAddInputPort(id, manufacturer, name, version, state);
 }
 
-void MIDIAccessor::DidAddOutputPort(const WebString& id,
-                                    const WebString& manufacturer,
-                                    const WebString& name,
-                                    const WebString& version,
+void MIDIAccessor::DidAddOutputPort(const String& id,
+                                    const String& manufacturer,
+                                    const String& name,
+                                    const String& version,
                                     PortState state) {
   client_->DidAddOutputPort(id, manufacturer, name, version, state);
 }
diff --git a/third_party/blink/renderer/modules/webmidi/midi_accessor.h b/third_party/blink/renderer/modules/webmidi/midi_accessor.h
index fdd8214..1c7977a 100644
--- a/third_party/blink/renderer/modules/webmidi/midi_accessor.h
+++ b/third_party/blink/renderer/modules/webmidi/midi_accessor.h
@@ -34,21 +34,21 @@
 #include <memory>
 #include "base/time/time.h"
 #include "media/midi/midi_service.mojom-blink.h"
-#include "third_party/blink/public/platform/modules/webmidi/web_midi_accessor.h"
-#include "third_party/blink/public/platform/modules/webmidi/web_midi_accessor_client.h"
+#include "third_party/blink/renderer/modules/webmidi/midi_dispatcher.h"
 #include "third_party/blink/renderer/platform/wtf/allocator.h"
 
 namespace blink {
 
 class MIDIAccessorClient;
 
-class MIDIAccessor final : public WebMIDIAccessorClient {
+// TODO(https://crbug.com/582328): Remove this class, and call MIDIDispatcher
+// directly.
+class MIDIAccessor final {
   USING_FAST_MALLOC(MIDIAccessor);
 
  public:
   static std::unique_ptr<MIDIAccessor> Create(MIDIAccessorClient*);
-
-  ~MIDIAccessor() override = default;
+  ~MIDIAccessor();
 
   void StartSession();
   void SendMIDIData(unsigned port_index,
@@ -60,32 +60,31 @@
   // once the initialization successfully finishes.
   void SetClient(MIDIAccessorClient* client) { client_ = client; }
 
-  // WebMIDIAccessorClient
-  void DidAddInputPort(const WebString& id,
-                       const WebString& manufacturer,
-                       const WebString& name,
-                       const WebString& version,
-                       midi::mojom::PortState) override;
-  void DidAddOutputPort(const WebString& id,
-                        const WebString& manufacturer,
-                        const WebString& name,
-                        const WebString& version,
-                        midi::mojom::PortState) override;
-  void DidSetInputPortState(unsigned port_index,
-                            midi::mojom::PortState) override;
-  void DidSetOutputPortState(unsigned port_index,
-                             midi::mojom::PortState) override;
-  void DidStartSession(midi::mojom::Result) override;
+  // The following methods are used by MIDIDispatcher to forward messages from
+  // the browser process.
+  void DidAddInputPort(const String& id,
+                       const String& manufacturer,
+                       const String& name,
+                       const String& version,
+                       midi::mojom::PortState);
+  void DidAddOutputPort(const String& id,
+                        const String& manufacturer,
+                        const String& name,
+                        const String& version,
+                        midi::mojom::PortState);
+  void DidSetInputPortState(unsigned port_index, midi::mojom::PortState);
+  void DidSetOutputPortState(unsigned port_index, midi::mojom::PortState);
+  void DidStartSession(midi::mojom::Result);
   void DidReceiveMIDIData(unsigned port_index,
                           const unsigned char* data,
                           size_t length,
-                          base::TimeTicks time_stamp) override;
+                          base::TimeTicks time_stamp);
 
  private:
   explicit MIDIAccessor(MIDIAccessorClient*);
 
   MIDIAccessorClient* client_;
-  std::unique_ptr<WebMIDIAccessor> accessor_;
+  bool called_start_session_ = false;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/webmidi/midi_dispatcher.cc b/third_party/blink/renderer/modules/webmidi/midi_dispatcher.cc
new file mode 100644
index 0000000..916406c
--- /dev/null
+++ b/third_party/blink/renderer/modules/webmidi/midi_dispatcher.cc
@@ -0,0 +1,177 @@
+// 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 "third_party/blink/renderer/modules/webmidi/midi_dispatcher.h"
+
+#include "third_party/blink/public/platform/interface_provider.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/renderer/modules/webmidi/midi_accessor.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
+
+namespace blink {
+
+namespace {
+// The maximum number of bytes which we're allowed to send to the browser
+// before getting acknowledgement back from the browser that they've been
+// successfully sent.
+static const size_t kMaxUnacknowledgedBytesSent = 10 * 1024 * 1024;  // 10 MB.
+}  // namespace
+
+MIDIDispatcher::MIDIDispatcher() : binding_(this) {}
+
+MIDIDispatcher::~MIDIDispatcher() = default;
+
+MIDIDispatcher& MIDIDispatcher::Instance() {
+  DEFINE_STATIC_LOCAL(Persistent<MIDIDispatcher>, midi_dispatcher,
+                      (MakeGarbageCollected<MIDIDispatcher>()));
+  return *midi_dispatcher;
+}
+
+void MIDIDispatcher::Trace(Visitor* visitor) {}
+
+void MIDIDispatcher::AddAccessor(MIDIAccessor* accessor) {
+  TRACE_EVENT0("midi", "MIDIDispatcher::AddAccessor");
+  accessors_waiting_session_queue_.push_back(accessor);
+  if (session_result_ != midi::mojom::Result::NOT_INITIALIZED) {
+    SessionStarted(session_result_);
+  } else if (accessors_waiting_session_queue_.size() == 1u) {
+    midi::mojom::blink::MidiSessionClientPtr client_ptr;
+    binding_.Bind(mojo::MakeRequest(&client_ptr));
+    GetMidiSessionProvider().StartSession(mojo::MakeRequest(&midi_session_),
+                                          std::move(client_ptr));
+  }
+}
+
+void MIDIDispatcher::RemoveAccessor(MIDIAccessor* accessor) {
+  DCHECK(accessors_.Contains(accessor) ||
+         accessors_waiting_session_queue_.Contains(accessor))
+      << "RemoveAccessor call was not balanced with AddAccessor call";
+  accessors_.EraseAt(accessors_.Find(accessor));
+  auto** it = std::find(accessors_waiting_session_queue_.begin(),
+                        accessors_waiting_session_queue_.end(), accessor);
+  if (it != accessors_waiting_session_queue_.end())
+    accessors_waiting_session_queue_.erase(it);
+  if (accessors_.IsEmpty() && accessors_waiting_session_queue_.IsEmpty()) {
+    session_result_ = midi::mojom::Result::NOT_INITIALIZED;
+    inputs_.clear();
+    outputs_.clear();
+    midi_session_.reset();
+    midi_session_provider_.reset();
+    binding_.Close();
+  }
+}
+
+void MIDIDispatcher::SendMidiData(uint32_t port,
+                                  const uint8_t* data,
+                                  size_t length,
+                                  base::TimeTicks timestamp) {
+  if ((kMaxUnacknowledgedBytesSent - unacknowledged_bytes_sent_) < length) {
+    // TODO(toyoshim): buffer up the data to send at a later time.
+    // For now we're just dropping these bytes on the floor.
+    return;
+  }
+
+  unacknowledged_bytes_sent_ += length;
+  Vector<uint8_t> v;
+  v.Append(data, length);
+  GetMidiSession().SendData(port, std::move(v), timestamp);
+}
+
+void MIDIDispatcher::AddInputPort(midi::mojom::blink::PortInfoPtr info) {
+  inputs_.push_back(*info);
+  // Iterating over a copy of |accessors_| as callback could result in
+  // |accessors_| being modified. Applies to for-loops later in this file as
+  // well.
+  for (auto* accessor : AccessorList(accessors_)) {
+    accessor->DidAddInputPort(info->id, info->manufacturer, info->name,
+                              info->version, info->state);
+  }
+}
+
+void MIDIDispatcher::AddOutputPort(midi::mojom::blink::PortInfoPtr info) {
+  outputs_.push_back(*info);
+  for (auto* accessor : AccessorList(accessors_)) {
+    accessor->DidAddOutputPort(info->id, info->manufacturer, info->name,
+                               info->version, info->state);
+  }
+}
+
+void MIDIDispatcher::SetInputPortState(uint32_t port,
+                                       midi::mojom::blink::PortState state) {
+  if (inputs_[port].state == state)
+    return;
+  inputs_[port].state = state;
+  for (auto* accessor : AccessorList(accessors_))
+    accessor->DidSetInputPortState(port, state);
+}
+
+void MIDIDispatcher::SetOutputPortState(uint32_t port,
+                                        midi::mojom::blink::PortState state) {
+  if (outputs_[port].state == state)
+    return;
+  outputs_[port].state = state;
+  for (auto* accessor : AccessorList(accessors_))
+    accessor->DidSetOutputPortState(port, state);
+}
+
+void MIDIDispatcher::SessionStarted(midi::mojom::blink::Result result) {
+  TRACE_EVENT0("midi", "MIDIDispatcher::OnSessionStarted");
+  session_result_ = result;
+
+  // A for-loop using iterators does not work because |accessor| may touch
+  // |accessors_waiting_session_queue_| in callbacks.
+  while (!accessors_waiting_session_queue_.IsEmpty()) {
+    auto* accessor = accessors_waiting_session_queue_.back();
+    accessors_waiting_session_queue_.pop_back();
+    if (result == midi::mojom::blink::Result::OK) {
+      // Add the accessor's input and output ports.
+      for (const auto& info : inputs_) {
+        accessor->DidAddInputPort(info.id, info.manufacturer, info.name,
+                                  info.version, info.state);
+      }
+
+      for (const auto& info : outputs_) {
+        accessor->DidAddOutputPort(info.id, info.manufacturer, info.name,
+                                   info.version, info.state);
+      }
+    }
+    accessor->DidStartSession(result);
+    accessors_.push_back(accessor);
+  }
+}
+
+void MIDIDispatcher::AcknowledgeSentData(uint32_t bytes_sent) {
+  DCHECK_GE(unacknowledged_bytes_sent_, bytes_sent);
+  if (unacknowledged_bytes_sent_ >= bytes_sent)
+    unacknowledged_bytes_sent_ -= bytes_sent;
+}
+
+void MIDIDispatcher::DataReceived(uint32_t port,
+                                  const Vector<uint8_t>& data,
+                                  base::TimeTicks timestamp) {
+  TRACE_EVENT0("midi", "MIDIDispatcher::DataReceived");
+  DCHECK(!data.IsEmpty());
+
+  for (auto* accessor : AccessorList(accessors_))
+    accessor->DidReceiveMIDIData(port, &data[0], data.size(), timestamp);
+}
+
+midi::mojom::blink::MidiSessionProvider&
+MIDIDispatcher::GetMidiSessionProvider() {
+  if (!midi_session_provider_) {
+    Platform::Current()->GetInterfaceProvider()->GetInterface(
+        mojo::MakeRequest(&midi_session_provider_));
+  }
+  return *midi_session_provider_;
+}
+
+midi::mojom::blink::MidiSession& MIDIDispatcher::GetMidiSession() {
+  DCHECK(midi_session_);
+  return *midi_session_;
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/webmidi/midi_dispatcher.h b/third_party/blink/renderer/modules/webmidi/midi_dispatcher.h
new file mode 100644
index 0000000..7b0ebf0
--- /dev/null
+++ b/third_party/blink/renderer/modules/webmidi/midi_dispatcher.h
@@ -0,0 +1,80 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_MODULES_WEBMIDI_MIDI_DISPATCHER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBMIDI_MIDI_DISPATCHER_H_
+
+#include "media/midi/midi_service.mojom-blink.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+class MIDIAccessor;
+
+class MIDIDispatcher : public GarbageCollectedFinalized<MIDIDispatcher>,
+                       public midi::mojom::blink::MidiSessionClient {
+ public:
+  static MIDIDispatcher& Instance();
+  ~MIDIDispatcher() override;
+
+  void Trace(Visitor* visitor);
+
+  void AddAccessor(MIDIAccessor* accessor);
+  void RemoveAccessor(MIDIAccessor* accessor);
+  void SendMidiData(uint32_t port,
+                    const uint8_t* data,
+                    size_t length,
+                    base::TimeTicks timestamp);
+
+  // midi::mojom::blink::MidiSessionClient implementation.
+  // All of the following methods are run on the main thread.
+  void AddInputPort(midi::mojom::blink::PortInfoPtr info) override;
+  void AddOutputPort(midi::mojom::blink::PortInfoPtr info) override;
+  void SetInputPortState(uint32_t port,
+                         midi::mojom::blink::PortState state) override;
+  void SetOutputPortState(uint32_t port,
+                          midi::mojom::blink::PortState state) override;
+  void SessionStarted(midi::mojom::blink::Result result) override;
+  void AcknowledgeSentData(uint32_t bytes) override;
+  void DataReceived(uint32_t port,
+                    const Vector<uint8_t>& data,
+                    base::TimeTicks timestamp) override;
+
+ private:
+  friend class ConstructTrait<MIDIDispatcher>;
+
+  MIDIDispatcher();
+
+  midi::mojom::blink::MidiSessionProvider& GetMidiSessionProvider();
+  midi::mojom::blink::MidiSession& GetMidiSession();
+
+  // Keeps track of all MIDI accessors.
+  typedef Vector<MIDIAccessor*> AccessorList;
+  AccessorList accessors_;
+
+  // Represents accessors that are waiting for a session being open.
+  typedef Vector<MIDIAccessor*> AccessorQueue;
+  AccessorQueue accessors_waiting_session_queue_;
+
+  // Represents a result on starting a session.
+  midi::mojom::blink::Result session_result_ =
+      midi::mojom::Result::NOT_INITIALIZED;
+
+  // Holds MidiPortInfoList for input ports and output ports.
+  Vector<midi::mojom::blink::PortInfo> inputs_;
+  Vector<midi::mojom::blink::PortInfo> outputs_;
+
+  size_t unacknowledged_bytes_sent_ = 0u;
+
+  midi::mojom::blink::MidiSessionProviderPtr midi_session_provider_;
+  midi::mojom::blink::MidiSessionPtr midi_session_;
+
+  mojo::Binding<midi::mojom::blink::MidiSessionClient> binding_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBMIDI_MIDI_DISPATCHER_H_
diff --git a/third_party/blink/renderer/platform/exported/platform.cc b/third_party/blink/renderer/platform/exported/platform.cc
index 5e03ba6e..286717cd 100644
--- a/third_party/blink/renderer/platform/exported/platform.cc
+++ b/third_party/blink/renderer/platform/exported/platform.cc
@@ -39,7 +39,6 @@
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "third_party/blink/public/platform/interface_provider.h"
-#include "third_party/blink/public/platform/modules/webmidi/web_midi_accessor.h"
 #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
 #include "third_party/blink/public/platform/web_canvas_capture_handler.h"
 #include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
@@ -264,11 +263,6 @@
   return InterfaceProvider::GetEmptyInterfaceProvider();
 }
 
-std::unique_ptr<WebMIDIAccessor> Platform::CreateMIDIAccessor(
-    WebMIDIAccessorClient*) {
-  return nullptr;
-}
-
 std::unique_ptr<WebStorageNamespace> Platform::CreateLocalStorageNamespace() {
   return nullptr;
 }
diff --git a/third_party/blink/renderer/platform/fonts/script_run_iterator.cc b/third_party/blink/renderer/platform/fonts/script_run_iterator.cc
index 012238f..cf3bf209 100644
--- a/third_party/blink/renderer/platform/fonts/script_run_iterator.cc
+++ b/third_party/blink/renderer/platform/fonts/script_run_iterator.cc
@@ -168,7 +168,7 @@
 ScriptRunIterator::ScriptRunIterator(const UChar* text, wtf_size_t length)
     : ScriptRunIterator(text, length, ICUScriptData::Instance()) {}
 
-bool ScriptRunIterator::Consume(unsigned& limit, UScriptCode& script) {
+bool ScriptRunIterator::Consume(unsigned* limit, UScriptCode* script) {
   if (current_set_.IsEmpty()) {
     return false;
   }
@@ -188,16 +188,16 @@
         break;
     }
     if (!MergeSets()) {
-      limit = pos;
-      script = ResolveCurrentScript();
-      FixupStack(script);
+      *limit = pos;
+      *script = ResolveCurrentScript();
+      FixupStack(*script);
       current_set_ = *next_set_;
       return true;
     }
   }
 
-  limit = length_;
-  script = ResolveCurrentScript();
+  *limit = length_;
+  *script = ResolveCurrentScript();
   current_set_.clear();
   return true;
 }
diff --git a/third_party/blink/renderer/platform/fonts/script_run_iterator.h b/third_party/blink/renderer/platform/fonts/script_run_iterator.h
index 6f3f16ae..39d23e3 100644
--- a/third_party/blink/renderer/platform/fonts/script_run_iterator.h
+++ b/third_party/blink/renderer/platform/fonts/script_run_iterator.h
@@ -31,7 +31,7 @@
   // the process.
   ScriptRunIterator(const UChar* text, wtf_size_t length, const ScriptData*);
 
-  bool Consume(unsigned& limit, UScriptCode&);
+  bool Consume(unsigned* limit, UScriptCode*);
 
   static constexpr int kMaxScriptCount = 20;
   using UScriptCodeList = Vector<UScriptCode, kMaxScriptCount>;
diff --git a/third_party/blink/renderer/platform/fonts/script_run_iterator_test.cc b/third_party/blink/renderer/platform/fonts/script_run_iterator_test.cc
index a792bdf..0432f68 100644
--- a/third_party/blink/renderer/platform/fonts/script_run_iterator_test.cc
+++ b/third_party/blink/renderer/platform/fonts/script_run_iterator_test.cc
@@ -316,7 +316,7 @@
     unsigned limit;
     UScriptCode code;
     unsigned long run_count = 0;
-    while (script_run_iterator->Consume(limit, code)) {
+    while (script_run_iterator->Consume(&limit, &code)) {
       ASSERT_LT(run_count, expect.size());
       ASSERT_EQ(expect[run_count].limit, limit);
       ASSERT_EQ(expect[run_count].code, code);
@@ -331,7 +331,7 @@
   ScriptRunIterator script_run_iterator(empty.Characters16(), empty.length());
   unsigned limit = 0;
   UScriptCode code = USCRIPT_INVALID_CODE;
-  DCHECK(!script_run_iterator.Consume(limit, code));
+  DCHECK(!script_run_iterator.Consume(&limit, &code));
   ASSERT_EQ(limit, 0u);
   ASSERT_EQ(code, USCRIPT_INVALID_CODE);
 }
diff --git a/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.cc b/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.cc
index b6c634c..910b4ba 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h"
 
+#include <algorithm>
 #include <memory>
 
 #include "third_party/blink/renderer/platform/fonts/script_run_iterator.h"
@@ -37,38 +38,14 @@
       symbols_iterator_position_(0),
       at_end_(!buffer_size_) {}
 
-void RunSegmenter::ConsumeScriptIteratorPastLastSplit() {
-  DCHECK(script_run_iterator_);
-  if (script_run_iterator_position_ <= last_split_ &&
-      script_run_iterator_position_ < buffer_size_) {
-    while (script_run_iterator_->Consume(script_run_iterator_position_,
-                                         candidate_range_.script)) {
-      if (script_run_iterator_position_ > last_split_)
-        return;
-    }
-  }
-}
-
-void RunSegmenter::ConsumeOrientationIteratorPastLastSplit() {
-  if (orientation_iterator_ && orientation_iterator_position_ <= last_split_ &&
-      orientation_iterator_position_ < buffer_size_) {
-    while (
-        orientation_iterator_->Consume(&orientation_iterator_position_,
-                                       &candidate_range_.render_orientation)) {
-      if (orientation_iterator_position_ > last_split_)
-        return;
-    }
-  }
-}
-
-void RunSegmenter::ConsumeSymbolsIteratorPastLastSplit() {
-  DCHECK(symbols_iterator_);
-  if (symbols_iterator_position_ <= last_split_ &&
-      symbols_iterator_position_ < buffer_size_) {
-    while (
-        symbols_iterator_->Consume(&symbols_iterator_position_,
-                                   &candidate_range_.font_fallback_priority)) {
-      if (symbols_iterator_position_ > last_split_)
+template <class Iterator, typename SegmentationCategory>
+void RunSegmenter::ConsumeIteratorPastLastSplit(
+    std::unique_ptr<Iterator>& iterator,
+    unsigned* iterator_position,
+    SegmentationCategory* segmentation_category) {
+  if (*iterator_position <= last_split_ && *iterator_position < buffer_size_) {
+    while (iterator->Consume(iterator_position, segmentation_category)) {
+      if (*iterator_position > last_split_)
         return;
     }
   }
@@ -80,24 +57,20 @@
   if (at_end_)
     return false;
 
-  ConsumeScriptIteratorPastLastSplit();
-  ConsumeOrientationIteratorPastLastSplit();
-  ConsumeSymbolsIteratorPastLastSplit();
+  ConsumeIteratorPastLastSplit(script_run_iterator_,
+                               &script_run_iterator_position_,
+                               &candidate_range_.script);
+  ConsumeIteratorPastLastSplit(orientation_iterator_,
+                               &orientation_iterator_position_,
+                               &candidate_range_.render_orientation);
+  ConsumeIteratorPastLastSplit(symbols_iterator_, &symbols_iterator_position_,
+                               &candidate_range_.font_fallback_priority);
 
-  if (script_run_iterator_position_ <= orientation_iterator_position_ &&
-      script_run_iterator_position_ <= symbols_iterator_position_) {
-    last_split_ = script_run_iterator_position_;
-  }
+  unsigned positions[] = {script_run_iterator_position_,
+                          orientation_iterator_position_,
+                          symbols_iterator_position_};
 
-  if (orientation_iterator_position_ <= script_run_iterator_position_ &&
-      orientation_iterator_position_ <= symbols_iterator_position_) {
-    last_split_ = orientation_iterator_position_;
-  }
-
-  if (symbols_iterator_position_ <= script_run_iterator_position_ &&
-      symbols_iterator_position_ <= orientation_iterator_position_) {
-    last_split_ = symbols_iterator_position_;
-  }
+  last_split_ = *std::min_element(std::begin(positions), std::end(positions));
 
   candidate_range_.start = candidate_range_.end;
   candidate_range_.end = last_split_;
diff --git a/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h b/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h
index 86bfc77..84647ca 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h
+++ b/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h
@@ -47,9 +47,11 @@
   }
 
  private:
-  void ConsumeOrientationIteratorPastLastSplit();
-  void ConsumeScriptIteratorPastLastSplit();
-  void ConsumeSymbolsIteratorPastLastSplit();
+  template <class Iterator, typename SegmentationCategory>
+  void ConsumeIteratorPastLastSplit(
+      std::unique_ptr<Iterator>& iterator,
+      unsigned* iterator_position,
+      SegmentationCategory* segmentation_category);
 
   unsigned buffer_size_;
   RunSegmenterRange candidate_range_;
diff --git a/third_party/blink/renderer/platform/heap/heap_test.cc b/third_party/blink/renderer/platform/heap/heap_test.cc
index b198b09..2120b6a 100644
--- a/third_party/blink/renderer/platform/heap/heap_test.cc
+++ b/third_party/blink/renderer/platform/heap/heap_test.cc
@@ -5499,7 +5499,14 @@
   static volatile uintptr_t worker_object_pointer_;
 };
 
-TEST(HeapTest, ThreadedStrongification) {
+#if defined(THREAD_SANITIZER)
+// https://crbug.com/915200
+#define MAYBE_ThreadedStrongification DISABLED_ThreadedStrongification
+#else
+#define MAYBE_ThreadedStrongification ThreadedStrongification
+#endif
+
+TEST(HeapTest, MAYBE_ThreadedStrongification) {
   ThreadedStrongificationTester::Test();
 }
 
@@ -6385,7 +6392,14 @@
 
 }  // anonymous namespace
 
-TEST(HeapTest, CrossThreadWeakPersistent) {
+#if defined(THREAD_SANITIZER)
+// https://crbug.com/915200
+#define MAYBE_CrossThreadWeakPersistent DISABLED_CrossThreadWeakPersistent
+#else
+#define MAYBE_CrossThreadWeakPersistent CrossThreadWeakPersistent
+#endif
+
+TEST(HeapTest, MAYBE_CrossThreadWeakPersistent) {
   // Create an object in the worker thread, have a CrossThreadWeakPersistent
   // pointing to it on the main thread, clear the reference in the worker
   // thread, run a GC in the worker thread, and see if the
diff --git a/third_party/blink/renderer/platform/wtf/text/string_view.cc b/third_party/blink/renderer/platform/wtf/text/string_view.cc
index f578dd6..6f0bb88 100644
--- a/third_party/blink/renderer/platform/wtf/text/string_view.cc
+++ b/third_party/blink/renderer/platform/wtf/text/string_view.cc
@@ -51,6 +51,8 @@
     return a.IsNull() == b.IsNull();
   if (a.length() != b.length())
     return false;
+  if (a.Bytes() == b.Bytes() && a.Is8Bit() == b.Is8Bit())
+    return true;
   if (a.Is8Bit()) {
     if (b.Is8Bit())
       return Equal(a.Characters8(), b.Characters8(), a.length());
@@ -92,6 +94,8 @@
     return a.IsNull() == b.IsNull();
   if (a.length() != b.length())
     return false;
+  if (a.Bytes() == b.Bytes() && a.Is8Bit() == b.Is8Bit())
+    return true;
   if (a.Is8Bit()) {
     if (b.Is8Bit())
       return EqualIgnoringASCIICase(a.Characters8(), b.Characters8(),
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index a90054e..6fc700f 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -2999,6 +2999,8 @@
 crbug.com/893480 external/wpt/infrastructure/testdriver/actions/multiDevice.html [ Failure Timeout ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-span-all-005.html [ Failure ]
+crbug.com/626703 external/wpt/css/css-multicol/multicol-span-all-005.html [ Failure ]
 crbug.com/626703 [ Android ] external/wpt/css/css-layout-api/auto-block-size-absolute.https.html [ Failure ]
 crbug.com/626703 [ Mac10.10 ] external/wpt/css/css-layout-api/auto-block-size-absolute.https.html [ Failure ]
 crbug.com/626703 external/wpt/infrastructure/testdriver/file_upload.sub.html [ Skip ]
@@ -5480,7 +5482,6 @@
 crbug.com/874162 [ Mac ] virtual/mouseevent_fractional/fast/events/middleClickAutoscroll-drag.html [ Skip ]
 crbug.com/874162 [ Mac ] virtual/user-activation-v2/fast/events/middleClickAutoscroll-drag.html [ Skip ]
 crbug.com/874162 [ Mac ] fast/events/middleClickAutoscroll-event-fired.html [ Skip ]
-crbug.com/874162 [ Mac ] virtual/user-activation-v2/fast/events/middleClickAutoscroll-event-fired.html [ Skip ]
 crbug.com/874162 [ Mac ] fast/events/middleClickAutoscroll-in-iframe.html [ Skip ]
 crbug.com/874162 [ Mac ] virtual/mouseevent_fractional/fast/events/middleClickAutoscroll-in-iframe.html [ Skip ]
 crbug.com/874162 [ Mac ] virtual/user-activation-v2/fast/events/middleClickAutoscroll-in-iframe.html [ Skip ]
@@ -5535,6 +5536,8 @@
 crbug.com/869492 virtual/threaded/external/wpt/feature-policy/experimental-features/lazyload/lazyload-enabled-tentative.sub.html [ Failure ]
 crbug.com/869492 virtual/video-surface-layer/external/wpt/feature-policy/experimental-features/lazyload/lazyload-disabled-tentative.sub.html [ Failure ]
 
+crbug.com/914441 external/wpt/user-timing/mark-measure-feature-detection.html [ Failure ]
+
 # The below is only supported with network service.
 crbug.com/896924 http/tests/inspector-protocol/network/interception-multiclient.js [ Skip ]
 crbug.com/899303 http/tests/inspector-protocol/fetch/fetch-basic.js [ Timeout ]
@@ -5581,8 +5584,6 @@
 crbug.com/891155 [ Win ] virtual/mouseevent_fractional/fast/events/middleClickAutoscroll-drag.html [ Failure Pass ]
 crbug.com/891155 [ Linux ] virtual/user-activation-v2/fast/events/middleClickAutoscroll-drag.html [ Failure Pass ]
 crbug.com/891155 [ Win ] virtual/user-activation-v2/fast/events/middleClickAutoscroll-drag.html [ Failure Pass ]
-crbug.com/891155 [ Linux ] virtual/user-activation-v2/fast/events/middleClickAutoscroll-event-fired.html [ Failure Pass ]
-crbug.com/891155 [ Win ] virtual/user-activation-v2/fast/events/middleClickAutoscroll-event-fired.html [ Failure Pass ]
 
 # Sheriff 2018-10-15
 crbug.com/895257 [ Mac ] external/wpt/css/css-fonts/variations/at-font-face-font-matching.html [ Failure Pass ]
@@ -5721,6 +5722,12 @@
 crbug.com/910452 virtual/video-surface-layer/media/controls/buttons-after-reset.html [ Pass Failure ]
 crbug.com/914782 [ Linux ] fast/scrolling/no-hover-during-scroll.html [ Pass Failure ]
 
+# Sheriff 2018-12-14
+crbug.com/914782 [ Linux ] virtual/fractional_scrolling/fast/scrolling/no-hover-during-scroll.html [ Pass Failure ]
+crbug.com/914782 [ Linux ] virtual/scroll_customization/fast/scrolling/no-hover-during-scroll.html [ Pass Failure ]
+crbug.com/891155 virtual/user-activation-v2/fast/events/middleClickAutoscroll-event-fired.html [ Skip ]
+crbug.com/913931 [ Mac10.11 ] external/wpt/css/css-layout-api/auto-block-size-absolute.https.html [ Pass Failure ]
+
 # These tests will fail until upstream v8 changes are landed.
 crbug.com/v8/8381 http/tests/devtools/coverage/coverage-repeated.js [ Pass Failure ]
 crbug.com/v8/8381 http/tests/devtools/coverage/coverage-view-filter.js [ Pass Failure ]
diff --git a/third_party/blink/web_tests/animations/animations-csstext.html b/third_party/blink/web_tests/animations/animations-csstext.html
index c2e07c5..f9ffc30 100644
--- a/third_party/blink/web_tests/animations/animations-csstext.html
+++ b/third_party/blink/web_tests/animations/animations-csstext.html
@@ -9,6 +9,6 @@
     div.style.animationName = "\\ ";
     assert_equals(div.style.cssText, 'animation-name: \\ ;');
     div.style.animation = 'hello 2s';
-    assert_equals(div.style.cssText, 'animation: hello 2s ease 0s 1 normal none running;');
+    assert_equals(div.style.cssText, 'animation: 2s ease 0s 1 normal none running hello;');
 }, 'cssText serializes animation properties sanely');
 </script>
diff --git a/third_party/blink/web_tests/animations/animations-parsing-005.html b/third_party/blink/web_tests/animations/animations-parsing-005.html
index e1c8064..6ec66aa 100644
--- a/third_party/blink/web_tests/animations/animations-parsing-005.html
+++ b/third_party/blink/web_tests/animations/animations-parsing-005.html
@@ -33,54 +33,54 @@
   style.animation = "myShorthandAnim";
   assert_not_equals(Object.keys(style).indexOf('animation'), -1);
   assert_not_equals(Object.keys(style).indexOf('webkitAnimation'), -1);
-  assert_equals(style.animation, 'myShorthandAnim 0s ease 0s 1 normal none running');
-  assert_equals(computedStyle.animation, 'myShorthandAnim 0s ease 0s 1 normal none running');
-  assert_equals(style.webkitAnimation, 'myShorthandAnim 0s ease 0s 1 normal none running');
-  assert_equals(computedStyle.webkitAnimation, 'myShorthandAnim 0s ease 0s 1 normal none running');
+  assert_equals(style.animation, '0s ease 0s 1 normal none running myShorthandAnim');
+  assert_equals(computedStyle.animation, '0s ease 0s 1 normal none running myShorthandAnim');
+  assert_equals(style.webkitAnimation, '0s ease 0s 1 normal none running myShorthandAnim');
+  assert_equals(computedStyle.webkitAnimation, '0s ease 0s 1 normal none running myShorthandAnim');
   assert_true(checkAnimationShorthandValue());
 
   style.animation = "none";
   assert_not_equals(Object.keys(style).indexOf('animation'), -1);
   assert_not_equals(Object.keys(style).indexOf('webkitAnimation'), -1);
-  assert_equals(style.animation, 'none 0s ease 0s 1 normal none running');
-  assert_equals(computedStyle.animation, 'none 0s ease 0s 1 normal none running');
-  assert_equals(style.webkitAnimation, 'none 0s ease 0s 1 normal none running');
-  assert_equals(computedStyle.webkitAnimation, 'none 0s ease 0s 1 normal none running');
+  assert_equals(style.animation, '0s ease 0s 1 normal none running none');
+  assert_equals(computedStyle.animation, '0s ease 0s 1 normal none running none');
+  assert_equals(style.webkitAnimation, '0s ease 0s 1 normal none running none');
+  assert_equals(computedStyle.webkitAnimation, '0s ease 0s 1 normal none running none');
   assert_true(checkAnimationShorthandValue());
 
   style.animation = "none 20s";
-  assert_equals(style.animation, 'none 20s ease 0s 1 normal none running');
-  assert_equals(computedStyle.animation, 'none 20s ease 0s 1 normal none running');
-  assert_equals(style.webkitAnimation, 'none 20s ease 0s 1 normal none running');
-  assert_equals(computedStyle.webkitAnimation, 'none 20s ease 0s 1 normal none running');
+  assert_equals(style.animation, '20s ease 0s 1 normal none running none');
+  assert_equals(computedStyle.animation, '20s ease 0s 1 normal none running none');
+  assert_equals(style.webkitAnimation, '20s ease 0s 1 normal none running none');
+  assert_equals(computedStyle.webkitAnimation, '20s ease 0s 1 normal none running none');
   assert_true(checkAnimationShorthandValue());
 
   style.animation = "myShorthandAnim none 20s";
-  assert_equals(style.animation, 'myShorthandAnim 20s ease 0s 1 normal none running');
-  assert_equals(computedStyle.animation, 'myShorthandAnim 20s ease 0s 1 normal none running');
-  assert_equals(style.webkitAnimation, 'myShorthandAnim 20s ease 0s 1 normal none running');
-  assert_equals(computedStyle.webkitAnimation, 'myShorthandAnim 20s ease 0s 1 normal none running');
+  assert_equals(style.animation, '20s ease 0s 1 normal none running myShorthandAnim');
+  assert_equals(computedStyle.animation, '20s ease 0s 1 normal none running myShorthandAnim');
+  assert_equals(style.webkitAnimation, '20s ease 0s 1 normal none running myShorthandAnim');
+  assert_equals(computedStyle.webkitAnimation, '20s ease 0s 1 normal none running myShorthandAnim');
   assert_true(checkAnimationShorthandValue());
 
   style.animation = "myShorthandAnim ease-in none 20s";
-  assert_equals(style.animation, 'myShorthandAnim 20s ease-in 0s 1 normal none running');
-  assert_equals(computedStyle.animation, 'myShorthandAnim 20s ease-in 0s 1 normal none running');
-  assert_equals(style.webkitAnimation, 'myShorthandAnim 20s ease-in 0s 1 normal none running');
-  assert_equals(computedStyle.webkitAnimation, 'myShorthandAnim 20s ease-in 0s 1 normal none running');
+  assert_equals(style.animation, '20s ease-in 0s 1 normal none running myShorthandAnim');
+  assert_equals(computedStyle.animation, '20s ease-in 0s 1 normal none running myShorthandAnim');
+  assert_equals(style.webkitAnimation, '20s ease-in 0s 1 normal none running myShorthandAnim');
+  assert_equals(computedStyle.webkitAnimation, '20s ease-in 0s 1 normal none running myShorthandAnim');
   assert_true(checkAnimationShorthandValue());
 
   style.animation = "myShorthandAnim ease-in 20s";
-  assert_equals(style.animation, 'myShorthandAnim 20s ease-in 0s 1 normal none running');
-  assert_equals(computedStyle.animation, 'myShorthandAnim 20s ease-in 0s 1 normal none running');
-  assert_equals(style.webkitAnimation, 'myShorthandAnim 20s ease-in 0s 1 normal none running');
-  assert_equals(computedStyle.webkitAnimation, 'myShorthandAnim 20s ease-in 0s 1 normal none running');
+  assert_equals(style.animation, '20s ease-in 0s 1 normal none running myShorthandAnim');
+  assert_equals(computedStyle.animation, '20s ease-in 0s 1 normal none running myShorthandAnim');
+  assert_equals(style.webkitAnimation, '20s ease-in 0s 1 normal none running myShorthandAnim');
+  assert_equals(computedStyle.webkitAnimation, '20s ease-in 0s 1 normal none running myShorthandAnim');
   assert_true(checkAnimationShorthandValue());
 
   style.animation = "myShorthandAnim ease-in 20s 10s";
-  assert_equals(style.animation, 'myShorthandAnim 20s ease-in 10s 1 normal none running');
-  assert_equals(computedStyle.animation, 'myShorthandAnim 20s ease-in 10s 1 normal none running');
-  assert_equals(style.webkitAnimation, 'myShorthandAnim 20s ease-in 10s 1 normal none running');
-  assert_equals(computedStyle.webkitAnimation, 'myShorthandAnim 20s ease-in 10s 1 normal none running');
+  assert_equals(style.animation, '20s ease-in 10s 1 normal none running myShorthandAnim');
+  assert_equals(computedStyle.animation, '20s ease-in 10s 1 normal none running myShorthandAnim');
+  assert_equals(style.webkitAnimation, '20s ease-in 10s 1 normal none running myShorthandAnim');
+  assert_equals(computedStyle.webkitAnimation, '20s ease-in 10s 1 normal none running myShorthandAnim');
   // Let's double check here the delay and duration. As stated in the spec the first value parsed
   // is assigned to the duration.
   assert_equals(computedStyle.animationDuration, '20s');
@@ -90,10 +90,10 @@
   assert_true(checkAnimationShorthandValue());
 
   style.animation = "myShorthandAnim 20s ease-in 10s";
-  assert_equals(style.animation, 'myShorthandAnim 20s ease-in 10s 1 normal none running');
-  assert_equals(computedStyle.animation, 'myShorthandAnim 20s ease-in 10s 1 normal none running');
-  assert_equals(style.webkitAnimation, 'myShorthandAnim 20s ease-in 10s 1 normal none running');
-  assert_equals(computedStyle.webkitAnimation, 'myShorthandAnim 20s ease-in 10s 1 normal none running');
+  assert_equals(style.animation, '20s ease-in 10s 1 normal none running myShorthandAnim');
+  assert_equals(computedStyle.animation, '20s ease-in 10s 1 normal none running myShorthandAnim');
+  assert_equals(style.webkitAnimation, '20s ease-in 10s 1 normal none running myShorthandAnim');
+  assert_equals(computedStyle.webkitAnimation, '20s ease-in 10s 1 normal none running myShorthandAnim');
   assert_equals(computedStyle.animationDuration, '20s');
   assert_equals(computedStyle.webkitAnimationDuration, '20s');
   assert_equals(computedStyle.animationDelay, '10s');
@@ -101,10 +101,10 @@
   assert_true(checkAnimationShorthandValue());
 
   style.animation = "myShorthandAnim paused 20s ease-in 10s";
-  assert_equals(style.animation, 'myShorthandAnim 20s ease-in 10s 1 normal none paused');
-  assert_equals(computedStyle.animation, 'myShorthandAnim 20s ease-in 10s 1 normal none paused');
-  assert_equals(style.webkitAnimation, 'myShorthandAnim 20s ease-in 10s 1 normal none paused');
-  assert_equals(computedStyle.webkitAnimation, 'myShorthandAnim 20s ease-in 10s 1 normal none paused');
+  assert_equals(style.animation, '20s ease-in 10s 1 normal none paused myShorthandAnim');
+  assert_equals(computedStyle.animation, '20s ease-in 10s 1 normal none paused myShorthandAnim');
+  assert_equals(style.webkitAnimation, '20s ease-in 10s 1 normal none paused myShorthandAnim');
+  assert_equals(computedStyle.webkitAnimation, '20s ease-in 10s 1 normal none paused myShorthandAnim');
   assert_equals(computedStyle.animationDuration, '20s');
   assert_equals(computedStyle.webkitAnimationDuration, '20s');
   assert_equals(computedStyle.animationDelay, '10s');
@@ -112,52 +112,52 @@
   assert_true(checkAnimationShorthandValue());
 
   style.animation = "myShorthandAnim ease-in both 20s 5";
-  assert_equals(style.animation, 'myShorthandAnim 20s ease-in 0s 5 normal both running');
-  assert_equals(computedStyle.animation, 'myShorthandAnim 20s ease-in 0s 5 normal both running');
-  assert_equals(style.webkitAnimation, 'myShorthandAnim 20s ease-in 0s 5 normal both running');
-  assert_equals(computedStyle.webkitAnimation, 'myShorthandAnim 20s ease-in 0s 5 normal both running');
+  assert_equals(style.animation, '20s ease-in 0s 5 normal both running myShorthandAnim');
+  assert_equals(computedStyle.animation, '20s ease-in 0s 5 normal both running myShorthandAnim');
+  assert_equals(style.webkitAnimation, '20s ease-in 0s 5 normal both running myShorthandAnim');
+  assert_equals(computedStyle.webkitAnimation, '20s ease-in 0s 5 normal both running myShorthandAnim');
   assert_true(checkAnimationShorthandValue());
 
   style.animation = "myShorthandAnim ease-in 20s 5 backwards";
-  assert_equals(style.animation, 'myShorthandAnim 20s ease-in 0s 5 normal backwards running');
-  assert_equals(computedStyle.animation, 'myShorthandAnim 20s ease-in 0s 5 normal backwards running');
-  assert_equals(style.webkitAnimation, 'myShorthandAnim 20s ease-in 0s 5 normal backwards running');
-  assert_equals(computedStyle.webkitAnimation, 'myShorthandAnim 20s ease-in 0s 5 normal backwards running');
+  assert_equals(style.animation, '20s ease-in 0s 5 normal backwards running myShorthandAnim');
+  assert_equals(computedStyle.animation, '20s ease-in 0s 5 normal backwards running myShorthandAnim');
+  assert_equals(style.webkitAnimation, '20s ease-in 0s 5 normal backwards running myShorthandAnim');
+  assert_equals(computedStyle.webkitAnimation, '20s ease-in 0s 5 normal backwards running myShorthandAnim');
   assert_true(checkAnimationShorthandValue());
 
   style.animation = "myShorthandAnim forwards 20s 5";
-  assert_equals(style.animation, 'myShorthandAnim 20s ease 0s 5 normal forwards running');
-  assert_equals(computedStyle.animation, 'myShorthandAnim 20s ease 0s 5 normal forwards running');
-  assert_equals(style.webkitAnimation, 'myShorthandAnim 20s ease 0s 5 normal forwards running');
-  assert_equals(computedStyle.webkitAnimation, 'myShorthandAnim 20s ease 0s 5 normal forwards running');
+  assert_equals(style.animation, '20s ease 0s 5 normal forwards running myShorthandAnim');
+  assert_equals(computedStyle.animation, '20s ease 0s 5 normal forwards running myShorthandAnim');
+  assert_equals(style.webkitAnimation, '20s ease 0s 5 normal forwards running myShorthandAnim');
+  assert_equals(computedStyle.webkitAnimation, '20s ease 0s 5 normal forwards running myShorthandAnim');
   assert_true(checkAnimationShorthandValue());
 
   style.animation = "myShorthandAnim ease-in 20s 5";
-  assert_equals(style.animation, 'myShorthandAnim 20s ease-in 0s 5 normal none running');
-  assert_equals(computedStyle.animation, 'myShorthandAnim 20s ease-in 0s 5 normal none running');
-  assert_equals(style.webkitAnimation, 'myShorthandAnim 20s ease-in 0s 5 normal none running');
-  assert_equals(computedStyle.webkitAnimation, 'myShorthandAnim 20s ease-in 0s 5 normal none running');
+  assert_equals(style.animation, '20s ease-in 0s 5 normal none running myShorthandAnim');
+  assert_equals(computedStyle.animation, '20s ease-in 0s 5 normal none running myShorthandAnim');
+  assert_equals(style.webkitAnimation, '20s ease-in 0s 5 normal none running myShorthandAnim');
+  assert_equals(computedStyle.webkitAnimation, '20s ease-in 0s 5 normal none running myShorthandAnim');
   assert_true(checkAnimationShorthandValue());
 
   style.animation = "myShorthandAnim reverse ease-in 20s 5";
-  assert_equals(style.animation, 'myShorthandAnim 20s ease-in 0s 5 reverse none running');
-  assert_equals(computedStyle.animation, 'myShorthandAnim 20s ease-in 0s 5 reverse none running');
-  assert_equals(style.webkitAnimation, 'myShorthandAnim 20s ease-in 0s 5 reverse none running');
-  assert_equals(computedStyle.webkitAnimation, 'myShorthandAnim 20s ease-in 0s 5 reverse none running');
+  assert_equals(style.animation, '20s ease-in 0s 5 reverse none running myShorthandAnim');
+  assert_equals(computedStyle.animation, '20s ease-in 0s 5 reverse none running myShorthandAnim');
+  assert_equals(style.webkitAnimation, '20s ease-in 0s 5 reverse none running myShorthandAnim');
+  assert_equals(computedStyle.webkitAnimation, '20s ease-in 0s 5 reverse none running myShorthandAnim');
   assert_true(checkAnimationShorthandValue());
 
   style.animation = "myShorthandAnim reverse ease-in backwards 20s 5 paused";
-  assert_equals(style.animation, 'myShorthandAnim 20s ease-in 0s 5 reverse backwards paused');
-  assert_equals(computedStyle.animation, 'myShorthandAnim 20s ease-in 0s 5 reverse backwards paused');
-  assert_equals(style.webkitAnimation, 'myShorthandAnim 20s ease-in 0s 5 reverse backwards paused');
-  assert_equals(computedStyle.webkitAnimation, 'myShorthandAnim 20s ease-in 0s 5 reverse backwards paused');
+  assert_equals(style.animation, '20s ease-in 0s 5 reverse backwards paused myShorthandAnim');
+  assert_equals(computedStyle.animation, '20s ease-in 0s 5 reverse backwards paused myShorthandAnim');
+  assert_equals(style.webkitAnimation, '20s ease-in 0s 5 reverse backwards paused myShorthandAnim');
+  assert_equals(computedStyle.webkitAnimation, '20s ease-in 0s 5 reverse backwards paused myShorthandAnim');
   assert_true(checkAnimationShorthandValue());
 
   style.animation = "myShorthandAnim ease-in 20s 10s, width cubic-bezier(0.32, 0, 1, 1) 10s 20s";
-  assert_equals(style.animation, 'myShorthandAnim 20s ease-in 10s 1 normal none running, width 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal none running');
-  assert_equals(computedStyle.animation, 'myShorthandAnim 20s ease-in 10s 1 normal none running, width 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal none running');
-  assert_equals(style.webkitAnimation, 'myShorthandAnim 20s ease-in 10s 1 normal none running, width 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal none running');
-  assert_equals(computedStyle.webkitAnimation, 'myShorthandAnim 20s ease-in 10s 1 normal none running, width 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal none running');
+  assert_equals(style.animation, '20s ease-in 10s 1 normal none running myShorthandAnim, 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal none running width');
+  assert_equals(computedStyle.animation, '20s ease-in 10s 1 normal none running myShorthandAnim, 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal none running width');
+  assert_equals(style.webkitAnimation, '20s ease-in 10s 1 normal none running myShorthandAnim, 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal none running width');
+  assert_equals(computedStyle.webkitAnimation, '20s ease-in 10s 1 normal none running myShorthandAnim, 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal none running width');
   // Let's double check here the delay and duration. As stated in the spec the first value parsed
   // is assigned to the duration.
   assert_equals(computedStyle.animationDuration, '20s, 10s');
@@ -167,10 +167,10 @@
   assert_true(checkAnimationShorthandValue());
 
   style.animation = "myShorthandAnim ease-in 20s 10s paused, width cubic-bezier(0.32, 0, 1, 1) 10s 20s";
-  assert_equals(style.animation, 'myShorthandAnim 20s ease-in 10s 1 normal none paused, width 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal none running');
-  assert_equals(computedStyle.animation, 'myShorthandAnim 20s ease-in 10s 1 normal none paused, width 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal none running');
-  assert_equals(style.webkitAnimation, 'myShorthandAnim 20s ease-in 10s 1 normal none paused, width 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal none running');
-  assert_equals(computedStyle.webkitAnimation, 'myShorthandAnim 20s ease-in 10s 1 normal none paused, width 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal none running');
+  assert_equals(style.animation, '20s ease-in 10s 1 normal none paused myShorthandAnim, 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal none running width');
+  assert_equals(computedStyle.animation, '20s ease-in 10s 1 normal none paused myShorthandAnim, 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal none running width');
+  assert_equals(style.webkitAnimation, '20s ease-in 10s 1 normal none paused myShorthandAnim, 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal none running width');
+  assert_equals(computedStyle.webkitAnimation, '20s ease-in 10s 1 normal none paused myShorthandAnim, 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal none running width');
   // Let's double check here the delay and duration. As stated in the spec the first value parsed
   // is assigned to the duration.
   assert_equals(computedStyle.animationDuration, '20s, 10s');
@@ -180,50 +180,50 @@
   assert_true(checkAnimationShorthandValue());
 
   style.animation = "myShorthandAnim reverse ease-in 20s 10s paused, test cubic-bezier(0.32, 0, 1, 1) 10s 20s both";
-  assert_equals(style.animation, 'myShorthandAnim 20s ease-in 10s 1 reverse none paused, test 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal both running');
-  assert_equals(computedStyle.animation, 'myShorthandAnim 20s ease-in 10s 1 reverse none paused, test 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal both running');
-  assert_equals(style.webkitAnimation, 'myShorthandAnim 20s ease-in 10s 1 reverse none paused, test 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal both running');
-  assert_equals(computedStyle.webkitAnimation, 'myShorthandAnim 20s ease-in 10s 1 reverse none paused, test 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal both running');
+  assert_equals(style.animation, '20s ease-in 10s 1 reverse none paused myShorthandAnim, 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal both running test');
+  assert_equals(computedStyle.animation, '20s ease-in 10s 1 reverse none paused myShorthandAnim, 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal both running test');
+  assert_equals(style.webkitAnimation, '20s ease-in 10s 1 reverse none paused myShorthandAnim, 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal both running test');
+  assert_equals(computedStyle.webkitAnimation, '20s ease-in 10s 1 reverse none paused myShorthandAnim, 10s cubic-bezier(0.32, 0, 1, 1) 20s 1 normal both running test');
   assert_true(checkAnimationShorthandValue());
 
   style.animation = "none, none";
-  assert_equals(style.animation, 'none 0s ease 0s 1 normal none running, none 0s ease 0s 1 normal none running');
-  assert_equals(computedStyle.animation, 'none 0s ease 0s 1 normal none running, none 0s ease 0s 1 normal none running');
-  assert_equals(style.webkitAnimation, 'none 0s ease 0s 1 normal none running, none 0s ease 0s 1 normal none running');
-  assert_equals(computedStyle.webkitAnimation, 'none 0s ease 0s 1 normal none running, none 0s ease 0s 1 normal none running');
+  assert_equals(style.animation, '0s ease 0s 1 normal none running none, 0s ease 0s 1 normal none running none');
+  assert_equals(computedStyle.animation, '0s ease 0s 1 normal none running none, 0s ease 0s 1 normal none running none');
+  assert_equals(style.webkitAnimation, '0s ease 0s 1 normal none running none, 0s ease 0s 1 normal none running none');
+  assert_equals(computedStyle.webkitAnimation, '0s ease 0s 1 normal none running none, 0s ease 0s 1 normal none running none');
 
   style.animation = "ease-in test 20s 10s, none";
-  assert_equals(style.animation, 'test 20s ease-in 10s 1 normal none running, none 0s ease 0s 1 normal none running');
-  assert_equals(computedStyle.animation, 'test 20s ease-in 10s 1 normal none running, none 0s ease 0s 1 normal none running');
-  assert_equals(style.webkitAnimation, 'test 20s ease-in 10s 1 normal none running, none 0s ease 0s 1 normal none running');
-  assert_equals(computedStyle.webkitAnimation, 'test 20s ease-in 10s 1 normal none running, none 0s ease 0s 1 normal none running');
+  assert_equals(style.animation, '20s ease-in 10s 1 normal none running test, 0s ease 0s 1 normal none running none');
+  assert_equals(computedStyle.animation, '20s ease-in 10s 1 normal none running test, 0s ease 0s 1 normal none running none');
+  assert_equals(style.webkitAnimation, '20s ease-in 10s 1 normal none running test, 0s ease 0s 1 normal none running none');
+  assert_equals(computedStyle.webkitAnimation, '20s ease-in 10s 1 normal none running test, 0s ease 0s 1 normal none running none');
   assert_equals(computedStyle.animationName, 'test, none');
 
   style.animation = "none, ease-in test 20s 10s";
-  assert_equals(style.animation, 'none 0s ease 0s 1 normal none running, test 20s ease-in 10s 1 normal none running');
-  assert_equals(computedStyle.animation, 'none 0s ease 0s 1 normal none running, test 20s ease-in 10s 1 normal none running');
-  assert_equals(style.webkitAnimation, 'none 0s ease 0s 1 normal none running, test 20s ease-in 10s 1 normal none running');
-  assert_equals(computedStyle.webkitAnimation, 'none 0s ease 0s 1 normal none running, test 20s ease-in 10s 1 normal none running');
+  assert_equals(style.animation, '0s ease 0s 1 normal none running none, 20s ease-in 10s 1 normal none running test');
+  assert_equals(computedStyle.animation, '0s ease 0s 1 normal none running none, 20s ease-in 10s 1 normal none running test');
+  assert_equals(style.webkitAnimation, '0s ease 0s 1 normal none running none, 20s ease-in 10s 1 normal none running test');
+  assert_equals(computedStyle.webkitAnimation, '0s ease 0s 1 normal none running none, 20s ease-in 10s 1 normal none running test');
   assert_equals(computedStyle.animationName, 'none, test');
 
   style.animation = "myShorthandAnim both 20s 10s ease-in paused, myShorthandAnim ease-out 20s";
-  assert_equals(style.animation, 'myShorthandAnim 20s ease-in 10s 1 normal both paused, myShorthandAnim 20s ease-out 0s 1 normal none running');
-  assert_equals(computedStyle.animation, 'myShorthandAnim 20s ease-in 10s 1 normal both paused, myShorthandAnim 20s ease-out 0s 1 normal none running');
-  assert_equals(style.webkitAnimation, 'myShorthandAnim 20s ease-in 10s 1 normal both paused, myShorthandAnim 20s ease-out 0s 1 normal none running');
-  assert_equals(computedStyle.webkitAnimation, 'myShorthandAnim 20s ease-in 10s 1 normal both paused, myShorthandAnim 20s ease-out 0s 1 normal none running');
+  assert_equals(style.animation, '20s ease-in 10s 1 normal both paused myShorthandAnim, 20s ease-out 0s 1 normal none running myShorthandAnim');
+  assert_equals(computedStyle.animation, '20s ease-in 10s 1 normal both paused myShorthandAnim, 20s ease-out 0s 1 normal none running myShorthandAnim');
+  assert_equals(style.webkitAnimation, '20s ease-in 10s 1 normal both paused myShorthandAnim, 20s ease-out 0s 1 normal none running myShorthandAnim');
+  assert_equals(computedStyle.webkitAnimation, '20s ease-in 10s 1 normal both paused myShorthandAnim, 20s ease-out 0s 1 normal none running myShorthandAnim');
 
   style.animation = "myShorthandAnim ease-in 4 20s 10s backwards, myShorthandAnim2 50 ease-out 20s";
-  assert_equals(style.animation, 'myShorthandAnim 20s ease-in 10s 4 normal backwards running, myShorthandAnim2 20s ease-out 0s 50 normal none running');
-  assert_equals(computedStyle.animation, 'myShorthandAnim 20s ease-in 10s 4 normal backwards running, myShorthandAnim2 20s ease-out 0s 50 normal none running');
-  assert_equals(style.webkitAnimation, 'myShorthandAnim 20s ease-in 10s 4 normal backwards running, myShorthandAnim2 20s ease-out 0s 50 normal none running');
-  assert_equals(computedStyle.webkitAnimation, 'myShorthandAnim 20s ease-in 10s 4 normal backwards running, myShorthandAnim2 20s ease-out 0s 50 normal none running');
+  assert_equals(style.animation, '20s ease-in 10s 4 normal backwards running myShorthandAnim, 20s ease-out 0s 50 normal none running myShorthandAnim2');
+  assert_equals(computedStyle.animation, '20s ease-in 10s 4 normal backwards running myShorthandAnim, 20s ease-out 0s 50 normal none running myShorthandAnim2');
+  assert_equals(style.webkitAnimation, '20s ease-in 10s 4 normal backwards running myShorthandAnim, 20s ease-out 0s 50 normal none running myShorthandAnim2');
+  assert_equals(computedStyle.webkitAnimation, '20s ease-in 10s 4 normal backwards running myShorthandAnim, 20s ease-out 0s 50 normal none running myShorthandAnim2');
   assert_true(checkAnimationShorthandValue());
 
   style.animation = "myShorthandAnim2 reverse ease-out 20s, ease-in myShorthandAnim 20s 10s paused";
-  assert_equals(style.animation, 'myShorthandAnim2 20s ease-out 0s 1 reverse none running, myShorthandAnim 20s ease-in 10s 1 normal none paused');
-  assert_equals(computedStyle.animation, 'myShorthandAnim2 20s ease-out 0s 1 reverse none running, myShorthandAnim 20s ease-in 10s 1 normal none paused');
-  assert_equals(style.webkitAnimation, 'myShorthandAnim2 20s ease-out 0s 1 reverse none running, myShorthandAnim 20s ease-in 10s 1 normal none paused');
-  assert_equals(computedStyle.webkitAnimation, 'myShorthandAnim2 20s ease-out 0s 1 reverse none running, myShorthandAnim 20s ease-in 10s 1 normal none paused');
+  assert_equals(style.animation, '20s ease-out 0s 1 reverse none running myShorthandAnim2, 20s ease-in 10s 1 normal none paused myShorthandAnim');
+  assert_equals(computedStyle.animation, '20s ease-out 0s 1 reverse none running myShorthandAnim2, 20s ease-in 10s 1 normal none paused myShorthandAnim');
+  assert_equals(style.webkitAnimation, '20s ease-out 0s 1 reverse none running myShorthandAnim2, 20s ease-in 10s 1 normal none paused myShorthandAnim');
+  assert_equals(computedStyle.webkitAnimation, '20s ease-out 0s 1 reverse none running myShorthandAnim2, 20s ease-in 10s 1 normal none paused myShorthandAnim');
   assert_true(checkAnimationShorthandValue());
 }, "Valid animation shorthand values.");
 
@@ -315,10 +315,10 @@
   assert_equals(computedStyle.webkitAnimation, 'none 0s ease 0s 1 normal none running');
 
   style.animation = "2 default";
-  assert_equals(style.animation, 'default 0s ease 0s 2 normal none running');
-  assert_equals(computedStyle.animation, 'default 0s ease 0s 2 normal none running');
-  assert_equals(style.webkitAnimation, 'default 0s ease 0s 2 normal none running');
-  assert_equals(computedStyle.webkitAnimation, 'default 0s ease 0s 2 normal none running');
+  assert_equals(style.animation, '0s ease 0s 2 normal none running default');
+  assert_equals(computedStyle.animation, '0s ease 0s 2 normal none running default');
+  assert_equals(style.webkitAnimation, '0s ease 0s 2 normal none running default');
+  assert_equals(computedStyle.webkitAnimation, '0s ease 0s 2 normal none running default');
 }, "Invalid animation shorthand values.");
 </script>
 </body>
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
index 5a574ba..d16084e 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
@@ -52915,6 +52915,18 @@
      {}
     ]
    ],
+   "css/css-multicol/multicol-span-all-005.html": [
+    [
+     "/css/css-multicol/multicol-span-all-005.html",
+     [
+      [
+       "/css/css-multicol/multicol-span-all-005-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-multicol/multicol-span-all-block-sibling-003.xht": [
     [
      "/css/css-multicol/multicol-span-all-block-sibling-003.xht",
@@ -136611,6 +136623,11 @@
      {}
     ]
    ],
+   "css/css-multicol/multicol-span-all-005-ref.html": [
+    [
+     {}
+    ]
+   ],
    "css/css-multicol/multicol-span-all-block-sibling-3-ref.xht": [
     [
      {}
@@ -148606,11 +148623,6 @@
      {}
     ]
    ],
-   "css/cssom/stylesheet-same-origin.sub-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "css/cssom/support/1x1-green.png": [
     [
      {}
@@ -181026,16 +181038,6 @@
      {}
     ]
    ],
-   "storage/resources/appcache.manifest": [
-    [
-     {}
-    ]
-   ],
-   "storage/resources/iframe_with_appcache_manifest.html": [
-    [
-     {}
-    ]
-   ],
    "streams/META.yml": [
     [
      {}
@@ -203517,6 +203519,12 @@
      }
     ]
    ],
+   "css/css-animations/animations-parsing.html": [
+    [
+     "/css/css-animations/animations-parsing.html",
+     {}
+    ]
+   ],
    "css/css-animations/event-dispatch.tentative.html": [
     [
      "/css/css-animations/event-dispatch.tentative.html",
@@ -207967,6 +207975,12 @@
      {}
     ]
    ],
+   "css/css-scoping/slotted-nested.html": [
+    [
+     "/css/css-scoping/slotted-nested.html",
+     {}
+    ]
+   ],
    "css/css-scoping/slotted-parsing.html": [
     [
      "/css/css-scoping/slotted-parsing.html",
@@ -272227,22 +272241,6 @@
      {}
     ]
    ],
-   "storage/estimate-usage-details-application-cache.https.tentative.html": [
-    [
-     "/storage/estimate-usage-details-application-cache.https.tentative.html",
-     {}
-    ]
-   ],
-   "storage/estimate-usage-details-caches.https.tentative.any.js": [
-    [
-     "/storage/estimate-usage-details-caches.https.tentative.any.html",
-     {}
-    ],
-    [
-     "/storage/estimate-usage-details-caches.https.tentative.any.worker.html",
-     {}
-    ]
-   ],
    "storage/estimate-usage-details-indexeddb.https.tentative.any.js": [
     [
      "/storage/estimate-usage-details-indexeddb.https.tentative.any.html",
@@ -272253,22 +272251,6 @@
      {}
     ]
    ],
-   "storage/estimate-usage-details-service-workers.https.tentative.window.js": [
-    [
-     "/storage/estimate-usage-details-service-workers.https.tentative.window.html",
-     {}
-    ]
-   ],
-   "storage/estimate-usage-details.https.tentative.any.js": [
-    [
-     "/storage/estimate-usage-details.https.tentative.any.html",
-     {}
-    ],
-    [
-     "/storage/estimate-usage-details.https.tentative.any.worker.html",
-     {}
-    ]
-   ],
    "storage/idlharness.https.any.js": [
     [
      "/storage/idlharness.https.any.html",
@@ -322460,6 +322442,10 @@
    "77f514a297bfd271abb488f086723af7ed0c9ff6",
    "testharness"
   ],
+  "css/css-animations/animations-parsing.html": [
+   "edf3061532c27a72d6cbbcdb57ff930c70611c6d",
+   "testharness"
+  ],
   "css/css-animations/animationstart-and-animationend-events-manual.html": [
    "4ca5eb736e76274eee9883121970fee0ab8280ca",
    "manual"
@@ -345156,6 +345142,14 @@
    "e9165658c11fea62e4f714fc4643f33853e95500",
    "reftest"
   ],
+  "css/css-multicol/multicol-span-all-005-ref.html": [
+   "641fbb9dcf5e093ab0892aba918c05965c9f23e1",
+   "support"
+  ],
+  "css/css-multicol/multicol-span-all-005.html": [
+   "249b69b7107e3ee65cf52986af0f298e18ea743e",
+   "reftest"
+  ],
   "css/css-multicol/multicol-span-all-block-sibling-003.xht": [
    "bd2cdd6cdab0fc15c2e16e2237f6b025230332c4",
    "reftest"
@@ -347596,6 +347590,10 @@
    "c06c96143ba0d478940fb54208d241adb4f6ee8b",
    "testharness"
   ],
+  "css/css-scoping/slotted-nested.html": [
+   "c7139fea4c280585197db5bd432931bcf53c2e53",
+   "testharness"
+  ],
   "css/css-scoping/slotted-parsing-expected.txt": [
    "a23c947e96e1639f3aec3a459eff35f8780216f5",
    "support"
@@ -373337,7 +373335,7 @@
    "testharness"
   ],
   "css/cssom/CSSStyleSheet-constructable.html": [
-   "e8596c914e0f54de4915e5a9b530c8356a8ccc77",
+   "7df1820c0437edbe0edfe4d7bb25c02f832dd3bc",
    "testharness"
   ],
   "css/cssom/CSSStyleSheet.html": [
@@ -373712,10 +373710,6 @@
    "d61a8dd67c9e74e7ca620f08dc1bd2ed1998fa8f",
    "support"
   ],
-  "css/cssom/stylesheet-same-origin.sub-expected.txt": [
-   "bbbc413ee75424f31428aad93f2788ea01c88cba",
-   "support"
-  ],
   "css/cssom/stylesheet-same-origin.sub.html": [
    "ef714670f5488f76d987a464a2732d60410f22ab",
    "testharness"
@@ -375213,11 +375207,11 @@
    "reftest"
   ],
   "css/selectors/attribute-selectors/attribute-case/cssom-expected.txt": [
-   "046b3a4218ec76035592f73d8c28a379ad4d4057",
+   "97a000beb6146c15577cdeb8c95e72d5e40541af",
    "support"
   ],
   "css/selectors/attribute-selectors/attribute-case/cssom.html": [
-   "d03d820a3e6ed93b217558de2c3b91c040b22dd7",
+   "74e7b9645f89423c628914cd3f246728de8ac71f",
    "testharness"
   ],
   "css/selectors/attribute-selectors/attribute-case/resources/semantics-quirks.html": [
@@ -436437,7 +436431,7 @@
    "testharness"
   ],
   "service-workers/service-worker/fetch-request-css-base-url.https-expected.txt": [
-   "d59cfa9f4200c3f24288868c82aeff42d03f71c3",
+   "441ac917dc1cd52a30d72cfb570b2fca1155cac3",
    "support"
   ],
   "service-workers/service-worker/fetch-request-css-base-url.https.html": [
@@ -439264,26 +439258,10 @@
    "090f004b8514bc9c99e8f85f9e8f9073dff2a263",
    "testharness"
   ],
-  "storage/estimate-usage-details-application-cache.https.tentative.html": [
-   "464a99887bdb1a5b38c3bce395552bf6b50ff0fe",
-   "testharness"
-  ],
-  "storage/estimate-usage-details-caches.https.tentative.any.js": [
-   "bf889f84184f0c8cb17997d392f738d062cce908",
-   "testharness"
-  ],
   "storage/estimate-usage-details-indexeddb.https.tentative.any.js": [
    "c854d5b8848638d11563a48348e7c3393ff58459",
    "testharness"
   ],
-  "storage/estimate-usage-details-service-workers.https.tentative.window.js": [
-   "be91cd61febaddc2d2a057c335bfa80dbe4a6b37",
-   "testharness"
-  ],
-  "storage/estimate-usage-details.https.tentative.any.js": [
-   "2a1cea5fb8dfa78c320328e667bb7ffd940802b0",
-   "testharness"
-  ],
   "storage/helpers.js": [
    "fbc746a30b6dfa6d00fc2db747c78ec09a7beefc",
    "support"
@@ -439312,14 +439290,6 @@
    "57e15f0e811de3e94652b2f16c5482a94be63c24",
    "testharness"
   ],
-  "storage/resources/appcache.manifest": [
-   "ce90bafd21feba90680448fd930ad477bf188638",
-   "support"
-  ],
-  "storage/resources/iframe_with_appcache_manifest.html": [
-   "8365ce41f494936a8f8f4b7c2be9d80ffbe38cf8",
-   "support"
-  ],
   "storage/storagemanager-estimate.https.any.js": [
    "d1d2e21924cd016165b02436dea994f44c193cd9",
    "testharness"
diff --git a/third_party/blink/web_tests/external/wpt/css/css-animations/computed-style-animation-parsing.html b/third_party/blink/web_tests/external/wpt/css/css-animations/computed-style-animation-parsing.html
new file mode 100644
index 0000000..15a1665b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-animations/computed-style-animation-parsing.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Animations: parsing computedStyle.animation</title>
+<link rel="help" href="https://drafts.csswg.org/css-animations/#animation">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="test1"></div>
+<div id="test2"></div>
+<script>
+function testComputedStyle(computedStyle1, computedStyle2, name) {
+  assert_equals(computedStyle1.animationName, name, "computedStyle1.animationName");
+  assert_equals(computedStyle2.animationName, name, "computedStyle2.animationName");
+  assert_equals(computedStyle1.animation, computedStyle2.animation,
+                "computedStyle1 and computedStyle2 should have the same animation");
+}
+
+function testAnimation(input, name) {
+  var style1 = test1.style;
+  var style2 = test2.style;
+  var computedStyle1 = getComputedStyle(test1);
+  var computedStyle2 = getComputedStyle(test2);
+
+  style1.animation = input;
+  style2.animation = style1.animation;
+  testComputedStyle(computedStyle1, computedStyle2, name);
+  style2.animation = computedStyle1.animation;
+  testComputedStyle(computedStyle1, computedStyle2, name);
+}
+
+test(() => {
+  // We are duplicating the logic of testAnimation because the animationName of
+  // the getComputedStyle is "none" when there is no animation.
+  var style1 = test1.style;
+  var style2 = test2.style;
+  var computedStyle1 = getComputedStyle(test1);
+  var computedStyle2 = getComputedStyle(test2);
+
+  style1.animation = "";
+  style2.animation = style1.animation;
+  testComputedStyle(computedStyle1, computedStyle2, "none");
+  style2.animation = computedStyle1.animation;
+  assert_equals(computedStyle2.animationName, "none");
+}, "Test animation name being empty.");
+
+test(() => {
+  testAnimation("myShorthandAnim", "myShorthandAnim");
+}, "Test a non-conflicting animation name.");
+
+test(() => {
+  testAnimation("none", "none");
+  testAnimation("forwards", "none");
+  testAnimation("none forwards", "forwards");
+}, "Test an animation name that is the same as a possible animation fill-mode.");
+
+test(() => {
+  testAnimation("normal", "none");
+  testAnimation("reverse", "none");
+  testAnimation("normal normal", "normal");
+  testAnimation("normal reverse", "reverse");
+}, "Test an animation name that is the same as a possible animation direction.");
+
+test(() => {
+  testAnimation("running", "none");
+  testAnimation("paused", "none");
+  testAnimation("running running", "running");
+  testAnimation("running paused", "paused");
+}, "Test an animation name that is the same as a possible running state.");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-animations/style-animation-parsing.html b/third_party/blink/web_tests/external/wpt/css/css-animations/style-animation-parsing.html
new file mode 100644
index 0000000..792fda3
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-animations/style-animation-parsing.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Animations: parsing style.animation</title>
+<link rel="help" href="https://drafts.csswg.org/css-animations/#animation">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="test1"></div>
+<div id="test2"></div>
+<script>
+function testStyle(style1, style2, name) {
+  assert_equals(style1.animationName, name, "style1.animationName");
+  assert_equals(style2.animationName, name, "style2.animationName");
+  assert_equals(style1.animation, style2.animation,
+                "style1 and style2 should have the same animation");
+}
+
+function testAnimation(input, name) {
+  var style1 = test1.style;
+  var style2 = test2.style;
+
+  style1.animation = input;
+  style2.animation = style1.animation;
+  testStyle(style1, style2, name);
+}
+
+test(() => {
+  testAnimation("", "");
+}, "Test animation name being empty.");
+
+test(() => {
+  testAnimation("myShorthandAnim", "myShorthandAnim");
+}, "Test a non-conflicting animation name.");
+
+test(() => {
+  testAnimation("none", "none");
+  testAnimation("forwards", "none");
+  testAnimation("none forwards", "forwards");
+}, "Test an animation name that is the same as a possible animation fill-mode.");
+
+test(() => {
+  testAnimation("normal", "none");
+  testAnimation("reverse", "none");
+  testAnimation("normal normal", "normal");
+  testAnimation("normal reverse", "reverse");
+}, "Test an animation name that is the same as a possible animation direction.");
+
+test(() => {
+  testAnimation("running", "none");
+  testAnimation("paused", "none");
+  testAnimation("running running", "running");
+  testAnimation("running paused", "paused");
+}, "Test an animation name that is the same as a possible running state.");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-span-all-005-ref.html b/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-span-all-005-ref.html
new file mode 100644
index 0000000..641fbb9
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-span-all-005-ref.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+  <meta charset="utf-8">
+  <title>CSS Multi-column Layout Test Reference: Test column-span:all with various display types</title>
+  <link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
+  <link rel="author" title="Mozilla" href="http://www.mozilla.org/">
+
+  <style>
+  .column {
+    column-count: 1;
+    column-rule: 6px solid;
+    width: 600px;
+    outline: 1px solid black;
+  }
+  .spanner {
+    /* column-count: 1 makes this behave like a real spanner. */
+    outline: 1px solid blue;
+  }
+  fieldset {
+    margin: 0;
+    padding: 0;
+    border: 0;
+  }
+  </style>
+
+  <body>
+    <article class="column">
+      <div>block1</div>
+      <table class="spanner">
+        <tr>
+          <td>table as a spanner</td>
+        </tr>
+      </table>
+      <div>block2</div>
+    </article>
+    <br>
+
+    <article class="column">
+      <div>block1</div>
+      <div class="spanner" style="display: grid;">grid as a spanner</div>
+      <div>block2</div>
+    </article>
+    <br>
+
+    <article class="column">
+      <div>block1</div>
+      <div class="spanner" style="display: flex;">flex as a spanner</div>
+      <div>block2</div>
+    </article>
+    <br>
+
+    <article class="column">
+      <div>block1</div>
+      <fieldset class="spanner">fieldset as a spanner</fieldset>
+      <div>block2</div>
+    </article>
+    <br>
+
+    <article class="column">
+      <div>block1</div>
+      <details open class="spanner">details as a spanner</details>
+      <div>block2</div>
+    </article>
+    <br>
+
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-span-all-005.html b/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-span-all-005.html
new file mode 100644
index 0000000..249b69b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-span-all-005.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+  <meta charset="utf-8">
+  <title>CSS Multi-column Layout Test: Test column-span:all with various display types</title>
+  <link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
+  <link rel="author" title="Mozilla" href="http://www.mozilla.org/">
+  <link rel="help" href="https://drafts.csswg.org/css-multicol-1/#column-span">
+  <link rel="match" href="multicol-span-all-005-ref.html">
+  <meta name="assert" content="This test checks a column-span:all element should act like column-span: none if it's under different block formatting context.">
+
+  <style>
+  .column {
+    column-count: 3;
+    column-rule: 6px solid;
+    width: 600px;
+    outline: 1px solid black;
+  }
+  .spanner {
+    column-span: all;
+    outline: 1px solid blue;
+  }
+  fieldset {
+    margin: 0;
+    padding: 0;
+    border: 0;
+  }
+  </style>
+
+  <body>
+    <article class="column">
+      <div>block1</div>
+      <table class="spanner">
+        <tr>
+          <td>table as a spanner</td>
+        </tr>
+      </table>
+      <div>block2</div>
+    </article>
+    <br>
+
+    <article class="column">
+      <div>block1</div>
+      <div class="spanner" style="display: grid;">grid as a spanner</div>
+      <div>block2</div>
+    </article>
+    <br>
+
+    <article class="column">
+      <div>block1</div>
+      <div class="spanner" style="display: flex;">flex as a spanner</div>
+      <div>block2</div>
+    </article>
+    <br>
+
+    <article class="column">
+      <div>block1</div>
+      <fieldset class="spanner">fieldset as a spanner</fieldset>
+      <div>block2</div>
+    </article>
+    <br>
+
+    <article class="column">
+      <div>block1</div>
+      <details open class="spanner">details as a spanner</details>
+      <div>block2</div>
+    </article>
+    <br>
+
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scoping/slotted-nested.html b/third_party/blink/web_tests/external/wpt/css/css-scoping/slotted-nested.html
new file mode 100644
index 0000000..c7139fe
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-scoping/slotted-nested.html
@@ -0,0 +1,49 @@
+<!doctype html>
+<link rel="href" href="https://mozilla.org" title="Mozilla">
+<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<link rel="help" href="https://drafts.csswg.org/css-scoping/#slotted-pseudo">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="host"><p>This text should be green</p></div>
+<script>
+  let shadow = host.attachShadow({ mode: "open" });
+  shadow.innerHTML = `
+    <style>
+      /* This is not expected to match */
+      .container ::slotted(p) {
+        color: red !important;
+      }
+
+      /* This _is_ expected to match */
+      #nested ::slotted(p) {
+        background-color: green;
+      }
+    </style>
+    <div id="nested"><slot></slot></div>
+  `;
+
+  let nested = shadow.querySelector("#nested").attachShadow({ mode: "open" });
+  nested.innerHTML = `
+    <style>
+      .container ::slotted(p) {
+        color: green;
+      }
+    </style>
+    <div class="container">
+      <slot></slot>
+    </div>
+  `;
+
+  let p = document.querySelector("p");
+  test(function() {
+    assert_equals(getComputedStyle(p).color, "rgb(0, 128, 0)");
+    assert_equals(getComputedStyle(p).backgroundColor, "rgb(0, 128, 0)");
+  }, "Slotted matches rules against the slot in the right tree");
+  test(function() {
+    nested.querySelector(".container").classList.remove("container");
+    assert_not_equals(getComputedStyle(p).color, "rgb(0, 128, 0)");
+
+    nested.host.removeAttribute("id");
+    assert_not_equals(getComputedStyle(p).backgroundColor, "rgb(0, 128, 0)");
+  }, "Style invalidation works correctly for nested slots");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable.html b/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable.html
index e8596c91..7df1820 100644
--- a/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable.html
+++ b/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet-constructable.html
@@ -466,5 +466,50 @@
     assert_equals(reason.name, "NotAllowedError");
   });
 }, 'CSSStyleSheet.replace returns rejected promise on failed imports');
+
+test(() => {
+  const span = document.createElement("span");
+  thirdSection.appendChild(span);
+  const shadowDiv = attachShadowDiv(span);
+  const sheet = new CSSStyleSheet();
+  span.shadowRoot.adoptedStyleSheets = [sheet];
+
+  const newSpan = span.cloneNode(true);
+  assert_equals(newSpan.shadowRoot, null);
+}, 'Cloning a shadow host will not clone shadow root, and also adoptedStyleSheets');
+
+test(() => {
+  const span = document.createElement("span");
+  thirdSection.appendChild(span);
+  const shadowDiv = attachShadowDiv(span);
+  const sheet = new CSSStyleSheet();
+  span.shadowRoot.adoptedStyleSheets = [sheet];
+
+  const iframe = document.createElement("iframe");
+  document.body.appendChild(iframe);
+  const newSpan = iframe.contentDocument.importNode(span, true);
+  iframe.contentDocument.body.appendChild(newSpan);
+  assert_equals(newSpan.shadowRoot, null);
+}, 'Importing a shadow host will not copy shadow root, and also adoptedStyleSheets');
+
+test(() => {
+  const span = document.createElement("span");
+  thirdSection.appendChild(span);
+  const shadowDiv = attachShadowDiv(span);
+  const sheet = new CSSStyleSheet();
+  sheet.replaceSync("* { color: red; }");
+  span.shadowRoot.adoptedStyleSheets = [sheet];
+  assert_equals(getComputedStyle(shadowDiv).color, "rgb(255, 0, 0)");
+
+  const iframe = document.createElement("iframe");
+  document.body.appendChild(iframe);
+  iframe.contentDocument.adoptNode(span);
+  iframe.contentDocument.body.appendChild(span);
+  assert_not_equals(span.shadowRoot, null);
+  assert_equals(span.shadowRoot.adoptedStyleSheets.length, 1);
+  assert_equals(span.shadowRoot.adoptedStyleSheets[0], sheet);
+  assert_equals(getComputedStyle(shadowDiv).color, "rgb(0, 0, 0)");
+}, 'Adopting a shadow host will move adoptedStyleSheets but it is not applied');
+
 </script>
 
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/attribute-selectors/attribute-case/cssom-expected.txt b/third_party/blink/web_tests/external/wpt/css/selectors/attribute-selectors/attribute-case/cssom-expected.txt
index 046b3a42..97a000b 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/attribute-selectors/attribute-case/cssom-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/attribute-selectors/attribute-case/cssom-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 56 tests; 32 PASS, 24 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 72 tests; 40 PASS, 32 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS [foo="bar"] /* sanity check */ insertRule
 PASS [foo="bar"] /* sanity check */ getting CSSRule#cssText
 PASS [foo="bar"] /* sanity check */ getting CSSStyleRule#selectorText
@@ -32,6 +32,14 @@
 PASS [foo="bar"/**/i] getting CSSRule#cssText in @media
 PASS [foo="bar"/**/i] getting CSSStyleRule#selectorText in @media
 PASS [foo="bar"/**/i] setting CSSStyleRule#selectorText in @media
+PASS [*|foo="bar" i] insertRule
+PASS [*|foo="bar" i] getting CSSRule#cssText
+PASS [*|foo="bar" i] getting CSSStyleRule#selectorText
+PASS [*|foo="bar" i] setting CSSStyleRule#selectorText
+PASS [*|foo="bar" i] insertRule in @media
+PASS [*|foo="bar" i] getting CSSRule#cssText in @media
+PASS [*|foo="bar" i] getting CSSStyleRule#selectorText in @media
+PASS [*|foo="bar" i] setting CSSStyleRule#selectorText in @media
 FAIL [foo="bar" s] insertRule Failed to execute 'insertRule' on 'CSSStyleSheet': Failed to parse the rule '[foo="bar" s] {}'.
 FAIL [foo="bar" s] getting CSSRule#cssText Failed to execute 'insertRule' on 'CSSStyleSheet': Failed to parse the rule '[foo="bar" s] {}'.
 FAIL [foo="bar" s] getting CSSStyleRule#selectorText Failed to execute 'insertRule' on 'CSSStyleSheet': Failed to parse the rule '[foo="bar" s] {}'.
@@ -56,5 +64,13 @@
 FAIL [foo="bar"/**/s] getting CSSRule#cssText in @media Failed to execute 'insertRule' on 'CSSGroupingRule': the rule '[foo="bar"/**/s] {}' is invalid and cannot be parsed.
 FAIL [foo="bar"/**/s] getting CSSStyleRule#selectorText in @media Failed to execute 'insertRule' on 'CSSGroupingRule': the rule '[foo="bar"/**/s] {}' is invalid and cannot be parsed.
 FAIL [foo="bar"/**/s] setting CSSStyleRule#selectorText in @media assert_equals: expected "[foo=\"bar\" s]" but got "foobar"
+FAIL [*|foo="bar" s] insertRule Failed to execute 'insertRule' on 'CSSStyleSheet': Failed to parse the rule '[*|foo="bar" s] {}'.
+FAIL [*|foo="bar" s] getting CSSRule#cssText Failed to execute 'insertRule' on 'CSSStyleSheet': Failed to parse the rule '[*|foo="bar" s] {}'.
+FAIL [*|foo="bar" s] getting CSSStyleRule#selectorText Failed to execute 'insertRule' on 'CSSStyleSheet': Failed to parse the rule '[*|foo="bar" s] {}'.
+FAIL [*|foo="bar" s] setting CSSStyleRule#selectorText assert_equals: expected "[*|foo=\"bar\" s]" but got "foobar"
+FAIL [*|foo="bar" s] insertRule in @media Failed to execute 'insertRule' on 'CSSGroupingRule': the rule '[*|foo="bar" s] {}' is invalid and cannot be parsed.
+FAIL [*|foo="bar" s] getting CSSRule#cssText in @media Failed to execute 'insertRule' on 'CSSGroupingRule': the rule '[*|foo="bar" s] {}' is invalid and cannot be parsed.
+FAIL [*|foo="bar" s] getting CSSStyleRule#selectorText in @media Failed to execute 'insertRule' on 'CSSGroupingRule': the rule '[*|foo="bar" s] {}' is invalid and cannot be parsed.
+FAIL [*|foo="bar" s] setting CSSStyleRule#selectorText in @media assert_equals: expected "[*|foo=\"bar\" s]" but got "foobar"
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/attribute-selectors/attribute-case/cssom.html b/third_party/blink/web_tests/external/wpt/css/selectors/attribute-selectors/attribute-case/cssom.html
index d03d820..74e7b9645 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/attribute-selectors/attribute-case/cssom.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/attribute-selectors/attribute-case/cssom.html
@@ -24,9 +24,11 @@
   ['[foo="bar" i]', '[foo="bar" i]'],
   ['[foo="bar" /**/ i]', '[foo="bar" i]'],
   ['[foo="bar"/**/i]', '[foo="bar" i]'],
+  ['[*|foo="bar" i]', '[*|foo="bar" i]'],
   ['[foo="bar" s]', '[foo="bar" s]'],
   ['[foo="bar" /**/ s]', '[foo="bar" s]'],
   ['[foo="bar"/**/s]', '[foo="bar" s]'],
+  ['[*|foo="bar" s]', '[*|foo="bar" s]'],
 ]
 
 tests.forEach(function(arr) {
diff --git a/third_party/blink/web_tests/external/wpt/storage/estimate-usage-details-application-cache.https.tentative.html b/third_party/blink/web_tests/external/wpt/storage/estimate-usage-details-application-cache.https.tentative.html
deleted file mode 100644
index 464a998..0000000
--- a/third_party/blink/web_tests/external/wpt/storage/estimate-usage-details-application-cache.https.tentative.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!doctype html>
-<html>
-<title>Quota Estimate: usage details reflect application cache changes.</title>
-<meta charset='utf-8'>
-<link rel='author' href='jarrydg@chromium.org' title='Jarryd Goodman'>
-<script src='/resources/testharness.js'></script>
-<script src='/resources/testharnessreport.js'></script>
-<script src='../cookie-store/resources/helpers.js'></script>
-<script>
-'use strict';
-
-promise_test(async t => {
-  let estimate = await navigator.storage.estimate();
-
-  const usageBeforeCreate = estimate.usageDetails.applicationCache || 0;
-
-  const iframe = await
-      createIframe('./resources/iframe_with_appcache_manifest.html', t);
-  await waitForMessage();
-
-  estimate = await navigator.storage.estimate();
-  assert_true('applicationCache' in estimate.usageDetails);
-  const usageAfterCreate = estimate.usageDetails.applicationCache;
-
-  assert_greater_than(
-      usageAfterCreate, usageBeforeCreate);
-}, 'estimate() shows usage increase after app is cached');
-</script>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/storage/estimate-usage-details-caches.https.tentative.any.js b/third_party/blink/web_tests/external/wpt/storage/estimate-usage-details-caches.https.tentative.any.js
deleted file mode 100644
index bf889f84..0000000
--- a/third_party/blink/web_tests/external/wpt/storage/estimate-usage-details-caches.https.tentative.any.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// META: title=StorageManager: estimate() for caches
-
-promise_test(async t => {
-  let estimate = await navigator.storage.estimate();
-
-  const cachesUsageBeforeCreate = estimate.usageDetails.caches || 0;
-
-  const cacheName = 'testCache';
-  const cache = await caches.open(cacheName);
-  t.add_cleanup(() => caches.delete(cacheName));
-
-  await cache.put('/test.json', new Response('x'.repeat(1024*1024)));
-
-  estimate = await navigator.storage.estimate();
-  assert_true('caches' in estimate.usageDetails);
-  const cachesUsageAfterPut = estimate.usageDetails.caches;
-  assert_greater_than(
-      cachesUsageAfterPut, cachesUsageBeforeCreate,
-      'estimated usage should increase after value is stored');
-}, 'estimate() shows usage increase after large value is stored');
diff --git a/third_party/blink/web_tests/external/wpt/storage/estimate-usage-details-service-workers.https.tentative.window.js b/third_party/blink/web_tests/external/wpt/storage/estimate-usage-details-service-workers.https.tentative.window.js
deleted file mode 100644
index be91cd61..0000000
--- a/third_party/blink/web_tests/external/wpt/storage/estimate-usage-details-service-workers.https.tentative.window.js
+++ /dev/null
@@ -1,22 +0,0 @@
-// META: title=StorageManager: estimate() for service worker registrations
-
-promise_test(async t => {
-  let estimate = await navigator.storage.estimate();
-
-  const usageBeforeCreate = estimate.usageDetails.serviceWorkerRegistrations ||
-      0;
-
-  // Note: helpers.js is an arbitrary file; it could be any file that
-  // exists, but this test does not depend on the contents of said file.
-  const serviceWorkerRegistration = await
-      navigator.serviceWorker.register('./helpers.js');
-  t.add_cleanup(() => serviceWorkerRegistration.unregister());
-
-  estimate = await navigator.storage.estimate();
-  assert_true('serviceWorkerRegistrations' in estimate.usageDetails);
-  const usageAfterCreate = estimate.usageDetails.serviceWorkerRegistrations;
-
-  assert_greater_than(
-      usageAfterCreate, usageBeforeCreate,
-      'estimated usage should increase after service worker is registered');
-}, 'estimate() shows usage increase after large value is stored');
diff --git a/third_party/blink/web_tests/external/wpt/storage/estimate-usage-details.https.tentative.any.js b/third_party/blink/web_tests/external/wpt/storage/estimate-usage-details.https.tentative.any.js
deleted file mode 100644
index 2a1cea5..0000000
--- a/third_party/blink/web_tests/external/wpt/storage/estimate-usage-details.https.tentative.any.js
+++ /dev/null
@@ -1,12 +0,0 @@
-// META: title=StorageManager: estimate() should have usage details
-
-promise_test(async t => {
-  const estimate = await navigator.storage.estimate();
-  assert_equals(typeof estimate, 'object');
-  assert_true('usage' in estimate);
-  assert_equals(typeof estimate.usage, 'number');
-  assert_true('quota' in estimate);
-  assert_equals(typeof estimate.quota, 'number');
-  assert_true('usageDetails' in estimate);
-  assert_equals(typeof estimate.usageDetails, 'object');
-}, 'estimate() resolves to dictionary with members, including usageDetails');
diff --git a/third_party/blink/web_tests/external/wpt/storage/resources/appcache.manifest b/third_party/blink/web_tests/external/wpt/storage/resources/appcache.manifest
deleted file mode 100644
index ce90baf..0000000
--- a/third_party/blink/web_tests/external/wpt/storage/resources/appcache.manifest
+++ /dev/null
@@ -1,3 +0,0 @@
-CACHE MANIFEST
-# iframe_with_appcache_manifest.html references this manifest to get cached in
-# AppCache.
diff --git a/third_party/blink/web_tests/external/wpt/storage/resources/iframe_with_appcache_manifest.html b/third_party/blink/web_tests/external/wpt/storage/resources/iframe_with_appcache_manifest.html
deleted file mode 100644
index 8365ce41..0000000
--- a/third_party/blink/web_tests/external/wpt/storage/resources/iframe_with_appcache_manifest.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!doctype html>
-<html manifest="appcache.manifest">
-<title>Iframe that will be cached using application cache.</title>
-<meta charset='utf-8'>
-<link rel='author' href='jarrydg@chromium.org' title='Jarryd Goodman'>
-<script>
-(async () => {
-  const initPromise = new Promise(resolve => {
-    applicationCache.addEventListener('cached', resolve);
-    applicationCache.addEventListener('noupdate', resolve);
-  });
-  await initPromise;
-
-  window.parent.postMessage('document cached');
-})();
-</script>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/svg/pservers/parsing/stop-color-computed.svg b/third_party/blink/web_tests/external/wpt/svg/pservers/parsing/stop-color-computed.svg
new file mode 100644
index 0000000..b05a69f1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/svg/pservers/parsing/stop-color-computed.svg
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml">
+  <title>SVG Paint Servers: getComputedStyle().stopColor</title>
+  <metadata>
+    <h:link rel="help" href="https://svgwg.org/svg2-draft/pservers.html#StopColorProperty"/>
+    <h:link rel="help" href="https://drafts.csswg.org/css-color/#resolve-color-values"/>
+    <h:link rel="help" href="https://drafts.csswg.org/cssom/#serializing-css-values"/>
+  </metadata>
+  <g id="target" style="color: blue"></g>
+  <h:script src="/resources/testharness.js"/>
+  <h:script src="/resources/testharnessreport.js"/>
+  <h:script src="/css/support/computed-testcommon.js"/>
+  <script><![CDATA[
+
+test_computed_value("stop-color", "currentcolor", "rgb(0, 0, 255)");
+test_computed_value("stop-color", "white", "rgb(255, 255, 255)");
+test_computed_value("stop-color", "transparent", "rgba(0, 0, 0, 0)");
+test_computed_value("stop-color", "rgb(255, 255, 255)");
+test_computed_value("stop-color", "#ffffff", "rgb(255, 255, 255)");
+test_computed_value("stop-color", "rgba(255, 255, 255, 1.0)", "rgb(255, 255, 255)");
+test_computed_value("stop-color", "rgba(255, 255, 255, 0.4)");
+test_computed_value("stop-color", "hsl(0deg, 100%, 100%)", "rgb(255, 255, 255)");
+test_computed_value("stop-color", "hsla(0deg, 100%, 100%, 1.0)", "rgb(255, 255, 255)");
+test_computed_value("stop-color", "hsla(0deg, 100%, 100%, 0.4)", "rgba(255, 255, 255, 0.4)");
+
+  ]]></script>
+</svg>
diff --git a/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/reference/green-100x100.svg b/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/reference/green-100x100.svg
new file mode 100644
index 0000000..1209414
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/reference/green-100x100.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+  <rect width="100" height="100" fill="green"/>
+</svg>
diff --git a/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/stop-color-currentcolor-dynamic-001.svg b/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/stop-color-currentcolor-dynamic-001.svg
new file mode 100644
index 0000000..da0a05dd
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/stop-color-currentcolor-dynamic-001.svg
@@ -0,0 +1,18 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml"
+     style="color: red">
+  <title>stop-color: Dynamically changing 'color' for a gradient with a stop with 'currentcolor'</title>
+  <h:link rel="help" href="https://svgwg.org/svg2-draft/pservers.html#StopColorProperty"/>
+  <h:link rel="match" href="reference/green-100x100.svg"/>
+  <linearGradient id="g">
+    <stop stop-color="currentcolor"/>
+  </linearGradient>
+  <rect width="50" height="100" fill="url(#g)"/>
+  <rect width="50" height="100" x="50" fill="currentcolor"/>
+  <script>
+    <![CDATA[
+      let root = document.querySelector(':root');
+      root.getBoundingClientRect();  // Force layout
+      root.style.color = 'green';
+    ]]>
+  </script>
+</svg>
diff --git a/third_party/blink/web_tests/external/wpt/svg/pservers/scripted/stop-color-inheritance-currentcolor.svg b/third_party/blink/web_tests/external/wpt/svg/pservers/scripted/stop-color-inheritance-currentcolor.svg
new file mode 100644
index 0000000..22bf513c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/svg/pservers/scripted/stop-color-inheritance-currentcolor.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml"
+     color="red">
+  <title>SVG Paint Servers: 'stop-color' inheritance of 'currentcolor'</title>
+  <metadata>
+    <h:link rel="help" href="https://svgwg.org/svg2-draft/pservers.html#StopColorProperty"/>
+    <h:link rel="help" href="https://drafts.csswg.org/css-color/#resolve-color-values"/>
+  </metadata>
+  <h:script src="/resources/testharness.js"/>
+  <h:script src="/resources/testharnessreport.js"/>
+  <linearGradient stop-color="currentcolor" id="g">
+    <stop stop-color="inherit" color="green"/>
+  </linearGradient>
+  <script><![CDATA[
+
+    test(function() {
+      let stop = document.querySelector('stop');
+      assert_equals(getComputedStyle(stop).stopColor, 'rgb(0, 128, 0)');
+    }, '"currentcolor" is inherited as a keyword');
+
+  ]]></script>
+</svg>
diff --git a/third_party/blink/web_tests/external/wpt/user-timing/mark-measure-feature-detection.html b/third_party/blink/web_tests/external/wpt/user-timing/mark-measure-feature-detection.html
new file mode 100644
index 0000000..6f1ad48
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/user-timing/mark-measure-feature-detection.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>User Timing: L2 vs L3 feature detection</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+  test(() => {
+    // Feature detection for PerformanceMark.
+    assert_equals(typeof(PerformanceMark.prototype), "object");
+    // Test for UserTiming L3.
+    if (PerformanceMark.prototype.hasOwnProperty('detail')) {
+      assert_equals(typeof(performance.mark("mark")), "object",
+        "performance.mark should return an object in UserTiming L3.");
+    }
+    // Test for UserTiming L2.
+    else {
+      assert_equals(typeof(performance.mark("mark")), "undefined",
+        "performance.mark should be void in UserTiming L2.");
+    }
+  }, "Test PerformanceMark existence and feature detection");
+
+  test(() => {
+    // Feature detection for PerformanceMeasure.
+    assert_equals(typeof(PerformanceMeasure.prototype), "object");
+    // Test for UserTiming L3.
+    if (PerformanceMeasure.prototype.hasOwnProperty('detail')) {
+      assert_equals(typeof(performance.measure("measure")), "object",
+        "performance.measure should return an object in UserTiming L3.");
+    }
+    // Test for UserTiming L2.
+    else {
+      assert_equals(typeof(performance.measure("measure")), "undefined",
+        "performance.measure should be void in UserTiming L2.");
+    }
+  }, "Test PerformanceMeasure existence and feature detection");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/user-timing/mark-measure-return-null.html b/third_party/blink/web_tests/external/wpt/user-timing/mark-measure-return-null.html
deleted file mode 100644
index 5afd963..0000000
--- a/third_party/blink/web_tests/external/wpt/user-timing/mark-measure-return-null.html
+++ /dev/null
@@ -1,46 +0,0 @@
-<!DOCTYPE HTML>
-<meta charset=utf-8>
-<title>User Timing: L2 APIs return null</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<p>User Timing: L2 APIs return null</p>
-<div id="log"></div>
-<script>
-  async_test(function (t) {
-    self.performance.clearMeasures();
-    const measure = self.performance.measure("measure1");
-    assert_equals(measure, null);
-    t.done();
-  }, "L2: performance.measure(name) should return null.");
-
-  async_test(function (t) {
-    self.performance.clearMeasures();
-    self.performance.mark("1");
-    const measure = self.performance.measure("measure2", 1);
-    assert_equals(measure, null);
-    t.done();
-  }, "L2: performance.measure(name, param1) should return null.");
-
-  async_test(function (t) {
-    self.performance.clearMeasures();
-    self.performance.mark("1");
-    self.performance.mark("2");
-    const measure = self.performance.measure("measure3", 1, 2);
-    assert_equals(measure, null);
-    t.done();
-  }, "L2: performance.measure(name, param1, param2) should return null.");
-
-  async_test(function (t) {
-    self.performance.clearMarks();
-    const mark = self.performance.mark("mark1");
-    assert_equals(mark, null);
-    t.done();
-  }, "L2: performance.mark(name) should return null.");
-
-  async_test(function (t) {
-    self.performance.clearMarks();
-    const mark = self.performance.mark("mark2", { startTime: 34 });
-    assert_equals(mark, null);
-    t.done();
-  }, "L2: performance.mark(name, param) should return null.");
-</script>
diff --git a/third_party/blink/web_tests/fast/css/text-align-pre-trailing-spaces-expected.html b/third_party/blink/web_tests/fast/css/text-align-pre-trailing-spaces-expected.html
new file mode 100644
index 0000000..f28a2e6
--- /dev/null
+++ b/third_party/blink/web_tests/fast/css/text-align-pre-trailing-spaces-expected.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<style>
+section {
+  display: inline-block;
+}
+div {
+  white-space: pre;
+  font-family: Ahem;
+  font-size: 20px;
+  line-height: 1;
+  width: 10ch;
+  border: 1px solid black;
+}
+</style>
+<section>
+  <div>12345<br>12345<br>12345</div>
+  <div>12345<br> 12345<br> 12345</div>
+  <div>12345<br>  12345<br>  12345</div>
+  <div>12345<br>12345<br>12345</div>
+  <div>12345<br>  12345<br>  12345</div>
+</section>
+<section>
+  <div>     12345<br>   12345<br>   12345</div>
+  <div>     12345<br>    12345<br>    12345</div>
+  <div>     12345<br>     12345<br>     12345</div>
+  <div>     12345<br>     12345<br>     12345</div>
+  <div>     12345<br>   12345<br>   12345</div>
+</section>
diff --git a/third_party/blink/web_tests/fast/css/text-align-pre-trailing-spaces.html b/third_party/blink/web_tests/fast/css/text-align-pre-trailing-spaces.html
new file mode 100644
index 0000000..bb72be2
--- /dev/null
+++ b/third_party/blink/web_tests/fast/css/text-align-pre-trailing-spaces.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!--
+This tests a behavior that is not defined in the spec today.
+We can move to wpt once it's resolved.
+https://github.com/w3c/csswg-drafts/issues/3440
+-->
+<style>
+section {
+  display: inline-block;
+}
+div {
+  white-space: pre;
+  font-family: Ahem;
+  font-size: 20px;
+  line-height: 1;
+  width: 10ch;
+  border: 1px solid black;
+}
+.left { text-align: left; }
+.center { text-align: center; }
+.right { text-align: right; }
+.start { text-align: start; }
+.end { text-align: end; }
+</style>
+<section>
+  <div class="left">12345       <br>12345   <br>12345   </div>
+  <div class="center">12345       <br>12345   <br>12345   </div>
+  <div class="right">12345       <br>12345   <br>12345   </div>
+  <div class="start">12345       <br>12345   <br>12345   </div>
+  <div class="end">12345       <br>12345   <br>12345   </div>
+</section>
+<section dir="rtl">
+  <div class="left">12345       <br>12345   <br>12345   </div>
+  <div class="center">12345       <br>12345   <br>12345   </div>
+  <div class="right">12345       <br>12345   <br>12345   </div>
+  <div class="start">12345       <br>12345   <br>12345   </div>
+  <div class="end">12345       <br>12345   <br>12345   </div>
+</section>
diff --git a/third_party/blink/web_tests/fast/css/text-align-pre-wrap-trailing-spaces-multi-lines-expected.html b/third_party/blink/web_tests/fast/css/text-align-pre-wrap-trailing-spaces-multi-lines-expected.html
new file mode 100644
index 0000000..f28a2e6
--- /dev/null
+++ b/third_party/blink/web_tests/fast/css/text-align-pre-wrap-trailing-spaces-multi-lines-expected.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<style>
+section {
+  display: inline-block;
+}
+div {
+  white-space: pre;
+  font-family: Ahem;
+  font-size: 20px;
+  line-height: 1;
+  width: 10ch;
+  border: 1px solid black;
+}
+</style>
+<section>
+  <div>12345<br>12345<br>12345</div>
+  <div>12345<br> 12345<br> 12345</div>
+  <div>12345<br>  12345<br>  12345</div>
+  <div>12345<br>12345<br>12345</div>
+  <div>12345<br>  12345<br>  12345</div>
+</section>
+<section>
+  <div>     12345<br>   12345<br>   12345</div>
+  <div>     12345<br>    12345<br>    12345</div>
+  <div>     12345<br>     12345<br>     12345</div>
+  <div>     12345<br>     12345<br>     12345</div>
+  <div>     12345<br>   12345<br>   12345</div>
+</section>
diff --git a/third_party/blink/web_tests/fast/css/text-align-pre-wrap-trailing-spaces-multi-lines.html b/third_party/blink/web_tests/fast/css/text-align-pre-wrap-trailing-spaces-multi-lines.html
new file mode 100644
index 0000000..b7d74a2
--- /dev/null
+++ b/third_party/blink/web_tests/fast/css/text-align-pre-wrap-trailing-spaces-multi-lines.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!--
+This tests a behavior that is not defined in the spec today.
+We can move to wpt once it's resolved.
+https://github.com/w3c/csswg-drafts/issues/3440
+-->
+<style>
+section {
+  display: inline-block;
+}
+div {
+  white-space: pre-wrap;
+  font-family: Ahem;
+  font-size: 20px;
+  line-height: 1;
+  width: 10ch;
+  border: 1px solid black;
+}
+.left { text-align: left; }
+.center { text-align: center; }
+.right { text-align: right; }
+.start { text-align: start; }
+.end { text-align: end; }
+</style>
+<section>
+  <div class="left">12345       12345   12345   </div>
+  <div class="center">12345       12345   12345   </div>
+  <div class="right">12345       12345   12345   </div>
+  <div class="start">12345       12345   12345   </div>
+  <div class="end">12345       12345   12345   </div>
+</section>
+<section dir="rtl">
+  <div class="left">12345       12345   12345   </div>
+  <div class="center">12345       12345   12345   </div>
+  <div class="right">12345       12345   12345   </div>
+  <div class="start">12345       12345   12345   </div>
+  <div class="end">12345       12345   12345   </div>
+</section>
diff --git a/third_party/blink/web_tests/fast/css/transform-inline-style-remove-expected.txt b/third_party/blink/web_tests/fast/css/transform-inline-style-remove-expected.txt
index 36969a2e..f217e1a 100644
--- a/third_party/blink/web_tests/fast/css/transform-inline-style-remove-expected.txt
+++ b/third_party/blink/web_tests/fast/css/transform-inline-style-remove-expected.txt
@@ -19,7 +19,7 @@
 transform origin X (after):
 transform origin Y (after):
 
-animation (before): test 5s ease-in-out 0s infinite alternate none running
+animation (before): 5s ease-in-out 0s infinite alternate none running test
 animation name (before): test
 animation duration (before): 5s
 animation timing function (before): ease-in-out
diff --git a/third_party/blink/web_tests/http/tests/cache/history-only-cached-subresource-loads-max-age-https-expected.txt b/third_party/blink/web_tests/http/tests/cache/history-only-cached-subresource-loads-max-age-https-expected.txt
index 7a2d6c31..55d449ce 100644
--- a/third_party/blink/web_tests/http/tests/cache/history-only-cached-subresource-loads-max-age-https-expected.txt
+++ b/third_party/blink/web_tests/http/tests/cache/history-only-cached-subresource-loads-max-age-https-expected.txt
@@ -1,7 +1,3 @@
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/cache/resources/max-age-resource.html' attempted to load subresource at 'https://127.0.0.1:8443/cache/resources/random-max-age.cgi' over broken HTTPS.
-CONSOLE ERROR: line 1: Mixed Content: The page at 'https://127.0.0.1:8443/cache/resources/max-age-resource.html' attempted to load subresource at 'https://127.0.0.1:8443/cache/resources/random-max-age.cgi' over broken HTTPS.
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/cache/resources/max-age-resource.html' attempted to load subresource at 'https://127.0.0.1:8443/cache/resources/random-max-age.cgi' over broken HTTPS.
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/cache/resources/max-age-resource-next.html' attempted to load subresource at 'https://127.0.0.1:8443/cache/resources/random-max-age.cgi' over broken HTTPS.
 This test checks that loading a subresource with "Cache-Control: max-age=0" is cached and reused in back navigation when the page is not in the page cache.
 
 We then test that loading the same subresource is refetched when used in non-stale loads such as refreshes or normal navigation.
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-keyframes-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-keyframes-expected.txt
index fbff4ec..67d8f33 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-keyframes-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/styles-keyframes-expected.txt
@@ -7,7 +7,6 @@
 [expanded] 
 #element { (keyframes.css:1 -> keyframes.css:1:11)
     animation: animName 1s 2s, mediaAnim 2s, doesNotExist 3s, styleSheetAnim 0s;
-        animation-name: animName, mediaAnim, doesNotExist, styleSheetAnim;
         animation-duration: 1s, 2s, 3s, 0s;
         animation-timing-function: ease, ease, ease, ease;
         animation-delay: 2s, 0s, 0s, 0s;
@@ -15,6 +14,7 @@
         animation-direction: normal, normal, normal, normal;
         animation-fill-mode: none, none, none, none;
         animation-play-state: running, running, running, running;
+        animation-name: animName, mediaAnim, doesNotExist, styleSheetAnim;
 
 [expanded] 
 div { (user agent stylesheet)
@@ -59,7 +59,6 @@
 [expanded] 
 #element { (keyframes.css:1 -> keyframes.css:1:11)
     animation: animName 1s 2s, mediaAnim 2s, doesNotExist 3s, styleSheetAnim 0s;
-        animation-name: animName, mediaAnim, doesNotExist, styleSheetAnim;
         animation-duration: 1s, 2s, 3s, 0s;
         animation-timing-function: ease, ease, ease, ease;
         animation-delay: 2s, 0s, 0s, 0s;
@@ -67,6 +66,7 @@
         animation-direction: normal, normal, normal, normal;
         animation-fill-mode: none, none, none, none;
         animation-play-state: running, running, running, running;
+        animation-name: animName, mediaAnim, doesNotExist, styleSheetAnim;
 
 [expanded] 
 div { (user agent stylesheet)
@@ -111,7 +111,6 @@
 [expanded] 
 #element { (keyframes.css:1 -> keyframes.css:1:11)
     animation: animName 1s 2s, mediaAnim 2s, doesNotExist 3s, styleSheetAnim 0s;
-        animation-name: animName, mediaAnim, doesNotExist, styleSheetAnim;
         animation-duration: 1s, 2s, 3s, 0s;
         animation-timing-function: ease, ease, ease, ease;
         animation-delay: 2s, 0s, 0s, 0s;
@@ -119,6 +118,7 @@
         animation-direction: normal, normal, normal, normal;
         animation-fill-mode: none, none, none, none;
         animation-play-state: running, running, running, running;
+        animation-name: animName, mediaAnim, doesNotExist, styleSheetAnim;
 
 [expanded] 
 div { (user agent stylesheet)
@@ -163,7 +163,6 @@
 [expanded] 
 #element { (keyframes.css:1 -> keyframes.css:1:11)
     animation: animName 1s 2s, mediaAnim 2s, doesNotExist 3s, styleSheetAnim 0s;
-        animation-name: animName, mediaAnim, doesNotExist, styleSheetAnim;
         animation-duration: 1s, 2s, 3s, 0s;
         animation-timing-function: ease, ease, ease, ease;
         animation-delay: 2s, 0s, 0s, 0s;
@@ -171,6 +170,7 @@
         animation-direction: normal, normal, normal, normal;
         animation-fill-mode: none, none, none, none;
         animation-play-state: running, running, running, running;
+        animation-name: animName, mediaAnim, doesNotExist, styleSheetAnim;
 
 [expanded] 
 div { (user agent stylesheet)
@@ -215,7 +215,6 @@
 [expanded] 
 #element { (keyframes.css:1 -> keyframes.css:1:11)
     animation: animName 1s 2s, mediaAnim 2s, doesNotExist 3s, styleSheetAnim 0s;
-        animation-name: animName, mediaAnim, doesNotExist, styleSheetAnim;
         animation-duration: 1s, 2s, 3s, 0s;
         animation-timing-function: ease, ease, ease, ease;
         animation-delay: 2s, 0s, 0s, 0s;
@@ -223,6 +222,7 @@
         animation-direction: normal, normal, normal, normal;
         animation-fill-mode: none, none, none, none;
         animation-play-state: running, running, running, running;
+        animation-name: animName, mediaAnim, doesNotExist, styleSheetAnim;
 
 [expanded] 
 div { (user agent stylesheet)
diff --git a/third_party/blink/web_tests/http/tests/mixed-autoupgrade/optionally/image-upgrade-console-message.https-expected.txt b/third_party/blink/web_tests/http/tests/mixed-autoupgrade/optionally/image-upgrade-console-message.https-expected.txt
index 2bebfe4..4d9d826 100644
--- a/third_party/blink/web_tests/http/tests/mixed-autoupgrade/optionally/image-upgrade-console-message.https-expected.txt
+++ b/third_party/blink/web_tests/http/tests/mixed-autoupgrade/optionally/image-upgrade-console-message.https-expected.txt
@@ -1,3 +1,2 @@
 CONSOLE WARNING: line 2: Mixed Content: The page at 'https://127.0.0.1:8443/mixed-autoupgrade/optionally/image-upgrade-console-message.https.html' was loaded over HTTPS, but requested an insecure element 'http://web-platform.test:8443/mixed-autoupgrade/resources/pass.png'. As part of an experiment this request was automatically upgraded to HTTPS, For more information see https://chromium.googlesource.com/chromium/src/+/master/docs/security/autougprade-mixed.md
 CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/mixed-autoupgrade/optionally/image-upgrade-console-message.https.html' was loaded over HTTPS, but requested an insecure element 'http://web-platform.test:8443/mixed-autoupgrade/resources/pass.png'. As part of an experiment this request was automatically upgraded to HTTPS, For more information see https://chromium.googlesource.com/chromium/src/+/master/docs/security/autougprade-mixed.md
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/mixed-autoupgrade/optionally/image-upgrade-console-message.https.html' attempted to load subresource at 'https://web-platform.test:8443/mixed-autoupgrade/resources/pass.png' over broken HTTPS.
diff --git a/third_party/blink/web_tests/http/tests/navigation/ping-cross-origin-from-https-expected.txt b/third_party/blink/web_tests/http/tests/navigation/ping-cross-origin-from-https-expected.txt
index 960c102..60751e8 100644
--- a/third_party/blink/web_tests/http/tests/navigation/ping-cross-origin-from-https-expected.txt
+++ b/third_party/blink/web_tests/http/tests/navigation/ping-cross-origin-from-https-expected.txt
@@ -1,4 +1,3 @@
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/navigation/resources/ping-cross-origin-from-https-target.html' attempted to load subresource at 'https://127.0.0.1:8443/navigation/resources/resources/delete-ping.php?test=cross-origin-from-https' over broken HTTPS.
 PingLoader dispatched to 'http://example.test:8000/navigation/resources/save-Ping.php?test=cross-origin-from-https'.
 CONSOLE ERROR: line 25: Mixed Content: The page at 'https://127.0.0.1:8443/navigation/resources/ping-cross-origin-from-https-target.html' was loaded over HTTPS, but requested an insecure hyperlink auditing endpoint 'http://example.test:8000/navigation/resources/save-Ping.php?test=cross-origin-from-https'. This request has been blocked; the content must be served over HTTPS.
 This page calls testRunner.notifyDone().
diff --git a/third_party/blink/web_tests/http/tests/navigatorcontentutils/register-protocol-handler-expected.txt b/third_party/blink/web_tests/http/tests/navigatorcontentutils/register-protocol-handler-expected.txt
deleted file mode 100644
index 0578523..0000000
--- a/third_party/blink/web_tests/http/tests/navigatorcontentutils/register-protocol-handler-expected.txt
+++ /dev/null
@@ -1,49 +0,0 @@
-This test makes sure that navigator.registerProtocolHandler throws the proper exceptions and has no-op default implementation.
-
-PASS window.navigator.registerProtocolHandler is defined.
-PASS Invalid scheme "http" threw SecurityError exception: "Failed to execute 'registerProtocolHandler' on 'Navigator': The scheme 'http' doesn't belong to the scheme whitelist. Please prefix non-whitelisted schemes with the string 'web+'.".
-PASS Invalid scheme "https" threw SecurityError exception: "Failed to execute 'registerProtocolHandler' on 'Navigator': The scheme 'https' doesn't belong to the scheme whitelist. Please prefix non-whitelisted schemes with the string 'web+'.".
-PASS Invalid scheme "file" threw SecurityError exception: "Failed to execute 'registerProtocolHandler' on 'Navigator': The scheme 'file' doesn't belong to the scheme whitelist. Please prefix non-whitelisted schemes with the string 'web+'.".
-PASS Invalid scheme "web+" threw SecurityError exception: "Failed to execute 'registerProtocolHandler' on 'Navigator': The scheme 'web+' is less than five characters long.".
-PASS Valid scheme "bitcoin" allowed.
-PASS Valid scheme "BitcoIn" allowed.
-PASS Valid scheme "geo" allowed.
-PASS Valid scheme "im" allowed.
-PASS Valid scheme "irc" allowed.
-PASS Valid scheme "Irc" allowed.
-PASS Valid scheme "ircs" allowed.
-PASS Valid scheme "magnet" allowed.
-PASS Valid scheme "MagneT" allowed.
-PASS Valid scheme "mailto" allowed.
-PASS Valid scheme "mms" allowed.
-PASS Valid scheme "news" allowed.
-PASS Valid scheme "nntp" allowed.
-PASS Valid scheme "openpgp4fpr" allowed.
-PASS Valid scheme "sip" allowed.
-PASS Valid scheme "sms" allowed.
-PASS Valid scheme "smsto" allowed.
-PASS Valid scheme "SmsTo" allowed.
-PASS Valid scheme "ssh" allowed.
-PASS Valid scheme "tel" allowed.
-PASS Valid scheme "urn" allowed.
-PASS Valid scheme "webcal" allowed.
-PASS Valid scheme "WebCAL" allowed.
-PASS Valid scheme "wtai" allowed.
-PASS Valid scheme "WTAI" allowed.
-PASS Valid scheme "xmpp" allowed.
-PASS Invalid scheme "mailto:" falied.
-PASS Invalid scheme "ssh:/" falied.
-PASS Invalid scheme "magnet:+" falied.
-PASS Invalid scheme "tel:sip" falied.
-PASS Invalid url "" threw SyntaxError exception: "Failed to execute 'registerProtocolHandler' on 'Navigator': The url provided ('') does not contain '%s'.".
-PASS Invalid url "%S" threw SyntaxError exception: "Failed to execute 'registerProtocolHandler' on 'Navigator': The url provided ('%S') does not contain '%s'.".
-PASS Invalid url "http://[v8.:::]//url=%s" threw SyntaxError exception: "Failed to execute 'registerProtocolHandler' on 'Navigator': The custom handler URL created by removing '%s' and prepending 'http://127.0.0.1:8000/navigatorcontentutils/register-protocol-handler.html' is invalid.".
-PASS The registeration of URL that has the same origin with the document origin is allowed.
-PASS URL with origin different than document origin threw SecurityError exception: "Failed to execute 'registerProtocolHandler' on 'Navigator': Can only register custom handler in the document's origin.".
-PASS Valid call succeeded.
-
-
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/blink/web_tests/http/tests/navigatorcontentutils/register-protocol-handler.html b/third_party/blink/web_tests/http/tests/navigatorcontentutils/register-protocol-handler.html
deleted file mode 100644
index 92c094f4a..0000000
--- a/third_party/blink/web_tests/http/tests/navigatorcontentutils/register-protocol-handler.html
+++ /dev/null
@@ -1,129 +0,0 @@
-<html>
-<head>
-<script src="/js-test-resources/js-test.js"></script>
-</head>
-<body>
-<p>This test makes sure that navigator.registerProtocolHandler throws the proper exceptions and has no-op default implementation.</p>
-<pre id="console"></pre>
-<script>
-if (window.internals)
-    internals.setNavigatorContentUtilsClientMock(document);
-
-if (window.navigator.registerProtocolHandler)
-    debug('PASS window.navigator.registerProtocolHandler is defined.');
-else
-    debug('FAIL window.navigator.registerProtocolHandler is not defined.');
-
-var invalid_schemes = ['http', 'https', 'file', 'web+'];
-invalid_schemes.forEach(function (scheme) {
-    var succeeded = false;
-    var errorMessage;
-    try {
-        window.navigator.registerProtocolHandler(scheme, "invalid scheme %s", "title");
-    } catch (e) {
-        succeeded = 'SecurityError' == e.name;
-        errorMessage = e.message;
-    }
-
-    if (succeeded) {
-        debug('PASS Invalid scheme "' + scheme + '" threw SecurityError exception: "' + errorMessage + '".');
-    }else
-        debug('FAIL Invalid scheme "' + scheme + '" allowed.');
-});
-
-var valid_schemes = ['bitcoin', 'BitcoIn', 'geo', 'im', 'irc', 'Irc', 'ircs', 'magnet', 'MagneT', 'mailto', 'mms', 'news', 'nntp', 'openpgp4fpr', 'sip', 'sms', 'smsto', 'SmsTo', 'ssh', 'tel', 'urn', 'webcal', 'WebCAL', 'wtai', 'WTAI', 'xmpp'];
-valid_schemes.forEach(function (scheme) {
-    var succeeded = false;
-    try {
-        window.navigator.registerProtocolHandler(scheme, "valid scheme %s", "title");
-        succeeded = true;
-    } catch (e) {
-        succeeded = false;
-    }
-
-    if (succeeded)
-        debug('PASS Valid scheme "' + scheme + '" allowed.');
-    else
-        debug('FAIL Valid scheme "' + scheme + '" failed.');
-});
-
-var invalid_schemes = ['mailto:', 'ssh:/', 'magnet:+', 'tel:sip'];
-invalid_schemes.forEach(function (scheme) {
-    var succeeded = false;
-    try {
-        window.navigator.registerProtocolHandler(scheme, 'invalid scheme uri=%s', 'title');
-    } catch (e) {
-        succeeded = 'SecurityError' == e.name;
-        errorMessage = e.message;
-    }
-
-    if (succeeded)
-        debug('PASS Invalid scheme "' + scheme + '" falied.');
-    else
-        debug('Fail: Invalid scheme "' + scheme + '" allowed. Threw exception: "' + errorMessage + '".');
-});
-
-var invalid_urls = ["", "%S", "http://[v8.:::]//url=%s"];
-invalid_urls.forEach(function (url) {
-    var succeeded = false;
-    try {
-        window.navigator.registerProtocolHandler('web+myscheme', url, 'title');
-    } catch (e) {
-        succeeded = 'SyntaxError' == e.name;
-        errorMessage = e.message;
-    }
-
-    if (succeeded)
-        debug('PASS Invalid url "' + url + '" threw SyntaxError exception: "' + errorMessage + '".');
-    else
-        debug('FAIL Invalid url "' + url + '" allowed.');
-});
-
-// Test if the API can register when URL's origin is same with the document's origin.
-var succeeded = false;
-var errorMessage;
-try {
-    window.navigator.registerProtocolHandler('web+myprotocol', "http://127.0.0.1:8000/navigatorcontentutils/url=%s", "title");
-    succeeded = true;
-} catch (e) {
-    errorMessage = e.message;
-}
-
-if (succeeded)
-    debug('PASS The registeration of URL that has the same origin with the document origin is allowed.');
-else
-    debug('FAIL The registeration of URL that has the same origin with the document origin is denied. errorMessage: "' + errorMessage + '".');
-
-// Test that the API throws SecurityError exception if the URL's origin differs from the document's origin.
-succeeded = false;
-var errorMessage;
-try {
-    window.navigator.registerProtocolHandler('web+myprotocol', "http://www.example.com/soup?url=%s", "title");
-} catch (e) {
-    succeeded = true;
-    errorMessage = e.message;
-}
-
-if (succeeded)
-    debug('PASS URL with origin different than document origin threw SecurityError exception: "' + errorMessage + '".');
-else
-    debug('FAIL URL with origin different than document origin is allowed.');
-
-// Test that the API has default no-op implementation.
-var succeeded = true;
-try {
-    window.navigator.registerProtocolHandler('web+myscheme', "%s", "title");
-} catch (e) {
-    succeeded = false;
-}
-
-if (succeeded)
-    debug('PASS Valid call succeeded.');
-else
-    debug('FAIL Invalid call did not succeed.');
-
-debug("\n");
-
-</script>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/http/tests/navigatorcontentutils/unregister-protocol-handler-expected.txt b/third_party/blink/web_tests/http/tests/navigatorcontentutils/unregister-protocol-handler-expected.txt
deleted file mode 100644
index fb88ce0..0000000
--- a/third_party/blink/web_tests/http/tests/navigatorcontentutils/unregister-protocol-handler-expected.txt
+++ /dev/null
@@ -1,48 +0,0 @@
-This test makes sure that navigator.unregisterProtocolHandler throws the proper exceptions and has no-op default implementation.
-
-PASS window.navigator.unregisterProtocolHandler is defined.
-PASS Invalid scheme "http" threw SecurityError exception: "Failed to execute 'unregisterProtocolHandler' on 'Navigator': The scheme 'http' doesn't belong to the scheme whitelist. Please prefix non-whitelisted schemes with the string 'web+'.".
-PASS Invalid scheme "https" threw SecurityError exception: "Failed to execute 'unregisterProtocolHandler' on 'Navigator': The scheme 'https' doesn't belong to the scheme whitelist. Please prefix non-whitelisted schemes with the string 'web+'.".
-PASS Invalid scheme "file" threw SecurityError exception: "Failed to execute 'unregisterProtocolHandler' on 'Navigator': The scheme 'file' doesn't belong to the scheme whitelist. Please prefix non-whitelisted schemes with the string 'web+'.".
-PASS Invalid scheme "web+" threw SecurityError exception: "Failed to execute 'unregisterProtocolHandler' on 'Navigator': The scheme 'web+' is less than five characters long.".
-PASS Valid scheme "bitcoin" allowed.
-PASS Valid scheme "BitcoIn" allowed.
-PASS Valid scheme "geo" allowed.
-PASS Valid scheme "im" allowed.
-PASS Valid scheme "irc" allowed.
-PASS Valid scheme "Irc" allowed.
-PASS Valid scheme "ircs" allowed.
-PASS Valid scheme "magnet" allowed.
-PASS Valid scheme "MagneT" allowed.
-PASS Valid scheme "mailto" allowed.
-PASS Valid scheme "mms" allowed.
-PASS Valid scheme "news" allowed.
-PASS Valid scheme "nntp" allowed.
-PASS Valid scheme "openpgp4fpr" allowed.
-PASS Valid scheme "sip" allowed.
-PASS Valid scheme "sms" allowed.
-PASS Valid scheme "smsto" allowed.
-PASS Valid scheme "SmsTo" allowed.
-PASS Valid scheme "ssh" allowed.
-PASS Valid scheme "tel" allowed.
-PASS Valid scheme "urn" allowed.
-PASS Valid scheme "webcal" allowed.
-PASS Valid scheme "WebCAL" allowed.
-PASS Valid scheme "wtai" allowed.
-PASS Valid scheme "WTAI" allowed.
-PASS Valid scheme "xmpp" allowed.
-PASS Invalid scheme "mailto:" falied.
-PASS Invalid scheme "ssh:/" falied.
-PASS Invalid scheme "magnet:+" falied.
-PASS Invalid scheme "tel:sip" falied.
-PASS Invalid url "" threw SyntaxError exception.Failed to execute 'unregisterProtocolHandler' on 'Navigator': The url provided ('') does not contain '%s'.".
-PASS Invalid url "%S" threw SyntaxError exception.Failed to execute 'unregisterProtocolHandler' on 'Navigator': The url provided ('%S') does not contain '%s'.".
-PASS Invalid url "http://[v8.:::]//url=%s" threw SyntaxError exception.Failed to execute 'unregisterProtocolHandler' on 'Navigator': The custom handler URL created by removing '%s' and prepending 'http://127.0.0.1:8000/navigatorcontentutils/unregister-protocol-handler.html' is invalid.".
-PASS URL with origin different than document origin threw SecurityError exception: "Failed to execute 'unregisterProtocolHandler' on 'Navigator': Can only register custom handler in the document's origin.".
-PASS Valid call succeeded.
-
-
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/blink/web_tests/http/tests/navigatorcontentutils/unregister-protocol-handler.html b/third_party/blink/web_tests/http/tests/navigatorcontentutils/unregister-protocol-handler.html
deleted file mode 100644
index 0adc9bcd..0000000
--- a/third_party/blink/web_tests/http/tests/navigatorcontentutils/unregister-protocol-handler.html
+++ /dev/null
@@ -1,113 +0,0 @@
-<html>
-<head>
-<script src="/js-test-resources/js-test.js"></script>
-</head>
-<body>
-<p>This test makes sure that navigator.unregisterProtocolHandler throws the proper exceptions and has no-op default implementation.</p>
-<pre id="console"></pre>
-<script>
-if (window.internals)
-    internals.setNavigatorContentUtilsClientMock(document);
-
-if (window.navigator.unregisterProtocolHandler)
-    debug('PASS window.navigator.unregisterProtocolHandler is defined.');
-else
-    debug('FAIL window.navigator.unregisterProtocolHandler is not defined.');
-
-var invalid_schemes = ['http', 'https', 'file', 'web+'];
-invalid_schemes.forEach(function (scheme) {
-    var succeeded = false;
-    try {
-        window.navigator.unregisterProtocolHandler(scheme, "invalid scheme %s");
-    } catch (e) {
-        succeeded = 'SecurityError' == e.name;
-        errorMessage = e.message;
-    }
-
-    if (succeeded)
-        debug('PASS Invalid scheme "' + scheme + '" threw SecurityError exception: "' + errorMessage + '".');
-    else
-        debug('FAIL Invalid scheme "' + scheme + '" allowed.');
-});
-
-var valid_schemes = ['bitcoin', 'BitcoIn', 'geo', 'im', 'irc', 'Irc', 'ircs', 'magnet', 'MagneT', 'mailto', 'mms', 'news', 'nntp', 'openpgp4fpr', 'sip', 'sms', 'smsto', 'SmsTo', 'ssh', 'tel', 'urn', 'webcal', 'WebCAL', 'wtai', 'WTAI', 'xmpp'];
-valid_schemes.forEach(function (scheme) {
-    var succeeded = false;
-    try {
-        window.navigator.unregisterProtocolHandler(scheme, "valid scheme %s");
-        succeeded = true;
-    } catch (e) {
-        succeeded = false;
-    }
-
-    if (succeeded)
-        debug('PASS Valid scheme "' + scheme + '" allowed.');
-    else
-        debug('FAIL Valid scheme "' + scheme + '" failed.');
-});
-
-var invalid_schemes = ['mailto:', 'ssh:/', 'magnet:+', 'tel:sip'];
-invalid_schemes.forEach(function (scheme) {
-    var succeeded = false;
-    try {
-        window.navigator.unregisterProtocolHandler(scheme, 'invalid scheme uri=%s');
-    } catch (e) {
-        succeeded = 'SecurityError' == e.name;
-        errorMessage = e.message;
-    }
-
-    if (succeeded)
-        debug('PASS Invalid scheme "' + scheme + '" falied.');
-    else
-        debug('Fail: Invalid scheme "' + scheme + '" allowed. Threw exception: "' + errorMessage + '".');
-});
-
-var invalid_urls = ["", "%S", "http://[v8.:::]//url=%s"];
-invalid_urls.forEach(function (url) {
-   var succeeded = false;
-   try {
-        window.navigator.unregisterProtocolHandler('web+myscheme', url);
-    } catch (e) {
-        succeeded = 'SyntaxError' == e.name;
-        errorMessage = e.message;
-    }
-
-    if (succeeded)
-        debug('PASS Invalid url "' + url + '" threw SyntaxError exception.' + errorMessage + '".');
-    else
-        debug('FAIL Invalid url "' + url + '" allowed.');
-});
-
-// Test that the API throws SecurityError exception if the URL's origin differs from the document's origin.
-succeeded = false;
-var errorMessage;
-try {
-    window.navigator.unregisterProtocolHandler('web+myprotocol', "http://www.example.com/soup?url=%s");
-} catch (e) {
-    succeeded = true;
-    errorMessage = e.message;
-}
-
-if (succeeded)
-    debug('PASS URL with origin different than document origin threw SecurityError exception: "' + errorMessage + '".');
-else
-    debug('FAIL URL with origin different than document origin is allowed.');
-
-// Test that the API has default no-op implementation.
-var succeeded = true;
-try {
-    window.navigator.unregisterProtocolHandler('web+myscheme', "%s");
-} catch (e) {
-    succeeded = false;
-}
-
-if (succeeded)
-    debug('PASS Valid call succeeded.');
-else
-    debug('FAIL Invalid call did not succeed.');
-
-debug("\n");
-
-</script>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/register-bypassing-scheme-script.https-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/register-bypassing-scheme-script.https-expected.txt
index 61d51174..28997ad5 100644
--- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/register-bypassing-scheme-script.https-expected.txt
+++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/register-bypassing-scheme-script.https-expected.txt
@@ -1,5 +1,3 @@
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/contentSecurityPolicy/register-bypassing-scheme-script.https.html' attempted to load subresource at 'https://127.0.0.1:8443/resources/testharness.js' over broken HTTPS.
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/contentSecurityPolicy/register-bypassing-scheme-script.https.html' attempted to load subresource at 'https://127.0.0.1:8443/resources/testharnessreport.js' over broken HTTPS.
 CONSOLE ERROR: Refused to load the script 'http://127.0.0.1:8000/security/contentSecurityPolicy/resources/script-set-attribute.js?t1' because it violates the following Content Security Policy directive: "script-src 'nonce-abc'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.
 
 This is a testharness.js-based test.
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/active-subresource-in-iframe-blocked.https-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/active-subresource-in-iframe-blocked.https-expected.txt
index f3d17af8..c53814e3a 100644
--- a/third_party/blink/web_tests/http/tests/security/mixedContent/active-subresource-in-iframe-blocked.https-expected.txt
+++ b/third_party/blink/web_tests/http/tests/security/mixedContent/active-subresource-in-iframe-blocked.https-expected.txt
@@ -1,3 +1,2 @@
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/active-subresource-in-iframe-blocked.https.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-css.html' over broken HTTPS.
 CONSOLE ERROR: line 4: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/active-subresource-in-iframe-blocked.https.html' was loaded over HTTPS, but requested an insecure stylesheet 'http://example.test:8080/security/mixedContent/resources/style.css'. This request has been blocked; the content must be served over HTTPS.
 This test passes if the active subresource in the frame below is blocked.
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-css-image-with-reload-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-css-image-with-reload-expected.txt
index 09aa8621..607bd51 100644
--- a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-css-image-with-reload-expected.txt
+++ b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-css-image-with-reload-expected.txt
@@ -1,9 +1,5 @@
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-subframe-and-reload.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-css-image.html' over broken HTTPS.
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-css-image.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/fetch-insecure-css-image.css' over broken HTTPS.
 CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-subframe-and-reload.html' was loaded over HTTPS, but requested an insecure image 'http://example.test:8080/security/resources/compass.jpg'. This content should also be served over HTTPS.
 CONSOLE MESSAGE: line 12: Reloading...
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-subframe-and-reload.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-css-image.html' over broken HTTPS.
-CONSOLE ERROR: line 2: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-css-image.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/fetch-insecure-css-image.css' over broken HTTPS.
 CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-subframe-and-reload.html' was loaded over HTTPS, but requested an insecure image 'http://example.test:8080/security/resources/compass.jpg'. This content should also be served over HTTPS.
 CONSOLE MESSAGE: line 17: Second load finished.
 This test opens a window that loads a frame with a subframe which contains insecure css image. The subframe is refreshed after it loads. We should trigger a mixed content callback twice despite the fact that on a second load of the subframe a css cache might be used to fetch an image.
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-css-resources-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-css-resources-expected.txt
index 6b333e7..523fd49 100644
--- a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-css-resources-expected.txt
+++ b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-css-resources-expected.txt
@@ -1,4 +1,3 @@
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-css-resources.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/fetch-insecure-css-resources.css' over broken HTTPS.
 CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-css-resources.html' was loaded over HTTPS, but requested an insecure font 'http://example.test:8080/css/resources/cors-ahem.php'. This content should also be served over HTTPS.
 CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-css-resources.html' was loaded over HTTPS, but requested an insecure image 'http://example.test:8080/resources/square20.png'. This content should also be served over HTTPS.
 This test opens a window that loads a style sheet which fetches an insecure background image and an insecure web font. We should trigger a mixed content callback because the main frame in the window is HTTPS but is running insecure content.
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-fetch-on-dedicated-worker-allowed.https-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-fetch-on-dedicated-worker-allowed.https-expected.txt
index 47c2dc0d..ff75b78d 100644
--- a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-fetch-on-dedicated-worker-allowed.https-expected.txt
+++ b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-fetch-on-dedicated-worker-allowed.https-expected.txt
@@ -1,6 +1,3 @@
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/insecure-fetch-on-dedicated-worker-allowed.https.html' attempted to load subresource at 'https://127.0.0.1:8443/resources/testharness.js' over broken HTTPS.
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/insecure-fetch-on-dedicated-worker-allowed.https.html' attempted to load subresource at 'https://127.0.0.1:8443/resources/testharnessreport.js' over broken HTTPS.
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/insecure-fetch-on-dedicated-worker-allowed.https.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/insecure-fetch-in-dedicated-worker.js' over broken HTTPS.
 CONSOLE WARNING: line 1: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/insecure-fetch-in-dedicated-worker.js' was loaded over HTTPS, but requested an insecure resource 'http://example.test:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=*'. This content should also be served over HTTPS.
 This is a testharness.js-based test.
 PASS Insecure resource loads inside Worker when 'AllowRunningInsecureContent' is set.
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-fetch-on-dedicated-worker-blocked.https-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-fetch-on-dedicated-worker-blocked.https-expected.txt
index 717c6c3..f9e4011e 100644
--- a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-fetch-on-dedicated-worker-blocked.https-expected.txt
+++ b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-fetch-on-dedicated-worker-blocked.https-expected.txt
@@ -1,6 +1,3 @@
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/insecure-fetch-on-dedicated-worker-blocked.https.html' attempted to load subresource at 'https://127.0.0.1:8443/resources/testharness.js' over broken HTTPS.
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/insecure-fetch-on-dedicated-worker-blocked.https.html' attempted to load subresource at 'https://127.0.0.1:8443/resources/testharnessreport.js' over broken HTTPS.
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/insecure-fetch-on-dedicated-worker-blocked.https.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/insecure-fetch-in-dedicated-worker.js' over broken HTTPS.
 CONSOLE ERROR: line 1: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/insecure-fetch-in-dedicated-worker.js' was loaded over HTTPS, but requested an insecure resource 'http://example.test:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=*'. This request has been blocked; the content must be served over HTTPS.
 This is a testharness.js-based test.
 PASS Insecure resource loads inside Worker failes when 'AllowRunningInsecureContent' is not set.
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-iframe-with-hsts.https-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-iframe-with-hsts.https-expected.txt
index c70f6d2..121dc87 100644
--- a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-iframe-with-hsts.https-expected.txt
+++ b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-iframe-with-hsts.https-expected.txt
@@ -1,10 +1,7 @@
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/insecure-iframe-with-hsts.https.html' attempted to load subresource at 'https://127.0.0.1:8443/resources/testharness.js' over broken HTTPS.
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/insecure-iframe-with-hsts.https.html' attempted to load subresource at 'https://127.0.0.1:8443/resources/testharnessreport.js' over broken HTTPS.
 main frame - didReceiveTitle: 
 main frame - didFinishDocumentLoadForFrame
 main frame - didHandleOnloadEventsForFrame
 main frame - didFinishLoadForFrame
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/insecure-iframe-with-hsts.https.html' attempted to load subresource at 'https://hsts-example.test:8443/security/resources/hsts.php?as-fetch' over broken HTTPS.
 frame "<!--framePath //<!--frame0-->-->" - didReceiveTitle: 
 frame "<!--framePath //<!--frame0-->-->" - didStartProvisionalLoadForFrame
 CONSOLE ERROR: line 18: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/insecure-iframe-with-hsts.https.html' was loaded over HTTPS, but requested an insecure resource 'http://hsts-example.test:8443/security/resources/hsts.php'. This request has been blocked; the content must be served over HTTPS.
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-http-to-https-iframe-in-main-frame-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-http-to-https-iframe-in-main-frame-expected.txt
index e48e146..e10c3a30 100644
--- a/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-http-to-https-iframe-in-main-frame-expected.txt
+++ b/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-http-to-https-iframe-in-main-frame-expected.txt
@@ -1,3 +1,2 @@
 CONSOLE WARNING: line 8: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-redirect-http-to-https-frame.html' was loaded over HTTPS, but requested an insecure resource 'http://example.test:8080/security/resources/redir.php?url=https://127.0.0.1:8443/security/mixedContent/resources/boring.html'. This content should also be served over HTTPS.
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-redirect-http-to-https-frame.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/boring.html' over broken HTTPS.
 This test opens a window that loads an insecure iframe (via a tricky redirect). We should trigger a mixed content callback because the main frame in the window is HTTPS but is running content that can be controlled by an active network attacker.
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-http-to-https-script-in-iframe-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-http-to-https-script-in-iframe-expected.txt
index 7914452..555131b 100644
--- a/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-http-to-https-script-in-iframe-expected.txt
+++ b/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-http-to-https-script-in-iframe-expected.txt
@@ -1,3 +1,2 @@
 CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-redirect-http-to-https-script.html' was loaded over HTTPS, but requested an insecure script 'http://example.test:8080/security/resources/redir.php?url=https://127.0.0.1:8443/security/mixedContent/resources/script.js'. This content should also be served over HTTPS.
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-redirect-http-to-https-script.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/script.js' over broken HTTPS.
 This test loads a secure iframe that loads an insecure script (but with a tricky redirect). We should trigger a mixed content callback because an active network attacker could have redirected the script load to https://attacker.com.
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-https-to-http-iframe-in-main-frame-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-https-to-http-iframe-in-main-frame-expected.txt
index e48e146..e10c3a30 100644
--- a/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-https-to-http-iframe-in-main-frame-expected.txt
+++ b/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-https-to-http-iframe-in-main-frame-expected.txt
@@ -1,3 +1,2 @@
 CONSOLE WARNING: line 8: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-redirect-http-to-https-frame.html' was loaded over HTTPS, but requested an insecure resource 'http://example.test:8080/security/resources/redir.php?url=https://127.0.0.1:8443/security/mixedContent/resources/boring.html'. This content should also be served over HTTPS.
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-redirect-http-to-https-frame.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/boring.html' over broken HTTPS.
 This test opens a window that loads an insecure iframe (via a tricky redirect). We should trigger a mixed content callback because the main frame in the window is HTTPS but is running content that can be controlled by an active network attacker.
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/strict-mode-image-in-frame-blocked.https-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/strict-mode-image-in-frame-blocked.https-expected.txt
index 434612e..e317165a 100644
--- a/third_party/blink/web_tests/http/tests/security/mixedContent/strict-mode-image-in-frame-blocked.https-expected.txt
+++ b/third_party/blink/web_tests/http/tests/security/mixedContent/strict-mode-image-in-frame-blocked.https-expected.txt
@@ -1,3 +1,2 @@
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/strict-mode-image-in-frame-blocked.https.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-image.html' over broken HTTPS.
 CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/strict-mode-image-in-frame-blocked.https.html' was loaded over HTTPS, but requested an insecure image 'http://example.test:8080/security/resources/compass.jpg'. This request has been blocked; the content must be served over HTTPS.
 This test passes if the image in the frame below is treated as blockable content.
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-on-client-redirect-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-on-client-redirect-expected.txt
index fb5e0f07b4..c2217e8 100644
--- a/third_party/blink/web_tests/http/tests/security/referrer-on-client-redirect-expected.txt
+++ b/third_party/blink/web_tests/http/tests/security/referrer-on-client-redirect-expected.txt
@@ -1,2 +1 @@
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/resources/referrer-on-client-redirect.html' attempted to load subresource at 'https://127.0.0.1:8443/security/resources/referrer-on-client-redirect.html?frame' over broken HTTPS.
 PASS: Referrer is empty
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-policy-attribute-img-no-referrer-when-downgrade-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-policy-attribute-img-no-referrer-when-downgrade-expected.txt
deleted file mode 100644
index 9b2a185..0000000
--- a/third_party/blink/web_tests/http/tests/security/referrer-policy-attribute-img-no-referrer-when-downgrade-expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/referrer-policy-attribute-img-no-referrer-when-downgrade.html' attempted to load subresource at 'https://127.0.0.1:8443/resources/get-host-info.js' over broken HTTPS.
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/report-script-tag-cross-origin-https-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/report-script-tag-cross-origin-https-expected.txt
index 2c6e65fb..e2188eb 100644
--- a/third_party/blink/web_tests/http/tests/security/xssAuditor/report-script-tag-cross-origin-https-expected.txt
+++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/report-script-tag-cross-origin-https-expected.txt
@@ -1,5 +1,4 @@
 CONSOLE ERROR: line 4: The XSS Auditor refused to execute a script in 'https://127.0.0.1:8443/security/xssAuditor/resources/echo-intertag.pl?test=report-script-tag.html&echo-report=1&enable-report-cross-origin=1&q=%3Cscript%3Ealert(String.fromCharCode(0x58,0x53,0x53))%3C/script%3E%3Cp%3EIf%20you%20see%20this%20message,%20no%20JavaScript%20alert(),%20and%20not%20dump%20of%20a%20report%20is%20displayed%20below,%20then%20the%20test%20PASSED.%3C/p%3E' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior.
-CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/xssAuditor/resources/echo-intertag.pl?test=report-script-tag.html&echo-report=1&enable-report-cross-origin=1&q=%3Cscript%3Ealert(String.fromCharCode(0x58,0x53,0x53))%3C/script%3E%3Cp%3EIf%20you%20see%20this%20message,%20no%20JavaScript%20alert(),%20and%20not%20dump%20of%20a%20report%20is%20displayed%20below,%20then%20the%20test%20PASSED.%3C/p%3E' attempted to load subresource at 'https://127.0.0.1:8443/security/contentSecurityPolicy/resources/go-to-echo-report.js' over broken HTTPS.
 This tests that the X-XSS-Protection reports are sent out properly
 
 --------
diff --git a/third_party/blink/web_tests/http/tests/webmidi/midi-default-feature-policy.https.sub.html b/third_party/blink/web_tests/http/tests/webmidi/midi-default-feature-policy.https.sub.html
index 4bd8a55..edbf0bc 100644
--- a/third_party/blink/web_tests/http/tests/webmidi/midi-default-feature-policy.https.sub.html
+++ b/third_party/blink/web_tests/http/tests/webmidi/midi-default-feature-policy.https.sub.html
@@ -3,6 +3,9 @@
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
 <script src=../resources/feature-policy-permissions-test.js></script>
+<script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="/gen/media/midi/midi_service.mojom.js"></script>
+<script src="mock-midiservice.js"></script>
 <script>
 'use strict';
 
@@ -10,7 +13,10 @@
   location.protocol + '//localhost:' + location.port,
   'midi',
   'SecurityError',
-  function() { return navigator.requestMIDIAccess(); });
+  function() {
+    return navigator.requestMIDIAccess();
+  }
+);
 
 </script>
 </body>
diff --git a/third_party/blink/web_tests/http/tests/webmidi/mock-midiservice.js b/third_party/blink/web_tests/http/tests/webmidi/mock-midiservice.js
new file mode 100644
index 0000000..fed94f7d
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/webmidi/mock-midiservice.js
@@ -0,0 +1,75 @@
+'use strict'
+
+let MICROSECONDS_TO_MILLISECONDS = 0.001;
+
+class MockMIDIService {
+  constructor() {
+    this.next_input_port_index_ = 0;
+    this.next_output_port_index_ = 0;
+    this.start_session_result_ = midi.mojom.Result.OK;
+
+    this.interceptor_ = new MojoInterfaceInterceptor(
+        midi.mojom.MidiSessionProvider.name, 'process');
+    this.binding_ = new mojo.Binding(midi.mojom.MidiSessionProvider, this);
+    this.session_binding_ = new mojo.Binding(midi.mojom.MidiSession, this);
+    this.interceptor_.oninterfacerequest = e => {
+      this.binding_.bind(e.handle);
+    };
+    this.interceptor_.start();
+  }
+
+  setStartSessionResult(result) {
+    this.start_session_result_ = result;
+  }
+
+  addInputPort(portState) {
+    this.client_.addInputPort(new midi.mojom.PortInfo({
+      id: `MockInputID-${this.next_input_port_index_++}`,
+      manufacturer: 'MockInputManufacturer',
+      name: 'MockInputName',
+      version: 'MockInputVersion',
+      state: portState
+    }));
+  }
+
+  addOutputPort(portState) {
+    this.client_.addOutputPort(new midi.mojom.PortInfo({
+      id: `MockOutputID-${this.next_output_port_index_++}`,
+      manufacturer: 'MockOutputManufacturer',
+      name: 'MockOutputName',
+      version: 'MockOutputVersion',
+      state: portState
+    }));
+  }
+
+  startSession(request, client) {
+    this.client_ = client;
+    this.session_binding_.bind(request);
+    this.addInputPort(midi.mojom.PortState.CONNECTED);
+    this.addOutputPort(midi.mojom.PortState.CONNECTED);
+    this.client_.sessionStarted(this.start_session_result_);
+  }
+
+  sendData(port, data, timestamp) {
+    if (timestamp.internalValue > internals.currentTimeTicks()) {
+      setTimeout(
+          this.sendData.bind(this, port, data, timestamp),
+          (timestamp.internalValue - internals.currentTimeTicks())
+            * MICROSECONDS_TO_MILLISECONDS);
+      return;
+    }
+    if (port < this.next_input_port_index_) {
+      this.client_.dataReceived(port, data, timestamp);
+    }
+  }
+}
+
+let mockMIDIService = undefined;
+try { mockMIDIService = new MockMIDIService(); }
+catch (err) {
+  // InvalidModificationError can be thrown if an interceptor has already been
+  // created in the same process. In this case, we just rely on the mock
+  // that's already been created.
+  if (err.name != "InvalidModificationError")
+    throw err;
+}
diff --git a/third_party/blink/web_tests/webmidi/add-port.html b/third_party/blink/web_tests/webmidi/add-port.html
index 66f2504..b2c312e 100644
--- a/third_party/blink/web_tests/webmidi/add-port.html
+++ b/third_party/blink/web_tests/webmidi/add-port.html
@@ -2,26 +2,18 @@
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
 <script src="../http/tests/resources/permissions-helper.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/media/midi/midi_service.mojom.js"></script>
+<script src="../http/tests/webmidi/mock-midiservice.js"></script>
 <script>
 async_test(t => {
-  var sysexHeader = [ 0xf0, 0x00, 0x02, 0x0d, 0x7f ];
-  var sysexFooter = [ 0xf7 ];
-  var sysexPayloadToAddInputAsConnected = [ 0x00, 0x00 ];
-  var sysexPayloadToAddOutputAsConnected = [ 0x00, 0x01 ];
-  var sysexPayloadToAddInputAsOpened = [ 0x00, 0x02 ];
-  var sysexPayloadToAddOutputAsOpened = [ 0x00, 0x03 ];
-  var noteOn = [ 0x90, 0x45, 0x7f ];
-
-  function createSysex(payload) {
-    return sysexHeader.concat(payload).concat(sysexFooter);
-  }
+  let noteOn = [ 0x90, 0x45, 0x7f ];
 
   t.step(() => {
     Promise.all([
         PermissionsHelper.setPermission('midi', 'granted'),
-        PermissionsHelper.setPermission('midi-sysex', 'granted')
     ]).then(() => {
-      return navigator.requestMIDIAccess({sysex : true});
+      return navigator.requestMIDIAccess();
     }).then(a => {
       var started = false;
       var receivedMessages = 0;
@@ -56,11 +48,10 @@
 
       output = a.outputs.values().next().value;
 
-      // Send sysex messages to request dynamically adding mock devices.
-      output.send(createSysex(sysexPayloadToAddInputAsConnected));
-      output.send(createSysex(sysexPayloadToAddOutputAsConnected));
-      output.send(createSysex(sysexPayloadToAddInputAsOpened));
-      output.send(createSysex(sysexPayloadToAddOutputAsOpened));
+      mockMIDIService.addInputPort(midi.mojom.PortState.CONNECTED);
+      mockMIDIService.addOutputPort(midi.mojom.PortState.CONNECTED);
+      mockMIDIService.addInputPort(midi.mojom.PortState.OPENED);
+      mockMIDIService.addOutputPort(midi.mojom.PortState.OPENED);
     }).catch(e => assert_unreached(e));
   });
 }, "Test if newly connected ports work correctly");
diff --git a/third_party/blink/web_tests/webmidi/implicit-open.html b/third_party/blink/web_tests/webmidi/implicit-open.html
index 8a80ee5..b5dbecaa 100644
--- a/third_party/blink/web_tests/webmidi/implicit-open.html
+++ b/third_party/blink/web_tests/webmidi/implicit-open.html
@@ -4,6 +4,9 @@
 <script src="../resources/js-test.js"></script>
 <script src="../http/tests/resources/permissions-helper.js"></script>
 <script src="state-check-utils.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/media/midi/midi_service.mojom.js"></script>
+<script src="../http/tests/webmidi/mock-midiservice.js"></script>
 </head>
 <body>
 <script>
diff --git a/third_party/blink/web_tests/webmidi/loopback-receive.html b/third_party/blink/web_tests/webmidi/loopback-receive.html
index 5e2f1880..fb35141 100644
--- a/third_party/blink/web_tests/webmidi/loopback-receive.html
+++ b/third_party/blink/web_tests/webmidi/loopback-receive.html
@@ -3,6 +3,9 @@
 <head>
 <script src="../resources/js-test.js"></script>
 <script src="../http/tests/resources/permissions-helper.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/media/midi/midi_service.mojom.js"></script>
+<script src="../http/tests/webmidi/mock-midiservice.js"></script>
 </head>
 <body>
 <script>
@@ -43,10 +46,14 @@
     expected = testData[receiveCount];
     actual = e.data;
     shouldBe("actual", "expected");
-    midiMessageEvent = e;
     receiveCount++;
-    if (receiveCount == testData.length)
-        e.target.resolve();
+    if (receiveCount == testData.length) {
+      // Clear the event handler in case the input object isn't GC'ed, to
+      // prevent it from being called on the second run of test().
+      e.target.onmidimessage = undefined;
+      e.target.removeEventListener('midimessage', verifyData);
+      e.target.resolve();
+    }
 }
 
 function test(useAddEventListener) {
diff --git a/third_party/blink/web_tests/webmidi/loopback-with-timestamp.html b/third_party/blink/web_tests/webmidi/loopback-with-timestamp.html
index 6dd70c9..752de60 100644
--- a/third_party/blink/web_tests/webmidi/loopback-with-timestamp.html
+++ b/third_party/blink/web_tests/webmidi/loopback-with-timestamp.html
@@ -2,6 +2,9 @@
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
 <script src="../http/tests/resources/permissions-helper.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/media/midi/midi_service.mojom.js"></script>
+<script src="../http/tests/webmidi/mock-midiservice.js"></script>
 <p>Regression test to check if non-zero timestamp works well.</p>
 <script>
 promise_test(async () => {
diff --git a/third_party/blink/web_tests/webmidi/open-close.html b/third_party/blink/web_tests/webmidi/open-close.html
index f059fa6..4bb6c88 100644
--- a/third_party/blink/web_tests/webmidi/open-close.html
+++ b/third_party/blink/web_tests/webmidi/open-close.html
@@ -4,6 +4,9 @@
 <script src="../resources/js-test.js"></script>
 <script src="../http/tests/resources/permissions-helper.js"></script>
 <script src="state-check-utils.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/media/midi/midi_service.mojom.js"></script>
+<script src="../http/tests/webmidi/mock-midiservice.js"></script>
 </head>
 <body>
 <script>
diff --git a/third_party/blink/web_tests/webmidi/permission.html b/third_party/blink/web_tests/webmidi/permission.html
index 2c6bdf80..220f1416 100644
--- a/third_party/blink/web_tests/webmidi/permission.html
+++ b/third_party/blink/web_tests/webmidi/permission.html
@@ -3,6 +3,9 @@
 <head>
 <script src="../resources/js-test.js"></script>
 <script src="../http/tests/resources/permissions-helper.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/media/midi/midi_service.mojom.js"></script>
+<script src="../http/tests/webmidi/mock-midiservice.js"></script>
 </head>
 <body>
 <script>
diff --git a/third_party/blink/web_tests/webmidi/requestmidiaccess-fail.html b/third_party/blink/web_tests/webmidi/requestmidiaccess-fail.html
index ccdf1eb9b..ec819ad5 100644
--- a/third_party/blink/web_tests/webmidi/requestmidiaccess-fail.html
+++ b/third_party/blink/web_tests/webmidi/requestmidiaccess-fail.html
@@ -3,6 +3,9 @@
 <head>
 <script src="../resources/js-test.js"></script>
 <script src="../http/tests/resources/permissions-helper.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/media/midi/midi_service.mojom.js"></script>
+<script src="../http/tests/webmidi/mock-midiservice.js"></script>
 </head>
 <body>
 <script>
@@ -26,8 +29,7 @@
 
 // Set default permission behavior that grants non-sysex requests.
 PermissionsHelper.setPermission('midi', 'granted').then(function() {
-    // set testRunner configuration so that requestMIDIAccess returns "InvalidStateError".
-    testRunner.setMIDIAccessorResult(false);
+    mockMIDIService.setStartSessionResult(midi.mojom.Result.INITIALIZATION_ERROR);
     navigator.requestMIDIAccess().then(successCallback, errorCallback);
 });
 
diff --git a/third_party/blink/web_tests/webmidi/requestmidiaccess-in-detached-frame.html b/third_party/blink/web_tests/webmidi/requestmidiaccess-in-detached-frame.html
index dbe30c2..edeccca 100644
--- a/third_party/blink/web_tests/webmidi/requestmidiaccess-in-detached-frame.html
+++ b/third_party/blink/web_tests/webmidi/requestmidiaccess-in-detached-frame.html
@@ -2,6 +2,9 @@
 <html>
 <head>
 <script src="../resources/js-test.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/media/midi/midi_service.mojom.js"></script>
+<script src="../http/tests/webmidi/mock-midiservice.js"></script>
 </head>
 <body>
 <script>
diff --git a/third_party/blink/web_tests/webmidi/requestmidiaccess-options.html b/third_party/blink/web_tests/webmidi/requestmidiaccess-options.html
index 76a751b..23d9319 100644
--- a/third_party/blink/web_tests/webmidi/requestmidiaccess-options.html
+++ b/third_party/blink/web_tests/webmidi/requestmidiaccess-options.html
@@ -3,6 +3,9 @@
 <head>
 <script src="../resources/js-test.js"></script>
 <script src="../http/tests/resources/permissions-helper.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/media/midi/midi_service.mojom.js"></script>
+<script src="../http/tests/webmidi/mock-midiservice.js"></script>
 </head>
 <body>
 <script>
diff --git a/third_party/blink/web_tests/webmidi/requestmidiaccess.html b/third_party/blink/web_tests/webmidi/requestmidiaccess.html
index 6e1d65e..a0b92f8 100644
--- a/third_party/blink/web_tests/webmidi/requestmidiaccess.html
+++ b/third_party/blink/web_tests/webmidi/requestmidiaccess.html
@@ -3,6 +3,9 @@
 <head>
 <script src="../resources/js-test.js"></script>
 <script src="../http/tests/resources/permissions-helper.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/media/midi/midi_service.mojom.js"></script>
+<script src="../http/tests/webmidi/mock-midiservice.js"></script>
 </head>
 <body>
 <script>
diff --git a/third_party/blink/web_tests/webmidi/send-messages.html b/third_party/blink/web_tests/webmidi/send-messages.html
index 53d9367..05de376 100644
--- a/third_party/blink/web_tests/webmidi/send-messages.html
+++ b/third_party/blink/web_tests/webmidi/send-messages.html
@@ -3,6 +3,9 @@
 <head>
 <script src="../resources/js-test.js"></script>
 <script src="../http/tests/resources/permissions-helper.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/media/midi/midi_service.mojom.js"></script>
+<script src="../http/tests/webmidi/mock-midiservice.js"></script>
 </head>
 <body>
 <script>
diff --git a/third_party/blink/web_tests/webmidi/send-system-messages.html b/third_party/blink/web_tests/webmidi/send-system-messages.html
index 83efe33..ccce32f 100644
--- a/third_party/blink/web_tests/webmidi/send-system-messages.html
+++ b/third_party/blink/web_tests/webmidi/send-system-messages.html
@@ -3,6 +3,9 @@
 <head>
 <script src="../resources/js-test.js"></script>
 <script src="../http/tests/resources/permissions-helper.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/media/midi/midi_service.mojom.js"></script>
+<script src="../http/tests/webmidi/mock-midiservice.js"></script>
 </head>
 <body>
 <script>
diff --git a/third_party/boringssl/BUILD.generated.gni b/third_party/boringssl/BUILD.generated.gni
index 16d5f4c6..f8810c5 100644
--- a/third_party/boringssl/BUILD.generated.gni
+++ b/third_party/boringssl/BUILD.generated.gni
@@ -133,6 +133,8 @@
   "src/crypto/fipsmodule/rsa/internal.h",
   "src/crypto/fipsmodule/tls/internal.h",
   "src/crypto/hkdf/hkdf.c",
+  "src/crypto/hrss/hrss.c",
+  "src/crypto/hrss/internal.h",
   "src/crypto/internal.h",
   "src/crypto/lhash/lhash.c",
   "src/crypto/mem.c",
@@ -306,6 +308,7 @@
   "src/include/openssl/ex_data.h",
   "src/include/openssl/hkdf.h",
   "src/include/openssl/hmac.h",
+  "src/include/openssl/hrss.h",
   "src/include/openssl/is_boringssl.h",
   "src/include/openssl/lhash.h",
   "src/include/openssl/md4.h",
@@ -475,6 +478,7 @@
   "linux-x86_64/crypto/fipsmodule/vpaes-x86_64.S",
   "linux-x86_64/crypto/fipsmodule/x86_64-mont.S",
   "linux-x86_64/crypto/fipsmodule/x86_64-mont5.S",
+  "src/crypto/hrss/asm/poly_rq_mul.S",
 ]
 
 crypto_sources_mac_x86 = [
diff --git a/third_party/boringssl/BUILD.generated_tests.gni b/third_party/boringssl/BUILD.generated_tests.gni
index 02fa36c..4eb6c6d 100644
--- a/third_party/boringssl/BUILD.generated_tests.gni
+++ b/third_party/boringssl/BUILD.generated_tests.gni
@@ -58,6 +58,7 @@
   "src/crypto/fipsmodule/rand/ctrdrbg_test.cc",
   "src/crypto/hkdf/hkdf_test.cc",
   "src/crypto/hmac_extra/hmac_test.cc",
+  "src/crypto/hrss/hrss_test.cc",
   "src/crypto/lhash/lhash_test.cc",
   "src/crypto/obj/obj_test.cc",
   "src/crypto/pem/pem_test.cc",
diff --git a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/bsaes-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/bsaes-x86_64.S
index 7dd3161..36c01ef 100644
--- a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/bsaes-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/bsaes-x86_64.S
@@ -1576,982 +1576,6 @@
 	.byte	0xf3,0xc3
 .cfi_endproc	
 .size	bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks
-.globl	bsaes_xts_encrypt
-.hidden bsaes_xts_encrypt
-.type	bsaes_xts_encrypt,@function
-.align	16
-bsaes_xts_encrypt:
-.cfi_startproc	
-	movq	%rsp,%rax
-.Lxts_enc_prologue:
-	pushq	%rbp
-.cfi_adjust_cfa_offset	8
-.cfi_offset	%rbp,-16
-	pushq	%rbx
-.cfi_adjust_cfa_offset	8
-.cfi_offset	%rbx,-24
-	pushq	%r12
-.cfi_adjust_cfa_offset	8
-.cfi_offset	%r12,-32
-	pushq	%r13
-.cfi_adjust_cfa_offset	8
-.cfi_offset	%r13,-40
-	pushq	%r14
-.cfi_adjust_cfa_offset	8
-.cfi_offset	%r14,-48
-	pushq	%r15
-.cfi_adjust_cfa_offset	8
-.cfi_offset	%r15,-56
-	leaq	-72(%rsp),%rsp
-.cfi_adjust_cfa_offset	0x48
-	movq	%rsp,%rbp
-.cfi_def_cfa_register	%rbp
-	movq	%rdi,%r12
-	movq	%rsi,%r13
-	movq	%rdx,%r14
-	movq	%rcx,%r15
-
-	leaq	(%r9),%rdi
-	leaq	32(%rbp),%rsi
-	leaq	(%r8),%rdx
-	call	aes_nohw_encrypt
-
-	movl	240(%r15),%eax
-	movq	%r14,%rbx
-
-	movl	%eax,%edx
-	shlq	$7,%rax
-	subq	$96,%rax
-	subq	%rax,%rsp
-
-	movq	%rsp,%rax
-	movq	%r15,%rcx
-	movl	%edx,%r10d
-	call	_bsaes_key_convert
-	pxor	%xmm6,%xmm7
-	movdqa	%xmm7,(%rax)
-
-	andq	$-16,%r14
-	subq	$0x80,%rsp
-	movdqa	32(%rbp),%xmm6
-
-	pxor	%xmm14,%xmm14
-	movdqa	.Lxts_magic(%rip),%xmm12
-	pcmpgtd	%xmm6,%xmm14
-
-	subq	$0x80,%r14
-	jc	.Lxts_enc_short
-	jmp	.Lxts_enc_loop
-
-.align	16
-.Lxts_enc_loop:
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm15
-	movdqa	%xmm6,0(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm0
-	movdqa	%xmm6,16(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	0(%r12),%xmm7
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm1
-	movdqa	%xmm6,32(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	16(%r12),%xmm8
-	pxor	%xmm7,%xmm15
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm2
-	movdqa	%xmm6,48(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	32(%r12),%xmm9
-	pxor	%xmm8,%xmm0
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm3
-	movdqa	%xmm6,64(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	48(%r12),%xmm10
-	pxor	%xmm9,%xmm1
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm4
-	movdqa	%xmm6,80(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	64(%r12),%xmm11
-	pxor	%xmm10,%xmm2
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm5
-	movdqa	%xmm6,96(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	80(%r12),%xmm12
-	pxor	%xmm11,%xmm3
-	movdqu	96(%r12),%xmm13
-	pxor	%xmm12,%xmm4
-	movdqu	112(%r12),%xmm14
-	leaq	128(%r12),%r12
-	movdqa	%xmm6,112(%rsp)
-	pxor	%xmm13,%xmm5
-	leaq	128(%rsp),%rax
-	pxor	%xmm14,%xmm6
-	movl	%edx,%r10d
-
-	call	_bsaes_encrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm3
-	movdqu	%xmm0,16(%r13)
-	pxor	48(%rsp),%xmm5
-	movdqu	%xmm3,32(%r13)
-	pxor	64(%rsp),%xmm2
-	movdqu	%xmm5,48(%r13)
-	pxor	80(%rsp),%xmm6
-	movdqu	%xmm2,64(%r13)
-	pxor	96(%rsp),%xmm1
-	movdqu	%xmm6,80(%r13)
-	pxor	112(%rsp),%xmm4
-	movdqu	%xmm1,96(%r13)
-	movdqu	%xmm4,112(%r13)
-	leaq	128(%r13),%r13
-
-	movdqa	112(%rsp),%xmm6
-	pxor	%xmm14,%xmm14
-	movdqa	.Lxts_magic(%rip),%xmm12
-	pcmpgtd	%xmm6,%xmm14
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-
-	subq	$0x80,%r14
-	jnc	.Lxts_enc_loop
-
-.Lxts_enc_short:
-	addq	$0x80,%r14
-	jz	.Lxts_enc_done
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm15
-	movdqa	%xmm6,0(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm0
-	movdqa	%xmm6,16(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	0(%r12),%xmm7
-	cmpq	$16,%r14
-	je	.Lxts_enc_1
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm1
-	movdqa	%xmm6,32(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	16(%r12),%xmm8
-	cmpq	$32,%r14
-	je	.Lxts_enc_2
-	pxor	%xmm7,%xmm15
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm2
-	movdqa	%xmm6,48(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	32(%r12),%xmm9
-	cmpq	$48,%r14
-	je	.Lxts_enc_3
-	pxor	%xmm8,%xmm0
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm3
-	movdqa	%xmm6,64(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	48(%r12),%xmm10
-	cmpq	$64,%r14
-	je	.Lxts_enc_4
-	pxor	%xmm9,%xmm1
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm4
-	movdqa	%xmm6,80(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	64(%r12),%xmm11
-	cmpq	$80,%r14
-	je	.Lxts_enc_5
-	pxor	%xmm10,%xmm2
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm5
-	movdqa	%xmm6,96(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	80(%r12),%xmm12
-	cmpq	$96,%r14
-	je	.Lxts_enc_6
-	pxor	%xmm11,%xmm3
-	movdqu	96(%r12),%xmm13
-	pxor	%xmm12,%xmm4
-	movdqa	%xmm6,112(%rsp)
-	leaq	112(%r12),%r12
-	pxor	%xmm13,%xmm5
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_encrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm3
-	movdqu	%xmm0,16(%r13)
-	pxor	48(%rsp),%xmm5
-	movdqu	%xmm3,32(%r13)
-	pxor	64(%rsp),%xmm2
-	movdqu	%xmm5,48(%r13)
-	pxor	80(%rsp),%xmm6
-	movdqu	%xmm2,64(%r13)
-	pxor	96(%rsp),%xmm1
-	movdqu	%xmm6,80(%r13)
-	movdqu	%xmm1,96(%r13)
-	leaq	112(%r13),%r13
-
-	movdqa	112(%rsp),%xmm6
-	jmp	.Lxts_enc_done
-.align	16
-.Lxts_enc_6:
-	pxor	%xmm11,%xmm3
-	leaq	96(%r12),%r12
-	pxor	%xmm12,%xmm4
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_encrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm3
-	movdqu	%xmm0,16(%r13)
-	pxor	48(%rsp),%xmm5
-	movdqu	%xmm3,32(%r13)
-	pxor	64(%rsp),%xmm2
-	movdqu	%xmm5,48(%r13)
-	pxor	80(%rsp),%xmm6
-	movdqu	%xmm2,64(%r13)
-	movdqu	%xmm6,80(%r13)
-	leaq	96(%r13),%r13
-
-	movdqa	96(%rsp),%xmm6
-	jmp	.Lxts_enc_done
-.align	16
-.Lxts_enc_5:
-	pxor	%xmm10,%xmm2
-	leaq	80(%r12),%r12
-	pxor	%xmm11,%xmm3
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_encrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm3
-	movdqu	%xmm0,16(%r13)
-	pxor	48(%rsp),%xmm5
-	movdqu	%xmm3,32(%r13)
-	pxor	64(%rsp),%xmm2
-	movdqu	%xmm5,48(%r13)
-	movdqu	%xmm2,64(%r13)
-	leaq	80(%r13),%r13
-
-	movdqa	80(%rsp),%xmm6
-	jmp	.Lxts_enc_done
-.align	16
-.Lxts_enc_4:
-	pxor	%xmm9,%xmm1
-	leaq	64(%r12),%r12
-	pxor	%xmm10,%xmm2
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_encrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm3
-	movdqu	%xmm0,16(%r13)
-	pxor	48(%rsp),%xmm5
-	movdqu	%xmm3,32(%r13)
-	movdqu	%xmm5,48(%r13)
-	leaq	64(%r13),%r13
-
-	movdqa	64(%rsp),%xmm6
-	jmp	.Lxts_enc_done
-.align	16
-.Lxts_enc_3:
-	pxor	%xmm8,%xmm0
-	leaq	48(%r12),%r12
-	pxor	%xmm9,%xmm1
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_encrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm3
-	movdqu	%xmm0,16(%r13)
-	movdqu	%xmm3,32(%r13)
-	leaq	48(%r13),%r13
-
-	movdqa	48(%rsp),%xmm6
-	jmp	.Lxts_enc_done
-.align	16
-.Lxts_enc_2:
-	pxor	%xmm7,%xmm15
-	leaq	32(%r12),%r12
-	pxor	%xmm8,%xmm0
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_encrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	movdqu	%xmm0,16(%r13)
-	leaq	32(%r13),%r13
-
-	movdqa	32(%rsp),%xmm6
-	jmp	.Lxts_enc_done
-.align	16
-.Lxts_enc_1:
-	pxor	%xmm15,%xmm7
-	leaq	16(%r12),%r12
-	movdqa	%xmm7,32(%rbp)
-	leaq	32(%rbp),%rdi
-	leaq	32(%rbp),%rsi
-	leaq	(%r15),%rdx
-	call	aes_nohw_encrypt
-	pxor	32(%rbp),%xmm15
-
-
-
-
-
-	movdqu	%xmm15,0(%r13)
-	leaq	16(%r13),%r13
-
-	movdqa	16(%rsp),%xmm6
-
-.Lxts_enc_done:
-	andl	$15,%ebx
-	jz	.Lxts_enc_ret
-	movq	%r13,%rdx
-
-.Lxts_enc_steal:
-	movzbl	(%r12),%eax
-	movzbl	-16(%rdx),%ecx
-	leaq	1(%r12),%r12
-	movb	%al,-16(%rdx)
-	movb	%cl,0(%rdx)
-	leaq	1(%rdx),%rdx
-	subl	$1,%ebx
-	jnz	.Lxts_enc_steal
-
-	movdqu	-16(%r13),%xmm15
-	leaq	32(%rbp),%rdi
-	pxor	%xmm6,%xmm15
-	leaq	32(%rbp),%rsi
-	movdqa	%xmm15,32(%rbp)
-	leaq	(%r15),%rdx
-	call	aes_nohw_encrypt
-	pxor	32(%rbp),%xmm6
-	movdqu	%xmm6,-16(%r13)
-
-.Lxts_enc_ret:
-	leaq	(%rsp),%rax
-	pxor	%xmm0,%xmm0
-.Lxts_enc_bzero:
-	movdqa	%xmm0,0(%rax)
-	movdqa	%xmm0,16(%rax)
-	leaq	32(%rax),%rax
-	cmpq	%rax,%rbp
-	ja	.Lxts_enc_bzero
-
-	leaq	120(%rbp),%rax
-.cfi_def_cfa	%rax,8
-	movq	-48(%rax),%r15
-.cfi_restore	%r15
-	movq	-40(%rax),%r14
-.cfi_restore	%r14
-	movq	-32(%rax),%r13
-.cfi_restore	%r13
-	movq	-24(%rax),%r12
-.cfi_restore	%r12
-	movq	-16(%rax),%rbx
-.cfi_restore	%rbx
-	movq	-8(%rax),%rbp
-.cfi_restore	%rbp
-	leaq	(%rax),%rsp
-.cfi_def_cfa_register	%rsp
-.Lxts_enc_epilogue:
-	.byte	0xf3,0xc3
-.cfi_endproc	
-.size	bsaes_xts_encrypt,.-bsaes_xts_encrypt
-
-.globl	bsaes_xts_decrypt
-.hidden bsaes_xts_decrypt
-.type	bsaes_xts_decrypt,@function
-.align	16
-bsaes_xts_decrypt:
-.cfi_startproc	
-	movq	%rsp,%rax
-.Lxts_dec_prologue:
-	pushq	%rbp
-.cfi_adjust_cfa_offset	8
-.cfi_offset	%rbp,-16
-	pushq	%rbx
-.cfi_adjust_cfa_offset	8
-.cfi_offset	%rbx,-24
-	pushq	%r12
-.cfi_adjust_cfa_offset	8
-.cfi_offset	%r12,-32
-	pushq	%r13
-.cfi_adjust_cfa_offset	8
-.cfi_offset	%r13,-40
-	pushq	%r14
-.cfi_adjust_cfa_offset	8
-.cfi_offset	%r14,-48
-	pushq	%r15
-.cfi_adjust_cfa_offset	8
-.cfi_offset	%r15,-56
-	leaq	-72(%rsp),%rsp
-.cfi_adjust_cfa_offset	0x48
-	movq	%rsp,%rbp
-	movq	%rdi,%r12
-	movq	%rsi,%r13
-	movq	%rdx,%r14
-	movq	%rcx,%r15
-
-	leaq	(%r9),%rdi
-	leaq	32(%rbp),%rsi
-	leaq	(%r8),%rdx
-	call	aes_nohw_encrypt
-
-	movl	240(%r15),%eax
-	movq	%r14,%rbx
-
-	movl	%eax,%edx
-	shlq	$7,%rax
-	subq	$96,%rax
-	subq	%rax,%rsp
-
-	movq	%rsp,%rax
-	movq	%r15,%rcx
-	movl	%edx,%r10d
-	call	_bsaes_key_convert
-	pxor	(%rsp),%xmm7
-	movdqa	%xmm6,(%rax)
-	movdqa	%xmm7,(%rsp)
-
-	xorl	%eax,%eax
-	andq	$-16,%r14
-	testl	$15,%ebx
-	setnz	%al
-	shlq	$4,%rax
-	subq	%rax,%r14
-
-	subq	$0x80,%rsp
-	movdqa	32(%rbp),%xmm6
-
-	pxor	%xmm14,%xmm14
-	movdqa	.Lxts_magic(%rip),%xmm12
-	pcmpgtd	%xmm6,%xmm14
-
-	subq	$0x80,%r14
-	jc	.Lxts_dec_short
-	jmp	.Lxts_dec_loop
-
-.align	16
-.Lxts_dec_loop:
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm15
-	movdqa	%xmm6,0(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm0
-	movdqa	%xmm6,16(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	0(%r12),%xmm7
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm1
-	movdqa	%xmm6,32(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	16(%r12),%xmm8
-	pxor	%xmm7,%xmm15
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm2
-	movdqa	%xmm6,48(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	32(%r12),%xmm9
-	pxor	%xmm8,%xmm0
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm3
-	movdqa	%xmm6,64(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	48(%r12),%xmm10
-	pxor	%xmm9,%xmm1
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm4
-	movdqa	%xmm6,80(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	64(%r12),%xmm11
-	pxor	%xmm10,%xmm2
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm5
-	movdqa	%xmm6,96(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	80(%r12),%xmm12
-	pxor	%xmm11,%xmm3
-	movdqu	96(%r12),%xmm13
-	pxor	%xmm12,%xmm4
-	movdqu	112(%r12),%xmm14
-	leaq	128(%r12),%r12
-	movdqa	%xmm6,112(%rsp)
-	pxor	%xmm13,%xmm5
-	leaq	128(%rsp),%rax
-	pxor	%xmm14,%xmm6
-	movl	%edx,%r10d
-
-	call	_bsaes_decrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm5
-	movdqu	%xmm0,16(%r13)
-	pxor	48(%rsp),%xmm3
-	movdqu	%xmm5,32(%r13)
-	pxor	64(%rsp),%xmm1
-	movdqu	%xmm3,48(%r13)
-	pxor	80(%rsp),%xmm6
-	movdqu	%xmm1,64(%r13)
-	pxor	96(%rsp),%xmm2
-	movdqu	%xmm6,80(%r13)
-	pxor	112(%rsp),%xmm4
-	movdqu	%xmm2,96(%r13)
-	movdqu	%xmm4,112(%r13)
-	leaq	128(%r13),%r13
-
-	movdqa	112(%rsp),%xmm6
-	pxor	%xmm14,%xmm14
-	movdqa	.Lxts_magic(%rip),%xmm12
-	pcmpgtd	%xmm6,%xmm14
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-
-	subq	$0x80,%r14
-	jnc	.Lxts_dec_loop
-
-.Lxts_dec_short:
-	addq	$0x80,%r14
-	jz	.Lxts_dec_done
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm15
-	movdqa	%xmm6,0(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm0
-	movdqa	%xmm6,16(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	0(%r12),%xmm7
-	cmpq	$16,%r14
-	je	.Lxts_dec_1
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm1
-	movdqa	%xmm6,32(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	16(%r12),%xmm8
-	cmpq	$32,%r14
-	je	.Lxts_dec_2
-	pxor	%xmm7,%xmm15
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm2
-	movdqa	%xmm6,48(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	32(%r12),%xmm9
-	cmpq	$48,%r14
-	je	.Lxts_dec_3
-	pxor	%xmm8,%xmm0
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm3
-	movdqa	%xmm6,64(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	48(%r12),%xmm10
-	cmpq	$64,%r14
-	je	.Lxts_dec_4
-	pxor	%xmm9,%xmm1
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm4
-	movdqa	%xmm6,80(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	64(%r12),%xmm11
-	cmpq	$80,%r14
-	je	.Lxts_dec_5
-	pxor	%xmm10,%xmm2
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm5
-	movdqa	%xmm6,96(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	80(%r12),%xmm12
-	cmpq	$96,%r14
-	je	.Lxts_dec_6
-	pxor	%xmm11,%xmm3
-	movdqu	96(%r12),%xmm13
-	pxor	%xmm12,%xmm4
-	movdqa	%xmm6,112(%rsp)
-	leaq	112(%r12),%r12
-	pxor	%xmm13,%xmm5
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_decrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm5
-	movdqu	%xmm0,16(%r13)
-	pxor	48(%rsp),%xmm3
-	movdqu	%xmm5,32(%r13)
-	pxor	64(%rsp),%xmm1
-	movdqu	%xmm3,48(%r13)
-	pxor	80(%rsp),%xmm6
-	movdqu	%xmm1,64(%r13)
-	pxor	96(%rsp),%xmm2
-	movdqu	%xmm6,80(%r13)
-	movdqu	%xmm2,96(%r13)
-	leaq	112(%r13),%r13
-
-	movdqa	112(%rsp),%xmm6
-	jmp	.Lxts_dec_done
-.align	16
-.Lxts_dec_6:
-	pxor	%xmm11,%xmm3
-	leaq	96(%r12),%r12
-	pxor	%xmm12,%xmm4
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_decrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm5
-	movdqu	%xmm0,16(%r13)
-	pxor	48(%rsp),%xmm3
-	movdqu	%xmm5,32(%r13)
-	pxor	64(%rsp),%xmm1
-	movdqu	%xmm3,48(%r13)
-	pxor	80(%rsp),%xmm6
-	movdqu	%xmm1,64(%r13)
-	movdqu	%xmm6,80(%r13)
-	leaq	96(%r13),%r13
-
-	movdqa	96(%rsp),%xmm6
-	jmp	.Lxts_dec_done
-.align	16
-.Lxts_dec_5:
-	pxor	%xmm10,%xmm2
-	leaq	80(%r12),%r12
-	pxor	%xmm11,%xmm3
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_decrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm5
-	movdqu	%xmm0,16(%r13)
-	pxor	48(%rsp),%xmm3
-	movdqu	%xmm5,32(%r13)
-	pxor	64(%rsp),%xmm1
-	movdqu	%xmm3,48(%r13)
-	movdqu	%xmm1,64(%r13)
-	leaq	80(%r13),%r13
-
-	movdqa	80(%rsp),%xmm6
-	jmp	.Lxts_dec_done
-.align	16
-.Lxts_dec_4:
-	pxor	%xmm9,%xmm1
-	leaq	64(%r12),%r12
-	pxor	%xmm10,%xmm2
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_decrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm5
-	movdqu	%xmm0,16(%r13)
-	pxor	48(%rsp),%xmm3
-	movdqu	%xmm5,32(%r13)
-	movdqu	%xmm3,48(%r13)
-	leaq	64(%r13),%r13
-
-	movdqa	64(%rsp),%xmm6
-	jmp	.Lxts_dec_done
-.align	16
-.Lxts_dec_3:
-	pxor	%xmm8,%xmm0
-	leaq	48(%r12),%r12
-	pxor	%xmm9,%xmm1
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_decrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm5
-	movdqu	%xmm0,16(%r13)
-	movdqu	%xmm5,32(%r13)
-	leaq	48(%r13),%r13
-
-	movdqa	48(%rsp),%xmm6
-	jmp	.Lxts_dec_done
-.align	16
-.Lxts_dec_2:
-	pxor	%xmm7,%xmm15
-	leaq	32(%r12),%r12
-	pxor	%xmm8,%xmm0
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_decrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	movdqu	%xmm0,16(%r13)
-	leaq	32(%r13),%r13
-
-	movdqa	32(%rsp),%xmm6
-	jmp	.Lxts_dec_done
-.align	16
-.Lxts_dec_1:
-	pxor	%xmm15,%xmm7
-	leaq	16(%r12),%r12
-	movdqa	%xmm7,32(%rbp)
-	leaq	32(%rbp),%rdi
-	leaq	32(%rbp),%rsi
-	leaq	(%r15),%rdx
-	call	aes_nohw_decrypt
-	pxor	32(%rbp),%xmm15
-
-
-
-
-
-	movdqu	%xmm15,0(%r13)
-	leaq	16(%r13),%r13
-
-	movdqa	16(%rsp),%xmm6
-
-.Lxts_dec_done:
-	andl	$15,%ebx
-	jz	.Lxts_dec_ret
-
-	pxor	%xmm14,%xmm14
-	movdqa	.Lxts_magic(%rip),%xmm12
-	pcmpgtd	%xmm6,%xmm14
-	pshufd	$0x13,%xmm14,%xmm13
-	movdqa	%xmm6,%xmm5
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	movdqu	(%r12),%xmm15
-	pxor	%xmm13,%xmm6
-
-	leaq	32(%rbp),%rdi
-	pxor	%xmm6,%xmm15
-	leaq	32(%rbp),%rsi
-	movdqa	%xmm15,32(%rbp)
-	leaq	(%r15),%rdx
-	call	aes_nohw_decrypt
-	pxor	32(%rbp),%xmm6
-	movq	%r13,%rdx
-	movdqu	%xmm6,(%r13)
-
-.Lxts_dec_steal:
-	movzbl	16(%r12),%eax
-	movzbl	(%rdx),%ecx
-	leaq	1(%r12),%r12
-	movb	%al,(%rdx)
-	movb	%cl,16(%rdx)
-	leaq	1(%rdx),%rdx
-	subl	$1,%ebx
-	jnz	.Lxts_dec_steal
-
-	movdqu	(%r13),%xmm15
-	leaq	32(%rbp),%rdi
-	pxor	%xmm5,%xmm15
-	leaq	32(%rbp),%rsi
-	movdqa	%xmm15,32(%rbp)
-	leaq	(%r15),%rdx
-	call	aes_nohw_decrypt
-	pxor	32(%rbp),%xmm5
-	movdqu	%xmm5,(%r13)
-
-.Lxts_dec_ret:
-	leaq	(%rsp),%rax
-	pxor	%xmm0,%xmm0
-.Lxts_dec_bzero:
-	movdqa	%xmm0,0(%rax)
-	movdqa	%xmm0,16(%rax)
-	leaq	32(%rax),%rax
-	cmpq	%rax,%rbp
-	ja	.Lxts_dec_bzero
-
-	leaq	120(%rbp),%rax
-.cfi_def_cfa	%rax,8
-	movq	-48(%rax),%r15
-.cfi_restore	%r15
-	movq	-40(%rax),%r14
-.cfi_restore	%r14
-	movq	-32(%rax),%r13
-.cfi_restore	%r13
-	movq	-24(%rax),%r12
-.cfi_restore	%r12
-	movq	-16(%rax),%rbx
-.cfi_restore	%rbx
-	movq	-8(%rax),%rbp
-.cfi_restore	%rbp
-	leaq	(%rax),%rsp
-.cfi_def_cfa_register	%rsp
-.Lxts_dec_epilogue:
-	.byte	0xf3,0xc3
-.cfi_endproc	
-.size	bsaes_xts_decrypt,.-bsaes_xts_decrypt
 .type	_bsaes_const,@object
 .align	64
 _bsaes_const:
diff --git a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha512-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha512-x86_64.S
index 3c47199f..509e144 100644
--- a/third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha512-x86_64.S
+++ b/third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha512-x86_64.S
@@ -25,8 +25,6 @@
 	movl	0(%r11),%r9d
 	movl	4(%r11),%r10d
 	movl	8(%r11),%r11d
-	testl	$2048,%r10d
-	jnz	.Lxop_shortcut
 	andl	$1073741824,%r9d
 	andl	$268435968,%r10d
 	orl	%r9d,%r10d
@@ -1825,1107 +1823,6 @@
 .quad	0x0001020304050607,0x08090a0b0c0d0e0f
 .quad	0x0001020304050607,0x08090a0b0c0d0e0f
 .byte	83,72,65,53,49,50,32,98,108,111,99,107,32,116,114,97,110,115,102,111,114,109,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
-.type	sha512_block_data_order_xop,@function
-.align	64
-sha512_block_data_order_xop:
-.cfi_startproc	
-.Lxop_shortcut:
-	movq	%rsp,%rax
-.cfi_def_cfa_register	%rax
-	pushq	%rbx
-.cfi_offset	%rbx,-16
-	pushq	%rbp
-.cfi_offset	%rbp,-24
-	pushq	%r12
-.cfi_offset	%r12,-32
-	pushq	%r13
-.cfi_offset	%r13,-40
-	pushq	%r14
-.cfi_offset	%r14,-48
-	pushq	%r15
-.cfi_offset	%r15,-56
-	shlq	$4,%rdx
-	subq	$160,%rsp
-	leaq	(%rsi,%rdx,8),%rdx
-	andq	$-64,%rsp
-	movq	%rdi,128+0(%rsp)
-	movq	%rsi,128+8(%rsp)
-	movq	%rdx,128+16(%rsp)
-	movq	%rax,152(%rsp)
-.cfi_escape	0x0f,0x06,0x77,0x98,0x01,0x06,0x23,0x08
-.Lprologue_xop:
-
-	vzeroupper
-	movq	0(%rdi),%rax
-	movq	8(%rdi),%rbx
-	movq	16(%rdi),%rcx
-	movq	24(%rdi),%rdx
-	movq	32(%rdi),%r8
-	movq	40(%rdi),%r9
-	movq	48(%rdi),%r10
-	movq	56(%rdi),%r11
-	jmp	.Lloop_xop
-.align	16
-.Lloop_xop:
-	vmovdqa	K512+1280(%rip),%xmm11
-	vmovdqu	0(%rsi),%xmm0
-	leaq	K512+128(%rip),%rbp
-	vmovdqu	16(%rsi),%xmm1
-	vmovdqu	32(%rsi),%xmm2
-	vpshufb	%xmm11,%xmm0,%xmm0
-	vmovdqu	48(%rsi),%xmm3
-	vpshufb	%xmm11,%xmm1,%xmm1
-	vmovdqu	64(%rsi),%xmm4
-	vpshufb	%xmm11,%xmm2,%xmm2
-	vmovdqu	80(%rsi),%xmm5
-	vpshufb	%xmm11,%xmm3,%xmm3
-	vmovdqu	96(%rsi),%xmm6
-	vpshufb	%xmm11,%xmm4,%xmm4
-	vmovdqu	112(%rsi),%xmm7
-	vpshufb	%xmm11,%xmm5,%xmm5
-	vpaddq	-128(%rbp),%xmm0,%xmm8
-	vpshufb	%xmm11,%xmm6,%xmm6
-	vpaddq	-96(%rbp),%xmm1,%xmm9
-	vpshufb	%xmm11,%xmm7,%xmm7
-	vpaddq	-64(%rbp),%xmm2,%xmm10
-	vpaddq	-32(%rbp),%xmm3,%xmm11
-	vmovdqa	%xmm8,0(%rsp)
-	vpaddq	0(%rbp),%xmm4,%xmm8
-	vmovdqa	%xmm9,16(%rsp)
-	vpaddq	32(%rbp),%xmm5,%xmm9
-	vmovdqa	%xmm10,32(%rsp)
-	vpaddq	64(%rbp),%xmm6,%xmm10
-	vmovdqa	%xmm11,48(%rsp)
-	vpaddq	96(%rbp),%xmm7,%xmm11
-	vmovdqa	%xmm8,64(%rsp)
-	movq	%rax,%r14
-	vmovdqa	%xmm9,80(%rsp)
-	movq	%rbx,%rdi
-	vmovdqa	%xmm10,96(%rsp)
-	xorq	%rcx,%rdi
-	vmovdqa	%xmm11,112(%rsp)
-	movq	%r8,%r13
-	jmp	.Lxop_00_47
-
-.align	16
-.Lxop_00_47:
-	addq	$256,%rbp
-	vpalignr	$8,%xmm0,%xmm1,%xmm8
-	rorq	$23,%r13
-	movq	%r14,%rax
-	vpalignr	$8,%xmm4,%xmm5,%xmm11
-	movq	%r9,%r12
-	rorq	$5,%r14
-.byte	143,72,120,195,200,56
-	xorq	%r8,%r13
-	xorq	%r10,%r12
-	vpsrlq	$7,%xmm8,%xmm8
-	rorq	$4,%r13
-	xorq	%rax,%r14
-	vpaddq	%xmm11,%xmm0,%xmm0
-	andq	%r8,%r12
-	xorq	%r8,%r13
-	addq	0(%rsp),%r11
-	movq	%rax,%r15
-.byte	143,72,120,195,209,7
-	xorq	%r10,%r12
-	rorq	$6,%r14
-	vpxor	%xmm9,%xmm8,%xmm8
-	xorq	%rbx,%r15
-	addq	%r12,%r11
-	rorq	$14,%r13
-	andq	%r15,%rdi
-.byte	143,104,120,195,223,3
-	xorq	%rax,%r14
-	addq	%r13,%r11
-	vpxor	%xmm10,%xmm8,%xmm8
-	xorq	%rbx,%rdi
-	rorq	$28,%r14
-	vpsrlq	$6,%xmm7,%xmm10
-	addq	%r11,%rdx
-	addq	%rdi,%r11
-	vpaddq	%xmm8,%xmm0,%xmm0
-	movq	%rdx,%r13
-	addq	%r11,%r14
-.byte	143,72,120,195,203,42
-	rorq	$23,%r13
-	movq	%r14,%r11
-	vpxor	%xmm10,%xmm11,%xmm11
-	movq	%r8,%r12
-	rorq	$5,%r14
-	xorq	%rdx,%r13
-	xorq	%r9,%r12
-	vpxor	%xmm9,%xmm11,%xmm11
-	rorq	$4,%r13
-	xorq	%r11,%r14
-	andq	%rdx,%r12
-	xorq	%rdx,%r13
-	vpaddq	%xmm11,%xmm0,%xmm0
-	addq	8(%rsp),%r10
-	movq	%r11,%rdi
-	xorq	%r9,%r12
-	rorq	$6,%r14
-	vpaddq	-128(%rbp),%xmm0,%xmm10
-	xorq	%rax,%rdi
-	addq	%r12,%r10
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%r11,%r14
-	addq	%r13,%r10
-	xorq	%rax,%r15
-	rorq	$28,%r14
-	addq	%r10,%rcx
-	addq	%r15,%r10
-	movq	%rcx,%r13
-	addq	%r10,%r14
-	vmovdqa	%xmm10,0(%rsp)
-	vpalignr	$8,%xmm1,%xmm2,%xmm8
-	rorq	$23,%r13
-	movq	%r14,%r10
-	vpalignr	$8,%xmm5,%xmm6,%xmm11
-	movq	%rdx,%r12
-	rorq	$5,%r14
-.byte	143,72,120,195,200,56
-	xorq	%rcx,%r13
-	xorq	%r8,%r12
-	vpsrlq	$7,%xmm8,%xmm8
-	rorq	$4,%r13
-	xorq	%r10,%r14
-	vpaddq	%xmm11,%xmm1,%xmm1
-	andq	%rcx,%r12
-	xorq	%rcx,%r13
-	addq	16(%rsp),%r9
-	movq	%r10,%r15
-.byte	143,72,120,195,209,7
-	xorq	%r8,%r12
-	rorq	$6,%r14
-	vpxor	%xmm9,%xmm8,%xmm8
-	xorq	%r11,%r15
-	addq	%r12,%r9
-	rorq	$14,%r13
-	andq	%r15,%rdi
-.byte	143,104,120,195,216,3
-	xorq	%r10,%r14
-	addq	%r13,%r9
-	vpxor	%xmm10,%xmm8,%xmm8
-	xorq	%r11,%rdi
-	rorq	$28,%r14
-	vpsrlq	$6,%xmm0,%xmm10
-	addq	%r9,%rbx
-	addq	%rdi,%r9
-	vpaddq	%xmm8,%xmm1,%xmm1
-	movq	%rbx,%r13
-	addq	%r9,%r14
-.byte	143,72,120,195,203,42
-	rorq	$23,%r13
-	movq	%r14,%r9
-	vpxor	%xmm10,%xmm11,%xmm11
-	movq	%rcx,%r12
-	rorq	$5,%r14
-	xorq	%rbx,%r13
-	xorq	%rdx,%r12
-	vpxor	%xmm9,%xmm11,%xmm11
-	rorq	$4,%r13
-	xorq	%r9,%r14
-	andq	%rbx,%r12
-	xorq	%rbx,%r13
-	vpaddq	%xmm11,%xmm1,%xmm1
-	addq	24(%rsp),%r8
-	movq	%r9,%rdi
-	xorq	%rdx,%r12
-	rorq	$6,%r14
-	vpaddq	-96(%rbp),%xmm1,%xmm10
-	xorq	%r10,%rdi
-	addq	%r12,%r8
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%r9,%r14
-	addq	%r13,%r8
-	xorq	%r10,%r15
-	rorq	$28,%r14
-	addq	%r8,%rax
-	addq	%r15,%r8
-	movq	%rax,%r13
-	addq	%r8,%r14
-	vmovdqa	%xmm10,16(%rsp)
-	vpalignr	$8,%xmm2,%xmm3,%xmm8
-	rorq	$23,%r13
-	movq	%r14,%r8
-	vpalignr	$8,%xmm6,%xmm7,%xmm11
-	movq	%rbx,%r12
-	rorq	$5,%r14
-.byte	143,72,120,195,200,56
-	xorq	%rax,%r13
-	xorq	%rcx,%r12
-	vpsrlq	$7,%xmm8,%xmm8
-	rorq	$4,%r13
-	xorq	%r8,%r14
-	vpaddq	%xmm11,%xmm2,%xmm2
-	andq	%rax,%r12
-	xorq	%rax,%r13
-	addq	32(%rsp),%rdx
-	movq	%r8,%r15
-.byte	143,72,120,195,209,7
-	xorq	%rcx,%r12
-	rorq	$6,%r14
-	vpxor	%xmm9,%xmm8,%xmm8
-	xorq	%r9,%r15
-	addq	%r12,%rdx
-	rorq	$14,%r13
-	andq	%r15,%rdi
-.byte	143,104,120,195,217,3
-	xorq	%r8,%r14
-	addq	%r13,%rdx
-	vpxor	%xmm10,%xmm8,%xmm8
-	xorq	%r9,%rdi
-	rorq	$28,%r14
-	vpsrlq	$6,%xmm1,%xmm10
-	addq	%rdx,%r11
-	addq	%rdi,%rdx
-	vpaddq	%xmm8,%xmm2,%xmm2
-	movq	%r11,%r13
-	addq	%rdx,%r14
-.byte	143,72,120,195,203,42
-	rorq	$23,%r13
-	movq	%r14,%rdx
-	vpxor	%xmm10,%xmm11,%xmm11
-	movq	%rax,%r12
-	rorq	$5,%r14
-	xorq	%r11,%r13
-	xorq	%rbx,%r12
-	vpxor	%xmm9,%xmm11,%xmm11
-	rorq	$4,%r13
-	xorq	%rdx,%r14
-	andq	%r11,%r12
-	xorq	%r11,%r13
-	vpaddq	%xmm11,%xmm2,%xmm2
-	addq	40(%rsp),%rcx
-	movq	%rdx,%rdi
-	xorq	%rbx,%r12
-	rorq	$6,%r14
-	vpaddq	-64(%rbp),%xmm2,%xmm10
-	xorq	%r8,%rdi
-	addq	%r12,%rcx
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%rdx,%r14
-	addq	%r13,%rcx
-	xorq	%r8,%r15
-	rorq	$28,%r14
-	addq	%rcx,%r10
-	addq	%r15,%rcx
-	movq	%r10,%r13
-	addq	%rcx,%r14
-	vmovdqa	%xmm10,32(%rsp)
-	vpalignr	$8,%xmm3,%xmm4,%xmm8
-	rorq	$23,%r13
-	movq	%r14,%rcx
-	vpalignr	$8,%xmm7,%xmm0,%xmm11
-	movq	%r11,%r12
-	rorq	$5,%r14
-.byte	143,72,120,195,200,56
-	xorq	%r10,%r13
-	xorq	%rax,%r12
-	vpsrlq	$7,%xmm8,%xmm8
-	rorq	$4,%r13
-	xorq	%rcx,%r14
-	vpaddq	%xmm11,%xmm3,%xmm3
-	andq	%r10,%r12
-	xorq	%r10,%r13
-	addq	48(%rsp),%rbx
-	movq	%rcx,%r15
-.byte	143,72,120,195,209,7
-	xorq	%rax,%r12
-	rorq	$6,%r14
-	vpxor	%xmm9,%xmm8,%xmm8
-	xorq	%rdx,%r15
-	addq	%r12,%rbx
-	rorq	$14,%r13
-	andq	%r15,%rdi
-.byte	143,104,120,195,218,3
-	xorq	%rcx,%r14
-	addq	%r13,%rbx
-	vpxor	%xmm10,%xmm8,%xmm8
-	xorq	%rdx,%rdi
-	rorq	$28,%r14
-	vpsrlq	$6,%xmm2,%xmm10
-	addq	%rbx,%r9
-	addq	%rdi,%rbx
-	vpaddq	%xmm8,%xmm3,%xmm3
-	movq	%r9,%r13
-	addq	%rbx,%r14
-.byte	143,72,120,195,203,42
-	rorq	$23,%r13
-	movq	%r14,%rbx
-	vpxor	%xmm10,%xmm11,%xmm11
-	movq	%r10,%r12
-	rorq	$5,%r14
-	xorq	%r9,%r13
-	xorq	%r11,%r12
-	vpxor	%xmm9,%xmm11,%xmm11
-	rorq	$4,%r13
-	xorq	%rbx,%r14
-	andq	%r9,%r12
-	xorq	%r9,%r13
-	vpaddq	%xmm11,%xmm3,%xmm3
-	addq	56(%rsp),%rax
-	movq	%rbx,%rdi
-	xorq	%r11,%r12
-	rorq	$6,%r14
-	vpaddq	-32(%rbp),%xmm3,%xmm10
-	xorq	%rcx,%rdi
-	addq	%r12,%rax
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%rbx,%r14
-	addq	%r13,%rax
-	xorq	%rcx,%r15
-	rorq	$28,%r14
-	addq	%rax,%r8
-	addq	%r15,%rax
-	movq	%r8,%r13
-	addq	%rax,%r14
-	vmovdqa	%xmm10,48(%rsp)
-	vpalignr	$8,%xmm4,%xmm5,%xmm8
-	rorq	$23,%r13
-	movq	%r14,%rax
-	vpalignr	$8,%xmm0,%xmm1,%xmm11
-	movq	%r9,%r12
-	rorq	$5,%r14
-.byte	143,72,120,195,200,56
-	xorq	%r8,%r13
-	xorq	%r10,%r12
-	vpsrlq	$7,%xmm8,%xmm8
-	rorq	$4,%r13
-	xorq	%rax,%r14
-	vpaddq	%xmm11,%xmm4,%xmm4
-	andq	%r8,%r12
-	xorq	%r8,%r13
-	addq	64(%rsp),%r11
-	movq	%rax,%r15
-.byte	143,72,120,195,209,7
-	xorq	%r10,%r12
-	rorq	$6,%r14
-	vpxor	%xmm9,%xmm8,%xmm8
-	xorq	%rbx,%r15
-	addq	%r12,%r11
-	rorq	$14,%r13
-	andq	%r15,%rdi
-.byte	143,104,120,195,219,3
-	xorq	%rax,%r14
-	addq	%r13,%r11
-	vpxor	%xmm10,%xmm8,%xmm8
-	xorq	%rbx,%rdi
-	rorq	$28,%r14
-	vpsrlq	$6,%xmm3,%xmm10
-	addq	%r11,%rdx
-	addq	%rdi,%r11
-	vpaddq	%xmm8,%xmm4,%xmm4
-	movq	%rdx,%r13
-	addq	%r11,%r14
-.byte	143,72,120,195,203,42
-	rorq	$23,%r13
-	movq	%r14,%r11
-	vpxor	%xmm10,%xmm11,%xmm11
-	movq	%r8,%r12
-	rorq	$5,%r14
-	xorq	%rdx,%r13
-	xorq	%r9,%r12
-	vpxor	%xmm9,%xmm11,%xmm11
-	rorq	$4,%r13
-	xorq	%r11,%r14
-	andq	%rdx,%r12
-	xorq	%rdx,%r13
-	vpaddq	%xmm11,%xmm4,%xmm4
-	addq	72(%rsp),%r10
-	movq	%r11,%rdi
-	xorq	%r9,%r12
-	rorq	$6,%r14
-	vpaddq	0(%rbp),%xmm4,%xmm10
-	xorq	%rax,%rdi
-	addq	%r12,%r10
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%r11,%r14
-	addq	%r13,%r10
-	xorq	%rax,%r15
-	rorq	$28,%r14
-	addq	%r10,%rcx
-	addq	%r15,%r10
-	movq	%rcx,%r13
-	addq	%r10,%r14
-	vmovdqa	%xmm10,64(%rsp)
-	vpalignr	$8,%xmm5,%xmm6,%xmm8
-	rorq	$23,%r13
-	movq	%r14,%r10
-	vpalignr	$8,%xmm1,%xmm2,%xmm11
-	movq	%rdx,%r12
-	rorq	$5,%r14
-.byte	143,72,120,195,200,56
-	xorq	%rcx,%r13
-	xorq	%r8,%r12
-	vpsrlq	$7,%xmm8,%xmm8
-	rorq	$4,%r13
-	xorq	%r10,%r14
-	vpaddq	%xmm11,%xmm5,%xmm5
-	andq	%rcx,%r12
-	xorq	%rcx,%r13
-	addq	80(%rsp),%r9
-	movq	%r10,%r15
-.byte	143,72,120,195,209,7
-	xorq	%r8,%r12
-	rorq	$6,%r14
-	vpxor	%xmm9,%xmm8,%xmm8
-	xorq	%r11,%r15
-	addq	%r12,%r9
-	rorq	$14,%r13
-	andq	%r15,%rdi
-.byte	143,104,120,195,220,3
-	xorq	%r10,%r14
-	addq	%r13,%r9
-	vpxor	%xmm10,%xmm8,%xmm8
-	xorq	%r11,%rdi
-	rorq	$28,%r14
-	vpsrlq	$6,%xmm4,%xmm10
-	addq	%r9,%rbx
-	addq	%rdi,%r9
-	vpaddq	%xmm8,%xmm5,%xmm5
-	movq	%rbx,%r13
-	addq	%r9,%r14
-.byte	143,72,120,195,203,42
-	rorq	$23,%r13
-	movq	%r14,%r9
-	vpxor	%xmm10,%xmm11,%xmm11
-	movq	%rcx,%r12
-	rorq	$5,%r14
-	xorq	%rbx,%r13
-	xorq	%rdx,%r12
-	vpxor	%xmm9,%xmm11,%xmm11
-	rorq	$4,%r13
-	xorq	%r9,%r14
-	andq	%rbx,%r12
-	xorq	%rbx,%r13
-	vpaddq	%xmm11,%xmm5,%xmm5
-	addq	88(%rsp),%r8
-	movq	%r9,%rdi
-	xorq	%rdx,%r12
-	rorq	$6,%r14
-	vpaddq	32(%rbp),%xmm5,%xmm10
-	xorq	%r10,%rdi
-	addq	%r12,%r8
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%r9,%r14
-	addq	%r13,%r8
-	xorq	%r10,%r15
-	rorq	$28,%r14
-	addq	%r8,%rax
-	addq	%r15,%r8
-	movq	%rax,%r13
-	addq	%r8,%r14
-	vmovdqa	%xmm10,80(%rsp)
-	vpalignr	$8,%xmm6,%xmm7,%xmm8
-	rorq	$23,%r13
-	movq	%r14,%r8
-	vpalignr	$8,%xmm2,%xmm3,%xmm11
-	movq	%rbx,%r12
-	rorq	$5,%r14
-.byte	143,72,120,195,200,56
-	xorq	%rax,%r13
-	xorq	%rcx,%r12
-	vpsrlq	$7,%xmm8,%xmm8
-	rorq	$4,%r13
-	xorq	%r8,%r14
-	vpaddq	%xmm11,%xmm6,%xmm6
-	andq	%rax,%r12
-	xorq	%rax,%r13
-	addq	96(%rsp),%rdx
-	movq	%r8,%r15
-.byte	143,72,120,195,209,7
-	xorq	%rcx,%r12
-	rorq	$6,%r14
-	vpxor	%xmm9,%xmm8,%xmm8
-	xorq	%r9,%r15
-	addq	%r12,%rdx
-	rorq	$14,%r13
-	andq	%r15,%rdi
-.byte	143,104,120,195,221,3
-	xorq	%r8,%r14
-	addq	%r13,%rdx
-	vpxor	%xmm10,%xmm8,%xmm8
-	xorq	%r9,%rdi
-	rorq	$28,%r14
-	vpsrlq	$6,%xmm5,%xmm10
-	addq	%rdx,%r11
-	addq	%rdi,%rdx
-	vpaddq	%xmm8,%xmm6,%xmm6
-	movq	%r11,%r13
-	addq	%rdx,%r14
-.byte	143,72,120,195,203,42
-	rorq	$23,%r13
-	movq	%r14,%rdx
-	vpxor	%xmm10,%xmm11,%xmm11
-	movq	%rax,%r12
-	rorq	$5,%r14
-	xorq	%r11,%r13
-	xorq	%rbx,%r12
-	vpxor	%xmm9,%xmm11,%xmm11
-	rorq	$4,%r13
-	xorq	%rdx,%r14
-	andq	%r11,%r12
-	xorq	%r11,%r13
-	vpaddq	%xmm11,%xmm6,%xmm6
-	addq	104(%rsp),%rcx
-	movq	%rdx,%rdi
-	xorq	%rbx,%r12
-	rorq	$6,%r14
-	vpaddq	64(%rbp),%xmm6,%xmm10
-	xorq	%r8,%rdi
-	addq	%r12,%rcx
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%rdx,%r14
-	addq	%r13,%rcx
-	xorq	%r8,%r15
-	rorq	$28,%r14
-	addq	%rcx,%r10
-	addq	%r15,%rcx
-	movq	%r10,%r13
-	addq	%rcx,%r14
-	vmovdqa	%xmm10,96(%rsp)
-	vpalignr	$8,%xmm7,%xmm0,%xmm8
-	rorq	$23,%r13
-	movq	%r14,%rcx
-	vpalignr	$8,%xmm3,%xmm4,%xmm11
-	movq	%r11,%r12
-	rorq	$5,%r14
-.byte	143,72,120,195,200,56
-	xorq	%r10,%r13
-	xorq	%rax,%r12
-	vpsrlq	$7,%xmm8,%xmm8
-	rorq	$4,%r13
-	xorq	%rcx,%r14
-	vpaddq	%xmm11,%xmm7,%xmm7
-	andq	%r10,%r12
-	xorq	%r10,%r13
-	addq	112(%rsp),%rbx
-	movq	%rcx,%r15
-.byte	143,72,120,195,209,7
-	xorq	%rax,%r12
-	rorq	$6,%r14
-	vpxor	%xmm9,%xmm8,%xmm8
-	xorq	%rdx,%r15
-	addq	%r12,%rbx
-	rorq	$14,%r13
-	andq	%r15,%rdi
-.byte	143,104,120,195,222,3
-	xorq	%rcx,%r14
-	addq	%r13,%rbx
-	vpxor	%xmm10,%xmm8,%xmm8
-	xorq	%rdx,%rdi
-	rorq	$28,%r14
-	vpsrlq	$6,%xmm6,%xmm10
-	addq	%rbx,%r9
-	addq	%rdi,%rbx
-	vpaddq	%xmm8,%xmm7,%xmm7
-	movq	%r9,%r13
-	addq	%rbx,%r14
-.byte	143,72,120,195,203,42
-	rorq	$23,%r13
-	movq	%r14,%rbx
-	vpxor	%xmm10,%xmm11,%xmm11
-	movq	%r10,%r12
-	rorq	$5,%r14
-	xorq	%r9,%r13
-	xorq	%r11,%r12
-	vpxor	%xmm9,%xmm11,%xmm11
-	rorq	$4,%r13
-	xorq	%rbx,%r14
-	andq	%r9,%r12
-	xorq	%r9,%r13
-	vpaddq	%xmm11,%xmm7,%xmm7
-	addq	120(%rsp),%rax
-	movq	%rbx,%rdi
-	xorq	%r11,%r12
-	rorq	$6,%r14
-	vpaddq	96(%rbp),%xmm7,%xmm10
-	xorq	%rcx,%rdi
-	addq	%r12,%rax
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%rbx,%r14
-	addq	%r13,%rax
-	xorq	%rcx,%r15
-	rorq	$28,%r14
-	addq	%rax,%r8
-	addq	%r15,%rax
-	movq	%r8,%r13
-	addq	%rax,%r14
-	vmovdqa	%xmm10,112(%rsp)
-	cmpb	$0,135(%rbp)
-	jne	.Lxop_00_47
-	rorq	$23,%r13
-	movq	%r14,%rax
-	movq	%r9,%r12
-	rorq	$5,%r14
-	xorq	%r8,%r13
-	xorq	%r10,%r12
-	rorq	$4,%r13
-	xorq	%rax,%r14
-	andq	%r8,%r12
-	xorq	%r8,%r13
-	addq	0(%rsp),%r11
-	movq	%rax,%r15
-	xorq	%r10,%r12
-	rorq	$6,%r14
-	xorq	%rbx,%r15
-	addq	%r12,%r11
-	rorq	$14,%r13
-	andq	%r15,%rdi
-	xorq	%rax,%r14
-	addq	%r13,%r11
-	xorq	%rbx,%rdi
-	rorq	$28,%r14
-	addq	%r11,%rdx
-	addq	%rdi,%r11
-	movq	%rdx,%r13
-	addq	%r11,%r14
-	rorq	$23,%r13
-	movq	%r14,%r11
-	movq	%r8,%r12
-	rorq	$5,%r14
-	xorq	%rdx,%r13
-	xorq	%r9,%r12
-	rorq	$4,%r13
-	xorq	%r11,%r14
-	andq	%rdx,%r12
-	xorq	%rdx,%r13
-	addq	8(%rsp),%r10
-	movq	%r11,%rdi
-	xorq	%r9,%r12
-	rorq	$6,%r14
-	xorq	%rax,%rdi
-	addq	%r12,%r10
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%r11,%r14
-	addq	%r13,%r10
-	xorq	%rax,%r15
-	rorq	$28,%r14
-	addq	%r10,%rcx
-	addq	%r15,%r10
-	movq	%rcx,%r13
-	addq	%r10,%r14
-	rorq	$23,%r13
-	movq	%r14,%r10
-	movq	%rdx,%r12
-	rorq	$5,%r14
-	xorq	%rcx,%r13
-	xorq	%r8,%r12
-	rorq	$4,%r13
-	xorq	%r10,%r14
-	andq	%rcx,%r12
-	xorq	%rcx,%r13
-	addq	16(%rsp),%r9
-	movq	%r10,%r15
-	xorq	%r8,%r12
-	rorq	$6,%r14
-	xorq	%r11,%r15
-	addq	%r12,%r9
-	rorq	$14,%r13
-	andq	%r15,%rdi
-	xorq	%r10,%r14
-	addq	%r13,%r9
-	xorq	%r11,%rdi
-	rorq	$28,%r14
-	addq	%r9,%rbx
-	addq	%rdi,%r9
-	movq	%rbx,%r13
-	addq	%r9,%r14
-	rorq	$23,%r13
-	movq	%r14,%r9
-	movq	%rcx,%r12
-	rorq	$5,%r14
-	xorq	%rbx,%r13
-	xorq	%rdx,%r12
-	rorq	$4,%r13
-	xorq	%r9,%r14
-	andq	%rbx,%r12
-	xorq	%rbx,%r13
-	addq	24(%rsp),%r8
-	movq	%r9,%rdi
-	xorq	%rdx,%r12
-	rorq	$6,%r14
-	xorq	%r10,%rdi
-	addq	%r12,%r8
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%r9,%r14
-	addq	%r13,%r8
-	xorq	%r10,%r15
-	rorq	$28,%r14
-	addq	%r8,%rax
-	addq	%r15,%r8
-	movq	%rax,%r13
-	addq	%r8,%r14
-	rorq	$23,%r13
-	movq	%r14,%r8
-	movq	%rbx,%r12
-	rorq	$5,%r14
-	xorq	%rax,%r13
-	xorq	%rcx,%r12
-	rorq	$4,%r13
-	xorq	%r8,%r14
-	andq	%rax,%r12
-	xorq	%rax,%r13
-	addq	32(%rsp),%rdx
-	movq	%r8,%r15
-	xorq	%rcx,%r12
-	rorq	$6,%r14
-	xorq	%r9,%r15
-	addq	%r12,%rdx
-	rorq	$14,%r13
-	andq	%r15,%rdi
-	xorq	%r8,%r14
-	addq	%r13,%rdx
-	xorq	%r9,%rdi
-	rorq	$28,%r14
-	addq	%rdx,%r11
-	addq	%rdi,%rdx
-	movq	%r11,%r13
-	addq	%rdx,%r14
-	rorq	$23,%r13
-	movq	%r14,%rdx
-	movq	%rax,%r12
-	rorq	$5,%r14
-	xorq	%r11,%r13
-	xorq	%rbx,%r12
-	rorq	$4,%r13
-	xorq	%rdx,%r14
-	andq	%r11,%r12
-	xorq	%r11,%r13
-	addq	40(%rsp),%rcx
-	movq	%rdx,%rdi
-	xorq	%rbx,%r12
-	rorq	$6,%r14
-	xorq	%r8,%rdi
-	addq	%r12,%rcx
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%rdx,%r14
-	addq	%r13,%rcx
-	xorq	%r8,%r15
-	rorq	$28,%r14
-	addq	%rcx,%r10
-	addq	%r15,%rcx
-	movq	%r10,%r13
-	addq	%rcx,%r14
-	rorq	$23,%r13
-	movq	%r14,%rcx
-	movq	%r11,%r12
-	rorq	$5,%r14
-	xorq	%r10,%r13
-	xorq	%rax,%r12
-	rorq	$4,%r13
-	xorq	%rcx,%r14
-	andq	%r10,%r12
-	xorq	%r10,%r13
-	addq	48(%rsp),%rbx
-	movq	%rcx,%r15
-	xorq	%rax,%r12
-	rorq	$6,%r14
-	xorq	%rdx,%r15
-	addq	%r12,%rbx
-	rorq	$14,%r13
-	andq	%r15,%rdi
-	xorq	%rcx,%r14
-	addq	%r13,%rbx
-	xorq	%rdx,%rdi
-	rorq	$28,%r14
-	addq	%rbx,%r9
-	addq	%rdi,%rbx
-	movq	%r9,%r13
-	addq	%rbx,%r14
-	rorq	$23,%r13
-	movq	%r14,%rbx
-	movq	%r10,%r12
-	rorq	$5,%r14
-	xorq	%r9,%r13
-	xorq	%r11,%r12
-	rorq	$4,%r13
-	xorq	%rbx,%r14
-	andq	%r9,%r12
-	xorq	%r9,%r13
-	addq	56(%rsp),%rax
-	movq	%rbx,%rdi
-	xorq	%r11,%r12
-	rorq	$6,%r14
-	xorq	%rcx,%rdi
-	addq	%r12,%rax
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%rbx,%r14
-	addq	%r13,%rax
-	xorq	%rcx,%r15
-	rorq	$28,%r14
-	addq	%rax,%r8
-	addq	%r15,%rax
-	movq	%r8,%r13
-	addq	%rax,%r14
-	rorq	$23,%r13
-	movq	%r14,%rax
-	movq	%r9,%r12
-	rorq	$5,%r14
-	xorq	%r8,%r13
-	xorq	%r10,%r12
-	rorq	$4,%r13
-	xorq	%rax,%r14
-	andq	%r8,%r12
-	xorq	%r8,%r13
-	addq	64(%rsp),%r11
-	movq	%rax,%r15
-	xorq	%r10,%r12
-	rorq	$6,%r14
-	xorq	%rbx,%r15
-	addq	%r12,%r11
-	rorq	$14,%r13
-	andq	%r15,%rdi
-	xorq	%rax,%r14
-	addq	%r13,%r11
-	xorq	%rbx,%rdi
-	rorq	$28,%r14
-	addq	%r11,%rdx
-	addq	%rdi,%r11
-	movq	%rdx,%r13
-	addq	%r11,%r14
-	rorq	$23,%r13
-	movq	%r14,%r11
-	movq	%r8,%r12
-	rorq	$5,%r14
-	xorq	%rdx,%r13
-	xorq	%r9,%r12
-	rorq	$4,%r13
-	xorq	%r11,%r14
-	andq	%rdx,%r12
-	xorq	%rdx,%r13
-	addq	72(%rsp),%r10
-	movq	%r11,%rdi
-	xorq	%r9,%r12
-	rorq	$6,%r14
-	xorq	%rax,%rdi
-	addq	%r12,%r10
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%r11,%r14
-	addq	%r13,%r10
-	xorq	%rax,%r15
-	rorq	$28,%r14
-	addq	%r10,%rcx
-	addq	%r15,%r10
-	movq	%rcx,%r13
-	addq	%r10,%r14
-	rorq	$23,%r13
-	movq	%r14,%r10
-	movq	%rdx,%r12
-	rorq	$5,%r14
-	xorq	%rcx,%r13
-	xorq	%r8,%r12
-	rorq	$4,%r13
-	xorq	%r10,%r14
-	andq	%rcx,%r12
-	xorq	%rcx,%r13
-	addq	80(%rsp),%r9
-	movq	%r10,%r15
-	xorq	%r8,%r12
-	rorq	$6,%r14
-	xorq	%r11,%r15
-	addq	%r12,%r9
-	rorq	$14,%r13
-	andq	%r15,%rdi
-	xorq	%r10,%r14
-	addq	%r13,%r9
-	xorq	%r11,%rdi
-	rorq	$28,%r14
-	addq	%r9,%rbx
-	addq	%rdi,%r9
-	movq	%rbx,%r13
-	addq	%r9,%r14
-	rorq	$23,%r13
-	movq	%r14,%r9
-	movq	%rcx,%r12
-	rorq	$5,%r14
-	xorq	%rbx,%r13
-	xorq	%rdx,%r12
-	rorq	$4,%r13
-	xorq	%r9,%r14
-	andq	%rbx,%r12
-	xorq	%rbx,%r13
-	addq	88(%rsp),%r8
-	movq	%r9,%rdi
-	xorq	%rdx,%r12
-	rorq	$6,%r14
-	xorq	%r10,%rdi
-	addq	%r12,%r8
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%r9,%r14
-	addq	%r13,%r8
-	xorq	%r10,%r15
-	rorq	$28,%r14
-	addq	%r8,%rax
-	addq	%r15,%r8
-	movq	%rax,%r13
-	addq	%r8,%r14
-	rorq	$23,%r13
-	movq	%r14,%r8
-	movq	%rbx,%r12
-	rorq	$5,%r14
-	xorq	%rax,%r13
-	xorq	%rcx,%r12
-	rorq	$4,%r13
-	xorq	%r8,%r14
-	andq	%rax,%r12
-	xorq	%rax,%r13
-	addq	96(%rsp),%rdx
-	movq	%r8,%r15
-	xorq	%rcx,%r12
-	rorq	$6,%r14
-	xorq	%r9,%r15
-	addq	%r12,%rdx
-	rorq	$14,%r13
-	andq	%r15,%rdi
-	xorq	%r8,%r14
-	addq	%r13,%rdx
-	xorq	%r9,%rdi
-	rorq	$28,%r14
-	addq	%rdx,%r11
-	addq	%rdi,%rdx
-	movq	%r11,%r13
-	addq	%rdx,%r14
-	rorq	$23,%r13
-	movq	%r14,%rdx
-	movq	%rax,%r12
-	rorq	$5,%r14
-	xorq	%r11,%r13
-	xorq	%rbx,%r12
-	rorq	$4,%r13
-	xorq	%rdx,%r14
-	andq	%r11,%r12
-	xorq	%r11,%r13
-	addq	104(%rsp),%rcx
-	movq	%rdx,%rdi
-	xorq	%rbx,%r12
-	rorq	$6,%r14
-	xorq	%r8,%rdi
-	addq	%r12,%rcx
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%rdx,%r14
-	addq	%r13,%rcx
-	xorq	%r8,%r15
-	rorq	$28,%r14
-	addq	%rcx,%r10
-	addq	%r15,%rcx
-	movq	%r10,%r13
-	addq	%rcx,%r14
-	rorq	$23,%r13
-	movq	%r14,%rcx
-	movq	%r11,%r12
-	rorq	$5,%r14
-	xorq	%r10,%r13
-	xorq	%rax,%r12
-	rorq	$4,%r13
-	xorq	%rcx,%r14
-	andq	%r10,%r12
-	xorq	%r10,%r13
-	addq	112(%rsp),%rbx
-	movq	%rcx,%r15
-	xorq	%rax,%r12
-	rorq	$6,%r14
-	xorq	%rdx,%r15
-	addq	%r12,%rbx
-	rorq	$14,%r13
-	andq	%r15,%rdi
-	xorq	%rcx,%r14
-	addq	%r13,%rbx
-	xorq	%rdx,%rdi
-	rorq	$28,%r14
-	addq	%rbx,%r9
-	addq	%rdi,%rbx
-	movq	%r9,%r13
-	addq	%rbx,%r14
-	rorq	$23,%r13
-	movq	%r14,%rbx
-	movq	%r10,%r12
-	rorq	$5,%r14
-	xorq	%r9,%r13
-	xorq	%r11,%r12
-	rorq	$4,%r13
-	xorq	%rbx,%r14
-	andq	%r9,%r12
-	xorq	%r9,%r13
-	addq	120(%rsp),%rax
-	movq	%rbx,%rdi
-	xorq	%r11,%r12
-	rorq	$6,%r14
-	xorq	%rcx,%rdi
-	addq	%r12,%rax
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%rbx,%r14
-	addq	%r13,%rax
-	xorq	%rcx,%r15
-	rorq	$28,%r14
-	addq	%rax,%r8
-	addq	%r15,%rax
-	movq	%r8,%r13
-	addq	%rax,%r14
-	movq	128+0(%rsp),%rdi
-	movq	%r14,%rax
-
-	addq	0(%rdi),%rax
-	leaq	128(%rsi),%rsi
-	addq	8(%rdi),%rbx
-	addq	16(%rdi),%rcx
-	addq	24(%rdi),%rdx
-	addq	32(%rdi),%r8
-	addq	40(%rdi),%r9
-	addq	48(%rdi),%r10
-	addq	56(%rdi),%r11
-
-	cmpq	128+16(%rsp),%rsi
-
-	movq	%rax,0(%rdi)
-	movq	%rbx,8(%rdi)
-	movq	%rcx,16(%rdi)
-	movq	%rdx,24(%rdi)
-	movq	%r8,32(%rdi)
-	movq	%r9,40(%rdi)
-	movq	%r10,48(%rdi)
-	movq	%r11,56(%rdi)
-	jb	.Lloop_xop
-
-	movq	152(%rsp),%rsi
-.cfi_def_cfa	%rsi,8
-	vzeroupper
-	movq	-48(%rsi),%r15
-.cfi_restore	%r15
-	movq	-40(%rsi),%r14
-.cfi_restore	%r14
-	movq	-32(%rsi),%r13
-.cfi_restore	%r13
-	movq	-24(%rsi),%r12
-.cfi_restore	%r12
-	movq	-16(%rsi),%rbp
-.cfi_restore	%rbp
-	movq	-8(%rsi),%rbx
-.cfi_restore	%rbx
-	leaq	(%rsi),%rsp
-.cfi_def_cfa_register	%rsp
-.Lepilogue_xop:
-	.byte	0xf3,0xc3
-.cfi_endproc	
-.size	sha512_block_data_order_xop,.-sha512_block_data_order_xop
 .type	sha512_block_data_order_avx,@function
 .align	64
 sha512_block_data_order_avx:
diff --git a/third_party/boringssl/mac-x86_64/crypto/fipsmodule/bsaes-x86_64.S b/third_party/boringssl/mac-x86_64/crypto/fipsmodule/bsaes-x86_64.S
index d0668ca..0149e0e5 100644
--- a/third_party/boringssl/mac-x86_64/crypto/fipsmodule/bsaes-x86_64.S
+++ b/third_party/boringssl/mac-x86_64/crypto/fipsmodule/bsaes-x86_64.S
@@ -1561,970 +1561,6 @@
 	.byte	0xf3,0xc3
 
 
-.globl	_bsaes_xts_encrypt
-.private_extern _bsaes_xts_encrypt
-
-.p2align	4
-_bsaes_xts_encrypt:
-
-	movq	%rsp,%rax
-L$xts_enc_prologue:
-	pushq	%rbp
-
-	pushq	%rbx
-
-	pushq	%r12
-
-	pushq	%r13
-
-	pushq	%r14
-
-	pushq	%r15
-
-	leaq	-72(%rsp),%rsp
-
-	movq	%rsp,%rbp
-
-	movq	%rdi,%r12
-	movq	%rsi,%r13
-	movq	%rdx,%r14
-	movq	%rcx,%r15
-
-	leaq	(%r9),%rdi
-	leaq	32(%rbp),%rsi
-	leaq	(%r8),%rdx
-	call	_aes_nohw_encrypt
-
-	movl	240(%r15),%eax
-	movq	%r14,%rbx
-
-	movl	%eax,%edx
-	shlq	$7,%rax
-	subq	$96,%rax
-	subq	%rax,%rsp
-
-	movq	%rsp,%rax
-	movq	%r15,%rcx
-	movl	%edx,%r10d
-	call	_bsaes_key_convert
-	pxor	%xmm6,%xmm7
-	movdqa	%xmm7,(%rax)
-
-	andq	$-16,%r14
-	subq	$0x80,%rsp
-	movdqa	32(%rbp),%xmm6
-
-	pxor	%xmm14,%xmm14
-	movdqa	L$xts_magic(%rip),%xmm12
-	pcmpgtd	%xmm6,%xmm14
-
-	subq	$0x80,%r14
-	jc	L$xts_enc_short
-	jmp	L$xts_enc_loop
-
-.p2align	4
-L$xts_enc_loop:
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm15
-	movdqa	%xmm6,0(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm0
-	movdqa	%xmm6,16(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	0(%r12),%xmm7
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm1
-	movdqa	%xmm6,32(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	16(%r12),%xmm8
-	pxor	%xmm7,%xmm15
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm2
-	movdqa	%xmm6,48(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	32(%r12),%xmm9
-	pxor	%xmm8,%xmm0
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm3
-	movdqa	%xmm6,64(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	48(%r12),%xmm10
-	pxor	%xmm9,%xmm1
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm4
-	movdqa	%xmm6,80(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	64(%r12),%xmm11
-	pxor	%xmm10,%xmm2
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm5
-	movdqa	%xmm6,96(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	80(%r12),%xmm12
-	pxor	%xmm11,%xmm3
-	movdqu	96(%r12),%xmm13
-	pxor	%xmm12,%xmm4
-	movdqu	112(%r12),%xmm14
-	leaq	128(%r12),%r12
-	movdqa	%xmm6,112(%rsp)
-	pxor	%xmm13,%xmm5
-	leaq	128(%rsp),%rax
-	pxor	%xmm14,%xmm6
-	movl	%edx,%r10d
-
-	call	_bsaes_encrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm3
-	movdqu	%xmm0,16(%r13)
-	pxor	48(%rsp),%xmm5
-	movdqu	%xmm3,32(%r13)
-	pxor	64(%rsp),%xmm2
-	movdqu	%xmm5,48(%r13)
-	pxor	80(%rsp),%xmm6
-	movdqu	%xmm2,64(%r13)
-	pxor	96(%rsp),%xmm1
-	movdqu	%xmm6,80(%r13)
-	pxor	112(%rsp),%xmm4
-	movdqu	%xmm1,96(%r13)
-	movdqu	%xmm4,112(%r13)
-	leaq	128(%r13),%r13
-
-	movdqa	112(%rsp),%xmm6
-	pxor	%xmm14,%xmm14
-	movdqa	L$xts_magic(%rip),%xmm12
-	pcmpgtd	%xmm6,%xmm14
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-
-	subq	$0x80,%r14
-	jnc	L$xts_enc_loop
-
-L$xts_enc_short:
-	addq	$0x80,%r14
-	jz	L$xts_enc_done
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm15
-	movdqa	%xmm6,0(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm0
-	movdqa	%xmm6,16(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	0(%r12),%xmm7
-	cmpq	$16,%r14
-	je	L$xts_enc_1
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm1
-	movdqa	%xmm6,32(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	16(%r12),%xmm8
-	cmpq	$32,%r14
-	je	L$xts_enc_2
-	pxor	%xmm7,%xmm15
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm2
-	movdqa	%xmm6,48(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	32(%r12),%xmm9
-	cmpq	$48,%r14
-	je	L$xts_enc_3
-	pxor	%xmm8,%xmm0
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm3
-	movdqa	%xmm6,64(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	48(%r12),%xmm10
-	cmpq	$64,%r14
-	je	L$xts_enc_4
-	pxor	%xmm9,%xmm1
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm4
-	movdqa	%xmm6,80(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	64(%r12),%xmm11
-	cmpq	$80,%r14
-	je	L$xts_enc_5
-	pxor	%xmm10,%xmm2
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm5
-	movdqa	%xmm6,96(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	80(%r12),%xmm12
-	cmpq	$96,%r14
-	je	L$xts_enc_6
-	pxor	%xmm11,%xmm3
-	movdqu	96(%r12),%xmm13
-	pxor	%xmm12,%xmm4
-	movdqa	%xmm6,112(%rsp)
-	leaq	112(%r12),%r12
-	pxor	%xmm13,%xmm5
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_encrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm3
-	movdqu	%xmm0,16(%r13)
-	pxor	48(%rsp),%xmm5
-	movdqu	%xmm3,32(%r13)
-	pxor	64(%rsp),%xmm2
-	movdqu	%xmm5,48(%r13)
-	pxor	80(%rsp),%xmm6
-	movdqu	%xmm2,64(%r13)
-	pxor	96(%rsp),%xmm1
-	movdqu	%xmm6,80(%r13)
-	movdqu	%xmm1,96(%r13)
-	leaq	112(%r13),%r13
-
-	movdqa	112(%rsp),%xmm6
-	jmp	L$xts_enc_done
-.p2align	4
-L$xts_enc_6:
-	pxor	%xmm11,%xmm3
-	leaq	96(%r12),%r12
-	pxor	%xmm12,%xmm4
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_encrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm3
-	movdqu	%xmm0,16(%r13)
-	pxor	48(%rsp),%xmm5
-	movdqu	%xmm3,32(%r13)
-	pxor	64(%rsp),%xmm2
-	movdqu	%xmm5,48(%r13)
-	pxor	80(%rsp),%xmm6
-	movdqu	%xmm2,64(%r13)
-	movdqu	%xmm6,80(%r13)
-	leaq	96(%r13),%r13
-
-	movdqa	96(%rsp),%xmm6
-	jmp	L$xts_enc_done
-.p2align	4
-L$xts_enc_5:
-	pxor	%xmm10,%xmm2
-	leaq	80(%r12),%r12
-	pxor	%xmm11,%xmm3
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_encrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm3
-	movdqu	%xmm0,16(%r13)
-	pxor	48(%rsp),%xmm5
-	movdqu	%xmm3,32(%r13)
-	pxor	64(%rsp),%xmm2
-	movdqu	%xmm5,48(%r13)
-	movdqu	%xmm2,64(%r13)
-	leaq	80(%r13),%r13
-
-	movdqa	80(%rsp),%xmm6
-	jmp	L$xts_enc_done
-.p2align	4
-L$xts_enc_4:
-	pxor	%xmm9,%xmm1
-	leaq	64(%r12),%r12
-	pxor	%xmm10,%xmm2
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_encrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm3
-	movdqu	%xmm0,16(%r13)
-	pxor	48(%rsp),%xmm5
-	movdqu	%xmm3,32(%r13)
-	movdqu	%xmm5,48(%r13)
-	leaq	64(%r13),%r13
-
-	movdqa	64(%rsp),%xmm6
-	jmp	L$xts_enc_done
-.p2align	4
-L$xts_enc_3:
-	pxor	%xmm8,%xmm0
-	leaq	48(%r12),%r12
-	pxor	%xmm9,%xmm1
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_encrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm3
-	movdqu	%xmm0,16(%r13)
-	movdqu	%xmm3,32(%r13)
-	leaq	48(%r13),%r13
-
-	movdqa	48(%rsp),%xmm6
-	jmp	L$xts_enc_done
-.p2align	4
-L$xts_enc_2:
-	pxor	%xmm7,%xmm15
-	leaq	32(%r12),%r12
-	pxor	%xmm8,%xmm0
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_encrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	movdqu	%xmm0,16(%r13)
-	leaq	32(%r13),%r13
-
-	movdqa	32(%rsp),%xmm6
-	jmp	L$xts_enc_done
-.p2align	4
-L$xts_enc_1:
-	pxor	%xmm15,%xmm7
-	leaq	16(%r12),%r12
-	movdqa	%xmm7,32(%rbp)
-	leaq	32(%rbp),%rdi
-	leaq	32(%rbp),%rsi
-	leaq	(%r15),%rdx
-	call	_aes_nohw_encrypt
-	pxor	32(%rbp),%xmm15
-
-
-
-
-
-	movdqu	%xmm15,0(%r13)
-	leaq	16(%r13),%r13
-
-	movdqa	16(%rsp),%xmm6
-
-L$xts_enc_done:
-	andl	$15,%ebx
-	jz	L$xts_enc_ret
-	movq	%r13,%rdx
-
-L$xts_enc_steal:
-	movzbl	(%r12),%eax
-	movzbl	-16(%rdx),%ecx
-	leaq	1(%r12),%r12
-	movb	%al,-16(%rdx)
-	movb	%cl,0(%rdx)
-	leaq	1(%rdx),%rdx
-	subl	$1,%ebx
-	jnz	L$xts_enc_steal
-
-	movdqu	-16(%r13),%xmm15
-	leaq	32(%rbp),%rdi
-	pxor	%xmm6,%xmm15
-	leaq	32(%rbp),%rsi
-	movdqa	%xmm15,32(%rbp)
-	leaq	(%r15),%rdx
-	call	_aes_nohw_encrypt
-	pxor	32(%rbp),%xmm6
-	movdqu	%xmm6,-16(%r13)
-
-L$xts_enc_ret:
-	leaq	(%rsp),%rax
-	pxor	%xmm0,%xmm0
-L$xts_enc_bzero:
-	movdqa	%xmm0,0(%rax)
-	movdqa	%xmm0,16(%rax)
-	leaq	32(%rax),%rax
-	cmpq	%rax,%rbp
-	ja	L$xts_enc_bzero
-
-	leaq	120(%rbp),%rax
-
-	movq	-48(%rax),%r15
-
-	movq	-40(%rax),%r14
-
-	movq	-32(%rax),%r13
-
-	movq	-24(%rax),%r12
-
-	movq	-16(%rax),%rbx
-
-	movq	-8(%rax),%rbp
-
-	leaq	(%rax),%rsp
-
-L$xts_enc_epilogue:
-	.byte	0xf3,0xc3
-
-
-
-.globl	_bsaes_xts_decrypt
-.private_extern _bsaes_xts_decrypt
-
-.p2align	4
-_bsaes_xts_decrypt:
-
-	movq	%rsp,%rax
-L$xts_dec_prologue:
-	pushq	%rbp
-
-	pushq	%rbx
-
-	pushq	%r12
-
-	pushq	%r13
-
-	pushq	%r14
-
-	pushq	%r15
-
-	leaq	-72(%rsp),%rsp
-
-	movq	%rsp,%rbp
-	movq	%rdi,%r12
-	movq	%rsi,%r13
-	movq	%rdx,%r14
-	movq	%rcx,%r15
-
-	leaq	(%r9),%rdi
-	leaq	32(%rbp),%rsi
-	leaq	(%r8),%rdx
-	call	_aes_nohw_encrypt
-
-	movl	240(%r15),%eax
-	movq	%r14,%rbx
-
-	movl	%eax,%edx
-	shlq	$7,%rax
-	subq	$96,%rax
-	subq	%rax,%rsp
-
-	movq	%rsp,%rax
-	movq	%r15,%rcx
-	movl	%edx,%r10d
-	call	_bsaes_key_convert
-	pxor	(%rsp),%xmm7
-	movdqa	%xmm6,(%rax)
-	movdqa	%xmm7,(%rsp)
-
-	xorl	%eax,%eax
-	andq	$-16,%r14
-	testl	$15,%ebx
-	setnz	%al
-	shlq	$4,%rax
-	subq	%rax,%r14
-
-	subq	$0x80,%rsp
-	movdqa	32(%rbp),%xmm6
-
-	pxor	%xmm14,%xmm14
-	movdqa	L$xts_magic(%rip),%xmm12
-	pcmpgtd	%xmm6,%xmm14
-
-	subq	$0x80,%r14
-	jc	L$xts_dec_short
-	jmp	L$xts_dec_loop
-
-.p2align	4
-L$xts_dec_loop:
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm15
-	movdqa	%xmm6,0(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm0
-	movdqa	%xmm6,16(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	0(%r12),%xmm7
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm1
-	movdqa	%xmm6,32(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	16(%r12),%xmm8
-	pxor	%xmm7,%xmm15
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm2
-	movdqa	%xmm6,48(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	32(%r12),%xmm9
-	pxor	%xmm8,%xmm0
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm3
-	movdqa	%xmm6,64(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	48(%r12),%xmm10
-	pxor	%xmm9,%xmm1
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm4
-	movdqa	%xmm6,80(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	64(%r12),%xmm11
-	pxor	%xmm10,%xmm2
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm5
-	movdqa	%xmm6,96(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	80(%r12),%xmm12
-	pxor	%xmm11,%xmm3
-	movdqu	96(%r12),%xmm13
-	pxor	%xmm12,%xmm4
-	movdqu	112(%r12),%xmm14
-	leaq	128(%r12),%r12
-	movdqa	%xmm6,112(%rsp)
-	pxor	%xmm13,%xmm5
-	leaq	128(%rsp),%rax
-	pxor	%xmm14,%xmm6
-	movl	%edx,%r10d
-
-	call	_bsaes_decrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm5
-	movdqu	%xmm0,16(%r13)
-	pxor	48(%rsp),%xmm3
-	movdqu	%xmm5,32(%r13)
-	pxor	64(%rsp),%xmm1
-	movdqu	%xmm3,48(%r13)
-	pxor	80(%rsp),%xmm6
-	movdqu	%xmm1,64(%r13)
-	pxor	96(%rsp),%xmm2
-	movdqu	%xmm6,80(%r13)
-	pxor	112(%rsp),%xmm4
-	movdqu	%xmm2,96(%r13)
-	movdqu	%xmm4,112(%r13)
-	leaq	128(%r13),%r13
-
-	movdqa	112(%rsp),%xmm6
-	pxor	%xmm14,%xmm14
-	movdqa	L$xts_magic(%rip),%xmm12
-	pcmpgtd	%xmm6,%xmm14
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-
-	subq	$0x80,%r14
-	jnc	L$xts_dec_loop
-
-L$xts_dec_short:
-	addq	$0x80,%r14
-	jz	L$xts_dec_done
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm15
-	movdqa	%xmm6,0(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm0
-	movdqa	%xmm6,16(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	0(%r12),%xmm7
-	cmpq	$16,%r14
-	je	L$xts_dec_1
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm1
-	movdqa	%xmm6,32(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	16(%r12),%xmm8
-	cmpq	$32,%r14
-	je	L$xts_dec_2
-	pxor	%xmm7,%xmm15
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm2
-	movdqa	%xmm6,48(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	32(%r12),%xmm9
-	cmpq	$48,%r14
-	je	L$xts_dec_3
-	pxor	%xmm8,%xmm0
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm3
-	movdqa	%xmm6,64(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	48(%r12),%xmm10
-	cmpq	$64,%r14
-	je	L$xts_dec_4
-	pxor	%xmm9,%xmm1
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm4
-	movdqa	%xmm6,80(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	64(%r12),%xmm11
-	cmpq	$80,%r14
-	je	L$xts_dec_5
-	pxor	%xmm10,%xmm2
-	pshufd	$0x13,%xmm14,%xmm13
-	pxor	%xmm14,%xmm14
-	movdqa	%xmm6,%xmm5
-	movdqa	%xmm6,96(%rsp)
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	pcmpgtd	%xmm6,%xmm14
-	pxor	%xmm13,%xmm6
-	movdqu	80(%r12),%xmm12
-	cmpq	$96,%r14
-	je	L$xts_dec_6
-	pxor	%xmm11,%xmm3
-	movdqu	96(%r12),%xmm13
-	pxor	%xmm12,%xmm4
-	movdqa	%xmm6,112(%rsp)
-	leaq	112(%r12),%r12
-	pxor	%xmm13,%xmm5
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_decrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm5
-	movdqu	%xmm0,16(%r13)
-	pxor	48(%rsp),%xmm3
-	movdqu	%xmm5,32(%r13)
-	pxor	64(%rsp),%xmm1
-	movdqu	%xmm3,48(%r13)
-	pxor	80(%rsp),%xmm6
-	movdqu	%xmm1,64(%r13)
-	pxor	96(%rsp),%xmm2
-	movdqu	%xmm6,80(%r13)
-	movdqu	%xmm2,96(%r13)
-	leaq	112(%r13),%r13
-
-	movdqa	112(%rsp),%xmm6
-	jmp	L$xts_dec_done
-.p2align	4
-L$xts_dec_6:
-	pxor	%xmm11,%xmm3
-	leaq	96(%r12),%r12
-	pxor	%xmm12,%xmm4
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_decrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm5
-	movdqu	%xmm0,16(%r13)
-	pxor	48(%rsp),%xmm3
-	movdqu	%xmm5,32(%r13)
-	pxor	64(%rsp),%xmm1
-	movdqu	%xmm3,48(%r13)
-	pxor	80(%rsp),%xmm6
-	movdqu	%xmm1,64(%r13)
-	movdqu	%xmm6,80(%r13)
-	leaq	96(%r13),%r13
-
-	movdqa	96(%rsp),%xmm6
-	jmp	L$xts_dec_done
-.p2align	4
-L$xts_dec_5:
-	pxor	%xmm10,%xmm2
-	leaq	80(%r12),%r12
-	pxor	%xmm11,%xmm3
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_decrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm5
-	movdqu	%xmm0,16(%r13)
-	pxor	48(%rsp),%xmm3
-	movdqu	%xmm5,32(%r13)
-	pxor	64(%rsp),%xmm1
-	movdqu	%xmm3,48(%r13)
-	movdqu	%xmm1,64(%r13)
-	leaq	80(%r13),%r13
-
-	movdqa	80(%rsp),%xmm6
-	jmp	L$xts_dec_done
-.p2align	4
-L$xts_dec_4:
-	pxor	%xmm9,%xmm1
-	leaq	64(%r12),%r12
-	pxor	%xmm10,%xmm2
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_decrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm5
-	movdqu	%xmm0,16(%r13)
-	pxor	48(%rsp),%xmm3
-	movdqu	%xmm5,32(%r13)
-	movdqu	%xmm3,48(%r13)
-	leaq	64(%r13),%r13
-
-	movdqa	64(%rsp),%xmm6
-	jmp	L$xts_dec_done
-.p2align	4
-L$xts_dec_3:
-	pxor	%xmm8,%xmm0
-	leaq	48(%r12),%r12
-	pxor	%xmm9,%xmm1
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_decrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	pxor	32(%rsp),%xmm5
-	movdqu	%xmm0,16(%r13)
-	movdqu	%xmm5,32(%r13)
-	leaq	48(%r13),%r13
-
-	movdqa	48(%rsp),%xmm6
-	jmp	L$xts_dec_done
-.p2align	4
-L$xts_dec_2:
-	pxor	%xmm7,%xmm15
-	leaq	32(%r12),%r12
-	pxor	%xmm8,%xmm0
-	leaq	128(%rsp),%rax
-	movl	%edx,%r10d
-
-	call	_bsaes_decrypt8
-
-	pxor	0(%rsp),%xmm15
-	pxor	16(%rsp),%xmm0
-	movdqu	%xmm15,0(%r13)
-	movdqu	%xmm0,16(%r13)
-	leaq	32(%r13),%r13
-
-	movdqa	32(%rsp),%xmm6
-	jmp	L$xts_dec_done
-.p2align	4
-L$xts_dec_1:
-	pxor	%xmm15,%xmm7
-	leaq	16(%r12),%r12
-	movdqa	%xmm7,32(%rbp)
-	leaq	32(%rbp),%rdi
-	leaq	32(%rbp),%rsi
-	leaq	(%r15),%rdx
-	call	_aes_nohw_decrypt
-	pxor	32(%rbp),%xmm15
-
-
-
-
-
-	movdqu	%xmm15,0(%r13)
-	leaq	16(%r13),%r13
-
-	movdqa	16(%rsp),%xmm6
-
-L$xts_dec_done:
-	andl	$15,%ebx
-	jz	L$xts_dec_ret
-
-	pxor	%xmm14,%xmm14
-	movdqa	L$xts_magic(%rip),%xmm12
-	pcmpgtd	%xmm6,%xmm14
-	pshufd	$0x13,%xmm14,%xmm13
-	movdqa	%xmm6,%xmm5
-	paddq	%xmm6,%xmm6
-	pand	%xmm12,%xmm13
-	movdqu	(%r12),%xmm15
-	pxor	%xmm13,%xmm6
-
-	leaq	32(%rbp),%rdi
-	pxor	%xmm6,%xmm15
-	leaq	32(%rbp),%rsi
-	movdqa	%xmm15,32(%rbp)
-	leaq	(%r15),%rdx
-	call	_aes_nohw_decrypt
-	pxor	32(%rbp),%xmm6
-	movq	%r13,%rdx
-	movdqu	%xmm6,(%r13)
-
-L$xts_dec_steal:
-	movzbl	16(%r12),%eax
-	movzbl	(%rdx),%ecx
-	leaq	1(%r12),%r12
-	movb	%al,(%rdx)
-	movb	%cl,16(%rdx)
-	leaq	1(%rdx),%rdx
-	subl	$1,%ebx
-	jnz	L$xts_dec_steal
-
-	movdqu	(%r13),%xmm15
-	leaq	32(%rbp),%rdi
-	pxor	%xmm5,%xmm15
-	leaq	32(%rbp),%rsi
-	movdqa	%xmm15,32(%rbp)
-	leaq	(%r15),%rdx
-	call	_aes_nohw_decrypt
-	pxor	32(%rbp),%xmm5
-	movdqu	%xmm5,(%r13)
-
-L$xts_dec_ret:
-	leaq	(%rsp),%rax
-	pxor	%xmm0,%xmm0
-L$xts_dec_bzero:
-	movdqa	%xmm0,0(%rax)
-	movdqa	%xmm0,16(%rax)
-	leaq	32(%rax),%rax
-	cmpq	%rax,%rbp
-	ja	L$xts_dec_bzero
-
-	leaq	120(%rbp),%rax
-
-	movq	-48(%rax),%r15
-
-	movq	-40(%rax),%r14
-
-	movq	-32(%rax),%r13
-
-	movq	-24(%rax),%r12
-
-	movq	-16(%rax),%rbx
-
-	movq	-8(%rax),%rbp
-
-	leaq	(%rax),%rsp
-
-L$xts_dec_epilogue:
-	.byte	0xf3,0xc3
-
-
 
 .p2align	6
 _bsaes_const:
diff --git a/third_party/boringssl/mac-x86_64/crypto/fipsmodule/sha512-x86_64.S b/third_party/boringssl/mac-x86_64/crypto/fipsmodule/sha512-x86_64.S
index 8a6d16cd..c550e79 100644
--- a/third_party/boringssl/mac-x86_64/crypto/fipsmodule/sha512-x86_64.S
+++ b/third_party/boringssl/mac-x86_64/crypto/fipsmodule/sha512-x86_64.S
@@ -24,8 +24,6 @@
 	movl	0(%r11),%r9d
 	movl	4(%r11),%r10d
 	movl	8(%r11),%r11d
-	testl	$2048,%r10d
-	jnz	L$xop_shortcut
 	andl	$1073741824,%r9d
 	andl	$268435968,%r10d
 	orl	%r9d,%r10d
@@ -1826,1107 +1824,6 @@
 .byte	83,72,65,53,49,50,32,98,108,111,99,107,32,116,114,97,110,115,102,111,114,109,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 
 .p2align	6
-sha512_block_data_order_xop:
-
-L$xop_shortcut:
-	movq	%rsp,%rax
-
-	pushq	%rbx
-
-	pushq	%rbp
-
-	pushq	%r12
-
-	pushq	%r13
-
-	pushq	%r14
-
-	pushq	%r15
-
-	shlq	$4,%rdx
-	subq	$160,%rsp
-	leaq	(%rsi,%rdx,8),%rdx
-	andq	$-64,%rsp
-	movq	%rdi,128+0(%rsp)
-	movq	%rsi,128+8(%rsp)
-	movq	%rdx,128+16(%rsp)
-	movq	%rax,152(%rsp)
-
-L$prologue_xop:
-
-	vzeroupper
-	movq	0(%rdi),%rax
-	movq	8(%rdi),%rbx
-	movq	16(%rdi),%rcx
-	movq	24(%rdi),%rdx
-	movq	32(%rdi),%r8
-	movq	40(%rdi),%r9
-	movq	48(%rdi),%r10
-	movq	56(%rdi),%r11
-	jmp	L$loop_xop
-.p2align	4
-L$loop_xop:
-	vmovdqa	K512+1280(%rip),%xmm11
-	vmovdqu	0(%rsi),%xmm0
-	leaq	K512+128(%rip),%rbp
-	vmovdqu	16(%rsi),%xmm1
-	vmovdqu	32(%rsi),%xmm2
-	vpshufb	%xmm11,%xmm0,%xmm0
-	vmovdqu	48(%rsi),%xmm3
-	vpshufb	%xmm11,%xmm1,%xmm1
-	vmovdqu	64(%rsi),%xmm4
-	vpshufb	%xmm11,%xmm2,%xmm2
-	vmovdqu	80(%rsi),%xmm5
-	vpshufb	%xmm11,%xmm3,%xmm3
-	vmovdqu	96(%rsi),%xmm6
-	vpshufb	%xmm11,%xmm4,%xmm4
-	vmovdqu	112(%rsi),%xmm7
-	vpshufb	%xmm11,%xmm5,%xmm5
-	vpaddq	-128(%rbp),%xmm0,%xmm8
-	vpshufb	%xmm11,%xmm6,%xmm6
-	vpaddq	-96(%rbp),%xmm1,%xmm9
-	vpshufb	%xmm11,%xmm7,%xmm7
-	vpaddq	-64(%rbp),%xmm2,%xmm10
-	vpaddq	-32(%rbp),%xmm3,%xmm11
-	vmovdqa	%xmm8,0(%rsp)
-	vpaddq	0(%rbp),%xmm4,%xmm8
-	vmovdqa	%xmm9,16(%rsp)
-	vpaddq	32(%rbp),%xmm5,%xmm9
-	vmovdqa	%xmm10,32(%rsp)
-	vpaddq	64(%rbp),%xmm6,%xmm10
-	vmovdqa	%xmm11,48(%rsp)
-	vpaddq	96(%rbp),%xmm7,%xmm11
-	vmovdqa	%xmm8,64(%rsp)
-	movq	%rax,%r14
-	vmovdqa	%xmm9,80(%rsp)
-	movq	%rbx,%rdi
-	vmovdqa	%xmm10,96(%rsp)
-	xorq	%rcx,%rdi
-	vmovdqa	%xmm11,112(%rsp)
-	movq	%r8,%r13
-	jmp	L$xop_00_47
-
-.p2align	4
-L$xop_00_47:
-	addq	$256,%rbp
-	vpalignr	$8,%xmm0,%xmm1,%xmm8
-	rorq	$23,%r13
-	movq	%r14,%rax
-	vpalignr	$8,%xmm4,%xmm5,%xmm11
-	movq	%r9,%r12
-	rorq	$5,%r14
-.byte	143,72,120,195,200,56
-	xorq	%r8,%r13
-	xorq	%r10,%r12
-	vpsrlq	$7,%xmm8,%xmm8
-	rorq	$4,%r13
-	xorq	%rax,%r14
-	vpaddq	%xmm11,%xmm0,%xmm0
-	andq	%r8,%r12
-	xorq	%r8,%r13
-	addq	0(%rsp),%r11
-	movq	%rax,%r15
-.byte	143,72,120,195,209,7
-	xorq	%r10,%r12
-	rorq	$6,%r14
-	vpxor	%xmm9,%xmm8,%xmm8
-	xorq	%rbx,%r15
-	addq	%r12,%r11
-	rorq	$14,%r13
-	andq	%r15,%rdi
-.byte	143,104,120,195,223,3
-	xorq	%rax,%r14
-	addq	%r13,%r11
-	vpxor	%xmm10,%xmm8,%xmm8
-	xorq	%rbx,%rdi
-	rorq	$28,%r14
-	vpsrlq	$6,%xmm7,%xmm10
-	addq	%r11,%rdx
-	addq	%rdi,%r11
-	vpaddq	%xmm8,%xmm0,%xmm0
-	movq	%rdx,%r13
-	addq	%r11,%r14
-.byte	143,72,120,195,203,42
-	rorq	$23,%r13
-	movq	%r14,%r11
-	vpxor	%xmm10,%xmm11,%xmm11
-	movq	%r8,%r12
-	rorq	$5,%r14
-	xorq	%rdx,%r13
-	xorq	%r9,%r12
-	vpxor	%xmm9,%xmm11,%xmm11
-	rorq	$4,%r13
-	xorq	%r11,%r14
-	andq	%rdx,%r12
-	xorq	%rdx,%r13
-	vpaddq	%xmm11,%xmm0,%xmm0
-	addq	8(%rsp),%r10
-	movq	%r11,%rdi
-	xorq	%r9,%r12
-	rorq	$6,%r14
-	vpaddq	-128(%rbp),%xmm0,%xmm10
-	xorq	%rax,%rdi
-	addq	%r12,%r10
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%r11,%r14
-	addq	%r13,%r10
-	xorq	%rax,%r15
-	rorq	$28,%r14
-	addq	%r10,%rcx
-	addq	%r15,%r10
-	movq	%rcx,%r13
-	addq	%r10,%r14
-	vmovdqa	%xmm10,0(%rsp)
-	vpalignr	$8,%xmm1,%xmm2,%xmm8
-	rorq	$23,%r13
-	movq	%r14,%r10
-	vpalignr	$8,%xmm5,%xmm6,%xmm11
-	movq	%rdx,%r12
-	rorq	$5,%r14
-.byte	143,72,120,195,200,56
-	xorq	%rcx,%r13
-	xorq	%r8,%r12
-	vpsrlq	$7,%xmm8,%xmm8
-	rorq	$4,%r13
-	xorq	%r10,%r14
-	vpaddq	%xmm11,%xmm1,%xmm1
-	andq	%rcx,%r12
-	xorq	%rcx,%r13
-	addq	16(%rsp),%r9
-	movq	%r10,%r15
-.byte	143,72,120,195,209,7
-	xorq	%r8,%r12
-	rorq	$6,%r14
-	vpxor	%xmm9,%xmm8,%xmm8
-	xorq	%r11,%r15
-	addq	%r12,%r9
-	rorq	$14,%r13
-	andq	%r15,%rdi
-.byte	143,104,120,195,216,3
-	xorq	%r10,%r14
-	addq	%r13,%r9
-	vpxor	%xmm10,%xmm8,%xmm8
-	xorq	%r11,%rdi
-	rorq	$28,%r14
-	vpsrlq	$6,%xmm0,%xmm10
-	addq	%r9,%rbx
-	addq	%rdi,%r9
-	vpaddq	%xmm8,%xmm1,%xmm1
-	movq	%rbx,%r13
-	addq	%r9,%r14
-.byte	143,72,120,195,203,42
-	rorq	$23,%r13
-	movq	%r14,%r9
-	vpxor	%xmm10,%xmm11,%xmm11
-	movq	%rcx,%r12
-	rorq	$5,%r14
-	xorq	%rbx,%r13
-	xorq	%rdx,%r12
-	vpxor	%xmm9,%xmm11,%xmm11
-	rorq	$4,%r13
-	xorq	%r9,%r14
-	andq	%rbx,%r12
-	xorq	%rbx,%r13
-	vpaddq	%xmm11,%xmm1,%xmm1
-	addq	24(%rsp),%r8
-	movq	%r9,%rdi
-	xorq	%rdx,%r12
-	rorq	$6,%r14
-	vpaddq	-96(%rbp),%xmm1,%xmm10
-	xorq	%r10,%rdi
-	addq	%r12,%r8
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%r9,%r14
-	addq	%r13,%r8
-	xorq	%r10,%r15
-	rorq	$28,%r14
-	addq	%r8,%rax
-	addq	%r15,%r8
-	movq	%rax,%r13
-	addq	%r8,%r14
-	vmovdqa	%xmm10,16(%rsp)
-	vpalignr	$8,%xmm2,%xmm3,%xmm8
-	rorq	$23,%r13
-	movq	%r14,%r8
-	vpalignr	$8,%xmm6,%xmm7,%xmm11
-	movq	%rbx,%r12
-	rorq	$5,%r14
-.byte	143,72,120,195,200,56
-	xorq	%rax,%r13
-	xorq	%rcx,%r12
-	vpsrlq	$7,%xmm8,%xmm8
-	rorq	$4,%r13
-	xorq	%r8,%r14
-	vpaddq	%xmm11,%xmm2,%xmm2
-	andq	%rax,%r12
-	xorq	%rax,%r13
-	addq	32(%rsp),%rdx
-	movq	%r8,%r15
-.byte	143,72,120,195,209,7
-	xorq	%rcx,%r12
-	rorq	$6,%r14
-	vpxor	%xmm9,%xmm8,%xmm8
-	xorq	%r9,%r15
-	addq	%r12,%rdx
-	rorq	$14,%r13
-	andq	%r15,%rdi
-.byte	143,104,120,195,217,3
-	xorq	%r8,%r14
-	addq	%r13,%rdx
-	vpxor	%xmm10,%xmm8,%xmm8
-	xorq	%r9,%rdi
-	rorq	$28,%r14
-	vpsrlq	$6,%xmm1,%xmm10
-	addq	%rdx,%r11
-	addq	%rdi,%rdx
-	vpaddq	%xmm8,%xmm2,%xmm2
-	movq	%r11,%r13
-	addq	%rdx,%r14
-.byte	143,72,120,195,203,42
-	rorq	$23,%r13
-	movq	%r14,%rdx
-	vpxor	%xmm10,%xmm11,%xmm11
-	movq	%rax,%r12
-	rorq	$5,%r14
-	xorq	%r11,%r13
-	xorq	%rbx,%r12
-	vpxor	%xmm9,%xmm11,%xmm11
-	rorq	$4,%r13
-	xorq	%rdx,%r14
-	andq	%r11,%r12
-	xorq	%r11,%r13
-	vpaddq	%xmm11,%xmm2,%xmm2
-	addq	40(%rsp),%rcx
-	movq	%rdx,%rdi
-	xorq	%rbx,%r12
-	rorq	$6,%r14
-	vpaddq	-64(%rbp),%xmm2,%xmm10
-	xorq	%r8,%rdi
-	addq	%r12,%rcx
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%rdx,%r14
-	addq	%r13,%rcx
-	xorq	%r8,%r15
-	rorq	$28,%r14
-	addq	%rcx,%r10
-	addq	%r15,%rcx
-	movq	%r10,%r13
-	addq	%rcx,%r14
-	vmovdqa	%xmm10,32(%rsp)
-	vpalignr	$8,%xmm3,%xmm4,%xmm8
-	rorq	$23,%r13
-	movq	%r14,%rcx
-	vpalignr	$8,%xmm7,%xmm0,%xmm11
-	movq	%r11,%r12
-	rorq	$5,%r14
-.byte	143,72,120,195,200,56
-	xorq	%r10,%r13
-	xorq	%rax,%r12
-	vpsrlq	$7,%xmm8,%xmm8
-	rorq	$4,%r13
-	xorq	%rcx,%r14
-	vpaddq	%xmm11,%xmm3,%xmm3
-	andq	%r10,%r12
-	xorq	%r10,%r13
-	addq	48(%rsp),%rbx
-	movq	%rcx,%r15
-.byte	143,72,120,195,209,7
-	xorq	%rax,%r12
-	rorq	$6,%r14
-	vpxor	%xmm9,%xmm8,%xmm8
-	xorq	%rdx,%r15
-	addq	%r12,%rbx
-	rorq	$14,%r13
-	andq	%r15,%rdi
-.byte	143,104,120,195,218,3
-	xorq	%rcx,%r14
-	addq	%r13,%rbx
-	vpxor	%xmm10,%xmm8,%xmm8
-	xorq	%rdx,%rdi
-	rorq	$28,%r14
-	vpsrlq	$6,%xmm2,%xmm10
-	addq	%rbx,%r9
-	addq	%rdi,%rbx
-	vpaddq	%xmm8,%xmm3,%xmm3
-	movq	%r9,%r13
-	addq	%rbx,%r14
-.byte	143,72,120,195,203,42
-	rorq	$23,%r13
-	movq	%r14,%rbx
-	vpxor	%xmm10,%xmm11,%xmm11
-	movq	%r10,%r12
-	rorq	$5,%r14
-	xorq	%r9,%r13
-	xorq	%r11,%r12
-	vpxor	%xmm9,%xmm11,%xmm11
-	rorq	$4,%r13
-	xorq	%rbx,%r14
-	andq	%r9,%r12
-	xorq	%r9,%r13
-	vpaddq	%xmm11,%xmm3,%xmm3
-	addq	56(%rsp),%rax
-	movq	%rbx,%rdi
-	xorq	%r11,%r12
-	rorq	$6,%r14
-	vpaddq	-32(%rbp),%xmm3,%xmm10
-	xorq	%rcx,%rdi
-	addq	%r12,%rax
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%rbx,%r14
-	addq	%r13,%rax
-	xorq	%rcx,%r15
-	rorq	$28,%r14
-	addq	%rax,%r8
-	addq	%r15,%rax
-	movq	%r8,%r13
-	addq	%rax,%r14
-	vmovdqa	%xmm10,48(%rsp)
-	vpalignr	$8,%xmm4,%xmm5,%xmm8
-	rorq	$23,%r13
-	movq	%r14,%rax
-	vpalignr	$8,%xmm0,%xmm1,%xmm11
-	movq	%r9,%r12
-	rorq	$5,%r14
-.byte	143,72,120,195,200,56
-	xorq	%r8,%r13
-	xorq	%r10,%r12
-	vpsrlq	$7,%xmm8,%xmm8
-	rorq	$4,%r13
-	xorq	%rax,%r14
-	vpaddq	%xmm11,%xmm4,%xmm4
-	andq	%r8,%r12
-	xorq	%r8,%r13
-	addq	64(%rsp),%r11
-	movq	%rax,%r15
-.byte	143,72,120,195,209,7
-	xorq	%r10,%r12
-	rorq	$6,%r14
-	vpxor	%xmm9,%xmm8,%xmm8
-	xorq	%rbx,%r15
-	addq	%r12,%r11
-	rorq	$14,%r13
-	andq	%r15,%rdi
-.byte	143,104,120,195,219,3
-	xorq	%rax,%r14
-	addq	%r13,%r11
-	vpxor	%xmm10,%xmm8,%xmm8
-	xorq	%rbx,%rdi
-	rorq	$28,%r14
-	vpsrlq	$6,%xmm3,%xmm10
-	addq	%r11,%rdx
-	addq	%rdi,%r11
-	vpaddq	%xmm8,%xmm4,%xmm4
-	movq	%rdx,%r13
-	addq	%r11,%r14
-.byte	143,72,120,195,203,42
-	rorq	$23,%r13
-	movq	%r14,%r11
-	vpxor	%xmm10,%xmm11,%xmm11
-	movq	%r8,%r12
-	rorq	$5,%r14
-	xorq	%rdx,%r13
-	xorq	%r9,%r12
-	vpxor	%xmm9,%xmm11,%xmm11
-	rorq	$4,%r13
-	xorq	%r11,%r14
-	andq	%rdx,%r12
-	xorq	%rdx,%r13
-	vpaddq	%xmm11,%xmm4,%xmm4
-	addq	72(%rsp),%r10
-	movq	%r11,%rdi
-	xorq	%r9,%r12
-	rorq	$6,%r14
-	vpaddq	0(%rbp),%xmm4,%xmm10
-	xorq	%rax,%rdi
-	addq	%r12,%r10
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%r11,%r14
-	addq	%r13,%r10
-	xorq	%rax,%r15
-	rorq	$28,%r14
-	addq	%r10,%rcx
-	addq	%r15,%r10
-	movq	%rcx,%r13
-	addq	%r10,%r14
-	vmovdqa	%xmm10,64(%rsp)
-	vpalignr	$8,%xmm5,%xmm6,%xmm8
-	rorq	$23,%r13
-	movq	%r14,%r10
-	vpalignr	$8,%xmm1,%xmm2,%xmm11
-	movq	%rdx,%r12
-	rorq	$5,%r14
-.byte	143,72,120,195,200,56
-	xorq	%rcx,%r13
-	xorq	%r8,%r12
-	vpsrlq	$7,%xmm8,%xmm8
-	rorq	$4,%r13
-	xorq	%r10,%r14
-	vpaddq	%xmm11,%xmm5,%xmm5
-	andq	%rcx,%r12
-	xorq	%rcx,%r13
-	addq	80(%rsp),%r9
-	movq	%r10,%r15
-.byte	143,72,120,195,209,7
-	xorq	%r8,%r12
-	rorq	$6,%r14
-	vpxor	%xmm9,%xmm8,%xmm8
-	xorq	%r11,%r15
-	addq	%r12,%r9
-	rorq	$14,%r13
-	andq	%r15,%rdi
-.byte	143,104,120,195,220,3
-	xorq	%r10,%r14
-	addq	%r13,%r9
-	vpxor	%xmm10,%xmm8,%xmm8
-	xorq	%r11,%rdi
-	rorq	$28,%r14
-	vpsrlq	$6,%xmm4,%xmm10
-	addq	%r9,%rbx
-	addq	%rdi,%r9
-	vpaddq	%xmm8,%xmm5,%xmm5
-	movq	%rbx,%r13
-	addq	%r9,%r14
-.byte	143,72,120,195,203,42
-	rorq	$23,%r13
-	movq	%r14,%r9
-	vpxor	%xmm10,%xmm11,%xmm11
-	movq	%rcx,%r12
-	rorq	$5,%r14
-	xorq	%rbx,%r13
-	xorq	%rdx,%r12
-	vpxor	%xmm9,%xmm11,%xmm11
-	rorq	$4,%r13
-	xorq	%r9,%r14
-	andq	%rbx,%r12
-	xorq	%rbx,%r13
-	vpaddq	%xmm11,%xmm5,%xmm5
-	addq	88(%rsp),%r8
-	movq	%r9,%rdi
-	xorq	%rdx,%r12
-	rorq	$6,%r14
-	vpaddq	32(%rbp),%xmm5,%xmm10
-	xorq	%r10,%rdi
-	addq	%r12,%r8
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%r9,%r14
-	addq	%r13,%r8
-	xorq	%r10,%r15
-	rorq	$28,%r14
-	addq	%r8,%rax
-	addq	%r15,%r8
-	movq	%rax,%r13
-	addq	%r8,%r14
-	vmovdqa	%xmm10,80(%rsp)
-	vpalignr	$8,%xmm6,%xmm7,%xmm8
-	rorq	$23,%r13
-	movq	%r14,%r8
-	vpalignr	$8,%xmm2,%xmm3,%xmm11
-	movq	%rbx,%r12
-	rorq	$5,%r14
-.byte	143,72,120,195,200,56
-	xorq	%rax,%r13
-	xorq	%rcx,%r12
-	vpsrlq	$7,%xmm8,%xmm8
-	rorq	$4,%r13
-	xorq	%r8,%r14
-	vpaddq	%xmm11,%xmm6,%xmm6
-	andq	%rax,%r12
-	xorq	%rax,%r13
-	addq	96(%rsp),%rdx
-	movq	%r8,%r15
-.byte	143,72,120,195,209,7
-	xorq	%rcx,%r12
-	rorq	$6,%r14
-	vpxor	%xmm9,%xmm8,%xmm8
-	xorq	%r9,%r15
-	addq	%r12,%rdx
-	rorq	$14,%r13
-	andq	%r15,%rdi
-.byte	143,104,120,195,221,3
-	xorq	%r8,%r14
-	addq	%r13,%rdx
-	vpxor	%xmm10,%xmm8,%xmm8
-	xorq	%r9,%rdi
-	rorq	$28,%r14
-	vpsrlq	$6,%xmm5,%xmm10
-	addq	%rdx,%r11
-	addq	%rdi,%rdx
-	vpaddq	%xmm8,%xmm6,%xmm6
-	movq	%r11,%r13
-	addq	%rdx,%r14
-.byte	143,72,120,195,203,42
-	rorq	$23,%r13
-	movq	%r14,%rdx
-	vpxor	%xmm10,%xmm11,%xmm11
-	movq	%rax,%r12
-	rorq	$5,%r14
-	xorq	%r11,%r13
-	xorq	%rbx,%r12
-	vpxor	%xmm9,%xmm11,%xmm11
-	rorq	$4,%r13
-	xorq	%rdx,%r14
-	andq	%r11,%r12
-	xorq	%r11,%r13
-	vpaddq	%xmm11,%xmm6,%xmm6
-	addq	104(%rsp),%rcx
-	movq	%rdx,%rdi
-	xorq	%rbx,%r12
-	rorq	$6,%r14
-	vpaddq	64(%rbp),%xmm6,%xmm10
-	xorq	%r8,%rdi
-	addq	%r12,%rcx
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%rdx,%r14
-	addq	%r13,%rcx
-	xorq	%r8,%r15
-	rorq	$28,%r14
-	addq	%rcx,%r10
-	addq	%r15,%rcx
-	movq	%r10,%r13
-	addq	%rcx,%r14
-	vmovdqa	%xmm10,96(%rsp)
-	vpalignr	$8,%xmm7,%xmm0,%xmm8
-	rorq	$23,%r13
-	movq	%r14,%rcx
-	vpalignr	$8,%xmm3,%xmm4,%xmm11
-	movq	%r11,%r12
-	rorq	$5,%r14
-.byte	143,72,120,195,200,56
-	xorq	%r10,%r13
-	xorq	%rax,%r12
-	vpsrlq	$7,%xmm8,%xmm8
-	rorq	$4,%r13
-	xorq	%rcx,%r14
-	vpaddq	%xmm11,%xmm7,%xmm7
-	andq	%r10,%r12
-	xorq	%r10,%r13
-	addq	112(%rsp),%rbx
-	movq	%rcx,%r15
-.byte	143,72,120,195,209,7
-	xorq	%rax,%r12
-	rorq	$6,%r14
-	vpxor	%xmm9,%xmm8,%xmm8
-	xorq	%rdx,%r15
-	addq	%r12,%rbx
-	rorq	$14,%r13
-	andq	%r15,%rdi
-.byte	143,104,120,195,222,3
-	xorq	%rcx,%r14
-	addq	%r13,%rbx
-	vpxor	%xmm10,%xmm8,%xmm8
-	xorq	%rdx,%rdi
-	rorq	$28,%r14
-	vpsrlq	$6,%xmm6,%xmm10
-	addq	%rbx,%r9
-	addq	%rdi,%rbx
-	vpaddq	%xmm8,%xmm7,%xmm7
-	movq	%r9,%r13
-	addq	%rbx,%r14
-.byte	143,72,120,195,203,42
-	rorq	$23,%r13
-	movq	%r14,%rbx
-	vpxor	%xmm10,%xmm11,%xmm11
-	movq	%r10,%r12
-	rorq	$5,%r14
-	xorq	%r9,%r13
-	xorq	%r11,%r12
-	vpxor	%xmm9,%xmm11,%xmm11
-	rorq	$4,%r13
-	xorq	%rbx,%r14
-	andq	%r9,%r12
-	xorq	%r9,%r13
-	vpaddq	%xmm11,%xmm7,%xmm7
-	addq	120(%rsp),%rax
-	movq	%rbx,%rdi
-	xorq	%r11,%r12
-	rorq	$6,%r14
-	vpaddq	96(%rbp),%xmm7,%xmm10
-	xorq	%rcx,%rdi
-	addq	%r12,%rax
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%rbx,%r14
-	addq	%r13,%rax
-	xorq	%rcx,%r15
-	rorq	$28,%r14
-	addq	%rax,%r8
-	addq	%r15,%rax
-	movq	%r8,%r13
-	addq	%rax,%r14
-	vmovdqa	%xmm10,112(%rsp)
-	cmpb	$0,135(%rbp)
-	jne	L$xop_00_47
-	rorq	$23,%r13
-	movq	%r14,%rax
-	movq	%r9,%r12
-	rorq	$5,%r14
-	xorq	%r8,%r13
-	xorq	%r10,%r12
-	rorq	$4,%r13
-	xorq	%rax,%r14
-	andq	%r8,%r12
-	xorq	%r8,%r13
-	addq	0(%rsp),%r11
-	movq	%rax,%r15
-	xorq	%r10,%r12
-	rorq	$6,%r14
-	xorq	%rbx,%r15
-	addq	%r12,%r11
-	rorq	$14,%r13
-	andq	%r15,%rdi
-	xorq	%rax,%r14
-	addq	%r13,%r11
-	xorq	%rbx,%rdi
-	rorq	$28,%r14
-	addq	%r11,%rdx
-	addq	%rdi,%r11
-	movq	%rdx,%r13
-	addq	%r11,%r14
-	rorq	$23,%r13
-	movq	%r14,%r11
-	movq	%r8,%r12
-	rorq	$5,%r14
-	xorq	%rdx,%r13
-	xorq	%r9,%r12
-	rorq	$4,%r13
-	xorq	%r11,%r14
-	andq	%rdx,%r12
-	xorq	%rdx,%r13
-	addq	8(%rsp),%r10
-	movq	%r11,%rdi
-	xorq	%r9,%r12
-	rorq	$6,%r14
-	xorq	%rax,%rdi
-	addq	%r12,%r10
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%r11,%r14
-	addq	%r13,%r10
-	xorq	%rax,%r15
-	rorq	$28,%r14
-	addq	%r10,%rcx
-	addq	%r15,%r10
-	movq	%rcx,%r13
-	addq	%r10,%r14
-	rorq	$23,%r13
-	movq	%r14,%r10
-	movq	%rdx,%r12
-	rorq	$5,%r14
-	xorq	%rcx,%r13
-	xorq	%r8,%r12
-	rorq	$4,%r13
-	xorq	%r10,%r14
-	andq	%rcx,%r12
-	xorq	%rcx,%r13
-	addq	16(%rsp),%r9
-	movq	%r10,%r15
-	xorq	%r8,%r12
-	rorq	$6,%r14
-	xorq	%r11,%r15
-	addq	%r12,%r9
-	rorq	$14,%r13
-	andq	%r15,%rdi
-	xorq	%r10,%r14
-	addq	%r13,%r9
-	xorq	%r11,%rdi
-	rorq	$28,%r14
-	addq	%r9,%rbx
-	addq	%rdi,%r9
-	movq	%rbx,%r13
-	addq	%r9,%r14
-	rorq	$23,%r13
-	movq	%r14,%r9
-	movq	%rcx,%r12
-	rorq	$5,%r14
-	xorq	%rbx,%r13
-	xorq	%rdx,%r12
-	rorq	$4,%r13
-	xorq	%r9,%r14
-	andq	%rbx,%r12
-	xorq	%rbx,%r13
-	addq	24(%rsp),%r8
-	movq	%r9,%rdi
-	xorq	%rdx,%r12
-	rorq	$6,%r14
-	xorq	%r10,%rdi
-	addq	%r12,%r8
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%r9,%r14
-	addq	%r13,%r8
-	xorq	%r10,%r15
-	rorq	$28,%r14
-	addq	%r8,%rax
-	addq	%r15,%r8
-	movq	%rax,%r13
-	addq	%r8,%r14
-	rorq	$23,%r13
-	movq	%r14,%r8
-	movq	%rbx,%r12
-	rorq	$5,%r14
-	xorq	%rax,%r13
-	xorq	%rcx,%r12
-	rorq	$4,%r13
-	xorq	%r8,%r14
-	andq	%rax,%r12
-	xorq	%rax,%r13
-	addq	32(%rsp),%rdx
-	movq	%r8,%r15
-	xorq	%rcx,%r12
-	rorq	$6,%r14
-	xorq	%r9,%r15
-	addq	%r12,%rdx
-	rorq	$14,%r13
-	andq	%r15,%rdi
-	xorq	%r8,%r14
-	addq	%r13,%rdx
-	xorq	%r9,%rdi
-	rorq	$28,%r14
-	addq	%rdx,%r11
-	addq	%rdi,%rdx
-	movq	%r11,%r13
-	addq	%rdx,%r14
-	rorq	$23,%r13
-	movq	%r14,%rdx
-	movq	%rax,%r12
-	rorq	$5,%r14
-	xorq	%r11,%r13
-	xorq	%rbx,%r12
-	rorq	$4,%r13
-	xorq	%rdx,%r14
-	andq	%r11,%r12
-	xorq	%r11,%r13
-	addq	40(%rsp),%rcx
-	movq	%rdx,%rdi
-	xorq	%rbx,%r12
-	rorq	$6,%r14
-	xorq	%r8,%rdi
-	addq	%r12,%rcx
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%rdx,%r14
-	addq	%r13,%rcx
-	xorq	%r8,%r15
-	rorq	$28,%r14
-	addq	%rcx,%r10
-	addq	%r15,%rcx
-	movq	%r10,%r13
-	addq	%rcx,%r14
-	rorq	$23,%r13
-	movq	%r14,%rcx
-	movq	%r11,%r12
-	rorq	$5,%r14
-	xorq	%r10,%r13
-	xorq	%rax,%r12
-	rorq	$4,%r13
-	xorq	%rcx,%r14
-	andq	%r10,%r12
-	xorq	%r10,%r13
-	addq	48(%rsp),%rbx
-	movq	%rcx,%r15
-	xorq	%rax,%r12
-	rorq	$6,%r14
-	xorq	%rdx,%r15
-	addq	%r12,%rbx
-	rorq	$14,%r13
-	andq	%r15,%rdi
-	xorq	%rcx,%r14
-	addq	%r13,%rbx
-	xorq	%rdx,%rdi
-	rorq	$28,%r14
-	addq	%rbx,%r9
-	addq	%rdi,%rbx
-	movq	%r9,%r13
-	addq	%rbx,%r14
-	rorq	$23,%r13
-	movq	%r14,%rbx
-	movq	%r10,%r12
-	rorq	$5,%r14
-	xorq	%r9,%r13
-	xorq	%r11,%r12
-	rorq	$4,%r13
-	xorq	%rbx,%r14
-	andq	%r9,%r12
-	xorq	%r9,%r13
-	addq	56(%rsp),%rax
-	movq	%rbx,%rdi
-	xorq	%r11,%r12
-	rorq	$6,%r14
-	xorq	%rcx,%rdi
-	addq	%r12,%rax
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%rbx,%r14
-	addq	%r13,%rax
-	xorq	%rcx,%r15
-	rorq	$28,%r14
-	addq	%rax,%r8
-	addq	%r15,%rax
-	movq	%r8,%r13
-	addq	%rax,%r14
-	rorq	$23,%r13
-	movq	%r14,%rax
-	movq	%r9,%r12
-	rorq	$5,%r14
-	xorq	%r8,%r13
-	xorq	%r10,%r12
-	rorq	$4,%r13
-	xorq	%rax,%r14
-	andq	%r8,%r12
-	xorq	%r8,%r13
-	addq	64(%rsp),%r11
-	movq	%rax,%r15
-	xorq	%r10,%r12
-	rorq	$6,%r14
-	xorq	%rbx,%r15
-	addq	%r12,%r11
-	rorq	$14,%r13
-	andq	%r15,%rdi
-	xorq	%rax,%r14
-	addq	%r13,%r11
-	xorq	%rbx,%rdi
-	rorq	$28,%r14
-	addq	%r11,%rdx
-	addq	%rdi,%r11
-	movq	%rdx,%r13
-	addq	%r11,%r14
-	rorq	$23,%r13
-	movq	%r14,%r11
-	movq	%r8,%r12
-	rorq	$5,%r14
-	xorq	%rdx,%r13
-	xorq	%r9,%r12
-	rorq	$4,%r13
-	xorq	%r11,%r14
-	andq	%rdx,%r12
-	xorq	%rdx,%r13
-	addq	72(%rsp),%r10
-	movq	%r11,%rdi
-	xorq	%r9,%r12
-	rorq	$6,%r14
-	xorq	%rax,%rdi
-	addq	%r12,%r10
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%r11,%r14
-	addq	%r13,%r10
-	xorq	%rax,%r15
-	rorq	$28,%r14
-	addq	%r10,%rcx
-	addq	%r15,%r10
-	movq	%rcx,%r13
-	addq	%r10,%r14
-	rorq	$23,%r13
-	movq	%r14,%r10
-	movq	%rdx,%r12
-	rorq	$5,%r14
-	xorq	%rcx,%r13
-	xorq	%r8,%r12
-	rorq	$4,%r13
-	xorq	%r10,%r14
-	andq	%rcx,%r12
-	xorq	%rcx,%r13
-	addq	80(%rsp),%r9
-	movq	%r10,%r15
-	xorq	%r8,%r12
-	rorq	$6,%r14
-	xorq	%r11,%r15
-	addq	%r12,%r9
-	rorq	$14,%r13
-	andq	%r15,%rdi
-	xorq	%r10,%r14
-	addq	%r13,%r9
-	xorq	%r11,%rdi
-	rorq	$28,%r14
-	addq	%r9,%rbx
-	addq	%rdi,%r9
-	movq	%rbx,%r13
-	addq	%r9,%r14
-	rorq	$23,%r13
-	movq	%r14,%r9
-	movq	%rcx,%r12
-	rorq	$5,%r14
-	xorq	%rbx,%r13
-	xorq	%rdx,%r12
-	rorq	$4,%r13
-	xorq	%r9,%r14
-	andq	%rbx,%r12
-	xorq	%rbx,%r13
-	addq	88(%rsp),%r8
-	movq	%r9,%rdi
-	xorq	%rdx,%r12
-	rorq	$6,%r14
-	xorq	%r10,%rdi
-	addq	%r12,%r8
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%r9,%r14
-	addq	%r13,%r8
-	xorq	%r10,%r15
-	rorq	$28,%r14
-	addq	%r8,%rax
-	addq	%r15,%r8
-	movq	%rax,%r13
-	addq	%r8,%r14
-	rorq	$23,%r13
-	movq	%r14,%r8
-	movq	%rbx,%r12
-	rorq	$5,%r14
-	xorq	%rax,%r13
-	xorq	%rcx,%r12
-	rorq	$4,%r13
-	xorq	%r8,%r14
-	andq	%rax,%r12
-	xorq	%rax,%r13
-	addq	96(%rsp),%rdx
-	movq	%r8,%r15
-	xorq	%rcx,%r12
-	rorq	$6,%r14
-	xorq	%r9,%r15
-	addq	%r12,%rdx
-	rorq	$14,%r13
-	andq	%r15,%rdi
-	xorq	%r8,%r14
-	addq	%r13,%rdx
-	xorq	%r9,%rdi
-	rorq	$28,%r14
-	addq	%rdx,%r11
-	addq	%rdi,%rdx
-	movq	%r11,%r13
-	addq	%rdx,%r14
-	rorq	$23,%r13
-	movq	%r14,%rdx
-	movq	%rax,%r12
-	rorq	$5,%r14
-	xorq	%r11,%r13
-	xorq	%rbx,%r12
-	rorq	$4,%r13
-	xorq	%rdx,%r14
-	andq	%r11,%r12
-	xorq	%r11,%r13
-	addq	104(%rsp),%rcx
-	movq	%rdx,%rdi
-	xorq	%rbx,%r12
-	rorq	$6,%r14
-	xorq	%r8,%rdi
-	addq	%r12,%rcx
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%rdx,%r14
-	addq	%r13,%rcx
-	xorq	%r8,%r15
-	rorq	$28,%r14
-	addq	%rcx,%r10
-	addq	%r15,%rcx
-	movq	%r10,%r13
-	addq	%rcx,%r14
-	rorq	$23,%r13
-	movq	%r14,%rcx
-	movq	%r11,%r12
-	rorq	$5,%r14
-	xorq	%r10,%r13
-	xorq	%rax,%r12
-	rorq	$4,%r13
-	xorq	%rcx,%r14
-	andq	%r10,%r12
-	xorq	%r10,%r13
-	addq	112(%rsp),%rbx
-	movq	%rcx,%r15
-	xorq	%rax,%r12
-	rorq	$6,%r14
-	xorq	%rdx,%r15
-	addq	%r12,%rbx
-	rorq	$14,%r13
-	andq	%r15,%rdi
-	xorq	%rcx,%r14
-	addq	%r13,%rbx
-	xorq	%rdx,%rdi
-	rorq	$28,%r14
-	addq	%rbx,%r9
-	addq	%rdi,%rbx
-	movq	%r9,%r13
-	addq	%rbx,%r14
-	rorq	$23,%r13
-	movq	%r14,%rbx
-	movq	%r10,%r12
-	rorq	$5,%r14
-	xorq	%r9,%r13
-	xorq	%r11,%r12
-	rorq	$4,%r13
-	xorq	%rbx,%r14
-	andq	%r9,%r12
-	xorq	%r9,%r13
-	addq	120(%rsp),%rax
-	movq	%rbx,%rdi
-	xorq	%r11,%r12
-	rorq	$6,%r14
-	xorq	%rcx,%rdi
-	addq	%r12,%rax
-	rorq	$14,%r13
-	andq	%rdi,%r15
-	xorq	%rbx,%r14
-	addq	%r13,%rax
-	xorq	%rcx,%r15
-	rorq	$28,%r14
-	addq	%rax,%r8
-	addq	%r15,%rax
-	movq	%r8,%r13
-	addq	%rax,%r14
-	movq	128+0(%rsp),%rdi
-	movq	%r14,%rax
-
-	addq	0(%rdi),%rax
-	leaq	128(%rsi),%rsi
-	addq	8(%rdi),%rbx
-	addq	16(%rdi),%rcx
-	addq	24(%rdi),%rdx
-	addq	32(%rdi),%r8
-	addq	40(%rdi),%r9
-	addq	48(%rdi),%r10
-	addq	56(%rdi),%r11
-
-	cmpq	128+16(%rsp),%rsi
-
-	movq	%rax,0(%rdi)
-	movq	%rbx,8(%rdi)
-	movq	%rcx,16(%rdi)
-	movq	%rdx,24(%rdi)
-	movq	%r8,32(%rdi)
-	movq	%r9,40(%rdi)
-	movq	%r10,48(%rdi)
-	movq	%r11,56(%rdi)
-	jb	L$loop_xop
-
-	movq	152(%rsp),%rsi
-
-	vzeroupper
-	movq	-48(%rsi),%r15
-
-	movq	-40(%rsi),%r14
-
-	movq	-32(%rsi),%r13
-
-	movq	-24(%rsi),%r12
-
-	movq	-16(%rsi),%rbp
-
-	movq	-8(%rsi),%rbx
-
-	leaq	(%rsi),%rsp
-
-L$epilogue_xop:
-	.byte	0xf3,0xc3
-
-
-
-.p2align	6
 sha512_block_data_order_avx:
 
 L$avx_shortcut:
diff --git a/third_party/boringssl/win-x86_64/crypto/fipsmodule/bsaes-x86_64.asm b/third_party/boringssl/win-x86_64/crypto/fipsmodule/bsaes-x86_64.asm
index 7dc0c5a..923c9fa 100644
--- a/third_party/boringssl/win-x86_64/crypto/fipsmodule/bsaes-x86_64.asm
+++ b/third_party/boringssl/win-x86_64/crypto/fipsmodule/bsaes-x86_64.asm
@@ -1609,1020 +1609,6 @@
 	DB	0F3h,0C3h		;repret
 
 
-global	bsaes_xts_encrypt
-
-ALIGN	16
-bsaes_xts_encrypt:
-
-	mov	rax,rsp
-$L$xts_enc_prologue:
-	push	rbp
-
-	push	rbx
-
-	push	r12
-
-	push	r13
-
-	push	r14
-
-	push	r15
-
-	lea	rsp,[((-72))+rsp]
-
-	mov	r10,QWORD[160+rsp]
-	mov	r11,QWORD[168+rsp]
-	lea	rsp,[((-160))+rsp]
-	movaps	XMMWORD[64+rsp],xmm6
-	movaps	XMMWORD[80+rsp],xmm7
-	movaps	XMMWORD[96+rsp],xmm8
-	movaps	XMMWORD[112+rsp],xmm9
-	movaps	XMMWORD[128+rsp],xmm10
-	movaps	XMMWORD[144+rsp],xmm11
-	movaps	XMMWORD[160+rsp],xmm12
-	movaps	XMMWORD[176+rsp],xmm13
-	movaps	XMMWORD[192+rsp],xmm14
-	movaps	XMMWORD[208+rsp],xmm15
-$L$xts_enc_body:
-	mov	rbp,rsp
-
-	mov	r12,rcx
-	mov	r13,rdx
-	mov	r14,r8
-	mov	r15,r9
-
-	lea	rcx,[r11]
-	lea	rdx,[32+rbp]
-	lea	r8,[r10]
-	call	aes_nohw_encrypt
-
-	mov	eax,DWORD[240+r15]
-	mov	rbx,r14
-
-	mov	edx,eax
-	shl	rax,7
-	sub	rax,96
-	sub	rsp,rax
-
-	mov	rax,rsp
-	mov	rcx,r15
-	mov	r10d,edx
-	call	_bsaes_key_convert
-	pxor	xmm7,xmm6
-	movdqa	XMMWORD[rax],xmm7
-
-	and	r14,-16
-	sub	rsp,0x80
-	movdqa	xmm6,XMMWORD[32+rbp]
-
-	pxor	xmm14,xmm14
-	movdqa	xmm12,XMMWORD[$L$xts_magic]
-	pcmpgtd	xmm14,xmm6
-
-	sub	r14,0x80
-	jc	NEAR $L$xts_enc_short
-	jmp	NEAR $L$xts_enc_loop
-
-ALIGN	16
-$L$xts_enc_loop:
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm15,xmm6
-	movdqa	XMMWORD[rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm0,xmm6
-	movdqa	XMMWORD[16+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm7,XMMWORD[r12]
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm1,xmm6
-	movdqa	XMMWORD[32+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm8,XMMWORD[16+r12]
-	pxor	xmm15,xmm7
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm2,xmm6
-	movdqa	XMMWORD[48+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm9,XMMWORD[32+r12]
-	pxor	xmm0,xmm8
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm3,xmm6
-	movdqa	XMMWORD[64+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm10,XMMWORD[48+r12]
-	pxor	xmm1,xmm9
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm4,xmm6
-	movdqa	XMMWORD[80+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm11,XMMWORD[64+r12]
-	pxor	xmm2,xmm10
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm5,xmm6
-	movdqa	XMMWORD[96+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm12,XMMWORD[80+r12]
-	pxor	xmm3,xmm11
-	movdqu	xmm13,XMMWORD[96+r12]
-	pxor	xmm4,xmm12
-	movdqu	xmm14,XMMWORD[112+r12]
-	lea	r12,[128+r12]
-	movdqa	XMMWORD[112+rsp],xmm6
-	pxor	xmm5,xmm13
-	lea	rax,[128+rsp]
-	pxor	xmm6,xmm14
-	mov	r10d,edx
-
-	call	_bsaes_encrypt8
-
-	pxor	xmm15,XMMWORD[rsp]
-	pxor	xmm0,XMMWORD[16+rsp]
-	movdqu	XMMWORD[r13],xmm15
-	pxor	xmm3,XMMWORD[32+rsp]
-	movdqu	XMMWORD[16+r13],xmm0
-	pxor	xmm5,XMMWORD[48+rsp]
-	movdqu	XMMWORD[32+r13],xmm3
-	pxor	xmm2,XMMWORD[64+rsp]
-	movdqu	XMMWORD[48+r13],xmm5
-	pxor	xmm6,XMMWORD[80+rsp]
-	movdqu	XMMWORD[64+r13],xmm2
-	pxor	xmm1,XMMWORD[96+rsp]
-	movdqu	XMMWORD[80+r13],xmm6
-	pxor	xmm4,XMMWORD[112+rsp]
-	movdqu	XMMWORD[96+r13],xmm1
-	movdqu	XMMWORD[112+r13],xmm4
-	lea	r13,[128+r13]
-
-	movdqa	xmm6,XMMWORD[112+rsp]
-	pxor	xmm14,xmm14
-	movdqa	xmm12,XMMWORD[$L$xts_magic]
-	pcmpgtd	xmm14,xmm6
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-
-	sub	r14,0x80
-	jnc	NEAR $L$xts_enc_loop
-
-$L$xts_enc_short:
-	add	r14,0x80
-	jz	NEAR $L$xts_enc_done
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm15,xmm6
-	movdqa	XMMWORD[rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm0,xmm6
-	movdqa	XMMWORD[16+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm7,XMMWORD[r12]
-	cmp	r14,16
-	je	NEAR $L$xts_enc_1
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm1,xmm6
-	movdqa	XMMWORD[32+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm8,XMMWORD[16+r12]
-	cmp	r14,32
-	je	NEAR $L$xts_enc_2
-	pxor	xmm15,xmm7
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm2,xmm6
-	movdqa	XMMWORD[48+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm9,XMMWORD[32+r12]
-	cmp	r14,48
-	je	NEAR $L$xts_enc_3
-	pxor	xmm0,xmm8
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm3,xmm6
-	movdqa	XMMWORD[64+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm10,XMMWORD[48+r12]
-	cmp	r14,64
-	je	NEAR $L$xts_enc_4
-	pxor	xmm1,xmm9
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm4,xmm6
-	movdqa	XMMWORD[80+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm11,XMMWORD[64+r12]
-	cmp	r14,80
-	je	NEAR $L$xts_enc_5
-	pxor	xmm2,xmm10
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm5,xmm6
-	movdqa	XMMWORD[96+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm12,XMMWORD[80+r12]
-	cmp	r14,96
-	je	NEAR $L$xts_enc_6
-	pxor	xmm3,xmm11
-	movdqu	xmm13,XMMWORD[96+r12]
-	pxor	xmm4,xmm12
-	movdqa	XMMWORD[112+rsp],xmm6
-	lea	r12,[112+r12]
-	pxor	xmm5,xmm13
-	lea	rax,[128+rsp]
-	mov	r10d,edx
-
-	call	_bsaes_encrypt8
-
-	pxor	xmm15,XMMWORD[rsp]
-	pxor	xmm0,XMMWORD[16+rsp]
-	movdqu	XMMWORD[r13],xmm15
-	pxor	xmm3,XMMWORD[32+rsp]
-	movdqu	XMMWORD[16+r13],xmm0
-	pxor	xmm5,XMMWORD[48+rsp]
-	movdqu	XMMWORD[32+r13],xmm3
-	pxor	xmm2,XMMWORD[64+rsp]
-	movdqu	XMMWORD[48+r13],xmm5
-	pxor	xmm6,XMMWORD[80+rsp]
-	movdqu	XMMWORD[64+r13],xmm2
-	pxor	xmm1,XMMWORD[96+rsp]
-	movdqu	XMMWORD[80+r13],xmm6
-	movdqu	XMMWORD[96+r13],xmm1
-	lea	r13,[112+r13]
-
-	movdqa	xmm6,XMMWORD[112+rsp]
-	jmp	NEAR $L$xts_enc_done
-ALIGN	16
-$L$xts_enc_6:
-	pxor	xmm3,xmm11
-	lea	r12,[96+r12]
-	pxor	xmm4,xmm12
-	lea	rax,[128+rsp]
-	mov	r10d,edx
-
-	call	_bsaes_encrypt8
-
-	pxor	xmm15,XMMWORD[rsp]
-	pxor	xmm0,XMMWORD[16+rsp]
-	movdqu	XMMWORD[r13],xmm15
-	pxor	xmm3,XMMWORD[32+rsp]
-	movdqu	XMMWORD[16+r13],xmm0
-	pxor	xmm5,XMMWORD[48+rsp]
-	movdqu	XMMWORD[32+r13],xmm3
-	pxor	xmm2,XMMWORD[64+rsp]
-	movdqu	XMMWORD[48+r13],xmm5
-	pxor	xmm6,XMMWORD[80+rsp]
-	movdqu	XMMWORD[64+r13],xmm2
-	movdqu	XMMWORD[80+r13],xmm6
-	lea	r13,[96+r13]
-
-	movdqa	xmm6,XMMWORD[96+rsp]
-	jmp	NEAR $L$xts_enc_done
-ALIGN	16
-$L$xts_enc_5:
-	pxor	xmm2,xmm10
-	lea	r12,[80+r12]
-	pxor	xmm3,xmm11
-	lea	rax,[128+rsp]
-	mov	r10d,edx
-
-	call	_bsaes_encrypt8
-
-	pxor	xmm15,XMMWORD[rsp]
-	pxor	xmm0,XMMWORD[16+rsp]
-	movdqu	XMMWORD[r13],xmm15
-	pxor	xmm3,XMMWORD[32+rsp]
-	movdqu	XMMWORD[16+r13],xmm0
-	pxor	xmm5,XMMWORD[48+rsp]
-	movdqu	XMMWORD[32+r13],xmm3
-	pxor	xmm2,XMMWORD[64+rsp]
-	movdqu	XMMWORD[48+r13],xmm5
-	movdqu	XMMWORD[64+r13],xmm2
-	lea	r13,[80+r13]
-
-	movdqa	xmm6,XMMWORD[80+rsp]
-	jmp	NEAR $L$xts_enc_done
-ALIGN	16
-$L$xts_enc_4:
-	pxor	xmm1,xmm9
-	lea	r12,[64+r12]
-	pxor	xmm2,xmm10
-	lea	rax,[128+rsp]
-	mov	r10d,edx
-
-	call	_bsaes_encrypt8
-
-	pxor	xmm15,XMMWORD[rsp]
-	pxor	xmm0,XMMWORD[16+rsp]
-	movdqu	XMMWORD[r13],xmm15
-	pxor	xmm3,XMMWORD[32+rsp]
-	movdqu	XMMWORD[16+r13],xmm0
-	pxor	xmm5,XMMWORD[48+rsp]
-	movdqu	XMMWORD[32+r13],xmm3
-	movdqu	XMMWORD[48+r13],xmm5
-	lea	r13,[64+r13]
-
-	movdqa	xmm6,XMMWORD[64+rsp]
-	jmp	NEAR $L$xts_enc_done
-ALIGN	16
-$L$xts_enc_3:
-	pxor	xmm0,xmm8
-	lea	r12,[48+r12]
-	pxor	xmm1,xmm9
-	lea	rax,[128+rsp]
-	mov	r10d,edx
-
-	call	_bsaes_encrypt8
-
-	pxor	xmm15,XMMWORD[rsp]
-	pxor	xmm0,XMMWORD[16+rsp]
-	movdqu	XMMWORD[r13],xmm15
-	pxor	xmm3,XMMWORD[32+rsp]
-	movdqu	XMMWORD[16+r13],xmm0
-	movdqu	XMMWORD[32+r13],xmm3
-	lea	r13,[48+r13]
-
-	movdqa	xmm6,XMMWORD[48+rsp]
-	jmp	NEAR $L$xts_enc_done
-ALIGN	16
-$L$xts_enc_2:
-	pxor	xmm15,xmm7
-	lea	r12,[32+r12]
-	pxor	xmm0,xmm8
-	lea	rax,[128+rsp]
-	mov	r10d,edx
-
-	call	_bsaes_encrypt8
-
-	pxor	xmm15,XMMWORD[rsp]
-	pxor	xmm0,XMMWORD[16+rsp]
-	movdqu	XMMWORD[r13],xmm15
-	movdqu	XMMWORD[16+r13],xmm0
-	lea	r13,[32+r13]
-
-	movdqa	xmm6,XMMWORD[32+rsp]
-	jmp	NEAR $L$xts_enc_done
-ALIGN	16
-$L$xts_enc_1:
-	pxor	xmm7,xmm15
-	lea	r12,[16+r12]
-	movdqa	XMMWORD[32+rbp],xmm7
-	lea	rcx,[32+rbp]
-	lea	rdx,[32+rbp]
-	lea	r8,[r15]
-	call	aes_nohw_encrypt
-	pxor	xmm15,XMMWORD[32+rbp]
-
-
-
-
-
-	movdqu	XMMWORD[r13],xmm15
-	lea	r13,[16+r13]
-
-	movdqa	xmm6,XMMWORD[16+rsp]
-
-$L$xts_enc_done:
-	and	ebx,15
-	jz	NEAR $L$xts_enc_ret
-	mov	rdx,r13
-
-$L$xts_enc_steal:
-	movzx	eax,BYTE[r12]
-	movzx	ecx,BYTE[((-16))+rdx]
-	lea	r12,[1+r12]
-	mov	BYTE[((-16))+rdx],al
-	mov	BYTE[rdx],cl
-	lea	rdx,[1+rdx]
-	sub	ebx,1
-	jnz	NEAR $L$xts_enc_steal
-
-	movdqu	xmm15,XMMWORD[((-16))+r13]
-	lea	rcx,[32+rbp]
-	pxor	xmm15,xmm6
-	lea	rdx,[32+rbp]
-	movdqa	XMMWORD[32+rbp],xmm15
-	lea	r8,[r15]
-	call	aes_nohw_encrypt
-	pxor	xmm6,XMMWORD[32+rbp]
-	movdqu	XMMWORD[(-16)+r13],xmm6
-
-$L$xts_enc_ret:
-	lea	rax,[rsp]
-	pxor	xmm0,xmm0
-$L$xts_enc_bzero:
-	movdqa	XMMWORD[rax],xmm0
-	movdqa	XMMWORD[16+rax],xmm0
-	lea	rax,[32+rax]
-	cmp	rbp,rax
-	ja	NEAR $L$xts_enc_bzero
-
-	lea	rax,[120+rbp]
-
-	movaps	xmm6,XMMWORD[64+rbp]
-	movaps	xmm7,XMMWORD[80+rbp]
-	movaps	xmm8,XMMWORD[96+rbp]
-	movaps	xmm9,XMMWORD[112+rbp]
-	movaps	xmm10,XMMWORD[128+rbp]
-	movaps	xmm11,XMMWORD[144+rbp]
-	movaps	xmm12,XMMWORD[160+rbp]
-	movaps	xmm13,XMMWORD[176+rbp]
-	movaps	xmm14,XMMWORD[192+rbp]
-	movaps	xmm15,XMMWORD[208+rbp]
-	lea	rax,[160+rax]
-$L$xts_enc_tail:
-	mov	r15,QWORD[((-48))+rax]
-
-	mov	r14,QWORD[((-40))+rax]
-
-	mov	r13,QWORD[((-32))+rax]
-
-	mov	r12,QWORD[((-24))+rax]
-
-	mov	rbx,QWORD[((-16))+rax]
-
-	mov	rbp,QWORD[((-8))+rax]
-
-	lea	rsp,[rax]
-
-$L$xts_enc_epilogue:
-	DB	0F3h,0C3h		;repret
-
-
-
-global	bsaes_xts_decrypt
-
-ALIGN	16
-bsaes_xts_decrypt:
-
-	mov	rax,rsp
-$L$xts_dec_prologue:
-	push	rbp
-
-	push	rbx
-
-	push	r12
-
-	push	r13
-
-	push	r14
-
-	push	r15
-
-	lea	rsp,[((-72))+rsp]
-
-	mov	r10,QWORD[160+rsp]
-	mov	r11,QWORD[168+rsp]
-	lea	rsp,[((-160))+rsp]
-	movaps	XMMWORD[64+rsp],xmm6
-	movaps	XMMWORD[80+rsp],xmm7
-	movaps	XMMWORD[96+rsp],xmm8
-	movaps	XMMWORD[112+rsp],xmm9
-	movaps	XMMWORD[128+rsp],xmm10
-	movaps	XMMWORD[144+rsp],xmm11
-	movaps	XMMWORD[160+rsp],xmm12
-	movaps	XMMWORD[176+rsp],xmm13
-	movaps	XMMWORD[192+rsp],xmm14
-	movaps	XMMWORD[208+rsp],xmm15
-$L$xts_dec_body:
-	mov	rbp,rsp
-	mov	r12,rcx
-	mov	r13,rdx
-	mov	r14,r8
-	mov	r15,r9
-
-	lea	rcx,[r11]
-	lea	rdx,[32+rbp]
-	lea	r8,[r10]
-	call	aes_nohw_encrypt
-
-	mov	eax,DWORD[240+r15]
-	mov	rbx,r14
-
-	mov	edx,eax
-	shl	rax,7
-	sub	rax,96
-	sub	rsp,rax
-
-	mov	rax,rsp
-	mov	rcx,r15
-	mov	r10d,edx
-	call	_bsaes_key_convert
-	pxor	xmm7,XMMWORD[rsp]
-	movdqa	XMMWORD[rax],xmm6
-	movdqa	XMMWORD[rsp],xmm7
-
-	xor	eax,eax
-	and	r14,-16
-	test	ebx,15
-	setnz	al
-	shl	rax,4
-	sub	r14,rax
-
-	sub	rsp,0x80
-	movdqa	xmm6,XMMWORD[32+rbp]
-
-	pxor	xmm14,xmm14
-	movdqa	xmm12,XMMWORD[$L$xts_magic]
-	pcmpgtd	xmm14,xmm6
-
-	sub	r14,0x80
-	jc	NEAR $L$xts_dec_short
-	jmp	NEAR $L$xts_dec_loop
-
-ALIGN	16
-$L$xts_dec_loop:
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm15,xmm6
-	movdqa	XMMWORD[rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm0,xmm6
-	movdqa	XMMWORD[16+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm7,XMMWORD[r12]
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm1,xmm6
-	movdqa	XMMWORD[32+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm8,XMMWORD[16+r12]
-	pxor	xmm15,xmm7
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm2,xmm6
-	movdqa	XMMWORD[48+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm9,XMMWORD[32+r12]
-	pxor	xmm0,xmm8
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm3,xmm6
-	movdqa	XMMWORD[64+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm10,XMMWORD[48+r12]
-	pxor	xmm1,xmm9
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm4,xmm6
-	movdqa	XMMWORD[80+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm11,XMMWORD[64+r12]
-	pxor	xmm2,xmm10
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm5,xmm6
-	movdqa	XMMWORD[96+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm12,XMMWORD[80+r12]
-	pxor	xmm3,xmm11
-	movdqu	xmm13,XMMWORD[96+r12]
-	pxor	xmm4,xmm12
-	movdqu	xmm14,XMMWORD[112+r12]
-	lea	r12,[128+r12]
-	movdqa	XMMWORD[112+rsp],xmm6
-	pxor	xmm5,xmm13
-	lea	rax,[128+rsp]
-	pxor	xmm6,xmm14
-	mov	r10d,edx
-
-	call	_bsaes_decrypt8
-
-	pxor	xmm15,XMMWORD[rsp]
-	pxor	xmm0,XMMWORD[16+rsp]
-	movdqu	XMMWORD[r13],xmm15
-	pxor	xmm5,XMMWORD[32+rsp]
-	movdqu	XMMWORD[16+r13],xmm0
-	pxor	xmm3,XMMWORD[48+rsp]
-	movdqu	XMMWORD[32+r13],xmm5
-	pxor	xmm1,XMMWORD[64+rsp]
-	movdqu	XMMWORD[48+r13],xmm3
-	pxor	xmm6,XMMWORD[80+rsp]
-	movdqu	XMMWORD[64+r13],xmm1
-	pxor	xmm2,XMMWORD[96+rsp]
-	movdqu	XMMWORD[80+r13],xmm6
-	pxor	xmm4,XMMWORD[112+rsp]
-	movdqu	XMMWORD[96+r13],xmm2
-	movdqu	XMMWORD[112+r13],xmm4
-	lea	r13,[128+r13]
-
-	movdqa	xmm6,XMMWORD[112+rsp]
-	pxor	xmm14,xmm14
-	movdqa	xmm12,XMMWORD[$L$xts_magic]
-	pcmpgtd	xmm14,xmm6
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-
-	sub	r14,0x80
-	jnc	NEAR $L$xts_dec_loop
-
-$L$xts_dec_short:
-	add	r14,0x80
-	jz	NEAR $L$xts_dec_done
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm15,xmm6
-	movdqa	XMMWORD[rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm0,xmm6
-	movdqa	XMMWORD[16+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm7,XMMWORD[r12]
-	cmp	r14,16
-	je	NEAR $L$xts_dec_1
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm1,xmm6
-	movdqa	XMMWORD[32+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm8,XMMWORD[16+r12]
-	cmp	r14,32
-	je	NEAR $L$xts_dec_2
-	pxor	xmm15,xmm7
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm2,xmm6
-	movdqa	XMMWORD[48+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm9,XMMWORD[32+r12]
-	cmp	r14,48
-	je	NEAR $L$xts_dec_3
-	pxor	xmm0,xmm8
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm3,xmm6
-	movdqa	XMMWORD[64+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm10,XMMWORD[48+r12]
-	cmp	r14,64
-	je	NEAR $L$xts_dec_4
-	pxor	xmm1,xmm9
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm4,xmm6
-	movdqa	XMMWORD[80+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm11,XMMWORD[64+r12]
-	cmp	r14,80
-	je	NEAR $L$xts_dec_5
-	pxor	xmm2,xmm10
-	pshufd	xmm13,xmm14,0x13
-	pxor	xmm14,xmm14
-	movdqa	xmm5,xmm6
-	movdqa	XMMWORD[96+rsp],xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	pcmpgtd	xmm14,xmm6
-	pxor	xmm6,xmm13
-	movdqu	xmm12,XMMWORD[80+r12]
-	cmp	r14,96
-	je	NEAR $L$xts_dec_6
-	pxor	xmm3,xmm11
-	movdqu	xmm13,XMMWORD[96+r12]
-	pxor	xmm4,xmm12
-	movdqa	XMMWORD[112+rsp],xmm6
-	lea	r12,[112+r12]
-	pxor	xmm5,xmm13
-	lea	rax,[128+rsp]
-	mov	r10d,edx
-
-	call	_bsaes_decrypt8
-
-	pxor	xmm15,XMMWORD[rsp]
-	pxor	xmm0,XMMWORD[16+rsp]
-	movdqu	XMMWORD[r13],xmm15
-	pxor	xmm5,XMMWORD[32+rsp]
-	movdqu	XMMWORD[16+r13],xmm0
-	pxor	xmm3,XMMWORD[48+rsp]
-	movdqu	XMMWORD[32+r13],xmm5
-	pxor	xmm1,XMMWORD[64+rsp]
-	movdqu	XMMWORD[48+r13],xmm3
-	pxor	xmm6,XMMWORD[80+rsp]
-	movdqu	XMMWORD[64+r13],xmm1
-	pxor	xmm2,XMMWORD[96+rsp]
-	movdqu	XMMWORD[80+r13],xmm6
-	movdqu	XMMWORD[96+r13],xmm2
-	lea	r13,[112+r13]
-
-	movdqa	xmm6,XMMWORD[112+rsp]
-	jmp	NEAR $L$xts_dec_done
-ALIGN	16
-$L$xts_dec_6:
-	pxor	xmm3,xmm11
-	lea	r12,[96+r12]
-	pxor	xmm4,xmm12
-	lea	rax,[128+rsp]
-	mov	r10d,edx
-
-	call	_bsaes_decrypt8
-
-	pxor	xmm15,XMMWORD[rsp]
-	pxor	xmm0,XMMWORD[16+rsp]
-	movdqu	XMMWORD[r13],xmm15
-	pxor	xmm5,XMMWORD[32+rsp]
-	movdqu	XMMWORD[16+r13],xmm0
-	pxor	xmm3,XMMWORD[48+rsp]
-	movdqu	XMMWORD[32+r13],xmm5
-	pxor	xmm1,XMMWORD[64+rsp]
-	movdqu	XMMWORD[48+r13],xmm3
-	pxor	xmm6,XMMWORD[80+rsp]
-	movdqu	XMMWORD[64+r13],xmm1
-	movdqu	XMMWORD[80+r13],xmm6
-	lea	r13,[96+r13]
-
-	movdqa	xmm6,XMMWORD[96+rsp]
-	jmp	NEAR $L$xts_dec_done
-ALIGN	16
-$L$xts_dec_5:
-	pxor	xmm2,xmm10
-	lea	r12,[80+r12]
-	pxor	xmm3,xmm11
-	lea	rax,[128+rsp]
-	mov	r10d,edx
-
-	call	_bsaes_decrypt8
-
-	pxor	xmm15,XMMWORD[rsp]
-	pxor	xmm0,XMMWORD[16+rsp]
-	movdqu	XMMWORD[r13],xmm15
-	pxor	xmm5,XMMWORD[32+rsp]
-	movdqu	XMMWORD[16+r13],xmm0
-	pxor	xmm3,XMMWORD[48+rsp]
-	movdqu	XMMWORD[32+r13],xmm5
-	pxor	xmm1,XMMWORD[64+rsp]
-	movdqu	XMMWORD[48+r13],xmm3
-	movdqu	XMMWORD[64+r13],xmm1
-	lea	r13,[80+r13]
-
-	movdqa	xmm6,XMMWORD[80+rsp]
-	jmp	NEAR $L$xts_dec_done
-ALIGN	16
-$L$xts_dec_4:
-	pxor	xmm1,xmm9
-	lea	r12,[64+r12]
-	pxor	xmm2,xmm10
-	lea	rax,[128+rsp]
-	mov	r10d,edx
-
-	call	_bsaes_decrypt8
-
-	pxor	xmm15,XMMWORD[rsp]
-	pxor	xmm0,XMMWORD[16+rsp]
-	movdqu	XMMWORD[r13],xmm15
-	pxor	xmm5,XMMWORD[32+rsp]
-	movdqu	XMMWORD[16+r13],xmm0
-	pxor	xmm3,XMMWORD[48+rsp]
-	movdqu	XMMWORD[32+r13],xmm5
-	movdqu	XMMWORD[48+r13],xmm3
-	lea	r13,[64+r13]
-
-	movdqa	xmm6,XMMWORD[64+rsp]
-	jmp	NEAR $L$xts_dec_done
-ALIGN	16
-$L$xts_dec_3:
-	pxor	xmm0,xmm8
-	lea	r12,[48+r12]
-	pxor	xmm1,xmm9
-	lea	rax,[128+rsp]
-	mov	r10d,edx
-
-	call	_bsaes_decrypt8
-
-	pxor	xmm15,XMMWORD[rsp]
-	pxor	xmm0,XMMWORD[16+rsp]
-	movdqu	XMMWORD[r13],xmm15
-	pxor	xmm5,XMMWORD[32+rsp]
-	movdqu	XMMWORD[16+r13],xmm0
-	movdqu	XMMWORD[32+r13],xmm5
-	lea	r13,[48+r13]
-
-	movdqa	xmm6,XMMWORD[48+rsp]
-	jmp	NEAR $L$xts_dec_done
-ALIGN	16
-$L$xts_dec_2:
-	pxor	xmm15,xmm7
-	lea	r12,[32+r12]
-	pxor	xmm0,xmm8
-	lea	rax,[128+rsp]
-	mov	r10d,edx
-
-	call	_bsaes_decrypt8
-
-	pxor	xmm15,XMMWORD[rsp]
-	pxor	xmm0,XMMWORD[16+rsp]
-	movdqu	XMMWORD[r13],xmm15
-	movdqu	XMMWORD[16+r13],xmm0
-	lea	r13,[32+r13]
-
-	movdqa	xmm6,XMMWORD[32+rsp]
-	jmp	NEAR $L$xts_dec_done
-ALIGN	16
-$L$xts_dec_1:
-	pxor	xmm7,xmm15
-	lea	r12,[16+r12]
-	movdqa	XMMWORD[32+rbp],xmm7
-	lea	rcx,[32+rbp]
-	lea	rdx,[32+rbp]
-	lea	r8,[r15]
-	call	aes_nohw_decrypt
-	pxor	xmm15,XMMWORD[32+rbp]
-
-
-
-
-
-	movdqu	XMMWORD[r13],xmm15
-	lea	r13,[16+r13]
-
-	movdqa	xmm6,XMMWORD[16+rsp]
-
-$L$xts_dec_done:
-	and	ebx,15
-	jz	NEAR $L$xts_dec_ret
-
-	pxor	xmm14,xmm14
-	movdqa	xmm12,XMMWORD[$L$xts_magic]
-	pcmpgtd	xmm14,xmm6
-	pshufd	xmm13,xmm14,0x13
-	movdqa	xmm5,xmm6
-	paddq	xmm6,xmm6
-	pand	xmm13,xmm12
-	movdqu	xmm15,XMMWORD[r12]
-	pxor	xmm6,xmm13
-
-	lea	rcx,[32+rbp]
-	pxor	xmm15,xmm6
-	lea	rdx,[32+rbp]
-	movdqa	XMMWORD[32+rbp],xmm15
-	lea	r8,[r15]
-	call	aes_nohw_decrypt
-	pxor	xmm6,XMMWORD[32+rbp]
-	mov	rdx,r13
-	movdqu	XMMWORD[r13],xmm6
-
-$L$xts_dec_steal:
-	movzx	eax,BYTE[16+r12]
-	movzx	ecx,BYTE[rdx]
-	lea	r12,[1+r12]
-	mov	BYTE[rdx],al
-	mov	BYTE[16+rdx],cl
-	lea	rdx,[1+rdx]
-	sub	ebx,1
-	jnz	NEAR $L$xts_dec_steal
-
-	movdqu	xmm15,XMMWORD[r13]
-	lea	rcx,[32+rbp]
-	pxor	xmm15,xmm5
-	lea	rdx,[32+rbp]
-	movdqa	XMMWORD[32+rbp],xmm15
-	lea	r8,[r15]
-	call	aes_nohw_decrypt
-	pxor	xmm5,XMMWORD[32+rbp]
-	movdqu	XMMWORD[r13],xmm5
-
-$L$xts_dec_ret:
-	lea	rax,[rsp]
-	pxor	xmm0,xmm0
-$L$xts_dec_bzero:
-	movdqa	XMMWORD[rax],xmm0
-	movdqa	XMMWORD[16+rax],xmm0
-	lea	rax,[32+rax]
-	cmp	rbp,rax
-	ja	NEAR $L$xts_dec_bzero
-
-	lea	rax,[120+rbp]
-
-	movaps	xmm6,XMMWORD[64+rbp]
-	movaps	xmm7,XMMWORD[80+rbp]
-	movaps	xmm8,XMMWORD[96+rbp]
-	movaps	xmm9,XMMWORD[112+rbp]
-	movaps	xmm10,XMMWORD[128+rbp]
-	movaps	xmm11,XMMWORD[144+rbp]
-	movaps	xmm12,XMMWORD[160+rbp]
-	movaps	xmm13,XMMWORD[176+rbp]
-	movaps	xmm14,XMMWORD[192+rbp]
-	movaps	xmm15,XMMWORD[208+rbp]
-	lea	rax,[160+rax]
-$L$xts_dec_tail:
-	mov	r15,QWORD[((-48))+rax]
-
-	mov	r14,QWORD[((-40))+rax]
-
-	mov	r13,QWORD[((-32))+rax]
-
-	mov	r12,QWORD[((-24))+rax]
-
-	mov	rbx,QWORD[((-16))+rax]
-
-	mov	rbp,QWORD[((-8))+rax]
-
-	lea	rsp,[rax]
-
-$L$xts_dec_epilogue:
-	DB	0F3h,0C3h		;repret
-
-
 
 ALIGN	64
 _bsaes_const:
@@ -2786,14 +1772,6 @@
 	DD	$L$ctr_enc_epilogue wrt ..imagebase
 	DD	$L$ctr_enc_info wrt ..imagebase
 
-	DD	$L$xts_enc_prologue wrt ..imagebase
-	DD	$L$xts_enc_epilogue wrt ..imagebase
-	DD	$L$xts_enc_info wrt ..imagebase
-
-	DD	$L$xts_dec_prologue wrt ..imagebase
-	DD	$L$xts_dec_epilogue wrt ..imagebase
-	DD	$L$xts_dec_info wrt ..imagebase
-
 section	.xdata rdata align=8
 ALIGN	8
 $L$cbc_dec_info:
@@ -2808,15 +1786,3 @@
 	DD	$L$ctr_enc_body wrt ..imagebase,$L$ctr_enc_epilogue wrt ..imagebase
 	DD	$L$ctr_enc_tail wrt ..imagebase
 	DD	0
-$L$xts_enc_info:
-DB	9,0,0,0
-	DD	se_handler wrt ..imagebase
-	DD	$L$xts_enc_body wrt ..imagebase,$L$xts_enc_epilogue wrt ..imagebase
-	DD	$L$xts_enc_tail wrt ..imagebase
-	DD	0
-$L$xts_dec_info:
-DB	9,0,0,0
-	DD	se_handler wrt ..imagebase
-	DD	$L$xts_dec_body wrt ..imagebase,$L$xts_dec_epilogue wrt ..imagebase
-	DD	$L$xts_dec_tail wrt ..imagebase
-	DD	0
diff --git a/third_party/boringssl/win-x86_64/crypto/fipsmodule/sha512-x86_64.asm b/third_party/boringssl/win-x86_64/crypto/fipsmodule/sha512-x86_64.asm
index ea6c4f17..33dc2c2 100644
--- a/third_party/boringssl/win-x86_64/crypto/fipsmodule/sha512-x86_64.asm
+++ b/third_party/boringssl/win-x86_64/crypto/fipsmodule/sha512-x86_64.asm
@@ -31,8 +31,6 @@
 	mov	r9d,DWORD[r11]
 	mov	r10d,DWORD[4+r11]
 	mov	r11d,DWORD[8+r11]
-	test	r10d,2048
-	jnz	NEAR $L$xop_shortcut
 	and	r9d,1073741824
 	and	r10d,268435968
 	or	r10d,r9d
@@ -1839,1130 +1837,6 @@
 DB	111,114,103,62,0
 
 ALIGN	64
-sha512_block_data_order_xop:
-	mov	QWORD[8+rsp],rdi	;WIN64 prologue
-	mov	QWORD[16+rsp],rsi
-	mov	rax,rsp
-$L$SEH_begin_sha512_block_data_order_xop:
-	mov	rdi,rcx
-	mov	rsi,rdx
-	mov	rdx,r8
-
-
-
-$L$xop_shortcut:
-	mov	rax,rsp
-
-	push	rbx
-
-	push	rbp
-
-	push	r12
-
-	push	r13
-
-	push	r14
-
-	push	r15
-
-	shl	rdx,4
-	sub	rsp,256
-	lea	rdx,[rdx*8+rsi]
-	and	rsp,-64
-	mov	QWORD[((128+0))+rsp],rdi
-	mov	QWORD[((128+8))+rsp],rsi
-	mov	QWORD[((128+16))+rsp],rdx
-	mov	QWORD[152+rsp],rax
-
-	movaps	XMMWORD[(128+32)+rsp],xmm6
-	movaps	XMMWORD[(128+48)+rsp],xmm7
-	movaps	XMMWORD[(128+64)+rsp],xmm8
-	movaps	XMMWORD[(128+80)+rsp],xmm9
-	movaps	XMMWORD[(128+96)+rsp],xmm10
-	movaps	XMMWORD[(128+112)+rsp],xmm11
-$L$prologue_xop:
-
-	vzeroupper
-	mov	rax,QWORD[rdi]
-	mov	rbx,QWORD[8+rdi]
-	mov	rcx,QWORD[16+rdi]
-	mov	rdx,QWORD[24+rdi]
-	mov	r8,QWORD[32+rdi]
-	mov	r9,QWORD[40+rdi]
-	mov	r10,QWORD[48+rdi]
-	mov	r11,QWORD[56+rdi]
-	jmp	NEAR $L$loop_xop
-ALIGN	16
-$L$loop_xop:
-	vmovdqa	xmm11,XMMWORD[((K512+1280))]
-	vmovdqu	xmm0,XMMWORD[rsi]
-	lea	rbp,[((K512+128))]
-	vmovdqu	xmm1,XMMWORD[16+rsi]
-	vmovdqu	xmm2,XMMWORD[32+rsi]
-	vpshufb	xmm0,xmm0,xmm11
-	vmovdqu	xmm3,XMMWORD[48+rsi]
-	vpshufb	xmm1,xmm1,xmm11
-	vmovdqu	xmm4,XMMWORD[64+rsi]
-	vpshufb	xmm2,xmm2,xmm11
-	vmovdqu	xmm5,XMMWORD[80+rsi]
-	vpshufb	xmm3,xmm3,xmm11
-	vmovdqu	xmm6,XMMWORD[96+rsi]
-	vpshufb	xmm4,xmm4,xmm11
-	vmovdqu	xmm7,XMMWORD[112+rsi]
-	vpshufb	xmm5,xmm5,xmm11
-	vpaddq	xmm8,xmm0,XMMWORD[((-128))+rbp]
-	vpshufb	xmm6,xmm6,xmm11
-	vpaddq	xmm9,xmm1,XMMWORD[((-96))+rbp]
-	vpshufb	xmm7,xmm7,xmm11
-	vpaddq	xmm10,xmm2,XMMWORD[((-64))+rbp]
-	vpaddq	xmm11,xmm3,XMMWORD[((-32))+rbp]
-	vmovdqa	XMMWORD[rsp],xmm8
-	vpaddq	xmm8,xmm4,XMMWORD[rbp]
-	vmovdqa	XMMWORD[16+rsp],xmm9
-	vpaddq	xmm9,xmm5,XMMWORD[32+rbp]
-	vmovdqa	XMMWORD[32+rsp],xmm10
-	vpaddq	xmm10,xmm6,XMMWORD[64+rbp]
-	vmovdqa	XMMWORD[48+rsp],xmm11
-	vpaddq	xmm11,xmm7,XMMWORD[96+rbp]
-	vmovdqa	XMMWORD[64+rsp],xmm8
-	mov	r14,rax
-	vmovdqa	XMMWORD[80+rsp],xmm9
-	mov	rdi,rbx
-	vmovdqa	XMMWORD[96+rsp],xmm10
-	xor	rdi,rcx
-	vmovdqa	XMMWORD[112+rsp],xmm11
-	mov	r13,r8
-	jmp	NEAR $L$xop_00_47
-
-ALIGN	16
-$L$xop_00_47:
-	add	rbp,256
-	vpalignr	xmm8,xmm1,xmm0,8
-	ror	r13,23
-	mov	rax,r14
-	vpalignr	xmm11,xmm5,xmm4,8
-	mov	r12,r9
-	ror	r14,5
-DB	143,72,120,195,200,56
-	xor	r13,r8
-	xor	r12,r10
-	vpsrlq	xmm8,xmm8,7
-	ror	r13,4
-	xor	r14,rax
-	vpaddq	xmm0,xmm0,xmm11
-	and	r12,r8
-	xor	r13,r8
-	add	r11,QWORD[rsp]
-	mov	r15,rax
-DB	143,72,120,195,209,7
-	xor	r12,r10
-	ror	r14,6
-	vpxor	xmm8,xmm8,xmm9
-	xor	r15,rbx
-	add	r11,r12
-	ror	r13,14
-	and	rdi,r15
-DB	143,104,120,195,223,3
-	xor	r14,rax
-	add	r11,r13
-	vpxor	xmm8,xmm8,xmm10
-	xor	rdi,rbx
-	ror	r14,28
-	vpsrlq	xmm10,xmm7,6
-	add	rdx,r11
-	add	r11,rdi
-	vpaddq	xmm0,xmm0,xmm8
-	mov	r13,rdx
-	add	r14,r11
-DB	143,72,120,195,203,42
-	ror	r13,23
-	mov	r11,r14
-	vpxor	xmm11,xmm11,xmm10
-	mov	r12,r8
-	ror	r14,5
-	xor	r13,rdx
-	xor	r12,r9
-	vpxor	xmm11,xmm11,xmm9
-	ror	r13,4
-	xor	r14,r11
-	and	r12,rdx
-	xor	r13,rdx
-	vpaddq	xmm0,xmm0,xmm11
-	add	r10,QWORD[8+rsp]
-	mov	rdi,r11
-	xor	r12,r9
-	ror	r14,6
-	vpaddq	xmm10,xmm0,XMMWORD[((-128))+rbp]
-	xor	rdi,rax
-	add	r10,r12
-	ror	r13,14
-	and	r15,rdi
-	xor	r14,r11
-	add	r10,r13
-	xor	r15,rax
-	ror	r14,28
-	add	rcx,r10
-	add	r10,r15
-	mov	r13,rcx
-	add	r14,r10
-	vmovdqa	XMMWORD[rsp],xmm10
-	vpalignr	xmm8,xmm2,xmm1,8
-	ror	r13,23
-	mov	r10,r14
-	vpalignr	xmm11,xmm6,xmm5,8
-	mov	r12,rdx
-	ror	r14,5
-DB	143,72,120,195,200,56
-	xor	r13,rcx
-	xor	r12,r8
-	vpsrlq	xmm8,xmm8,7
-	ror	r13,4
-	xor	r14,r10
-	vpaddq	xmm1,xmm1,xmm11
-	and	r12,rcx
-	xor	r13,rcx
-	add	r9,QWORD[16+rsp]
-	mov	r15,r10
-DB	143,72,120,195,209,7
-	xor	r12,r8
-	ror	r14,6
-	vpxor	xmm8,xmm8,xmm9
-	xor	r15,r11
-	add	r9,r12
-	ror	r13,14
-	and	rdi,r15
-DB	143,104,120,195,216,3
-	xor	r14,r10
-	add	r9,r13
-	vpxor	xmm8,xmm8,xmm10
-	xor	rdi,r11
-	ror	r14,28
-	vpsrlq	xmm10,xmm0,6
-	add	rbx,r9
-	add	r9,rdi
-	vpaddq	xmm1,xmm1,xmm8
-	mov	r13,rbx
-	add	r14,r9
-DB	143,72,120,195,203,42
-	ror	r13,23
-	mov	r9,r14
-	vpxor	xmm11,xmm11,xmm10
-	mov	r12,rcx
-	ror	r14,5
-	xor	r13,rbx
-	xor	r12,rdx
-	vpxor	xmm11,xmm11,xmm9
-	ror	r13,4
-	xor	r14,r9
-	and	r12,rbx
-	xor	r13,rbx
-	vpaddq	xmm1,xmm1,xmm11
-	add	r8,QWORD[24+rsp]
-	mov	rdi,r9
-	xor	r12,rdx
-	ror	r14,6
-	vpaddq	xmm10,xmm1,XMMWORD[((-96))+rbp]
-	xor	rdi,r10
-	add	r8,r12
-	ror	r13,14
-	and	r15,rdi
-	xor	r14,r9
-	add	r8,r13
-	xor	r15,r10
-	ror	r14,28
-	add	rax,r8
-	add	r8,r15
-	mov	r13,rax
-	add	r14,r8
-	vmovdqa	XMMWORD[16+rsp],xmm10
-	vpalignr	xmm8,xmm3,xmm2,8
-	ror	r13,23
-	mov	r8,r14
-	vpalignr	xmm11,xmm7,xmm6,8
-	mov	r12,rbx
-	ror	r14,5
-DB	143,72,120,195,200,56
-	xor	r13,rax
-	xor	r12,rcx
-	vpsrlq	xmm8,xmm8,7
-	ror	r13,4
-	xor	r14,r8
-	vpaddq	xmm2,xmm2,xmm11
-	and	r12,rax
-	xor	r13,rax
-	add	rdx,QWORD[32+rsp]
-	mov	r15,r8
-DB	143,72,120,195,209,7
-	xor	r12,rcx
-	ror	r14,6
-	vpxor	xmm8,xmm8,xmm9
-	xor	r15,r9
-	add	rdx,r12
-	ror	r13,14
-	and	rdi,r15
-DB	143,104,120,195,217,3
-	xor	r14,r8
-	add	rdx,r13
-	vpxor	xmm8,xmm8,xmm10
-	xor	rdi,r9
-	ror	r14,28
-	vpsrlq	xmm10,xmm1,6
-	add	r11,rdx
-	add	rdx,rdi
-	vpaddq	xmm2,xmm2,xmm8
-	mov	r13,r11
-	add	r14,rdx
-DB	143,72,120,195,203,42
-	ror	r13,23
-	mov	rdx,r14
-	vpxor	xmm11,xmm11,xmm10
-	mov	r12,rax
-	ror	r14,5
-	xor	r13,r11
-	xor	r12,rbx
-	vpxor	xmm11,xmm11,xmm9
-	ror	r13,4
-	xor	r14,rdx
-	and	r12,r11
-	xor	r13,r11
-	vpaddq	xmm2,xmm2,xmm11
-	add	rcx,QWORD[40+rsp]
-	mov	rdi,rdx
-	xor	r12,rbx
-	ror	r14,6
-	vpaddq	xmm10,xmm2,XMMWORD[((-64))+rbp]
-	xor	rdi,r8
-	add	rcx,r12
-	ror	r13,14
-	and	r15,rdi
-	xor	r14,rdx
-	add	rcx,r13
-	xor	r15,r8
-	ror	r14,28
-	add	r10,rcx
-	add	rcx,r15
-	mov	r13,r10
-	add	r14,rcx
-	vmovdqa	XMMWORD[32+rsp],xmm10
-	vpalignr	xmm8,xmm4,xmm3,8
-	ror	r13,23
-	mov	rcx,r14
-	vpalignr	xmm11,xmm0,xmm7,8
-	mov	r12,r11
-	ror	r14,5
-DB	143,72,120,195,200,56
-	xor	r13,r10
-	xor	r12,rax
-	vpsrlq	xmm8,xmm8,7
-	ror	r13,4
-	xor	r14,rcx
-	vpaddq	xmm3,xmm3,xmm11
-	and	r12,r10
-	xor	r13,r10
-	add	rbx,QWORD[48+rsp]
-	mov	r15,rcx
-DB	143,72,120,195,209,7
-	xor	r12,rax
-	ror	r14,6
-	vpxor	xmm8,xmm8,xmm9
-	xor	r15,rdx
-	add	rbx,r12
-	ror	r13,14
-	and	rdi,r15
-DB	143,104,120,195,218,3
-	xor	r14,rcx
-	add	rbx,r13
-	vpxor	xmm8,xmm8,xmm10
-	xor	rdi,rdx
-	ror	r14,28
-	vpsrlq	xmm10,xmm2,6
-	add	r9,rbx
-	add	rbx,rdi
-	vpaddq	xmm3,xmm3,xmm8
-	mov	r13,r9
-	add	r14,rbx
-DB	143,72,120,195,203,42
-	ror	r13,23
-	mov	rbx,r14
-	vpxor	xmm11,xmm11,xmm10
-	mov	r12,r10
-	ror	r14,5
-	xor	r13,r9
-	xor	r12,r11
-	vpxor	xmm11,xmm11,xmm9
-	ror	r13,4
-	xor	r14,rbx
-	and	r12,r9
-	xor	r13,r9
-	vpaddq	xmm3,xmm3,xmm11
-	add	rax,QWORD[56+rsp]
-	mov	rdi,rbx
-	xor	r12,r11
-	ror	r14,6
-	vpaddq	xmm10,xmm3,XMMWORD[((-32))+rbp]
-	xor	rdi,rcx
-	add	rax,r12
-	ror	r13,14
-	and	r15,rdi
-	xor	r14,rbx
-	add	rax,r13
-	xor	r15,rcx
-	ror	r14,28
-	add	r8,rax
-	add	rax,r15
-	mov	r13,r8
-	add	r14,rax
-	vmovdqa	XMMWORD[48+rsp],xmm10
-	vpalignr	xmm8,xmm5,xmm4,8
-	ror	r13,23
-	mov	rax,r14
-	vpalignr	xmm11,xmm1,xmm0,8
-	mov	r12,r9
-	ror	r14,5
-DB	143,72,120,195,200,56
-	xor	r13,r8
-	xor	r12,r10
-	vpsrlq	xmm8,xmm8,7
-	ror	r13,4
-	xor	r14,rax
-	vpaddq	xmm4,xmm4,xmm11
-	and	r12,r8
-	xor	r13,r8
-	add	r11,QWORD[64+rsp]
-	mov	r15,rax
-DB	143,72,120,195,209,7
-	xor	r12,r10
-	ror	r14,6
-	vpxor	xmm8,xmm8,xmm9
-	xor	r15,rbx
-	add	r11,r12
-	ror	r13,14
-	and	rdi,r15
-DB	143,104,120,195,219,3
-	xor	r14,rax
-	add	r11,r13
-	vpxor	xmm8,xmm8,xmm10
-	xor	rdi,rbx
-	ror	r14,28
-	vpsrlq	xmm10,xmm3,6
-	add	rdx,r11
-	add	r11,rdi
-	vpaddq	xmm4,xmm4,xmm8
-	mov	r13,rdx
-	add	r14,r11
-DB	143,72,120,195,203,42
-	ror	r13,23
-	mov	r11,r14
-	vpxor	xmm11,xmm11,xmm10
-	mov	r12,r8
-	ror	r14,5
-	xor	r13,rdx
-	xor	r12,r9
-	vpxor	xmm11,xmm11,xmm9
-	ror	r13,4
-	xor	r14,r11
-	and	r12,rdx
-	xor	r13,rdx
-	vpaddq	xmm4,xmm4,xmm11
-	add	r10,QWORD[72+rsp]
-	mov	rdi,r11
-	xor	r12,r9
-	ror	r14,6
-	vpaddq	xmm10,xmm4,XMMWORD[rbp]
-	xor	rdi,rax
-	add	r10,r12
-	ror	r13,14
-	and	r15,rdi
-	xor	r14,r11
-	add	r10,r13
-	xor	r15,rax
-	ror	r14,28
-	add	rcx,r10
-	add	r10,r15
-	mov	r13,rcx
-	add	r14,r10
-	vmovdqa	XMMWORD[64+rsp],xmm10
-	vpalignr	xmm8,xmm6,xmm5,8
-	ror	r13,23
-	mov	r10,r14
-	vpalignr	xmm11,xmm2,xmm1,8
-	mov	r12,rdx
-	ror	r14,5
-DB	143,72,120,195,200,56
-	xor	r13,rcx
-	xor	r12,r8
-	vpsrlq	xmm8,xmm8,7
-	ror	r13,4
-	xor	r14,r10
-	vpaddq	xmm5,xmm5,xmm11
-	and	r12,rcx
-	xor	r13,rcx
-	add	r9,QWORD[80+rsp]
-	mov	r15,r10
-DB	143,72,120,195,209,7
-	xor	r12,r8
-	ror	r14,6
-	vpxor	xmm8,xmm8,xmm9
-	xor	r15,r11
-	add	r9,r12
-	ror	r13,14
-	and	rdi,r15
-DB	143,104,120,195,220,3
-	xor	r14,r10
-	add	r9,r13
-	vpxor	xmm8,xmm8,xmm10
-	xor	rdi,r11
-	ror	r14,28
-	vpsrlq	xmm10,xmm4,6
-	add	rbx,r9
-	add	r9,rdi
-	vpaddq	xmm5,xmm5,xmm8
-	mov	r13,rbx
-	add	r14,r9
-DB	143,72,120,195,203,42
-	ror	r13,23
-	mov	r9,r14
-	vpxor	xmm11,xmm11,xmm10
-	mov	r12,rcx
-	ror	r14,5
-	xor	r13,rbx
-	xor	r12,rdx
-	vpxor	xmm11,xmm11,xmm9
-	ror	r13,4
-	xor	r14,r9
-	and	r12,rbx
-	xor	r13,rbx
-	vpaddq	xmm5,xmm5,xmm11
-	add	r8,QWORD[88+rsp]
-	mov	rdi,r9
-	xor	r12,rdx
-	ror	r14,6
-	vpaddq	xmm10,xmm5,XMMWORD[32+rbp]
-	xor	rdi,r10
-	add	r8,r12
-	ror	r13,14
-	and	r15,rdi
-	xor	r14,r9
-	add	r8,r13
-	xor	r15,r10
-	ror	r14,28
-	add	rax,r8
-	add	r8,r15
-	mov	r13,rax
-	add	r14,r8
-	vmovdqa	XMMWORD[80+rsp],xmm10
-	vpalignr	xmm8,xmm7,xmm6,8
-	ror	r13,23
-	mov	r8,r14
-	vpalignr	xmm11,xmm3,xmm2,8
-	mov	r12,rbx
-	ror	r14,5
-DB	143,72,120,195,200,56
-	xor	r13,rax
-	xor	r12,rcx
-	vpsrlq	xmm8,xmm8,7
-	ror	r13,4
-	xor	r14,r8
-	vpaddq	xmm6,xmm6,xmm11
-	and	r12,rax
-	xor	r13,rax
-	add	rdx,QWORD[96+rsp]
-	mov	r15,r8
-DB	143,72,120,195,209,7
-	xor	r12,rcx
-	ror	r14,6
-	vpxor	xmm8,xmm8,xmm9
-	xor	r15,r9
-	add	rdx,r12
-	ror	r13,14
-	and	rdi,r15
-DB	143,104,120,195,221,3
-	xor	r14,r8
-	add	rdx,r13
-	vpxor	xmm8,xmm8,xmm10
-	xor	rdi,r9
-	ror	r14,28
-	vpsrlq	xmm10,xmm5,6
-	add	r11,rdx
-	add	rdx,rdi
-	vpaddq	xmm6,xmm6,xmm8
-	mov	r13,r11
-	add	r14,rdx
-DB	143,72,120,195,203,42
-	ror	r13,23
-	mov	rdx,r14
-	vpxor	xmm11,xmm11,xmm10
-	mov	r12,rax
-	ror	r14,5
-	xor	r13,r11
-	xor	r12,rbx
-	vpxor	xmm11,xmm11,xmm9
-	ror	r13,4
-	xor	r14,rdx
-	and	r12,r11
-	xor	r13,r11
-	vpaddq	xmm6,xmm6,xmm11
-	add	rcx,QWORD[104+rsp]
-	mov	rdi,rdx
-	xor	r12,rbx
-	ror	r14,6
-	vpaddq	xmm10,xmm6,XMMWORD[64+rbp]
-	xor	rdi,r8
-	add	rcx,r12
-	ror	r13,14
-	and	r15,rdi
-	xor	r14,rdx
-	add	rcx,r13
-	xor	r15,r8
-	ror	r14,28
-	add	r10,rcx
-	add	rcx,r15
-	mov	r13,r10
-	add	r14,rcx
-	vmovdqa	XMMWORD[96+rsp],xmm10
-	vpalignr	xmm8,xmm0,xmm7,8
-	ror	r13,23
-	mov	rcx,r14
-	vpalignr	xmm11,xmm4,xmm3,8
-	mov	r12,r11
-	ror	r14,5
-DB	143,72,120,195,200,56
-	xor	r13,r10
-	xor	r12,rax
-	vpsrlq	xmm8,xmm8,7
-	ror	r13,4
-	xor	r14,rcx
-	vpaddq	xmm7,xmm7,xmm11
-	and	r12,r10
-	xor	r13,r10
-	add	rbx,QWORD[112+rsp]
-	mov	r15,rcx
-DB	143,72,120,195,209,7
-	xor	r12,rax
-	ror	r14,6
-	vpxor	xmm8,xmm8,xmm9
-	xor	r15,rdx
-	add	rbx,r12
-	ror	r13,14
-	and	rdi,r15
-DB	143,104,120,195,222,3
-	xor	r14,rcx
-	add	rbx,r13
-	vpxor	xmm8,xmm8,xmm10
-	xor	rdi,rdx
-	ror	r14,28
-	vpsrlq	xmm10,xmm6,6
-	add	r9,rbx
-	add	rbx,rdi
-	vpaddq	xmm7,xmm7,xmm8
-	mov	r13,r9
-	add	r14,rbx
-DB	143,72,120,195,203,42
-	ror	r13,23
-	mov	rbx,r14
-	vpxor	xmm11,xmm11,xmm10
-	mov	r12,r10
-	ror	r14,5
-	xor	r13,r9
-	xor	r12,r11
-	vpxor	xmm11,xmm11,xmm9
-	ror	r13,4
-	xor	r14,rbx
-	and	r12,r9
-	xor	r13,r9
-	vpaddq	xmm7,xmm7,xmm11
-	add	rax,QWORD[120+rsp]
-	mov	rdi,rbx
-	xor	r12,r11
-	ror	r14,6
-	vpaddq	xmm10,xmm7,XMMWORD[96+rbp]
-	xor	rdi,rcx
-	add	rax,r12
-	ror	r13,14
-	and	r15,rdi
-	xor	r14,rbx
-	add	rax,r13
-	xor	r15,rcx
-	ror	r14,28
-	add	r8,rax
-	add	rax,r15
-	mov	r13,r8
-	add	r14,rax
-	vmovdqa	XMMWORD[112+rsp],xmm10
-	cmp	BYTE[135+rbp],0
-	jne	NEAR $L$xop_00_47
-	ror	r13,23
-	mov	rax,r14
-	mov	r12,r9
-	ror	r14,5
-	xor	r13,r8
-	xor	r12,r10
-	ror	r13,4
-	xor	r14,rax
-	and	r12,r8
-	xor	r13,r8
-	add	r11,QWORD[rsp]
-	mov	r15,rax
-	xor	r12,r10
-	ror	r14,6
-	xor	r15,rbx
-	add	r11,r12
-	ror	r13,14
-	and	rdi,r15
-	xor	r14,rax
-	add	r11,r13
-	xor	rdi,rbx
-	ror	r14,28
-	add	rdx,r11
-	add	r11,rdi
-	mov	r13,rdx
-	add	r14,r11
-	ror	r13,23
-	mov	r11,r14
-	mov	r12,r8
-	ror	r14,5
-	xor	r13,rdx
-	xor	r12,r9
-	ror	r13,4
-	xor	r14,r11
-	and	r12,rdx
-	xor	r13,rdx
-	add	r10,QWORD[8+rsp]
-	mov	rdi,r11
-	xor	r12,r9
-	ror	r14,6
-	xor	rdi,rax
-	add	r10,r12
-	ror	r13,14
-	and	r15,rdi
-	xor	r14,r11
-	add	r10,r13
-	xor	r15,rax
-	ror	r14,28
-	add	rcx,r10
-	add	r10,r15
-	mov	r13,rcx
-	add	r14,r10
-	ror	r13,23
-	mov	r10,r14
-	mov	r12,rdx
-	ror	r14,5
-	xor	r13,rcx
-	xor	r12,r8
-	ror	r13,4
-	xor	r14,r10
-	and	r12,rcx
-	xor	r13,rcx
-	add	r9,QWORD[16+rsp]
-	mov	r15,r10
-	xor	r12,r8
-	ror	r14,6
-	xor	r15,r11
-	add	r9,r12
-	ror	r13,14
-	and	rdi,r15
-	xor	r14,r10
-	add	r9,r13
-	xor	rdi,r11
-	ror	r14,28
-	add	rbx,r9
-	add	r9,rdi
-	mov	r13,rbx
-	add	r14,r9
-	ror	r13,23
-	mov	r9,r14
-	mov	r12,rcx
-	ror	r14,5
-	xor	r13,rbx
-	xor	r12,rdx
-	ror	r13,4
-	xor	r14,r9
-	and	r12,rbx
-	xor	r13,rbx
-	add	r8,QWORD[24+rsp]
-	mov	rdi,r9
-	xor	r12,rdx
-	ror	r14,6
-	xor	rdi,r10
-	add	r8,r12
-	ror	r13,14
-	and	r15,rdi
-	xor	r14,r9
-	add	r8,r13
-	xor	r15,r10
-	ror	r14,28
-	add	rax,r8
-	add	r8,r15
-	mov	r13,rax
-	add	r14,r8
-	ror	r13,23
-	mov	r8,r14
-	mov	r12,rbx
-	ror	r14,5
-	xor	r13,rax
-	xor	r12,rcx
-	ror	r13,4
-	xor	r14,r8
-	and	r12,rax
-	xor	r13,rax
-	add	rdx,QWORD[32+rsp]
-	mov	r15,r8
-	xor	r12,rcx
-	ror	r14,6
-	xor	r15,r9
-	add	rdx,r12
-	ror	r13,14
-	and	rdi,r15
-	xor	r14,r8
-	add	rdx,r13
-	xor	rdi,r9
-	ror	r14,28
-	add	r11,rdx
-	add	rdx,rdi
-	mov	r13,r11
-	add	r14,rdx
-	ror	r13,23
-	mov	rdx,r14
-	mov	r12,rax
-	ror	r14,5
-	xor	r13,r11
-	xor	r12,rbx
-	ror	r13,4
-	xor	r14,rdx
-	and	r12,r11
-	xor	r13,r11
-	add	rcx,QWORD[40+rsp]
-	mov	rdi,rdx
-	xor	r12,rbx
-	ror	r14,6
-	xor	rdi,r8
-	add	rcx,r12
-	ror	r13,14
-	and	r15,rdi
-	xor	r14,rdx
-	add	rcx,r13
-	xor	r15,r8
-	ror	r14,28
-	add	r10,rcx
-	add	rcx,r15
-	mov	r13,r10
-	add	r14,rcx
-	ror	r13,23
-	mov	rcx,r14
-	mov	r12,r11
-	ror	r14,5
-	xor	r13,r10
-	xor	r12,rax
-	ror	r13,4
-	xor	r14,rcx
-	and	r12,r10
-	xor	r13,r10
-	add	rbx,QWORD[48+rsp]
-	mov	r15,rcx
-	xor	r12,rax
-	ror	r14,6
-	xor	r15,rdx
-	add	rbx,r12
-	ror	r13,14
-	and	rdi,r15
-	xor	r14,rcx
-	add	rbx,r13
-	xor	rdi,rdx
-	ror	r14,28
-	add	r9,rbx
-	add	rbx,rdi
-	mov	r13,r9
-	add	r14,rbx
-	ror	r13,23
-	mov	rbx,r14
-	mov	r12,r10
-	ror	r14,5
-	xor	r13,r9
-	xor	r12,r11
-	ror	r13,4
-	xor	r14,rbx
-	and	r12,r9
-	xor	r13,r9
-	add	rax,QWORD[56+rsp]
-	mov	rdi,rbx
-	xor	r12,r11
-	ror	r14,6
-	xor	rdi,rcx
-	add	rax,r12
-	ror	r13,14
-	and	r15,rdi
-	xor	r14,rbx
-	add	rax,r13
-	xor	r15,rcx
-	ror	r14,28
-	add	r8,rax
-	add	rax,r15
-	mov	r13,r8
-	add	r14,rax
-	ror	r13,23
-	mov	rax,r14
-	mov	r12,r9
-	ror	r14,5
-	xor	r13,r8
-	xor	r12,r10
-	ror	r13,4
-	xor	r14,rax
-	and	r12,r8
-	xor	r13,r8
-	add	r11,QWORD[64+rsp]
-	mov	r15,rax
-	xor	r12,r10
-	ror	r14,6
-	xor	r15,rbx
-	add	r11,r12
-	ror	r13,14
-	and	rdi,r15
-	xor	r14,rax
-	add	r11,r13
-	xor	rdi,rbx
-	ror	r14,28
-	add	rdx,r11
-	add	r11,rdi
-	mov	r13,rdx
-	add	r14,r11
-	ror	r13,23
-	mov	r11,r14
-	mov	r12,r8
-	ror	r14,5
-	xor	r13,rdx
-	xor	r12,r9
-	ror	r13,4
-	xor	r14,r11
-	and	r12,rdx
-	xor	r13,rdx
-	add	r10,QWORD[72+rsp]
-	mov	rdi,r11
-	xor	r12,r9
-	ror	r14,6
-	xor	rdi,rax
-	add	r10,r12
-	ror	r13,14
-	and	r15,rdi
-	xor	r14,r11
-	add	r10,r13
-	xor	r15,rax
-	ror	r14,28
-	add	rcx,r10
-	add	r10,r15
-	mov	r13,rcx
-	add	r14,r10
-	ror	r13,23
-	mov	r10,r14
-	mov	r12,rdx
-	ror	r14,5
-	xor	r13,rcx
-	xor	r12,r8
-	ror	r13,4
-	xor	r14,r10
-	and	r12,rcx
-	xor	r13,rcx
-	add	r9,QWORD[80+rsp]
-	mov	r15,r10
-	xor	r12,r8
-	ror	r14,6
-	xor	r15,r11
-	add	r9,r12
-	ror	r13,14
-	and	rdi,r15
-	xor	r14,r10
-	add	r9,r13
-	xor	rdi,r11
-	ror	r14,28
-	add	rbx,r9
-	add	r9,rdi
-	mov	r13,rbx
-	add	r14,r9
-	ror	r13,23
-	mov	r9,r14
-	mov	r12,rcx
-	ror	r14,5
-	xor	r13,rbx
-	xor	r12,rdx
-	ror	r13,4
-	xor	r14,r9
-	and	r12,rbx
-	xor	r13,rbx
-	add	r8,QWORD[88+rsp]
-	mov	rdi,r9
-	xor	r12,rdx
-	ror	r14,6
-	xor	rdi,r10
-	add	r8,r12
-	ror	r13,14
-	and	r15,rdi
-	xor	r14,r9
-	add	r8,r13
-	xor	r15,r10
-	ror	r14,28
-	add	rax,r8
-	add	r8,r15
-	mov	r13,rax
-	add	r14,r8
-	ror	r13,23
-	mov	r8,r14
-	mov	r12,rbx
-	ror	r14,5
-	xor	r13,rax
-	xor	r12,rcx
-	ror	r13,4
-	xor	r14,r8
-	and	r12,rax
-	xor	r13,rax
-	add	rdx,QWORD[96+rsp]
-	mov	r15,r8
-	xor	r12,rcx
-	ror	r14,6
-	xor	r15,r9
-	add	rdx,r12
-	ror	r13,14
-	and	rdi,r15
-	xor	r14,r8
-	add	rdx,r13
-	xor	rdi,r9
-	ror	r14,28
-	add	r11,rdx
-	add	rdx,rdi
-	mov	r13,r11
-	add	r14,rdx
-	ror	r13,23
-	mov	rdx,r14
-	mov	r12,rax
-	ror	r14,5
-	xor	r13,r11
-	xor	r12,rbx
-	ror	r13,4
-	xor	r14,rdx
-	and	r12,r11
-	xor	r13,r11
-	add	rcx,QWORD[104+rsp]
-	mov	rdi,rdx
-	xor	r12,rbx
-	ror	r14,6
-	xor	rdi,r8
-	add	rcx,r12
-	ror	r13,14
-	and	r15,rdi
-	xor	r14,rdx
-	add	rcx,r13
-	xor	r15,r8
-	ror	r14,28
-	add	r10,rcx
-	add	rcx,r15
-	mov	r13,r10
-	add	r14,rcx
-	ror	r13,23
-	mov	rcx,r14
-	mov	r12,r11
-	ror	r14,5
-	xor	r13,r10
-	xor	r12,rax
-	ror	r13,4
-	xor	r14,rcx
-	and	r12,r10
-	xor	r13,r10
-	add	rbx,QWORD[112+rsp]
-	mov	r15,rcx
-	xor	r12,rax
-	ror	r14,6
-	xor	r15,rdx
-	add	rbx,r12
-	ror	r13,14
-	and	rdi,r15
-	xor	r14,rcx
-	add	rbx,r13
-	xor	rdi,rdx
-	ror	r14,28
-	add	r9,rbx
-	add	rbx,rdi
-	mov	r13,r9
-	add	r14,rbx
-	ror	r13,23
-	mov	rbx,r14
-	mov	r12,r10
-	ror	r14,5
-	xor	r13,r9
-	xor	r12,r11
-	ror	r13,4
-	xor	r14,rbx
-	and	r12,r9
-	xor	r13,r9
-	add	rax,QWORD[120+rsp]
-	mov	rdi,rbx
-	xor	r12,r11
-	ror	r14,6
-	xor	rdi,rcx
-	add	rax,r12
-	ror	r13,14
-	and	r15,rdi
-	xor	r14,rbx
-	add	rax,r13
-	xor	r15,rcx
-	ror	r14,28
-	add	r8,rax
-	add	rax,r15
-	mov	r13,r8
-	add	r14,rax
-	mov	rdi,QWORD[((128+0))+rsp]
-	mov	rax,r14
-
-	add	rax,QWORD[rdi]
-	lea	rsi,[128+rsi]
-	add	rbx,QWORD[8+rdi]
-	add	rcx,QWORD[16+rdi]
-	add	rdx,QWORD[24+rdi]
-	add	r8,QWORD[32+rdi]
-	add	r9,QWORD[40+rdi]
-	add	r10,QWORD[48+rdi]
-	add	r11,QWORD[56+rdi]
-
-	cmp	rsi,QWORD[((128+16))+rsp]
-
-	mov	QWORD[rdi],rax
-	mov	QWORD[8+rdi],rbx
-	mov	QWORD[16+rdi],rcx
-	mov	QWORD[24+rdi],rdx
-	mov	QWORD[32+rdi],r8
-	mov	QWORD[40+rdi],r9
-	mov	QWORD[48+rdi],r10
-	mov	QWORD[56+rdi],r11
-	jb	NEAR $L$loop_xop
-
-	mov	rsi,QWORD[152+rsp]
-
-	vzeroupper
-	movaps	xmm6,XMMWORD[((128+32))+rsp]
-	movaps	xmm7,XMMWORD[((128+48))+rsp]
-	movaps	xmm8,XMMWORD[((128+64))+rsp]
-	movaps	xmm9,XMMWORD[((128+80))+rsp]
-	movaps	xmm10,XMMWORD[((128+96))+rsp]
-	movaps	xmm11,XMMWORD[((128+112))+rsp]
-	mov	r15,QWORD[((-48))+rsi]
-
-	mov	r14,QWORD[((-40))+rsi]
-
-	mov	r13,QWORD[((-32))+rsi]
-
-	mov	r12,QWORD[((-24))+rsi]
-
-	mov	rbp,QWORD[((-16))+rsi]
-
-	mov	rbx,QWORD[((-8))+rsi]
-
-	lea	rsp,[rsi]
-
-$L$epilogue_xop:
-	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
-	mov	rsi,QWORD[16+rsp]
-	DB	0F3h,0C3h		;repret
-
-$L$SEH_end_sha512_block_data_order_xop:
-
-ALIGN	64
 sha512_block_data_order_avx:
 	mov	QWORD[8+rsp],rdi	;WIN64 prologue
 	mov	QWORD[16+rsp],rsi
@@ -4250,9 +3124,6 @@
 	DD	$L$SEH_begin_sha512_block_data_order wrt ..imagebase
 	DD	$L$SEH_end_sha512_block_data_order wrt ..imagebase
 	DD	$L$SEH_info_sha512_block_data_order wrt ..imagebase
-	DD	$L$SEH_begin_sha512_block_data_order_xop wrt ..imagebase
-	DD	$L$SEH_end_sha512_block_data_order_xop wrt ..imagebase
-	DD	$L$SEH_info_sha512_block_data_order_xop wrt ..imagebase
 	DD	$L$SEH_begin_sha512_block_data_order_avx wrt ..imagebase
 	DD	$L$SEH_end_sha512_block_data_order_avx wrt ..imagebase
 	DD	$L$SEH_info_sha512_block_data_order_avx wrt ..imagebase
@@ -4262,10 +3133,6 @@
 DB	9,0,0,0
 	DD	se_handler wrt ..imagebase
 	DD	$L$prologue wrt ..imagebase,$L$epilogue wrt ..imagebase
-$L$SEH_info_sha512_block_data_order_xop:
-DB	9,0,0,0
-	DD	se_handler wrt ..imagebase
-	DD	$L$prologue_xop wrt ..imagebase,$L$epilogue_xop wrt ..imagebase
 $L$SEH_info_sha512_block_data_order_avx:
 DB	9,0,0,0
 	DD	se_handler wrt ..imagebase
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index e502ed4..f234614 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -12483,6 +12483,7 @@
   <int value="318" label="pyd"/>
   <int value="319" label="pyo"/>
   <int value="320" label="desktop"/>
+  <int value="321" label="cpi"/>
 </enum>
 
 <enum name="DownloadItem.DangerType">
@@ -15087,6 +15088,8 @@
   <int value="505" label="CloudManagementEnrollmentMandatory"/>
   <int value="506" label="PrintingSendUsernameAndFilenameEnabled"/>
   <int value="507" label="ParentAccessCodeConfig"/>
+  <int value="508" label="DeviceGpoCacheLifetime"/>
+  <int value="509" label="DeviceAuthDataCacheLifetime"/>
 </enum>
 
 <enum name="EnterprisePolicyInvalidations">
@@ -47672,6 +47675,7 @@
   <int value="13" label="DiceResponseHandler::Signin"/>
   <int value="14" label="DiceResponseHandler::Signout"/>
   <int value="15" label="DiceTurnOnSyncHelper::Abort"/>
+  <int value="16" label="MachineLogon::CredentialProvider"/>
 </enum>
 
 <enum name="SpareProcessMaybeTakeAction">
diff --git a/tools/perf/core/cli_helpers.py b/tools/perf/core/cli_helpers.py
new file mode 100644
index 0000000..45b3f370
--- /dev/null
+++ b/tools/perf/core/cli_helpers.py
@@ -0,0 +1,172 @@
+# 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.
+
+from __future__ import print_function
+
+import pipes
+import subprocess
+import sys
+
+
+COLOR_ANSI_CODE_MAP = {
+  'black': 90,
+  'red': 91,
+  'green': 92,
+  'yellow': 93,
+  'blue': 94,
+  'magenta': 95,
+  'cyan': 96,
+  'white': 97,
+}
+
+
+def colored(message, color):
+  """Wraps the message into ASCII color escape codes.
+
+  Args:
+    message: Message to be wrapped.
+    color: See COLOR_ANSI_CODE_MAP.keys() for available choices.
+  """
+  # This only works on Linux and OS X. Windows users must install ANSICON or
+  # use VT100 emulation on Windows 10.
+  assert color in COLOR_ANSI_CODE_MAP, 'Unsupported color'
+  return '\033[%dm%s\033[0m' % (COLOR_ANSI_CODE_MAP[color], message)
+
+
+def info(message, **kwargs):
+  print(message.format(**kwargs))
+
+
+def comment(message, **kwargs):
+  """Prints an import message to the user."""
+  print(colored(message.format(**kwargs), 'yellow'))
+
+
+def fatal(message, **kwargs):
+  """Displays an error to the user and terminates the program."""
+  error(message, **kwargs)
+  sys.exit(1)
+
+
+def error(message, **kwargs):
+  """Displays an error to the user."""
+  print(colored(message.format(**kwargs), 'red'))
+
+
+def step(name):
+  """Display a decorated message to the user.
+
+  This is useful to separate major stages of the script. For simple messages,
+  please use comment function above.
+  """
+  boundary = max(80, len(name))
+  print(colored('=' * boundary, 'green'))
+  print(colored(name, 'green'))
+  print(colored('=' * boundary, 'green'))
+
+
+def ask(question, answers=None, default=None):
+  """Asks the user to answer a question with multiple choices.
+
+  Users are able to press Return to access the default answer (if specified) and
+  to type part of the full answer, e.g. "y", "ye" or "yes" are all valid answers
+  for "yes". The func will ask user again in case an invalid answer is provided.
+
+  Raises ValueError if default is specified, but not listed an a valid answer.
+
+  Args:
+    question: Question to be asked.
+    answers: List or dictinary describing user choices. In case of a dictionary,
+        the keys are the options display to the user and values are the return
+        values for this method. In case of a list, returned values are same as
+        options displayed to the user. Defaults to {'yes': True, 'no', False}.
+    default: Default option chosen on empty answer. Defaults to 'yes' if default
+        value is used for answers parameter or to lack of default answer
+        otherwise.
+
+  Returns:
+    Chosen option from answers. Full option name is returned even if user only
+    enters part of it or chooses the default.
+  """
+  if answers is None:
+    answers = {'yes': True, 'no': False}
+    default = 'yes'
+  if isinstance(answers, list):
+    answers = {v: v for v in answers}
+
+  # Generate a set of prefixes for all answers such that the user can type just
+  # the minimum number of characters required, e.g. 'y' or 'ye' can be used for
+  # the 'yes' answer. Shared prefixes are ignored, e.g. 'n' and 'ne' will not be
+  # accepted if 'negate' and 'next' are both valid answers, whereas 'nex' and
+  # 'neg' would be accepted.
+  inputs = {}
+  common_prefixes = set()
+  for ans, retval in answers.iteritems():
+    for i in range(len(ans)):
+      inp = ans[:i+1]
+      if inp in inputs:
+        common_prefixes.add(inp)
+        del inputs[inp]
+      if inp not in common_prefixes:
+        inputs[inp] = retval
+
+  if default is None:
+    prompt = ' [%s] ' % '/'.join(answers)
+  elif default in answers:
+    ans_with_def = [a if a != default else a.upper()
+                    for a in sorted(answers.keys())]
+    prompt = ' [%s] ' % '/'.join(ans_with_def)
+  else:
+    raise ValueError('invalid default answer: "%s"' % default)
+
+  while True:
+    print(colored(question + prompt, 'cyan'), end=' ')
+    choice = raw_input().strip().lower()
+    if default is not None and choice == '':
+      return inputs[default]
+    elif choice in inputs:
+      return inputs[choice]
+    else:
+      choices = sorted(['"%s"' % a for a in sorted(answers.keys())])
+      error('Please respond with %s or %s.' % (
+        ', '.join(choices[:-1]), choices[-1]))
+
+
+def check_log(command, log_path, env=None):
+  """Executes a command and writes its stdout to a specified log file.
+
+  On non-zero return value, also prints the content of the file to the screen
+  and raises subprocess.CalledProcessError.
+
+  Args:
+    command: Command to be run as a list of arguments.
+    log_path: Path to a file to which the output will be written.
+    env: Environment to run the command in.
+  """
+  with open(log_path, 'w') as f:
+    try:
+      cmd_str = ' '.join(command) if isinstance(command, list) else command
+      print(colored(cmd_str, 'blue'))
+      print(colored('Logging stdout & stderr to %s' % log_path, 'blue'))
+      subprocess.check_call(
+          command, stdout=f, stderr=subprocess.STDOUT, shell=False, env=env)
+    except subprocess.CalledProcessError:
+      error('=' * 80)
+      error('Received non-zero return code. Log content:')
+      error('=' * 80)
+      subprocess.call(['cat', log_path])
+      error('=' * 80)
+      raise
+
+
+def run(command, ok_fail=False, **kwargs):
+  """Prints and runs the command. Allows to ignore non-zero exit code."""
+  if not isinstance(command, list):
+    raise ValueError('command must be a list')
+  print(colored(' '.join(pipes.quote(c) for c in command), 'blue'))
+  try:
+    return subprocess.check_call(command, **kwargs)
+  except subprocess.CalledProcessError:
+    if not ok_fail:
+      raise
diff --git a/tools/perf/core/cli_helpers_unittest.py b/tools/perf/core/cli_helpers_unittest.py
new file mode 100644
index 0000000..c103684
--- /dev/null
+++ b/tools/perf/core/cli_helpers_unittest.py
@@ -0,0 +1,151 @@
+# 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 subprocess
+import unittest
+
+import mock
+
+from core import cli_helpers
+
+
+class CLIHelpersTest(unittest.TestCase):
+  def testUnsupportedColor(self):
+    with self.assertRaises(AssertionError):
+      cli_helpers.colored('message', 'pink')
+
+  @mock.patch('__builtin__.print')
+  def testPrintsInfo(self, print_mock):
+    cli_helpers.info('foo {sval} {ival}', sval='s', ival=42)
+    print_mock.assert_called_once_with('foo s 42')
+
+  @mock.patch('__builtin__.print')
+  def testPrintsComment(self, print_mock):
+    cli_helpers.comment('foo')
+    print_mock.assert_called_once_with('\033[93mfoo\033[0m')
+
+  @mock.patch('__builtin__.print')
+  @mock.patch('sys.exit')
+  def testFatal(self, sys_exit_mock, print_mock):
+    cli_helpers.fatal('foo')
+    print_mock.assert_called_once_with('\033[91mfoo\033[0m')
+    sys_exit_mock.assert_called_once()
+
+  @mock.patch('__builtin__.print')
+  def testPrintsError(self, print_mock):
+    cli_helpers.error('foo')
+    print_mock.assert_called_once_with('\033[91mfoo\033[0m')
+
+  @mock.patch('__builtin__.print')
+  def testPrintsStep(self, print_mock):
+    long_step_name = 'foobar' * 15
+    cli_helpers.step(long_step_name)
+    self.assertListEqual(print_mock.call_args_list, [
+        mock.call('\033[92m' + ('=' * 90) + '\033[0m'),
+        mock.call('\033[92m' + long_step_name + '\033[0m'),
+        mock.call('\033[92m' + ('=' * 90) + '\033[0m'),
+    ])
+
+  @mock.patch('__builtin__.print')
+  @mock.patch('__builtin__.raw_input')
+  def testAskAgainOnInvalidAnswer(self, raw_input_mock, print_mock):
+    raw_input_mock.side_effect = ['foobar', 'y']
+    self.assertTrue(cli_helpers.ask('Ready?'))
+    self.assertListEqual(print_mock.mock_calls, [
+      mock.call('\033[96mReady? [no/YES] \033[0m', end=' '),
+      mock.call('\033[91mPlease respond with "no" or "yes".\033[0m'),
+      mock.call('\033[96mReady? [no/YES] \033[0m', end=' ')
+    ])
+
+  @mock.patch('__builtin__.print')
+  @mock.patch('__builtin__.raw_input')
+  def testAskWithCustomAnswersAndDefault(self, raw_input_mock, print_mock):
+    raw_input_mock.side_effect = ['']
+    self.assertFalse(
+        cli_helpers.ask('Ready?', {'foo': True, 'bar': False}, default='bar'))
+    print_mock.assert_called_once_with(
+        '\033[96mReady? [BAR/foo] \033[0m', end=' ')
+
+  @mock.patch('__builtin__.print')
+  @mock.patch('__builtin__.raw_input')
+  def testAskNoDefaultCustomAnswersAsList(self, raw_input_mock, print_mock):
+    raw_input_mock.side_effect = ['', 'FoO']
+    self.assertEqual(cli_helpers.ask('Ready?', ['foo', 'bar']), 'foo')
+    self.assertListEqual(print_mock.mock_calls, [
+      mock.call('\033[96mReady? [foo/bar] \033[0m', end=' '),
+      mock.call('\033[91mPlease respond with "bar" or "foo".\033[0m'),
+      mock.call('\033[96mReady? [foo/bar] \033[0m', end=' ')
+    ])
+
+  def testAskWithInvalidDefaultAnswer(self):
+    with self.assertRaises(ValueError):
+      cli_helpers.ask('Ready?', ['foo', 'bar'], 'baz')
+
+  @mock.patch('__builtin__.print')
+  @mock.patch('subprocess.check_call')
+  @mock.patch('__builtin__.open')
+  @mock.patch('datetime.datetime')
+  def testCheckLog(
+      self, dt_mock, open_mock, check_call_mock, print_mock):
+    file_mock = mock.Mock()
+    open_mock.return_value.__enter__.return_value = file_mock
+    dt_mock.now.return_value.strftime.return_value = '_2018_12_10_16_22_11'
+
+    cli_helpers.check_log(
+        ['command', 'arg1'], '/tmp/tmpXYZ.tmp', env={'foo': 'bar'})
+
+    check_call_mock.assert_called_once_with(
+        ['command', 'arg1'], stdout=file_mock, stderr=subprocess.STDOUT,
+        shell=False, env={'foo': 'bar'})
+    open_mock.assert_called_once_with('/tmp/tmpXYZ.tmp', 'w')
+    self.assertListEqual(print_mock.mock_calls, [
+      mock.call('\033[94mcommand arg1\033[0m'),
+      mock.call('\033[94mLogging stdout & stderr to /tmp/tmpXYZ.tmp\033[0m'),
+    ])
+
+  @mock.patch('__builtin__.print')
+  @mock.patch('core.cli_helpers.error')
+  @mock.patch('subprocess.check_call')
+  @mock.patch('subprocess.call')
+  @mock.patch('__builtin__.open')
+  def testCheckLogError(
+      self, open_mock, call_mock, check_call_mock, error_mock, print_mock):
+    del print_mock, open_mock  # Unused.
+    check_call_mock.side_effect = [subprocess.CalledProcessError(87, ['cmd'])]
+
+    with self.assertRaises(subprocess.CalledProcessError):
+      cli_helpers.check_log(['cmd'], '/tmp/tmpXYZ.tmp')
+
+    call_mock.assert_called_once_with(['cat', '/tmp/tmpXYZ.tmp'])
+    self.assertListEqual(error_mock.mock_calls, [
+      mock.call('=' * 80),
+      mock.call('Received non-zero return code. Log content:'),
+      mock.call('=' * 80),
+      mock.call('=' * 80),
+    ])
+
+  @mock.patch('__builtin__.print')
+  @mock.patch('subprocess.check_call')
+  def testRun(self, check_call_mock, print_mock):
+    check_call_mock.side_effect = [subprocess.CalledProcessError(87, ['cmd'])]
+    with self.assertRaises(subprocess.CalledProcessError):
+      cli_helpers.run(['cmd', 'arg with space'], env={'a': 'b'})
+    check_call_mock.assert_called_once_with(
+        ['cmd', 'arg with space'], env={'a': 'b'})
+    print_mock.assert_called_once_with('\033[94mcmd \'arg with space\'\033[0m')
+
+  @mock.patch('__builtin__.print')
+  @mock.patch('subprocess.check_call')
+  def testRunOkFail(self, check_call_mock, print_mock):
+    del print_mock  # Unused.
+    check_call_mock.side_effect = [subprocess.CalledProcessError(87, ['cmd'])]
+    cli_helpers.run(['cmd'], ok_fail=True)
+
+  def testRunWithNonListCommand(self):
+    with self.assertRaises(ValueError):
+      cli_helpers.run('cmd with args')
+
+
+if __name__ == "__main__":
+  unittest.main()
diff --git a/ui/base/ime/dummy_text_input_client.cc b/ui/base/ime/dummy_text_input_client.cc
index 3299270..34dfc79 100644
--- a/ui/base/ime/dummy_text_input_client.cc
+++ b/ui/base/ime/dummy_text_input_client.cc
@@ -92,11 +92,11 @@
   return false;
 }
 
-bool DummyTextInputClient::GetSelectionRange(gfx::Range* range) const {
+bool DummyTextInputClient::GetEditableSelectionRange(gfx::Range* range) const {
   return false;
 }
 
-bool DummyTextInputClient::SetSelectionRange(const gfx::Range& range) {
+bool DummyTextInputClient::SetEditableSelectionRange(const gfx::Range& range) {
   selection_history_.push_back(range);
   return false;
 }
diff --git a/ui/base/ime/dummy_text_input_client.h b/ui/base/ime/dummy_text_input_client.h
index acc72b86..e313b035 100644
--- a/ui/base/ime/dummy_text_input_client.h
+++ b/ui/base/ime/dummy_text_input_client.h
@@ -40,8 +40,8 @@
   ui::TextInputClient::FocusReason GetFocusReason() const override;
   bool GetTextRange(gfx::Range* range) const override;
   bool GetCompositionTextRange(gfx::Range* range) const override;
-  bool GetSelectionRange(gfx::Range* range) const override;
-  bool SetSelectionRange(const gfx::Range& range) override;
+  bool GetEditableSelectionRange(gfx::Range* range) const override;
+  bool SetEditableSelectionRange(const gfx::Range& range) override;
   bool DeleteRange(const gfx::Range& range) override;
   bool GetTextFromRange(const gfx::Range& range,
                         base::string16* text) const override;
diff --git a/ui/base/ime/input_method_auralinux.cc b/ui/base/ime/input_method_auralinux.cc
index f7343b3..9a79312 100644
--- a/ui/base/ime/input_method_auralinux.cc
+++ b/ui/base/ime/input_method_auralinux.cc
@@ -281,7 +281,7 @@
   base::string16 text;
   if (client->GetTextRange(&text_range) &&
       client->GetTextFromRange(text_range, &text) &&
-      client->GetSelectionRange(&selection_range)) {
+      client->GetEditableSelectionRange(&selection_range)) {
     context_->SetSurroundingText(text, selection_range);
   }
 
diff --git a/ui/base/ime/input_method_auralinux_unittest.cc b/ui/base/ime/input_method_auralinux_unittest.cc
index 24963915..cc67ef7 100644
--- a/ui/base/ime/input_method_auralinux_unittest.cc
+++ b/ui/base/ime/input_method_auralinux_unittest.cc
@@ -252,7 +252,7 @@
     *range = text_range;
     return true;
   }
-  bool GetSelectionRange(gfx::Range* range) const override {
+  bool GetEditableSelectionRange(gfx::Range* range) const override {
     *range = selection_range;
     return true;
   }
diff --git a/ui/base/ime/input_method_base.cc b/ui/base/ime/input_method_base.cc
index 76f14cac..fc96c61b 100644
--- a/ui/base/ime/input_method_base.cc
+++ b/ui/base/ime/input_method_base.cc
@@ -259,7 +259,7 @@
   TextInputClient* client = GetTextInputClient();
   if (!client->GetTextRange(&text_range) ||
       !client->GetTextFromRange(text_range, &info.surrounding_text) ||
-      !client->GetSelectionRange(&info.selection_range)) {
+      !client->GetEditableSelectionRange(&info.selection_range)) {
     return SurroundingTextInfo();
   }
   return info;
diff --git a/ui/base/ime/input_method_chromeos.cc b/ui/base/ime/input_method_chromeos.cc
index 918bd6e..79a9f5a6f 100644
--- a/ui/base/ime/input_method_chromeos.cc
+++ b/ui/base/ime/input_method_chromeos.cc
@@ -240,7 +240,7 @@
   base::string16 surrounding_text;
   if (!client->GetTextRange(&text_range) ||
       !client->GetTextFromRange(text_range, &surrounding_text) ||
-      !client->GetSelectionRange(&selection_range)) {
+      !client->GetEditableSelectionRange(&selection_range)) {
     previous_surrounding_text_.clear();
     previous_selection_range_ = gfx::Range::InvalidRange();
     return;
diff --git a/ui/base/ime/input_method_chromeos_unittest.cc b/ui/base/ime/input_method_chromeos_unittest.cc
index 5b4a72a8..3ab3975 100644
--- a/ui/base/ime/input_method_chromeos_unittest.cc
+++ b/ui/base/ime/input_method_chromeos_unittest.cc
@@ -275,7 +275,7 @@
     *range = text_range_;
     return true;
   }
-  bool GetSelectionRange(gfx::Range* range) const override {
+  bool GetEditableSelectionRange(gfx::Range* range) const override {
     *range = selection_range_;
     return true;
   }
diff --git a/ui/base/ime/input_method_win_base.cc b/ui/base/ime/input_method_win_base.cc
index 333607e7..6b7c3be 100644
--- a/ui/base/ime/input_method_win_base.cc
+++ b/ui/base/ime/input_method_win_base.cc
@@ -350,7 +350,8 @@
     result = client->GetCompositionTextRange(&target_range);
 
   if (!result || target_range.is_empty()) {
-    if (!client->GetSelectionRange(&target_range) || !target_range.IsValid()) {
+    if (!client->GetEditableSelectionRange(&target_range) ||
+        !target_range.IsValid()) {
       return 0;
     }
   }
@@ -411,7 +412,7 @@
     return 0;
 
   gfx::Range selection_range;
-  if (!client->GetSelectionRange(&selection_range) ||
+  if (!client->GetEditableSelectionRange(&selection_range) ||
       selection_range.is_empty()) {
     return 0;
   }
diff --git a/ui/base/ime/text_input_client.h b/ui/base/ime/text_input_client.h
index c475c43..4bcaf18c 100644
--- a/ui/base/ime/text_input_client.h
+++ b/ui/base/ime/text_input_client.h
@@ -127,23 +127,25 @@
   // Returns false if the information cannot be retrieved right now.
   virtual bool GetCompositionTextRange(gfx::Range* range) const = 0;
 
-  // Retrieves the UTF-16 based character range of current selection.
-  // Returns false if the information cannot be retrieved right now.
-  virtual bool GetSelectionRange(gfx::Range* range) const = 0;
+  // Retrieves the UTF-16 based character range of current selection in the text
+  // input. Returns false if the information cannot be retrieved right now.
+  // Returns false if the selected text is outside of the text input (== the
+  // text input is not focused)
+  virtual bool GetEditableSelectionRange(gfx::Range* range) const = 0;
 
   // Selects the given UTF-16 based character range. Current composition text
   // will be confirmed before selecting the range.
   // Returns false if the operation is not supported.
-  virtual bool SetSelectionRange(const gfx::Range& range) = 0;
+  virtual bool SetEditableSelectionRange(const gfx::Range& range) = 0;
 
   // Deletes contents in the given UTF-16 based character range. Current
   // composition text will be confirmed before deleting the range.
   // The input caret will be moved to the place where the range gets deleted.
   // ExtendSelectionAndDelete should be used instead as far as you are deleting
   // characters around current caret. This function with the range based on
-  // GetSelectionRange has a race condition due to asynchronous IPCs between
-  // browser and renderer.
-  // Returns false if the operation is not supported.
+  // GetEditableSelectionRange has a race condition due to asynchronous IPCs
+  // between browser and renderer. Returns false if the operation is not
+  // supported.
   virtual bool DeleteRange(const gfx::Range& range) = 0;
 
   // Retrieves the text content in a given UTF-16 based character range.
@@ -168,9 +170,9 @@
 
   // Deletes the current selection plus the specified number of characters
   // before and after the selection or caret. This function should be used
-  // instead of calling DeleteRange with GetSelectionRange, because
-  // GetSelectionRange may not be the latest value due to asynchronous of IPC
-  // between browser and renderer.
+  // instead of calling DeleteRange with GetEditableSelectionRange, because
+  // GetEditableSelectionRange may not be the latest value due to asynchronous
+  // of IPC between browser and renderer.
   virtual void ExtendSelectionAndDelete(size_t before, size_t after) = 0;
 
   // Ensure the caret is not in |rect|.  |rect| is in screen coordinates in
diff --git a/ui/base/ime/win/tsf_text_store_unittest.cc b/ui/base/ime/win/tsf_text_store_unittest.cc
index a65641e1..ed22f58 100644
--- a/ui/base/ime/win/tsf_text_store_unittest.cc
+++ b/ui/base/ime/win/tsf_text_store_unittest.cc
@@ -47,8 +47,8 @@
   MOCK_METHOD0(ShouldDoLearning, bool());
   MOCK_CONST_METHOD1(GetTextRange, bool(gfx::Range*));
   MOCK_CONST_METHOD1(GetCompositionTextRange, bool(gfx::Range*));
-  MOCK_CONST_METHOD1(GetSelectionRange, bool(gfx::Range*));
-  MOCK_METHOD1(SetSelectionRange, bool(const gfx::Range&));
+  MOCK_CONST_METHOD1(GetEditableSelectionRange, bool(gfx::Range*));
+  MOCK_METHOD1(SetEditableSelectionRange, bool(const gfx::Range&));
   MOCK_METHOD1(DeleteRange, bool(const gfx::Range&));
   MOCK_CONST_METHOD2(GetTextFromRange,
                      bool(const gfx::Range&, base::string16*));
diff --git a/ui/message_center/views/notification_view_md.cc b/ui/message_center/views/notification_view_md.cc
index e9fff25..4f60cc5 100644
--- a/ui/message_center/views/notification_view_md.cc
+++ b/ui/message_center/views/notification_view_md.cc
@@ -800,7 +800,7 @@
 
     title_view_ = new views::Label(title);
     title_view_->SetFontList(font_list);
-    title_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+    title_view_->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD);
     title_view_->SetEnabledColor(kRegularTextColorMD);
     left_content_->AddChildViewAt(title_view_, left_content_count_);
   } else {
diff --git a/ui/native_theme/OWNERS b/ui/native_theme/OWNERS
index 7768376..b3faa6e 100644
--- a/ui/native_theme/OWNERS
+++ b/ui/native_theme/OWNERS
@@ -1,3 +1,4 @@
+ellyjones@chromium.org
 estade@chromium.org
 pkasting@chromium.org
 
diff --git a/ui/native_theme/native_theme_mac.mm b/ui/native_theme/native_theme_mac.mm
index 9f98cd9..3c4bc11 100644
--- a/ui/native_theme/native_theme_mac.mm
+++ b/ui/native_theme/native_theme_mac.mm
@@ -155,20 +155,12 @@
 void NativeThemeMac::MaybeUpdateBrowserAppearance() {
   if (@available(macOS 10.14, *)) {
     if (!base::FeatureList::IsEnabled(features::kDarkMode)) {
-      ui::NativeTheme* theme = ui::NativeTheme::GetInstanceForNativeUi();
-      NSAppearanceName new_appearance_name;
-      if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-              switches::kForceDarkMode)) {
-        new_appearance_name =
-            theme->UsesHighContrastColors()
-                ? NSAppearanceNameAccessibilityHighContrastDarkAqua
-                : NSAppearanceNameDarkAqua;
-      } else {
-        new_appearance_name =
-            theme->UsesHighContrastColors()
-                ? NSAppearanceNameAccessibilityHighContrastAqua
-                : NSAppearanceNameAqua;
-      }
+      NSAppearanceName new_appearance_name =
+          base::CommandLine::ForCurrentProcess()->HasSwitch(
+              switches::kForceDarkMode)
+              ? NSAppearanceNameDarkAqua
+              : NSAppearanceNameAqua;
+
       [NSApp setAppearance:[NSAppearance appearanceNamed:new_appearance_name]];
     }
   }
@@ -295,7 +287,6 @@
                     object:nil
                      queue:nil
                 usingBlock:^(NSNotification* notification) {
-                  ui::NativeThemeMac::MaybeUpdateBrowserAppearance();
                   ui::NativeTheme::GetInstanceForNativeUi()->NotifyObservers();
                 }];
   }
diff --git a/ui/views/cocoa/bridged_native_widget_unittest.mm b/ui/views/cocoa/bridged_native_widget_unittest.mm
index 8f19410..5c729fcd 100644
--- a/ui/views/cocoa/bridged_native_widget_unittest.mm
+++ b/ui/views/cocoa/bridged_native_widget_unittest.mm
@@ -591,7 +591,7 @@
 
 void BridgedNativeWidgetTest::SetSelectionRange(NSRange range) {
   ui::TextInputClient* client = [ns_view_ textInputClient];
-  client->SetSelectionRange(gfx::Range(range));
+  client->SetEditableSelectionRange(gfx::Range(range));
 
   [dummy_text_view_ setSelectedRange:range];
 }
@@ -607,7 +607,7 @@
 
   // Although a gfx::Range is directed, the underlying model will not choose an
   // affinity until the cursor is moved.
-  client->SetSelectionRange(range);
+  client->SetEditableSelectionRange(range);
 
   // Set the range without an affinity. The first @selector sent to the text
   // field determines the affinity. Note that Range::ToNSRange() may discard
diff --git a/ui/views/controls/prefix_selector.cc b/ui/views/controls/prefix_selector.cc
index 98aab8c..fe8decc9 100644
--- a/ui/views/controls/prefix_selector.cc
+++ b/ui/views/controls/prefix_selector.cc
@@ -112,12 +112,12 @@
   return false;
 }
 
-bool PrefixSelector::GetSelectionRange(gfx::Range* range) const {
+bool PrefixSelector::GetEditableSelectionRange(gfx::Range* range) const {
   *range = gfx::Range();
   return false;
 }
 
-bool PrefixSelector::SetSelectionRange(const gfx::Range& range) {
+bool PrefixSelector::SetEditableSelectionRange(const gfx::Range& range) {
   return false;
 }
 
diff --git a/ui/views/controls/prefix_selector.h b/ui/views/controls/prefix_selector.h
index 801c9112..de9caa3 100644
--- a/ui/views/controls/prefix_selector.h
+++ b/ui/views/controls/prefix_selector.h
@@ -55,8 +55,8 @@
   FocusReason GetFocusReason() const override;
   bool GetTextRange(gfx::Range* range) const override;
   bool GetCompositionTextRange(gfx::Range* range) const override;
-  bool GetSelectionRange(gfx::Range* range) const override;
-  bool SetSelectionRange(const gfx::Range& range) override;
+  bool GetEditableSelectionRange(gfx::Range* range) const override;
+  bool SetEditableSelectionRange(const gfx::Range& range) override;
   bool DeleteRange(const gfx::Range& range) override;
   bool GetTextFromRange(const gfx::Range& range,
                         base::string16* text) const override;
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc
index 2ff6033..90968d5c 100644
--- a/ui/views/controls/textfield/textfield.cc
+++ b/ui/views/controls/textfield/textfield.cc
@@ -1046,7 +1046,7 @@
       return false;
     // TODO(nektar): Check that the focus_node_id matches the ID of this node.
     const gfx::Range range(action_data.anchor_offset, action_data.focus_offset);
-    return SetSelectionRange(range);
+    return SetEditableSelectionRange(range);
   }
 
   // Remaining actions cannot be performed on readonly fields.
@@ -1590,14 +1590,14 @@
   return true;
 }
 
-bool Textfield::GetSelectionRange(gfx::Range* range) const {
+bool Textfield::GetEditableSelectionRange(gfx::Range* range) const {
   if (!ImeEditingAllowed())
     return false;
   *range = GetRenderText()->selection();
   return true;
 }
 
-bool Textfield::SetSelectionRange(const gfx::Range& range) {
+bool Textfield::SetEditableSelectionRange(const gfx::Range& range) {
   if (!ImeEditingAllowed() || !range.IsValid())
     return false;
   OnBeforeUserAction();
diff --git a/ui/views/controls/textfield/textfield.h b/ui/views/controls/textfield/textfield.h
index f5d0914..38b5655 100644
--- a/ui/views/controls/textfield/textfield.h
+++ b/ui/views/controls/textfield/textfield.h
@@ -349,8 +349,8 @@
   FocusReason GetFocusReason() const override;
   bool GetTextRange(gfx::Range* range) const override;
   bool GetCompositionTextRange(gfx::Range* range) const override;
-  bool GetSelectionRange(gfx::Range* range) const override;
-  bool SetSelectionRange(const gfx::Range& range) override;
+  bool GetEditableSelectionRange(gfx::Range* range) const override;
+  bool SetEditableSelectionRange(const gfx::Range& range) override;
   bool DeleteRange(const gfx::Range& range) override;
   bool GetTextFromRange(const gfx::Range& range,
                         base::string16* text) const override;
diff --git a/ui/views/controls/textfield/textfield_unittest.cc b/ui/views/controls/textfield/textfield_unittest.cc
index 879ebf11..7b3f7fd 100644
--- a/ui/views/controls/textfield/textfield_unittest.cc
+++ b/ui/views/controls/textfield/textfield_unittest.cc
@@ -970,7 +970,7 @@
   textfield_->SetText(ASCIIToUTF16("12 34567 89"));
 
   // Place the cursor after "5".
-  textfield_->SetSelectionRange(gfx::Range(6));
+  textfield_->SetEditableSelectionRange(gfx::Range(6));
 
   // Select word towards right.
   SendWordEvent(ui::VKEY_RIGHT, true);
@@ -1013,7 +1013,7 @@
   textfield_->SetText(ASCIIToUTF16("12 34567 89"));
 
   // Place the cursor after "5".
-  textfield_->SetSelectionRange(gfx::Range(6));
+  textfield_->SetEditableSelectionRange(gfx::Range(6));
 
   // Select line towards right.
   SendEndEvent(true);
@@ -1042,7 +1042,7 @@
 TEST_F(TextfieldTest, MoveUpDownAndModifySelection) {
   InitTextfield();
   textfield_->SetText(ASCIIToUTF16("12 34567 89"));
-  textfield_->SetSelectionRange(gfx::Range(6));
+  textfield_->SetEditableSelectionRange(gfx::Range(6));
 
   // Up/Down keys won't be handled except on Mac where they map to move
   // commands.
@@ -1066,7 +1066,7 @@
 #endif
   textfield_->clear();
 
-  textfield_->SetSelectionRange(gfx::Range(6));
+  textfield_->SetEditableSelectionRange(gfx::Range(6));
 
   // Shift+[Up/Down] should select the text to the beginning and end of the
   // line, respectively.
@@ -1090,7 +1090,7 @@
 // enabled on Mac.
 #if defined(OS_MACOSX)
   textfield_->SetText(ASCIIToUTF16("12 34567 89"));
-  textfield_->SetSelectionRange(gfx::Range(6));
+  textfield_->SetEditableSelectionRange(gfx::Range(6));
 
   EXPECT_TRUE(
       textfield_->IsTextEditCommandEnabled(ui::TextEditCommand::MOVE_PAGE_UP));
@@ -1107,7 +1107,7 @@
   test_api_->ExecuteTextEditCommand(ui::TextEditCommand::MOVE_PAGE_DOWN);
   EXPECT_EQ(gfx::Range(11), textfield_->GetSelectedRange());
 
-  textfield_->SetSelectionRange(gfx::Range(6));
+  textfield_->SetEditableSelectionRange(gfx::Range(6));
   test_api_->ExecuteTextEditCommand(
       ui::TextEditCommand::MOVE_PAGE_UP_AND_MODIFY_SELECTION);
   EXPECT_EQ(gfx::Range(6, 0), textfield_->GetSelectedRange());
@@ -1130,7 +1130,7 @@
 TEST_F(TextfieldTest, MoveParagraphForwardBackwardAndModifySelection) {
   InitTextfield();
   textfield_->SetText(ASCIIToUTF16("12 34567 89"));
-  textfield_->SetSelectionRange(gfx::Range(6));
+  textfield_->SetEditableSelectionRange(gfx::Range(6));
 
   test_api_->ExecuteTextEditCommand(
       ui::TextEditCommand::MOVE_PARAGRAPH_FORWARD_AND_MODIFY_SELECTION);
@@ -2001,8 +2001,8 @@
   EXPECT_EQ(0U, range.start());
   EXPECT_EQ(10U, range.end());
 
-  EXPECT_TRUE(client->SetSelectionRange(gfx::Range(1, 4)));
-  EXPECT_TRUE(client->GetSelectionRange(&range));
+  EXPECT_TRUE(client->SetEditableSelectionRange(gfx::Range(1, 4)));
+  EXPECT_TRUE(client->GetEditableSelectionRange(&range));
   EXPECT_EQ(gfx::Range(1, 4), range);
 
   base::string16 substring;
@@ -2064,7 +2064,7 @@
 
   textfield_->clear();
   textfield_->SetText(ASCIIToUTF16("0123456789"));
-  EXPECT_TRUE(client->SetSelectionRange(gfx::Range(5, 5)));
+  EXPECT_TRUE(client->SetEditableSelectionRange(gfx::Range(5, 5)));
   client->ExtendSelectionAndDelete(4, 2);
   EXPECT_STR_EQ("0789", textfield_->text());
 
@@ -3227,23 +3227,23 @@
 
   // Select range |sel_range| and check if touch selection handles are not
   // present and correct range is selected.
-  textfield_->SetSelectionRange(sel_range);
+  textfield_->SetEditableSelectionRange(sel_range);
   gfx::Range range;
-  textfield_->GetSelectionRange(&range);
+  textfield_->GetEditableSelectionRange(&range);
   EXPECT_FALSE(test_api_->touch_selection_controller());
   EXPECT_EQ(sel_range, range);
 
   // Tap on selection and check if touch selectoin handles are shown, but
   // selection range is not modified.
   Tap(tap_point);
-  textfield_->GetSelectionRange(&range);
+  textfield_->GetEditableSelectionRange(&range);
   EXPECT_TRUE(test_api_->touch_selection_controller());
   EXPECT_EQ(sel_range, range);
 
   // Tap again on selection and check if touch selection handles are still
   // present and selection is changed to a cursor at tap location.
   Tap(tap_point);
-  textfield_->GetSelectionRange(&range);
+  textfield_->GetEditableSelectionRange(&range);
   EXPECT_TRUE(test_api_->touch_selection_controller());
   EXPECT_EQ(tap_range, range);
 }
diff --git a/ui/views/controls/webview/webview_unittest.cc b/ui/views/controls/webview/webview_unittest.cc
index 27be01b..3b4b95b1 100644
--- a/ui/views/controls/webview/webview_unittest.cc
+++ b/ui/views/controls/webview/webview_unittest.cc
@@ -125,7 +125,9 @@
 // Provides functionality to test a WebView.
 class WebViewUnitTest : public views::test::WidgetTest {
  public:
-  WebViewUnitTest() = default;
+  WebViewUnitTest()
+      : views::test::WidgetTest(
+            std::make_unique<content::TestBrowserThreadBundle>()) {}
 
   ~WebViewUnitTest() override {}
 
@@ -187,7 +189,6 @@
   }
 
  private:
-  content::TestBrowserThreadBundle test_browser_thread_bundle_;
   content::RenderViewHostTestEnabler rvh_enabler_;
   std::unique_ptr<content::TestBrowserContext> browser_context_;
   content::TestContentBrowserClient test_browser_client_;
diff --git a/ui/views/examples/label_example.cc b/ui/views/examples/label_example.cc
index 87189250..e1df4fe 100644
--- a/ui/views/examples/label_example.cc
+++ b/ui/views/examples/label_example.cc
@@ -181,7 +181,7 @@
   textfield_ = new Textfield();
   textfield_->SetText(ASCIIToUTF16("Use the provided controls to configure the "
       "content and presentation of this custom label."));
-  textfield_->SetSelectionRange(gfx::Range());
+  textfield_->SetEditableSelectionRange(gfx::Range());
   textfield_->set_controller(this);
   layout->AddView(textfield_);
 
diff --git a/ui/views/test/views_test_base.cc b/ui/views/test/views_test_base.cc
index 7f0542d..633235b 100644
--- a/ui/views/test/views_test_base.cc
+++ b/ui/views/test/views_test_base.cc
@@ -46,9 +46,9 @@
 
 }  // namespace
 
-ViewsTestBase::ViewsTestBase()
-    : scoped_task_environment_(
-          base::test::ScopedTaskEnvironment::MainThreadType::UI),
+ViewsTestBase::ViewsTestBase(
+    std::unique_ptr<ScopedTaskEnvironment> scoped_task_environment)
+    : scoped_task_environment_(std::move(scoped_task_environment)),
       setup_called_(false),
       teardown_called_(false),
       has_compositing_manager_(InitializeVisuals()) {}
diff --git a/ui/views/test/views_test_base.h b/ui/views/test/views_test_base.h
index 7702736..88a0b8c 100644
--- a/ui/views/test/views_test_base.h
+++ b/ui/views/test/views_test_base.h
@@ -26,7 +26,13 @@
 // to drive UI events and takes care of OLE initialization for windows.
 class ViewsTestBase : public PlatformTest {
  public:
-  ViewsTestBase();
+  using ScopedTaskEnvironment = base::test::ScopedTaskEnvironment;
+
+  explicit ViewsTestBase(
+      std::unique_ptr<ScopedTaskEnvironment> scoped_task_environment =
+          std::make_unique<ScopedTaskEnvironment>(
+              ScopedTaskEnvironment::MainThreadType::UI));
+
   ~ViewsTestBase() override;
 
   // Returns true if running aura-mus in a client configuration (not the window
@@ -63,7 +69,7 @@
   gfx::NativeWindow GetContext();
 
  private:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  std::unique_ptr<ScopedTaskEnvironment> scoped_task_environment_;
   std::unique_ptr<TestViewsDelegate> views_delegate_for_setup_;
   std::unique_ptr<ScopedViewsTestHelper> test_helper_;
   bool setup_called_;
diff --git a/ui/views/test/widget_test.cc b/ui/views/test/widget_test.cc
index 91f1691..95f83fe2 100644
--- a/ui/views/test/widget_test.cc
+++ b/ui/views/test/widget_test.cc
@@ -30,7 +30,9 @@
   widget->CloseNow();
 }
 
-WidgetTest::WidgetTest() {}
+WidgetTest::WidgetTest(
+    std::unique_ptr<ScopedTaskEnvironment> scoped_task_environment)
+    : ViewsTestBase(std::move(scoped_task_environment)) {}
 WidgetTest::~WidgetTest() {}
 
 Widget* WidgetTest::CreateTopLevelPlatformWidget() {
diff --git a/ui/views/test/widget_test.h b/ui/views/test/widget_test.h
index 2e871d9..3a3c082 100644
--- a/ui/views/test/widget_test.h
+++ b/ui/views/test/widget_test.h
@@ -44,7 +44,10 @@
 
   using WidgetAutoclosePtr = std::unique_ptr<Widget, WidgetCloser>;
 
-  WidgetTest();
+  explicit WidgetTest(
+      std::unique_ptr<ScopedTaskEnvironment> scoped_task_environment =
+          std::make_unique<ScopedTaskEnvironment>(
+              ScopedTaskEnvironment::MainThreadType::UI));
   ~WidgetTest() override;
 
   // Create Widgets with |native_widget| in InitParams set to an instance of
diff --git a/ui/views_bridge_mac/bridged_content_view.mm b/ui/views_bridge_mac/bridged_content_view.mm
index 397425e..08f50f84 100644
--- a/ui/views_bridge_mac/bridged_content_view.mm
+++ b/ui/views_bridge_mac/bridged_content_view.mm
@@ -97,7 +97,7 @@
 
   // If possible, modify actual_range to correspond to caret position.
   gfx::Range selection_range;
-  if (client->GetSelectionRange(&selection_range)) {
+  if (client->GetEditableSelectionRange(&selection_range)) {
     // Caret bounds correspond to end index of selection_range.
     *actual_range = gfx::Range(selection_range.end());
   }
@@ -1377,7 +1377,7 @@
     return NO;
 
   gfx::Range selectionRange;
-  if (!textInputClient_->GetSelectionRange(&selectionRange))
+  if (!textInputClient_->GetEditableSelectionRange(&selectionRange))
     return NO;
 
   base::string16 text;
@@ -1513,7 +1513,7 @@
     return NSMakeRange(NSNotFound, 0);
 
   gfx::Range range;
-  textInputClient_->GetSelectionRange(&range);
+  textInputClient_->GetEditableSelectionRange(&range);
   return range.ToNSRange();
 }