diff --git a/DEPS b/DEPS
index a00141e1..404001f 100644
--- a/DEPS
+++ b/DEPS
@@ -138,11 +138,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': '1811d1615ecb2810362ba552481494990b655a33',
+  'skia_revision': '384981be3dd2f98226a748628ace453a481050f9',
   # 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': '1bd055718ebc189f9ef28293898a6e96f7ff86be',
+  'v8_revision': '994af5984123b8daa5e26d584f6de961facd1f57',
   # 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.
@@ -150,7 +150,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': '3ea463bfa4ed941977fcb25055bddebe2b749a83',
+  'angle_revision': '661ed41972281348a8dfd9be682853a4382ca583',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -158,7 +158,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '99cfd6bbb447e1143c2717cb274a07141400c7c5',
+  'pdfium_revision': '0df52b5ccb27dab0bbcbec26c1d2f9ccd9203d11',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -201,7 +201,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': 'c1a8f15f6618f1910d1114b8398ae626f782d02c',
+  'catapult_revision': '94c77e7ec6164015e09be1463642987391ef5577',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -477,7 +477,7 @@
   },
 
   'src/ios/third_party/material_components_ios/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '0f1656a03a06f4c00561bf0664833125bdf4c08e',
+      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'e90aa11c4be39bce72ea4a05709f7ed3d5c7a438',
       'condition': 'checkout_ios',
   },
 
@@ -655,7 +655,7 @@
       'packages': [
           {
        'package': 'chromium/third_party/android_tools_bundletool',
-       'version': 'bGlR4jA25RgxNi_eSTqm3lX-DvXyHELRfoYIWkmfY1EC',
+       'version': 'sZ4fDz_PUiCe1yvyheO_yjeET3eVhFTFTmGaXsnrH9IC',
    },
       ],
       'condition': 'checkout_android',
@@ -807,7 +807,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'fd29621e673289e0bf3aefa4880955c225e8a91a',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '1f3511e80546f907078062d3bf99d2b2bb7b75f6',
       'condition': 'checkout_linux',
   },
 
@@ -832,7 +832,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '53ea429070b1d8c359f90309fd340b26d149a143',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '125f7cc4d52d831830561ebfed0d26bfa074003f',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -1396,7 +1396,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@7eef59e95dabbd5246b41a402a7c7ed3796045bd',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@2134e94151338bff9a4f88796c4e6e18c6d0eec9',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/ash/DEPS b/ash/DEPS
index 4584fdf..a219714 100644
--- a/ash/DEPS
+++ b/ash/DEPS
@@ -92,9 +92,6 @@
   "login_types\.*": [
     "+chromeos/components/proximity_auth/public/interfaces/auth_type.mojom.h",
   ],
-  "message_center_controller\.*": [
-    "+components/arc/common/notifications.mojom.h"
-  ],
   "policy_recommendation_restorer_unittest.cc": [
     "+components/sync_preferences/testing_pref_service_syncable.h"
   ],
diff --git a/ash/accessibility/accessibility_controller.cc b/ash/accessibility/accessibility_controller.cc
index 9085810..2cdf6b2a 100644
--- a/ash/accessibility/accessibility_controller.cc
+++ b/ash/accessibility/accessibility_controller.cc
@@ -5,6 +5,7 @@
 #include "ash/accessibility/accessibility_controller.h"
 
 #include <memory>
+#include <set>
 #include <utility>
 
 #include "ash/accelerators/accelerator_controller_impl.h"
@@ -237,6 +238,20 @@
       container->layout_manager());
 }
 
+std::string PrefKeyForSwitchAccessCommand(mojom::SwitchAccessCommand command) {
+  switch (command) {
+    case mojom::SwitchAccessCommand::kSelect:
+      return prefs::kAccessibilitySwitchAccessSelectKeyCodes;
+    case mojom::SwitchAccessCommand::kNext:
+      return prefs::kAccessibilitySwitchAccessNextKeyCodes;
+    case mojom::SwitchAccessCommand::kPrevious:
+      return prefs::kAccessibilitySwitchAccessPreviousKeyCodes;
+    case mojom::SwitchAccessCommand::kNone:
+      NOTREACHED();
+      return "";
+  }
+}
+
 }  // namespace
 
 AccessibilityController::AccessibilityController()
@@ -790,6 +805,13 @@
     switch_access_event_handler_->FlushMojoForTest();
 }
 
+SwitchAccessEventHandler*
+AccessibilityController::GetSwitchAccessEventHandlerForTest() {
+  if (switch_access_event_handler_)
+    return switch_access_event_handler_.get();
+  return nullptr;
+}
+
 void AccessibilityController::OnTabletModeStarted() {
   if (spoken_feedback_enabled())
     ShowAccessibilityNotification(A11yNotificationType::kSpokenFeedbackEnabled);
@@ -895,6 +917,21 @@
       base::BindRepeating(&AccessibilityController::UpdateSwitchAccessFromPref,
                           base::Unretained(this)));
   pref_change_registrar_->Add(
+      prefs::kAccessibilitySwitchAccessSelectKeyCodes,
+      base::BindRepeating(
+          &AccessibilityController::UpdateSwitchAccessKeyCodesFromPref,
+          base::Unretained(this), mojom::SwitchAccessCommand::kSelect));
+  pref_change_registrar_->Add(
+      prefs::kAccessibilitySwitchAccessNextKeyCodes,
+      base::BindRepeating(
+          &AccessibilityController::UpdateSwitchAccessKeyCodesFromPref,
+          base::Unretained(this), mojom::SwitchAccessCommand::kNext));
+  pref_change_registrar_->Add(
+      prefs::kAccessibilitySwitchAccessPreviousKeyCodes,
+      base::BindRepeating(
+          &AccessibilityController::UpdateSwitchAccessKeyCodesFromPref,
+          base::Unretained(this), mojom::SwitchAccessCommand::kPrevious));
+  pref_change_registrar_->Add(
       prefs::kAccessibilityVirtualKeyboardEnabled,
       base::BindRepeating(
           &AccessibilityController::UpdateVirtualKeyboardFromPref,
@@ -1243,6 +1280,24 @@
   NotifyAccessibilityStatusChanged();
 }
 
+void AccessibilityController::UpdateSwitchAccessKeyCodesFromPref(
+    mojom::SwitchAccessCommand command) {
+  if (!switch_access_event_handler_)
+    return;
+
+  DCHECK(active_user_prefs_);
+
+  std::string pref_key = PrefKeyForSwitchAccessCommand(command);
+  const base::ListValue* key_codes_pref = active_user_prefs_->GetList(pref_key);
+  std::set<int> key_codes;
+  for (const base::Value& v : *key_codes_pref) {
+    int key_code = v.GetInt();
+    key_codes.insert(key_code);
+  }
+
+  switch_access_event_handler_->SetKeyCodesForCommand(key_codes, command);
+}
+
 void AccessibilityController::MaybeCreateSwitchAccessEventHandler() {
   // Sometimes the handler is not yet created if the prefs change has taken
   // longer to propogate than setting the delegate from Chrome.
@@ -1255,6 +1310,14 @@
 
   switch_access_event_handler_ = std::make_unique<SwitchAccessEventHandler>(
       std::move(switch_access_event_handler_delegate_ptr_));
+
+  if (!active_user_prefs_)
+    return;
+
+  // Update the key codes for each command once the handler is initialized.
+  UpdateSwitchAccessKeyCodesFromPref(mojom::SwitchAccessCommand::kSelect);
+  UpdateSwitchAccessKeyCodesFromPref(mojom::SwitchAccessCommand::kNext);
+  UpdateSwitchAccessKeyCodesFromPref(mojom::SwitchAccessCommand::kPrevious);
 }
 
 void AccessibilityController::UpdateVirtualKeyboardFromPref() {
diff --git a/ash/accessibility/accessibility_controller.h b/ash/accessibility/accessibility_controller.h
index 87eccb70..5c03a0b 100644
--- a/ash/accessibility/accessibility_controller.h
+++ b/ash/accessibility/accessibility_controller.h
@@ -199,6 +199,7 @@
 
   // Test helpers:
   void FlushMojoForTest();
+  SwitchAccessEventHandler* GetSwitchAccessEventHandlerForTest();
 
  private:
   // TabletModeObserver:
@@ -227,6 +228,7 @@
   void UpdateSelectToSpeakFromPref();
   void UpdateStickyKeysFromPref();
   void UpdateSwitchAccessFromPref();
+  void UpdateSwitchAccessKeyCodesFromPref(mojom::SwitchAccessCommand command);
   void UpdateVirtualKeyboardFromPref();
   void UpdateAccessibilityHighlightingFromPrefs();
 
diff --git a/ash/events/switch_access_event_handler.cc b/ash/events/switch_access_event_handler.cc
index 121c92c..5a4ae41 100644
--- a/ash/events/switch_access_event_handler.cc
+++ b/ash/events/switch_access_event_handler.cc
@@ -4,6 +4,8 @@
 
 #include "ash/events/switch_access_event_handler.h"
 
+#include <set>
+
 #include "ash/accessibility/accessibility_controller.h"
 #include "ash/shell.h"
 
@@ -41,13 +43,68 @@
   delegate_ptr_.FlushForTesting();
 }
 
+bool SwitchAccessEventHandler::SetKeyCodesForCommand(
+    std::set<int> new_key_codes,
+    mojom::SwitchAccessCommand command) {
+  bool has_changed = false;
+  std::set<int> to_clear;
+
+  // Clear old values that conflict with the new assignment.
+  for (const auto& val : command_for_key_code_) {
+    int old_key_code = val.first;
+    mojom::SwitchAccessCommand old_command = val.second;
+
+    if (new_key_codes.count(old_key_code) > 0) {
+      if (old_command != command) {
+        has_changed = true;
+        // Modifying the map while iterating through it causes reference
+        // failures.
+        to_clear.insert(old_key_code);
+      } else {
+        new_key_codes.erase(old_key_code);
+      }
+      continue;
+    }
+
+    // This value was previously mapped to the command, but is no longer.
+    if (old_command == command) {
+      has_changed = true;
+      to_clear.insert(old_key_code);
+      key_codes_to_capture_.erase(old_key_code);
+    }
+  }
+  for (int key_code : to_clear) {
+    command_for_key_code_.erase(key_code);
+  }
+
+  if (new_key_codes.size() == 0)
+    return has_changed;
+
+  // Add any new key codes to the map.
+  for (int key_code : new_key_codes) {
+    key_codes_to_capture_.insert(key_code);
+    command_for_key_code_[key_code] = command;
+  }
+
+  return true;
+}
+
 void SwitchAccessEventHandler::OnKeyEvent(ui::KeyEvent* event) {
   DCHECK(IsSwitchAccessEnabled());
   DCHECK(event);
 
   if (ShouldForwardEvent(*event)) {
     CancelEvent(event);
+    // TODO(anastasi): Remove event dispatch once settings migration is
+    // complete.
     delegate_ptr_->DispatchKeyEvent(ui::Event::Clone(*event));
+
+    // The Command events are currently sent, but ignored. The next step of the
+    // migration will be to switch from using the key events to using the
+    // commands, and the final step will be to remove the key events entirely.
+    mojom::SwitchAccessCommand command =
+        command_for_key_code_[event->key_code()];
+    delegate_ptr_->SendSwitchAccessCommand(command);
   }
 }
 
diff --git a/ash/events/switch_access_event_handler.h b/ash/events/switch_access_event_handler.h
index 035473f..200f1c40 100644
--- a/ash/events/switch_access_event_handler.h
+++ b/ash/events/switch_access_event_handler.h
@@ -21,10 +21,15 @@
   ~SwitchAccessEventHandler() override;
 
   // Sets the keys that are captured by Switch Access.
+  // TODO(anastasi): Remove this function after Settings migration is complete.
   void set_keys_to_capture(std::vector<int> keys) {
     keys_to_capture_ = std::set<int>(keys.begin(), keys.end());
   }
 
+  // Sets what key_codes are captured for a given command.
+  bool SetKeyCodesForCommand(std::set<int> key_codes,
+                             mojom::SwitchAccessCommand command);
+
   // Sets whether virtual key events should be ignored.
   void set_ignore_virtual_key_events(bool should_ignore) {
     ignore_virtual_key_events_ = should_ignore;
@@ -38,6 +43,13 @@
 
   // For testing usage only.
   void FlushMojoForTest();
+  const std::set<int> key_codes_to_capture_for_test() {
+    return key_codes_to_capture_;
+  }
+  const std::map<int, mojom::SwitchAccessCommand>
+  command_for_key_code_map_for_test() {
+    return command_for_key_code_;
+  }
 
  private:
   // ui::EventHandler:
@@ -48,7 +60,11 @@
   // The delegate used to send key events to the Switch Access extension.
   mojom::SwitchAccessEventHandlerDelegatePtr delegate_ptr_;
 
+  // TODO(anastasi): Remove this once the settings migration is complete.
   std::set<int> keys_to_capture_;
+
+  std::set<int> key_codes_to_capture_;
+  std::map<int, mojom::SwitchAccessCommand> command_for_key_code_;
   bool forward_key_events_ = false;
   bool ignore_virtual_key_events_ = true;
 
diff --git a/ash/events/switch_access_event_handler_unittest.cc b/ash/events/switch_access_event_handler_unittest.cc
index b7520993..d56110c 100644
--- a/ash/events/switch_access_event_handler_unittest.cc
+++ b/ash/events/switch_access_event_handler_unittest.cc
@@ -61,6 +61,8 @@
     key_events_.push_back(std::make_unique<ui::KeyEvent>(event->AsKeyEvent()));
   }
 
+  void SendSwitchAccessCommand(mojom::SwitchAccessCommand command) override {}
+
   mojo::Binding<mojom::SwitchAccessEventHandlerDelegate> binding_;
   std::vector<std::unique_ptr<ui::KeyEvent>> key_events_;
 
@@ -106,6 +108,22 @@
     return delegate_.get();
   }
 
+  const std::set<int> GetKeyCodesToCapture() {
+    SwitchAccessEventHandler* handler =
+        controller_->GetSwitchAccessEventHandlerForTest();
+    if (handler)
+      return handler->key_codes_to_capture_for_test();
+    return std::set<int>();
+  }
+
+  const std::map<int, mojom::SwitchAccessCommand> GetCommandForKeyCodeMap() {
+    SwitchAccessEventHandler* handler =
+        controller_->GetSwitchAccessEventHandlerForTest();
+    if (handler)
+      return handler->command_for_key_code_map_for_test();
+    return std::map<int, mojom::SwitchAccessCommand>();
+  }
+
  protected:
   ui::test::EventGenerator* generator_ = nullptr;
   EventCapturer event_capturer_;
@@ -243,5 +261,91 @@
   generator_->ReleaseKey(ui::VKEY_T, ui::EF_NONE);
 }
 
+TEST_F(SwitchAccessEventHandlerTest, SetKeyCodesForCommand) {
+  SwitchAccessEventHandler* handler =
+      controller_->GetSwitchAccessEventHandlerForTest();
+  EXPECT_NE(nullptr, handler);
+
+  // Both the key codes to capture and the command map should be empty.
+  EXPECT_EQ(0ul /* unsigned long */, GetKeyCodesToCapture().size());
+  EXPECT_EQ(0ul /* unsigned long */, GetCommandForKeyCodeMap().size());
+
+  // Set key codes for Select command.
+  std::set<int> new_key_codes;
+  new_key_codes.insert(48 /* '0' */);
+  new_key_codes.insert(83 /* 's' */);
+  handler->SetKeyCodesForCommand(new_key_codes,
+                                 mojom::SwitchAccessCommand::kSelect);
+
+  // Check that values are added to both data structures.
+  std::set<int> kc_to_capture = GetKeyCodesToCapture();
+  EXPECT_EQ(2ul /* unsigned long */, kc_to_capture.size());
+  EXPECT_EQ(1ul /* unsigned long */, kc_to_capture.count(48));
+  EXPECT_EQ(1ul /* unsigned long */, kc_to_capture.count(83));
+
+  std::map<int, mojom::SwitchAccessCommand> command_map =
+      GetCommandForKeyCodeMap();
+  EXPECT_EQ(2ul /* unsigned long */, command_map.size());
+  EXPECT_EQ(mojom::SwitchAccessCommand::kSelect, command_map.at(48));
+  EXPECT_EQ(mojom::SwitchAccessCommand::kSelect, command_map.at(83));
+
+  // Set key codes for the Next command.
+  new_key_codes.clear();
+  new_key_codes.insert(49 /* '1' */);
+  new_key_codes.insert(78 /* 'n' */);
+  handler->SetKeyCodesForCommand(new_key_codes,
+                                 mojom::SwitchAccessCommand::kNext);
+
+  // Check that the new values are added and old values are not changed.
+  kc_to_capture = GetKeyCodesToCapture();
+  EXPECT_EQ(4ul /* unsigned long */, kc_to_capture.size());
+  EXPECT_EQ(1ul /* unsigned long */, kc_to_capture.count(49));
+  EXPECT_EQ(1ul /* unsigned long */, kc_to_capture.count(78));
+
+  command_map = GetCommandForKeyCodeMap();
+  EXPECT_EQ(4ul /* unsigned long */, command_map.size());
+  EXPECT_EQ(mojom::SwitchAccessCommand::kNext, command_map.at(49));
+  EXPECT_EQ(mojom::SwitchAccessCommand::kNext, command_map.at(78));
+
+  // Set key codes for the Previous command. Re-use a key code from above.
+  new_key_codes.clear();
+  new_key_codes.insert(49 /* '1' */);
+  new_key_codes.insert(80 /* 'p' */);
+  handler->SetKeyCodesForCommand(new_key_codes,
+                                 mojom::SwitchAccessCommand::kPrevious);
+
+  // Check that '1' has been remapped to Previous.
+  kc_to_capture = GetKeyCodesToCapture();
+  EXPECT_EQ(5ul /* unsigned long */, kc_to_capture.size());
+  EXPECT_EQ(1ul /* unsigned long */, kc_to_capture.count(49));
+  EXPECT_EQ(1ul /* unsigned long */, kc_to_capture.count(80));
+
+  command_map = GetCommandForKeyCodeMap();
+  EXPECT_EQ(5ul /* unsigned long */, command_map.size());
+  EXPECT_EQ(mojom::SwitchAccessCommand::kPrevious, command_map.at(49));
+  EXPECT_EQ(mojom::SwitchAccessCommand::kPrevious, command_map.at(80));
+  EXPECT_EQ(mojom::SwitchAccessCommand::kNext, command_map.at(78));
+
+  // Set a new key code for the Select command.
+  new_key_codes.clear();
+  new_key_codes.insert(51 /* '3' */);
+  new_key_codes.insert(83 /* 's' */);
+  handler->SetKeyCodesForCommand(new_key_codes,
+                                 mojom::SwitchAccessCommand::kSelect);
+
+  // Check that the previously set values for Select have been cleared.
+  kc_to_capture = GetKeyCodesToCapture();
+  EXPECT_EQ(5ul /* unsigned long */, kc_to_capture.size());
+  EXPECT_EQ(0ul /* unsigned long */, kc_to_capture.count(48));
+  EXPECT_EQ(1ul /* unsigned long */, kc_to_capture.count(51));
+  EXPECT_EQ(1ul /* unsigned long */, kc_to_capture.count(83));
+
+  command_map = GetCommandForKeyCodeMap();
+  EXPECT_EQ(5ul /* unsigned long */, command_map.size());
+  EXPECT_EQ(mojom::SwitchAccessCommand::kSelect, command_map.at(51));
+  EXPECT_EQ(mojom::SwitchAccessCommand::kSelect, command_map.at(83));
+  EXPECT_EQ(command_map.end(), command_map.find(48));
+}
+
 }  // namespace
 }  // namespace ash
diff --git a/ash/mojo_interface_factory.cc b/ash/mojo_interface_factory.cc
index 167bf56..2f9624ea 100644
--- a/ash/mojo_interface_factory.cc
+++ b/ash/mojo_interface_factory.cc
@@ -21,7 +21,6 @@
 #include "ash/public/cpp/voice_interaction_controller.h"
 #include "ash/shell.h"
 #include "ash/shell_delegate.h"
-#include "ash/system/message_center/message_center_controller.h"
 #include "ash/system/network/vpn_list.h"
 #include "ash/system/night_light/night_light_controller.h"
 #include "ash/tray_action/tray_action.h"
@@ -39,69 +38,81 @@
 
 void BindAccessibilityControllerRequestOnMainThread(
     mojom::AccessibilityControllerRequest request) {
-  Shell::Get()->accessibility_controller()->BindRequest(std::move(request));
+  if (Shell::HasInstance())
+    Shell::Get()->accessibility_controller()->BindRequest(std::move(request));
 }
 
 void BindAssistantAlarmTimerControllerRequestOnMainThread(
     mojom::AssistantAlarmTimerControllerRequest request) {
-  Shell::Get()->assistant_controller()->alarm_timer_controller()->BindRequest(
-      std::move(request));
+  if (Shell::HasInstance()) {
+    Shell::Get()->assistant_controller()->alarm_timer_controller()->BindRequest(
+        std::move(request));
+  }
 }
 
 void BindAssistantControllerRequestOnMainThread(
     mojom::AssistantControllerRequest request) {
-  Shell::Get()->assistant_controller()->BindRequest(std::move(request));
+  if (Shell::HasInstance())
+    Shell::Get()->assistant_controller()->BindRequest(std::move(request));
 }
 
 void BindAssistantNotificationControllerRequestOnMainThread(
     mojom::AssistantNotificationControllerRequest request) {
-  Shell::Get()->assistant_controller()->notification_controller()->BindRequest(
-      std::move(request));
+  if (Shell::HasInstance()) {
+    Shell::Get()
+        ->assistant_controller()
+        ->notification_controller()
+        ->BindRequest(std::move(request));
+  }
 }
 
 void BindAssistantScreenContextControllerRequestOnMainThread(
     mojom::AssistantScreenContextControllerRequest request) {
-  Shell::Get()
-      ->assistant_controller()
-      ->screen_context_controller()
-      ->BindRequest(std::move(request));
+  if (Shell::HasInstance()) {
+    Shell::Get()
+        ->assistant_controller()
+        ->screen_context_controller()
+        ->BindRequest(std::move(request));
+  }
 }
 
 void BindAssistantVolumeControlRequestOnMainThread(
     mojom::AssistantVolumeControlRequest request) {
-  Shell::Get()->assistant_controller()->BindRequest(std::move(request));
+  if (Shell::HasInstance())
+    Shell::Get()->assistant_controller()->BindRequest(std::move(request));
 }
 
 void BindCrosDisplayConfigControllerRequestOnMainThread(
     mojom::CrosDisplayConfigControllerRequest request) {
-  Shell::Get()->cros_display_config()->BindRequest(std::move(request));
-}
-
-void BindAshMessageCenterControllerRequestOnMainThread(
-    mojom::AshMessageCenterControllerRequest request) {
-  Shell::Get()->message_center_controller()->BindRequest(std::move(request));
+  if (Shell::HasInstance())
+    Shell::Get()->cros_display_config()->BindRequest(std::move(request));
 }
 
 void BindImeControllerRequestOnMainThread(mojom::ImeControllerRequest request) {
-  Shell::Get()->ime_controller()->BindRequest(std::move(request));
+  if (Shell::HasInstance())
+    Shell::Get()->ime_controller()->BindRequest(std::move(request));
 }
 
 void BindNightLightControllerRequestOnMainThread(
     mojom::NightLightControllerRequest request) {
-  Shell::Get()->night_light_controller()->BindRequest(std::move(request));
+  if (Shell::HasInstance())
+    Shell::Get()->night_light_controller()->BindRequest(std::move(request));
 }
 
 void BindTrayActionRequestOnMainThread(mojom::TrayActionRequest request) {
-  Shell::Get()->tray_action()->BindRequest(std::move(request));
+  if (Shell::HasInstance())
+    Shell::Get()->tray_action()->BindRequest(std::move(request));
 }
 
 void BindVoiceInteractionControllerRequestOnMainThread(
     mojom::VoiceInteractionControllerRequest request) {
-  VoiceInteractionController::Get()->BindRequest(std::move(request));
+  if (Shell::HasInstance())
+    VoiceInteractionController::Get()->BindRequest(std::move(request));
 }
 
 void BindVpnListRequestOnMainThread(mojom::VpnListRequest request) {
-  Shell::Get()->vpn_list()->BindRequest(std::move(request));
+  if (Shell::HasInstance())
+    Shell::Get()->vpn_list()->BindRequest(std::move(request));
 }
 
 }  // namespace
@@ -136,9 +147,6 @@
       base::BindRepeating(&BindCrosDisplayConfigControllerRequestOnMainThread),
       main_thread_task_runner);
   registry->AddInterface(
-      base::BindRepeating(&BindAshMessageCenterControllerRequestOnMainThread),
-      main_thread_task_runner);
-  registry->AddInterface(
       base::BindRepeating(&BindImeControllerRequestOnMainThread),
       main_thread_task_runner);
   registry->AddInterface(
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn
index fa59943..04b66a1c 100644
--- a/ash/public/cpp/BUILD.gn
+++ b/ash/public/cpp/BUILD.gn
@@ -41,6 +41,8 @@
     "app_types.h",
     "arc_app_id_provider.cc",
     "arc_app_id_provider.h",
+    "arc_notifications_host_initializer.cc",
+    "arc_notifications_host_initializer.h",
     "ash_constants.h",
     "ash_features.cc",
     "ash_features.h",
@@ -233,6 +235,7 @@
   public_deps = [
     "//ash/public/interfaces",
     "//base",
+    "//components/arc/common:notifications",
     "//components/session_manager:base",
     "//components/user_manager",
     "//ui/gfx",
diff --git a/ash/public/cpp/DEPS b/ash/public/cpp/DEPS
index 1da5717..76bf43e1d 100644
--- a/ash/public/cpp/DEPS
+++ b/ash/public/cpp/DEPS
@@ -1,6 +1,7 @@
 include_rules = [
   "+chromeos/constants",
   "+chromeos/services",
+  "+components/arc/common",
   "+components/prefs",
   "+services/data_decoder/public",
   "+services/device/public",
diff --git a/ash/public/cpp/arc_notifications_host_initializer.cc b/ash/public/cpp/arc_notifications_host_initializer.cc
new file mode 100644
index 0000000..9e8f472
--- /dev/null
+++ b/ash/public/cpp/arc_notifications_host_initializer.cc
@@ -0,0 +1,30 @@
+// Copyright 2019 The Chromium 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 "ash/public/cpp/arc_notifications_host_initializer.h"
+
+#include "base/logging.h"
+
+namespace ash {
+
+namespace {
+ArcNotificationsHostInitializer* g_instance = nullptr;
+}
+
+// static
+ArcNotificationsHostInitializer* ArcNotificationsHostInitializer::Get() {
+  return g_instance;
+}
+
+ArcNotificationsHostInitializer::ArcNotificationsHostInitializer() {
+  DCHECK_EQ(nullptr, g_instance);
+  g_instance = this;
+}
+
+ArcNotificationsHostInitializer::~ArcNotificationsHostInitializer() {
+  DCHECK_EQ(this, g_instance);
+  g_instance = nullptr;
+}
+
+}  // namespace ash
diff --git a/ash/public/cpp/arc_notifications_host_initializer.h b/ash/public/cpp/arc_notifications_host_initializer.h
new file mode 100644
index 0000000..35ef5f4
--- /dev/null
+++ b/ash/public/cpp/arc_notifications_host_initializer.h
@@ -0,0 +1,27 @@
+// Copyright 2019 The Chromium 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 ASH_PUBLIC_CPP_ARC_NOTIFICATIONS_HOST_INITIALIZER_H_
+#define ASH_PUBLIC_CPP_ARC_NOTIFICATIONS_HOST_INITIALIZER_H_
+
+#include "ash/public/cpp/ash_public_export.h"
+#include "components/arc/common/notifications.mojom.h"
+
+namespace ash {
+
+class ASH_PUBLIC_EXPORT ArcNotificationsHostInitializer {
+ public:
+  static ArcNotificationsHostInitializer* Get();
+
+  virtual void SetArcNotificationsInstance(
+      arc::mojom::NotificationsInstancePtr arc_notification_instance) = 0;
+
+ protected:
+  ArcNotificationsHostInitializer();
+  virtual ~ArcNotificationsHostInitializer();
+};
+
+}  // namespace ash
+
+#endif  // ASH_PUBLIC_CPP_ARC_NOTIFICATIONS_HOST_INITIALIZER_H_
diff --git a/ash/public/cpp/manifest.cc b/ash/public/cpp/manifest.cc
index 07d25a6c..8d1fd86b 100644
--- a/ash/public/cpp/manifest.cc
+++ b/ash/public/cpp/manifest.cc
@@ -5,7 +5,6 @@
 #include "ash/public/cpp/manifest.h"
 
 #include "ash/public/interfaces/accessibility_controller.mojom.h"
-#include "ash/public/interfaces/ash_message_center_controller.mojom.h"
 #include "ash/public/interfaces/assistant_controller.mojom.h"
 #include "ash/public/interfaces/assistant_volume_control.mojom.h"
 #include "ash/public/interfaces/constants.mojom.h"
@@ -47,7 +46,6 @@
               "system_ui",
               service_manager::Manifest::InterfaceList<
                   mojom::AccessibilityController,
-                  mojom::AshMessageCenterController,
                   mojom::AssistantAlarmTimerController,
                   mojom::AssistantController,
                   mojom::AssistantNotificationController,
diff --git a/ash/public/cpp/test/shell_test_api.h b/ash/public/cpp/test/shell_test_api.h
index 58bd7d2..fb0610b 100644
--- a/ash/public/cpp/test/shell_test_api.h
+++ b/ash/public/cpp/test/shell_test_api.h
@@ -39,6 +39,11 @@
   ShellTestApi();
   ~ShellTestApi();
 
+  // TabletModeController usually takes a screenshot before animating from
+  // clamshell to tablet mode for performance reasons. This is an async
+  // operation that we want to disable for most tests.
+  static void SetTabletControllerUseScreenshotForTest(bool use_screenshot);
+
   MessageCenterController* message_center_controller();
   SystemGestureEventFilter* system_gesture_event_filter();
   WorkspaceController* workspace_controller();
diff --git a/ash/public/interfaces/BUILD.gn b/ash/public/interfaces/BUILD.gn
index ef68aceb..5b26c75 100644
--- a/ash/public/interfaces/BUILD.gn
+++ b/ash/public/interfaces/BUILD.gn
@@ -10,7 +10,6 @@
   sources = [
     "accessibility_controller.mojom",
     "accessibility_controller_enums.mojom",
-    "ash_message_center_controller.mojom",
     "assistant_controller.mojom",
     "assistant_volume_control.mojom",
     "constants.mojom",
@@ -27,7 +26,6 @@
     "//chromeos/components/proximity_auth/public/interfaces",
     "//chromeos/services/assistant/public/mojom",
     "//components/account_id/interfaces",
-    "//components/arc/common:notifications",
     "//components/sync/mojo:interfaces",
     "//mojo/public/mojom/base",
     "//services/content/public/mojom",
diff --git a/ash/public/interfaces/accessibility_controller.mojom b/ash/public/interfaces/accessibility_controller.mojom
index 222ba80..699d655 100644
--- a/ash/public/interfaces/accessibility_controller.mojom
+++ b/ash/public/interfaces/accessibility_controller.mojom
@@ -28,7 +28,12 @@
 interface SwitchAccessEventHandlerDelegate {
   // Sends a KeyEvent to the Switch Access extension in Chrome. The event
   // is cast to a key event with a type CHECK.
+  // TODO(anastasi): Remove once settings migration is complete.
   DispatchKeyEvent(ui.mojom.Event event);
+
+  // Sends a command to Switch Access, based on what key was pressed and the
+  // user's settings.
+  SendSwitchAccessCommand(SwitchAccessCommand command);
 };
 
 // Interface for ash client (e.g. Chrome) to control and query accessibility
diff --git a/ash/public/interfaces/accessibility_controller_enums.mojom b/ash/public/interfaces/accessibility_controller_enums.mojom
index 8254baa1..f495a36 100644
--- a/ash/public/interfaces/accessibility_controller_enums.mojom
+++ b/ash/public/interfaces/accessibility_controller_enums.mojom
@@ -78,6 +78,17 @@
   kSelectToSpeakStateSpeaking,
 };
 
+enum SwitchAccessCommand {
+  // Do not perform a command.
+  kNone,
+  // Command to select the focused element.
+  kSelect,
+  // Command to move focus to the next element.
+  kNext,
+  // Command to move focus to the previous element.
+  kPrevious,
+};
+
 // The type of mouse event the Automatic Clicks feature should perform when
 // dwelling. These values are written to prefs and correspond to
 // AutoclickActionType in enums.xml, so should not be changed. New values
diff --git a/ash/public/interfaces/ash_message_center_controller.mojom b/ash/public/interfaces/ash_message_center_controller.mojom
deleted file mode 100644
index 4fc2fbf7..0000000
--- a/ash/public/interfaces/ash_message_center_controller.mojom
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module ash.mojom;
-
-import "components/arc/common/notifications.mojom";
-
-interface AshMessageCenterController {
-  // Sets the ARC notification instance.
-  SetArcNotificationsInstance(arc.mojom.NotificationsInstance instance);
-};
diff --git a/ash/shell.cc b/ash/shell.cc
index ecc719e6..22c1757 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -192,6 +192,7 @@
 #include "ui/events/event_target_iterator.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/image/image_skia.h"
+#include "ui/message_center/message_center.h"
 #include "ui/ozone/public/ozone_platform.h"
 #include "ui/views/corewm/tooltip_aura.h"
 #include "ui/views/corewm/tooltip_controller.h"
diff --git a/ash/shell/content/client/shell_browser_main_parts.cc b/ash/shell/content/client/shell_browser_main_parts.cc
index 4efba66..88bf8194 100644
--- a/ash/shell/content/client/shell_browser_main_parts.cc
+++ b/ash/shell/content/client/shell_browser_main_parts.cc
@@ -30,8 +30,8 @@
 #include "chromeos/dbus/power/power_policy_controller.h"
 #include "components/exo/file_helper.h"
 #include "content/public/browser/context_factory.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/content_switches.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/shell/browser/shell_browser_context.h"
 #include "content/shell/browser/shell_net_log.h"
 #include "device/bluetooth/dbus/bluez_dbus_manager.h"
@@ -84,15 +84,12 @@
   chromeos::PowerPolicyController::Initialize(
       chromeos::PowerManagerClient::Get());
 
-  service_manager::Connector* const connector =
-      content::ServiceManagerConnection::GetForProcess()->GetConnector();
-
   ui::MaterialDesignController::Initialize();
   ash::ShellInitParams init_params;
   init_params.delegate = std::make_unique<ash::shell::ShellDelegateImpl>();
   init_params.context_factory = content::GetContextFactory();
   init_params.context_factory_private = content::GetContextFactoryPrivate();
-  init_params.connector = connector;
+  init_params.connector = content::GetSystemConnector();
   init_params.keyboard_ui_factory = std::make_unique<TestKeyboardUIFactory>();
   ash::Shell::CreateInstance(std::move(init_params));
 
diff --git a/ash/shell_test_api.cc b/ash/shell_test_api.cc
index fd14036..0b0623b 100644
--- a/ash/shell_test_api.cc
+++ b/ash/shell_test_api.cc
@@ -137,6 +137,12 @@
 ShellTestApi::ShellTestApi() : shell_(Shell::Get()) {}
 ShellTestApi::~ShellTestApi() = default;
 
+// static
+void ShellTestApi::SetTabletControllerUseScreenshotForTest(
+    bool use_screenshot) {
+  TabletModeController::SetUseScreenshotForTest(use_screenshot);
+}
+
 MessageCenterController* ShellTestApi::message_center_controller() {
   return shell_->message_center_controller_.get();
 }
@@ -182,7 +188,6 @@
 
 void ShellTestApi::SetTabletModeEnabledForTest(bool enable) {
   AccelerometerReader::GetInstance()->DisableForTest();
-  TabletModeController::SetForceNoScreenshotForTest();
   shell_->tablet_mode_controller()->SetEnabledForTest(enable);
 }
 
diff --git a/ash/system/message_center/arc/arc_notification_manager_unittest.cc b/ash/system/message_center/arc/arc_notification_manager_unittest.cc
index 20d5920..ada0edf1 100644
--- a/ash/system/message_center/arc/arc_notification_manager_unittest.cc
+++ b/ash/system/message_center/arc/arc_notification_manager_unittest.cc
@@ -11,8 +11,8 @@
 #include "ash/public/cpp/arc_app_id_provider.h"
 #include "ash/system/message_center/arc/arc_notification_manager.h"
 #include "ash/system/message_center/arc/arc_notification_manager_delegate.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
 #include "components/arc/session/connection_holder.h"
 #include "components/arc/test/connection_holder_util.h"
 #include "components/arc/test/fake_notifications_instance.h"
@@ -167,7 +167,7 @@
     base::RunLoop().RunUntilIdle();
   }
 
-  base::MessageLoop loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   TestArcAppIdProvider app_id_provider_;
   std::unique_ptr<arc::FakeNotificationsInstance> arc_notifications_instance_;
   std::unique_ptr<mojo::Binding<arc::mojom::NotificationsInstance>> binding_;
diff --git a/ash/system/message_center/message_center_controller.cc b/ash/system/message_center/message_center_controller.cc
index d6e4e1e..6f47e3d 100644
--- a/ash/system/message_center/message_center_controller.cc
+++ b/ash/system/message_center/message_center_controller.cc
@@ -11,6 +11,7 @@
 #include "ash/session/session_controller_impl.h"
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
+#include "ash/system/message_center/arc/arc_notification_manager.h"
 #include "ash/system/message_center/arc_notification_manager_delegate_impl.h"
 #include "ash/system/message_center/ash_message_center_lock_screen_controller.h"
 #include "ash/system/message_center/fullscreen_notification_blocker.h"
@@ -95,11 +96,6 @@
   message_center::MessageCenter::Shutdown();
 }
 
-void MessageCenterController::BindRequest(
-    mojom::AshMessageCenterControllerRequest request) {
-  binding_set_.AddBinding(this, std::move(request));
-}
-
 void MessageCenterController::SetArcNotificationsInstance(
     arc::mojom::NotificationsInstancePtr arc_notification_instance) {
   if (!arc_notification_manager_) {
diff --git a/ash/system/message_center/message_center_controller.h b/ash/system/message_center/message_center_controller.h
index a5158cc..88bbc1e9 100644
--- a/ash/system/message_center/message_center_controller.h
+++ b/ash/system/message_center/message_center_controller.h
@@ -8,11 +8,8 @@
 #include <memory>
 
 #include "ash/ash_export.h"
-#include "ash/public/interfaces/ash_message_center_controller.mojom.h"
-#include "ash/system/message_center/arc/arc_notification_manager.h"
+#include "ash/public/cpp/arc_notifications_host_initializer.h"
 #include "base/macros.h"
-#include "components/arc/common/notifications.mojom.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
 
 class PrefRegistrySimple;
 
@@ -22,6 +19,7 @@
 
 namespace ash {
 
+class ArcNotificationManager;
 class FullscreenNotificationBlocker;
 class InactiveUserNotificationBlocker;
 class SessionStateNotificationBlocker;
@@ -29,16 +27,14 @@
 // This class manages the ash message center and allows clients (like Chrome) to
 // add and remove notifications.
 class ASH_EXPORT MessageCenterController
-    : public mojom::AshMessageCenterController {
+    : public ArcNotificationsHostInitializer {
  public:
   static void RegisterProfilePrefs(PrefRegistrySimple* registry);
 
   MessageCenterController();
   ~MessageCenterController() override;
 
-  void BindRequest(mojom::AshMessageCenterControllerRequest request);
-
-  // mojom::AshMessageCenterController:
+  // ArcNotificationsHostInitializer:
   void SetArcNotificationsInstance(
       arc::mojom::NotificationsInstancePtr arc_notification_instance) override;
 
@@ -56,8 +52,6 @@
       session_state_notification_blocker_;
   std::unique_ptr<message_center::NotificationBlocker> all_popup_blocker_;
 
-  mojo::BindingSet<mojom::AshMessageCenterController> binding_set_;
-
   std::unique_ptr<ArcNotificationManager> arc_notification_manager_;
 
   DISALLOW_COPY_AND_ASSIGN(MessageCenterController);
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc
index c56a525..2b9b9645 100644
--- a/ash/test/ash_test_helper.cc
+++ b/ash/test/ash_test_helper.cc
@@ -198,7 +198,7 @@
   // Ensure tests have a wallpaper as placeholder.
   shell->wallpaper_controller()->CreateEmptyWallpaperForTesting();
 
-  TabletModeController::SetForceNoScreenshotForTest();
+  TabletModeController::SetUseScreenshotForTest(false);
 }
 
 void AshTestHelper::TearDown() {
diff --git a/ash/wm/tablet_mode/tablet_mode_controller.cc b/ash/wm/tablet_mode/tablet_mode_controller.cc
index 5b2824c4..126f095 100644
--- a/ash/wm/tablet_mode/tablet_mode_controller.cc
+++ b/ash/wm/tablet_mode/tablet_mode_controller.cc
@@ -104,8 +104,8 @@
 constexpr char kTabletModeExitHistogram[] =
     "Ash.TabletMode.AnimationSmoothness.Exit";
 
-// Set to true for unit tests so tablet mode can be changed synchronously.
-bool force_no_screenshot = false;
+// Set to false for tests so tablet mode can be changed synchronously.
+bool use_screenshot_for_test = true;
 
 // The angle between AccelerometerReadings are considered stable if
 // their magnitudes do not differ greatly. This returns false if the deviation
@@ -261,8 +261,8 @@
 }
 
 // static
-void TabletModeController::SetForceNoScreenshotForTest() {
-  force_no_screenshot = true;
+void TabletModeController::SetUseScreenshotForTest(bool use_screenshot) {
+  use_screenshot_for_test = use_screenshot;
 }
 
 void TabletModeController::AddWindow(aura::Window* window) {
@@ -606,7 +606,7 @@
     bool top_window_on_primary_display =
         top_window &&
         top_window->GetRootWindow() == Shell::GetPrimaryRootWindow();
-    if (!force_no_screenshot && top_window_on_primary_display) {
+    if (use_screenshot_for_test && top_window_on_primary_display) {
       screenshot_set_callback_.Reset(
           base::BindOnce(&TabletModeController::FinishInitTabletMode,
                          weak_factory_.GetWeakPtr()));
diff --git a/ash/wm/tablet_mode/tablet_mode_controller.h b/ash/wm/tablet_mode/tablet_mode_controller.h
index 7bcdec0..bc2ef66 100644
--- a/ash/wm/tablet_mode/tablet_mode_controller.h
+++ b/ash/wm/tablet_mode/tablet_mode_controller.h
@@ -91,9 +91,9 @@
   TabletModeController();
   ~TabletModeController() override;
 
-  // Disables taking screenshots for testing as it makes the initialization flow
-  // async.
-  static void SetForceNoScreenshotForTest();
+  // Enable or disable using a screenshot for testing as it makes the
+  // initialization flow async, which makes most tests harder to write.
+  static void SetUseScreenshotForTest(bool use_screenshot);
 
   // Add a special window to the TabletModeWindowManager for tracking. This is
   // only required for special windows which are handled by other window
diff --git a/base/debug/elf_reader_unittest.cc b/base/debug/elf_reader_unittest.cc
index c247d75c..358e4bd 100644
--- a/base/debug/elf_reader_unittest.cc
+++ b/base/debug/elf_reader_unittest.cc
@@ -23,10 +23,10 @@
 // builds.
 #if defined(OFFICIAL_BUILD) || defined(OS_FUCHSIA)
 
-#if defined(OS_FUCHSIA)
-constexpr size_t kExpectedBuildIdStringLength = 16;  // 64-bit int in hex.
-#else
+#if defined(OFFICIAL_BUILD)
 constexpr size_t kExpectedBuildIdStringLength = 40;  // SHA1 hash in hex.
+#else
+constexpr size_t kExpectedBuildIdStringLength = 16;  // 64-bit int in hex.
 #endif
 
 TEST(ElfReaderTest, ReadElfBuildIdUppercase) {
diff --git a/base/test/scoped_feature_list.cc b/base/test/scoped_feature_list.cc
index 646f9fe..95dcfaf 100644
--- a/base/test/scoped_feature_list.cc
+++ b/base/test/scoped_feature_list.cc
@@ -110,6 +110,16 @@
 
 }  // namespace
 
+ScopedFeatureList::FeatureAndParams::FeatureAndParams(
+    const Feature& feature,
+    const FieldTrialParams& params)
+    : feature(feature), params(params) {}
+
+ScopedFeatureList::FeatureAndParams::~FeatureAndParams() = default;
+
+ScopedFeatureList::FeatureAndParams::FeatureAndParams(
+    const FeatureAndParams& other) = default;
+
 ScopedFeatureList::ScopedFeatureList() = default;
 
 ScopedFeatureList::~ScopedFeatureList() {
diff --git a/base/test/scoped_feature_list.h b/base/test/scoped_feature_list.h
index 5a637a6..1402c85 100644
--- a/base/test/scoped_feature_list.h
+++ b/base/test/scoped_feature_list.h
@@ -39,8 +39,13 @@
   ~ScopedFeatureList();
 
   struct FeatureAndParams {
+    FeatureAndParams(const Feature& feature, const FieldTrialParams& params);
+    ~FeatureAndParams();
+
+    FeatureAndParams(const FeatureAndParams& other);
+
     const Feature& feature;
-    const FieldTrialParams& params;
+    const FieldTrialParams params;
   };
 
   // Resets the instance to a non-initialized state.
diff --git a/base/threading/sequence_bound.h b/base/threading/sequence_bound.h
index 6404a78f7..df8e818 100644
--- a/base/threading/sequence_bound.h
+++ b/base/threading/sequence_bound.h
@@ -43,7 +43,7 @@
 //   // On any thread...
 //   scoped_refptr<SequencedTaskRunner> main_task_runner = ...;
 //   auto widget = SequenceBound<MyClass>(main_task_runner, "My Title");
-//   widget.Post(&MyClass::DoSomething, 1234);
+//   widget.Post(FROM_HERE, &MyClass::DoSomething, 1234);
 //
 // Note that |widget| is constructed asynchronously on |main_task_runner|,
 // but calling Post() immediately is safe, since the actual call is posted
diff --git a/build/android/BUILD.gn b/build/android/BUILD.gn
index 60c3ec8..80d017eb 100644
--- a/build/android/BUILD.gn
+++ b/build/android/BUILD.gn
@@ -119,7 +119,7 @@
 python_library("bundle_wrapper_script_py") {
   pydeps_file = "gyp/create_bundle_wrapper_script.pydeps"
   data = [
-    "//third_party/android_build_tools/bundletool/bundletool-all-0.9.0.jar",
+    "//third_party/android_build_tools/bundletool/bundletool-all-0.10.0.jar",
   ]
 }
 
diff --git a/build/android/gyp/bundletool.py b/build/android/gyp/bundletool.py
index ac9561e..4e06017 100755
--- a/build/android/gyp/bundletool.py
+++ b/build/android/gyp/bundletool.py
@@ -18,7 +18,7 @@
     __file__, '..', '..', '..', '..', 'third_party', 'android_build_tools',
     'bundletool'))
 
-BUNDLETOOL_VERSION = '0.9.0'
+BUNDLETOOL_VERSION = '0.10.0'
 
 BUNDLETOOL_JAR_PATH = os.path.join(
     BUNDLETOOL_DIR, 'bundletool-all-%s.jar' % BUNDLETOOL_VERSION)
diff --git a/build/config/fuchsia/BUILD.gn b/build/config/fuchsia/BUILD.gn
index 59da62e..a661b24 100644
--- a/build/config/fuchsia/BUILD.gn
+++ b/build/config/fuchsia/BUILD.gn
@@ -56,21 +56,22 @@
   libs = [ "zircon" ]
 }
 
-# Writes an extended version of fvm.blk to fvm.extended.blk.
-blobstore_extended_path = "$root_out_dir/fvm.extended.blk"
-action("blobstore_extended_fvm") {
+# Writes an extended version of storage-full.blk to fvm.extended.blk.
+blobstore_extended_path = "$root_out_dir/storage-extended.blk"
+action("blobstore_extended") {
   # The file is grown by 1GB, which should be large enough to hold packaged
   # binaries and assets. The value should be increased if the size becomes a
   # limitation in the future.
   _extend_size = "1073741824"  # 1GB
 
-  _target_dir = "${fuchsia_sdk}/target/${current_cpu}"
+  _blobstore_path =
+      "${fuchsia_sdk}/../images/${current_cpu}/qemu/storage-full.blk"
 
   script = "//build/config/fuchsia/extend_fvm.py"
 
   inputs = [
+    _blobstore_path,
     "${fuchsia_sdk}/tools/fvm",
-    "${_target_dir}/fvm.blk",
   ]
   outputs = [
     blobstore_extended_path,
@@ -78,7 +79,7 @@
 
   args = [
     rebase_path("${fuchsia_sdk}/tools/fvm", root_build_dir),
-    rebase_path("${_target_dir}/fvm.blk", root_build_dir),
+    rebase_path(_blobstore_path, root_build_dir),
     rebase_path(blobstore_extended_path, root_build_dir),
     _extend_size,
   ]
@@ -86,7 +87,7 @@
 
 #  _________________________________________
 # / Create a compressed copy-on-write (COW) \
-# \ image based on fvm.blk.                 /
+# \ image based on storage-extended.blk.    /
 #  -----------------------------------------
 #         \   ^__^
 #          \  (oo)\_______
@@ -97,7 +98,7 @@
   script = "//build/gn_run_binary.py"
 
   deps = [
-    ":blobstore_extended_fvm",
+    ":blobstore_extended",
   ]
   inputs = [
     blobstore_extended_path,
diff --git a/build/config/fuchsia/config.gni b/build/config/fuchsia/config.gni
index cdf684e2..4b88d70f 100644
--- a/build/config/fuchsia/config.gni
+++ b/build/config/fuchsia/config.gni
@@ -20,3 +20,6 @@
 
 # Compute the qemu path.
 qemu_root = "//third_party/qemu-${host_os}-${host_cpu}"
+
+# Compute the path to the arch-specific boot image directory.
+boot_image_root = "${fuchsia_sdk}/../images/${target_cpu}"
diff --git a/build/config/fuchsia/rules.gni b/build/config/fuchsia/rules.gni
index 11cb4f10a..06ea04c8 100644
--- a/build/config/fuchsia/rules.gni
+++ b/build/config/fuchsia/rules.gni
@@ -86,6 +86,7 @@
         "//third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer",
         "${qemu_root}/",
         "${fuchsia_sdk}/",
+        "${boot_image_root}/",
       ]
 
       data_deps = [
diff --git a/build/fuchsia/boot_data.py b/build/fuchsia/boot_data.py
index 7ff1efc..ce03827 100644
--- a/build/fuchsia/boot_data.py
+++ b/build/fuchsia/boot_data.py
@@ -33,11 +33,11 @@
 FVM_TYPE_QCOW = 'qcow'
 FVM_TYPE_SPARSE = 'sparse'
 
+# Specifies boot files intended for use by an emulator.
+TARGET_TYPE_QEMU = 'qemu'
 
-def _TargetCpuToSdkBinPath(target_arch):
-  """Returns the path to the SDK 'target' file directory for |target_cpu|."""
-
-  return os.path.join(common.SDK_ROOT, 'target', target_arch)
+# Specifies boot files intended for use by anything (incl. physical devices).
+TARGET_TYPE_GENERIC = 'generic'
 
 
 def _GetPubKeyPath(output_dir):
@@ -86,25 +86,27 @@
   return output_path
 
 
-def GetTargetFile(target_arch, filename):
-  """Computes a path to |filename| in the Fuchsia target directory specific to
-  |target_arch|."""
+def GetTargetFile(filename, target_arch, target_type):
+  """Computes a path to |filename| in the Fuchsia boot image directory specific
+  to |target_type| and |target_arch|."""
 
-  return os.path.join(_TargetCpuToSdkBinPath(target_arch), filename)
+  assert target_type == TARGET_TYPE_QEMU or target_type == TARGET_TYPE_GENERIC
+
+  return os.path.join(common.IMAGES_ROOT, target_arch, target_type, filename)
 
 
 def GetSSHConfigPath(output_dir):
   return output_dir + '/ssh_config'
 
 
-def GetBootImage(output_dir, target_arch):
+def GetBootImage(output_dir, target_arch, target_type):
   """"Gets a path to the Zircon boot image, with the SSH client public key
   added."""
 
   ProvisionSSH(output_dir)
   pubkey_path = _GetPubKeyPath(output_dir)
   zbi_tool = os.path.join(common.SDK_ROOT, 'tools', 'zbi')
-  image_source_path = GetTargetFile(target_arch, 'fuchsia.zbi')
+  image_source_path = GetTargetFile('zircon-a.zbi', target_arch, target_type)
   image_dest_path = os.path.join(output_dir, 'gen', 'fuchsia-with-keys.zbi')
 
   cmd = [ zbi_tool, '-o', image_dest_path, image_source_path,
diff --git a/build/fuchsia/common.py b/build/fuchsia/common.py
index 1993374b..3ec1e67 100644
--- a/build/fuchsia/common.py
+++ b/build/fuchsia/common.py
@@ -12,6 +12,8 @@
 DIR_SOURCE_ROOT = os.path.abspath(
     os.path.join(os.path.dirname(__file__), os.pardir, os.pardir))
 SDK_ROOT = os.path.join(DIR_SOURCE_ROOT, 'third_party', 'fuchsia-sdk', 'sdk')
+IMAGES_ROOT = os.path.join(DIR_SOURCE_ROOT, 'third_party', 'fuchsia-sdk',
+                           'images')
 
 def EnsurePathExists(path):
   """Checks that the file |path| exists on the filesystem and returns the path
diff --git a/build/fuchsia/device_target.py b/build/fuchsia/device_target.py
index a036a7b1..c989b16 100644
--- a/build/fuchsia/device_target.py
+++ b/build/fuchsia/device_target.py
@@ -224,10 +224,13 @@
         bootserver_path,
         '-1',
         '--fvm',
-        EnsurePathExists(boot_data.GetTargetFile(self._GetTargetSdkArch(),
-                                                 'fvm.sparse.blk')),
+        EnsurePathExists(
+            boot_data.GetTargetFile('storage-sparse.blk',
+                                    self._GetTargetSdkArch(),
+                                    boot_data.TARGET_TYPE_GENERIC)),
         EnsurePathExists(boot_data.GetBootImage(self._output_dir,
-                                                self._GetTargetSdkArch()))]
+                                                self._GetTargetSdkArch(),
+                                                boot_data.TARGET_TYPE_GENERIC))]
 
     if self._node_name:
       bootserver_command += ['-n', self._node_name]
diff --git a/build/fuchsia/qemu_target.py b/build/fuchsia/qemu_target.py
index 168364a..aebdee3 100644
--- a/build/fuchsia/qemu_target.py
+++ b/build/fuchsia/qemu_target.py
@@ -65,10 +65,12 @@
         '-m', str(self._ram_size_mb),
         '-nographic',
         '-kernel', EnsurePathExists(
-            boot_data.GetTargetFile(self._GetTargetSdkArch(),
-                                    'qemu-kernel.bin')),
+            boot_data.GetTargetFile('qemu-kernel.kernel',
+                                    self._GetTargetSdkArch(),
+                                    boot_data.TARGET_TYPE_QEMU)),
         '-initrd', EnsurePathExists(
-            boot_data.GetBootImage(self._output_dir, self._GetTargetSdkArch())),
+            boot_data.GetBootImage(self._output_dir, self._GetTargetSdkArch(),
+                                   boot_data.TARGET_TYPE_QEMU)),
         '-smp', str(self._cpu_cores),
 
         # Attach the blobstore and data volumes. Use snapshot mode to discard
diff --git a/build/fuchsia/update_sdk.py b/build/fuchsia/update_sdk.py
index 31a04c3..f6b59b2 100755
--- a/build/fuchsia/update_sdk.py
+++ b/build/fuchsia/update_sdk.py
@@ -16,7 +16,8 @@
 import tarfile
 import tempfile
 
-from common import GetHostOsFromPlatform, GetHostArchFromPlatform
+from common import GetHostOsFromPlatform, GetHostArchFromPlatform, SDK_ROOT, \
+                   IMAGES_ROOT
 
 REPOSITORY_ROOT = os.path.abspath(os.path.join(
     os.path.dirname(__file__), '..', '..'))
@@ -34,7 +35,7 @@
     return None
 
   cmd = [os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'gsutil.py'), 'ls',
-         '-L', GetBucketForPlatform() + hash]
+         '-L', GetSdkBucketForPlatform() + hash]
   sdk_details = subprocess.check_output(cmd)
   m = re.search('Generation:\s*(\d*)', sdk_details)
   if not m:
@@ -73,24 +74,24 @@
     return extra_sdk_hash
   return sdk_hash
 
-def GetBucketForPlatform():
+
+def GetSdkBucketForPlatform():
   return 'gs://fuchsia/sdk/core/{platform}-amd64/'.format(
       platform = GetHostOsFromPlatform())
 
 
 def EnsureDirExists(path):
   if not os.path.exists(path):
-    print('Creating directory %s' % path)
     os.makedirs(path)
 
 
 # Removes previous SDK from the specified path if it's detected there.
-def Cleanup(path):
-  hash_file = os.path.join(path, '.hash')
+def Cleanup():
+  hash_file = os.path.join(SDK_ROOT, '.hash')
   if os.path.exists(hash_file):
-    print('Removing old SDK from %s.' % path)
+    print('Removing old SDK from %s.' % SDK_ROOT)
     for d in SDK_SUBDIRS:
-      to_remove = os.path.join(path, d)
+      to_remove = os.path.join(SDK_ROOT, d)
       if os.path.isdir(to_remove):
         shutil.rmtree(to_remove)
     os.remove(hash_file)
@@ -98,14 +99,43 @@
 
 # Updates the modification timestamps of |path| and its contents to the
 # current time.
-def UpdateTimestampsRecursive(path):
-  for root, dirs, files in os.walk(path):
+def UpdateTimestampsRecursive():
+  for root, dirs, files in os.walk(SDK_ROOT):
     for f in files:
       os.utime(os.path.join(root, f), None)
     for d in dirs:
       os.utime(os.path.join(root, d), None)
 
 
+# Fetches a tarball from GCS and uncompresses it to |output_dir|.
+def DownloadAndUnpackFromCloudStorage(url, output_dir):
+  # Pass the compressed stream directly to 'tarfile'; don't bother writing it
+  # to disk first.
+  cmd = [os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'gsutil.py'),
+         'cp', url, '-']
+  task = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+  tarfile.open(mode='r|gz', fileobj=task.stdout).extractall(path=output_dir)
+  task.wait()
+  assert task.returncode == 0
+
+
+def DownloadSdkBootImages(sdk_hash):
+  print('Downloading Fuchsia boot images...')
+
+  if (os.path.exists(IMAGES_ROOT)):
+    shutil.rmtree(IMAGES_ROOT)
+  os.mkdir(IMAGES_ROOT)
+
+  for device_type in ['generic', 'qemu']:
+    for arch in ['arm64', 'x64']:
+      images_tarball_url = \
+          'gs://fuchsia/development/{sdk_hash}/images/'\
+          '{device_type}-{arch}.tgz'.format(
+              sdk_hash=sdk_hash, device_type=device_type, arch=arch)
+      image_output_dir = os.path.join(IMAGES_ROOT, arch, device_type)
+      DownloadAndUnpackFromCloudStorage(images_tarball_url, image_output_dir)
+
+
 def main():
   if len(sys.argv) != 1:
     print('usage: %s' % sys.argv[0], file=sys.stderr)
@@ -120,49 +150,49 @@
   # Previously SDK was unpacked in //third_party/fuchsia-sdk instead of
   # //third_party/fuchsia-sdk/sdk . Remove the old files if they are still
   # there.
-  sdk_root = os.path.join(REPOSITORY_ROOT, 'third_party', 'fuchsia-sdk')
-  Cleanup(sdk_root)
+  Cleanup()
 
   sdk_hash = GetSdkHashForPlatform()
   if not sdk_hash:
     return 1
 
-  output_dir = os.path.join(sdk_root, 'sdk')
-
-  hash_filename = os.path.join(output_dir, '.hash')
+  hash_filename = os.path.join(SDK_ROOT, '.hash')
   if os.path.exists(hash_filename):
     with open(hash_filename, 'r') as f:
       if f.read().strip() == sdk_hash:
-        # Nothing to do. Generate sdk/BUILD.gn anyways, in case the conversion
+        # Used to download boot images if "gclient runhooks" is called on a
+        # output directory which had previously built Fuchsia on the same SDK
+        # hash, but did not use separate boot images.
+        if not os.path.exists(IMAGES_ROOT):
+          DownloadSdkBootImages(sdk_hash)
+
+        # Nothing to do. Generate sdk/BUILD.gn anyway, in case the conversion
         # script changed.
-        subprocess.check_call([os.path.join(sdk_root, 'gen_build_defs.py')])
+        subprocess.check_call([os.path.join(SDK_ROOT, '..',
+                                            'gen_build_defs.py')])
         return 0
 
   print('Downloading SDK %s...' % sdk_hash)
 
-  if os.path.isdir(output_dir):
-    shutil.rmtree(output_dir)
+  if os.path.isdir(SDK_ROOT):
+    shutil.rmtree(SDK_ROOT)
 
   fd, tmp = tempfile.mkstemp()
   os.close(fd)
 
-  try:
-    cmd = [os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'gsutil.py'),
-           'cp', GetBucketForPlatform() + sdk_hash, tmp]
-    subprocess.check_call(cmd)
-    with open(tmp, 'rb') as f:
-      EnsureDirExists(output_dir)
-      tarfile.open(mode='r:gz', fileobj=f).extractall(path=output_dir)
-  finally:
-    os.remove(tmp)
+  EnsureDirExists(SDK_ROOT)
+  DownloadAndUnpackFromCloudStorage(GetSdkBucketForPlatform() + sdk_hash,
+                                   SDK_ROOT)
 
   # Generate sdk/BUILD.gn.
-  subprocess.check_call([os.path.join(sdk_root, 'gen_build_defs.py')])
+  subprocess.check_call([os.path.join(SDK_ROOT, '..', 'gen_build_defs.py')])
+
+  DownloadSdkBootImages(sdk_hash)
 
   with open(hash_filename, 'w') as f:
     f.write(sdk_hash)
 
-  UpdateTimestampsRecursive(output_dir)
+  UpdateTimestampsRecursive()
 
   return 0
 
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc
index 8bd0656..ef52f0e 100644
--- a/build/sanitizers/tsan_suppressions.cc
+++ b/build/sanitizers/tsan_suppressions.cc
@@ -148,6 +148,9 @@
     // https://crbug.com/965722
     "race:content::(anonymous namespace)::CorruptDBRequestHandler\n"
 
+    // https://crbug.com/977085
+    "race:vp3_update_thread_context\n"
+
     // End of suppressions.
     ;  // Please keep this semicolon.
 
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index b34ea29..25e01d1 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -655,6 +655,7 @@
     "raster/synchronous_task_graph_runner_unittest.cc",
     "raster/task_graph_work_queue_unittest.cc",
     "resources/resource_pool_unittest.cc",
+    "scheduler/compositor_frame_reporter_unittest.cc",
     "scheduler/compositor_frame_reporting_controller_unittest.cc",
     "scheduler/compositor_timing_history_unittest.cc",
     "scheduler/scheduler_state_machine_unittest.cc",
diff --git a/cc/base/rolling_time_delta_history.cc b/cc/base/rolling_time_delta_history.cc
index dde20a7..6973e42 100644
--- a/cc/base/rolling_time_delta_history.cc
+++ b/cc/base/rolling_time_delta_history.cc
@@ -29,6 +29,13 @@
   percentile_cache_.clear();
 }
 
+void RollingTimeDeltaHistory::RemoveOldestSample() {
+  if (sample_set_.size() > 0) {
+    sample_set_.erase(chronological_sample_deque_.front());
+    chronological_sample_deque_.pop_front();
+  }
+}
+
 void RollingTimeDeltaHistory::Clear() {
   chronological_sample_deque_.clear();
   sample_set_.clear();
diff --git a/cc/base/rolling_time_delta_history.h b/cc/base/rolling_time_delta_history.h
index 75832323..81aa8d26 100644
--- a/cc/base/rolling_time_delta_history.h
+++ b/cc/base/rolling_time_delta_history.h
@@ -28,6 +28,7 @@
   RollingTimeDeltaHistory& operator=(const RollingTimeDeltaHistory&) = delete;
 
   void InsertSample(base::TimeDelta time);
+  void RemoveOldestSample();
   size_t sample_count() const { return sample_set_.size(); }
 
   void Clear();
diff --git a/cc/scheduler/compositor_frame_reporter.cc b/cc/scheduler/compositor_frame_reporter.cc
index 9b4c7ac..5dd2d9b 100644
--- a/cc/scheduler/compositor_frame_reporter.cc
+++ b/cc/scheduler/compositor_frame_reporter.cc
@@ -4,35 +4,116 @@
 
 #include "cc/scheduler/compositor_frame_reporter.h"
 
+#include <string>
+
+#include "base/metrics/histogram_macros.h"
+#include "base/strings/stringprintf.h"
 #include "base/trace_event/trace_event.h"
+#include "cc/base/rolling_time_delta_history.h"
 
 namespace cc {
+namespace {
 
-CompositorFrameReporter::CompositorFrameReporter() {
-  TRACE_EVENT_ASYNC_BEGIN0("cc,benchmark", "PipelineReporter", this);
+// When considering if a time is abnormal, compare the stage execution
+// time to this percentile from the previous times of the same stage.
+static constexpr double kAbnormalityPercentile = 95;
+
+// Use for determining abnormal execution times. If the sample size is less
+// than this then don't check for abnormal execution time.
+static constexpr size_t kMinimumTimeDeltaSampleSize = 20;
+
+static constexpr int kMissedFrameReportTypeCount =
+    static_cast<int>(CompositorFrameReporter::MissedFrameReportTypes::
+                         kMissedFrameReportTypeCount);
+static constexpr int kStageTypeCount =
+    static_cast<int>(CompositorFrameReporter::StageType::kStageTypeCount);
+
+// Names for CompositorFrameReporter::StageType, which should be updated in case
+// of changes to the enum.
+constexpr const char* kStageNames[]{"BeginImplFrameToSendBeginMainFrame",
+                                    "SendBeginMainFrameToCommit",
+                                    "Commit",
+                                    "EndCommitToActivation",
+                                    "Activation",
+                                    "EndActivateToSubmitCompositorFrame",
+                                    "TotalLatency"};
+static_assert(sizeof(kStageNames) / sizeof(kStageNames[0]) == kStageTypeCount,
+              "Compositor latency stages has changed.");
+
+// Names for CompositorFrameReporter::MissedFrameReportTypes, which should be
+// updated in case of changes to the enum.
+constexpr const char* kReportTypeNames[]{"", "MissedFrame.",
+                                         "MissedFrameLatencyIncrease."};
+static_assert(sizeof(kReportTypeNames) / sizeof(kReportTypeNames[0]) ==
+                  kMissedFrameReportTypeCount,
+              "Compositor latency report types has changed.");
+
+// This value should be recalculate in case of changes to the number of values
+// in CompositorFrameReporter::MissedFrameReportTypes or in
+// CompositorFrameReporter::StageType
+static constexpr int kMaxHistogramIndex =
+    2 * kMissedFrameReportTypeCount * kStageTypeCount;
+static constexpr int kHistogramMin = 1;
+static constexpr int kHistogramMax = 350000;
+static constexpr int kHistogramBucketCount = 50;
+}  // namespace
+
+CompositorFrameReporter::CompositorFrameReporter(bool is_single_threaded)
+    : is_single_threaded_(is_single_threaded) {
+  TRACE_EVENT_ASYNC_BEGIN1("cc,benchmark", "PipelineReporter", this,
+                           "is_single_threaded", is_single_threaded);
 }
 
 CompositorFrameReporter::~CompositorFrameReporter() {
-  TerminateFrame();
+  TerminateReporter();
 }
 
-void CompositorFrameReporter::StartStage(const char* stage_name) {
-  TRACE_EVENT_ASYNC_STEP_INTO0("cc,benchmark", "PipelineReporter", this,
-                               TRACE_STR_COPY(stage_name));
+void CompositorFrameReporter::StartStage(
+    CompositorFrameReporter::StageType stage_type,
+    base::TimeTicks start_time,
+    RollingTimeDeltaHistory* stage_time_delta_history) {
+  EndCurrentStage(start_time);
+  current_stage_.stage_type = stage_type;
+  current_stage_.start_time = start_time;
+  current_stage_.time_delta_history = stage_time_delta_history;
+  int stage_type_index = static_cast<int>(current_stage_.stage_type);
+  CHECK_LT(stage_type_index, static_cast<int>(StageType::kStageTypeCount));
+  CHECK_GE(stage_type_index, 0);
+  TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0(
+      "cc,benchmark", "PipelineReporter", this,
+      TRACE_STR_COPY(kStageNames[stage_type_index]), start_time);
 }
 
-void CompositorFrameReporter::SetFrameTerminationStatus(
-    FrameTerminationStatus termination_status) {
+void CompositorFrameReporter::EndCurrentStage(base::TimeTicks end_time) {
+  if (current_stage_.start_time == base::TimeTicks())
+    return;
+  current_stage_.end_time = end_time;
+  stage_history_.emplace_back(current_stage_);
+  current_stage_.start_time = base::TimeTicks();
+  current_stage_.time_delta_history = nullptr;
+}
+
+void CompositorFrameReporter::TerminateFrame(
+    FrameTerminationStatus termination_status,
+    base::TimeTicks termination_time) {
   frame_termination_status_ = termination_status;
+  frame_termination_time_ = termination_time;
+  EndCurrentStage(frame_termination_time_);
 }
 
-void CompositorFrameReporter::TerminateFrame() {
-  const char* termination_status_str;
+void CompositorFrameReporter::TerminateReporter() {
+  DCHECK_EQ(current_stage_.start_time, base::TimeTicks());
+  bool report_latency = false;
+  bool missed_frame = false;
+  const char* termination_status_str = nullptr;
   switch (frame_termination_status_) {
     case FrameTerminationStatus::kSubmittedFrame:
+      report_latency = true;
       termination_status_str = "submitted_frame";
       break;
     case FrameTerminationStatus::kSubmittedFrameMissedDeadline:
+      report_latency = true;
+      missed_frame = true;
       termination_status_str = "missed_frame";
       break;
     case FrameTerminationStatus::kMainFrameAborted:
@@ -48,9 +129,91 @@
       NOTREACHED();
       break;
   }
-  TRACE_EVENT_ASYNC_END1("cc,benchmark", "PipelineReporter", this,
-                         "termination_status",
-                         TRACE_STR_COPY(termination_status_str));
-  // TODO(alsan): UMA histogram reporting
+
+  TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP1(
+      "cc,benchmark", "PipelineReporter", this, frame_termination_time_,
+      "termination_status", TRACE_STR_COPY(termination_status_str));
+  if (report_latency) {
+    DCHECK(stage_history_.size());
+    stage_history_.emplace_back(
+        StageData{StageType::kTotalLatency, stage_history_.front().start_time,
+                  stage_history_.back().end_time, nullptr});
+    ReportStageHistograms(missed_frame);
+  }
+}
+
+void CompositorFrameReporter::ReportStageHistograms(bool missed_frame) const {
+  CompositorFrameReporter::MissedFrameReportTypes report_type =
+      missed_frame
+          ? CompositorFrameReporter::MissedFrameReportTypes::kMissedFrame
+          : CompositorFrameReporter::MissedFrameReportTypes::kNonMissedFrame;
+
+  for (const StageData& stage : stage_history_) {
+    base::TimeDelta stage_delta = stage.end_time - stage.start_time;
+    ReportHistogram(report_type, stage.stage_type, stage_delta);
+
+    if (!stage.time_delta_history)
+      continue;
+
+    if (!missed_frame) {
+      stage.time_delta_history->InsertSample(stage_delta);
+    } else {
+      // If enough sample data is recorded compare the stage duration with the
+      // known normal stage duration and if it's higher than normal, report the
+      // difference.
+      if (stage.time_delta_history->sample_count() >=
+          kMinimumTimeDeltaSampleSize) {
+        base::TimeDelta time_upper_limit = GetStateNormalUpperLimit(stage);
+        if (stage_delta > time_upper_limit) {
+          ReportHistogram(CompositorFrameReporter::MissedFrameReportTypes::
+                              kMissedFrameLatencyIncrease,
+                          stage.stage_type, stage_delta - time_upper_limit);
+        }
+      }
+
+      // In case of a missing frame, remove a sample from the recorded normal
+      // stages. This invalidates the recorded normal durations if at a point
+      // all frames start missing for a while.
+      stage.time_delta_history->RemoveOldestSample();
+    }
+  }
+}
+
+void CompositorFrameReporter::ReportHistogram(
+    CompositorFrameReporter::MissedFrameReportTypes report_type,
+    CompositorFrameReporter::StageType stage_type,
+    base::TimeDelta time_delta) const {
+  const int report_type_index = static_cast<int>(report_type);
+  const int stage_type_index = static_cast<int>(stage_type);
+  const int histogram_index =
+      (stage_type_index * kMissedFrameReportTypeCount + report_type_index) * 2 +
+      (is_single_threaded_ ? 1 : 0);
+
+  CHECK_LT(stage_type_index, kStageTypeCount);
+  CHECK_GE(stage_type_index, 0);
+  CHECK_LT(report_type_index, kMissedFrameReportTypeCount);
+  CHECK_GE(report_type_index, 0);
+  CHECK_LT(histogram_index, kMaxHistogramIndex);
+  CHECK_GE(histogram_index, 0);
+
+  const char* compositor_type = is_single_threaded_ ? "SingleThreaded" : "";
+
+  STATIC_HISTOGRAM_POINTER_GROUP(
+      base::StringPrintf("%s%s%s%s", compositor_type, "CompositorLatency.",
+                         kReportTypeNames[static_cast<int>(report_type)],
+                         kStageNames[static_cast<int>(stage_type)]),
+      histogram_index, kMaxHistogramIndex,
+      AddTimeMicrosecondsGranularity(time_delta),
+      base::Histogram::FactoryGet(
+          base::StringPrintf("%s%s%s%s", compositor_type, "CompositorLatency.",
+                             kReportTypeNames[static_cast<int>(report_type)],
+                             kStageNames[static_cast<int>(stage_type)]),
+          kHistogramMin, kHistogramMax, kHistogramBucketCount,
+          base::HistogramBase::kUmaTargetedHistogramFlag));
+}
+
+base::TimeDelta CompositorFrameReporter::GetStateNormalUpperLimit(
+    const StageData& stage) const {
+  return stage.time_delta_history->Percentile(kAbnormalityPercentile);
 }
 }  // namespace cc
diff --git a/cc/scheduler/compositor_frame_reporter.h b/cc/scheduler/compositor_frame_reporter.h
index b122693..1fb0591 100644
--- a/cc/scheduler/compositor_frame_reporter.h
+++ b/cc/scheduler/compositor_frame_reporter.h
@@ -5,15 +5,27 @@
 #ifndef CC_SCHEDULER_COMPOSITOR_FRAME_REPORTER_H_
 #define CC_SCHEDULER_COMPOSITOR_FRAME_REPORTER_H_
 
+#include <vector>
+
+#include "base/time/time.h"
 #include "cc/base/base_export.h"
 #include "cc/cc_export.h"
 
 namespace cc {
-// This is used for tracing the pipeline stages of a single frame.
+class RollingTimeDeltaHistory;
+
+// This is used for tracing and reporting the duration of pipeline stages within
+// a single frame.
 //
 // For each stage in the frame pipeline, calling StartStage will start tracing
 // that stage (and end any currently running stages).
-// TODO(alsan): Report stage durations to UMA.
+//
+// If the tracked frame is submitted (i.e. the frame termination status is
+// kSubmittedFrame or kSubmittedFrameMissedDeadline), then the duration of each
+// stage along with the total latency will be reported to UMA. These reported
+// durations will be differentiated by whether the compositor is single threaded
+// and whether the submitted frame missed the deadline. The format of each stage
+// reported to UMA is "[SingleThreaded]Compositor.[MissedFrame.].<StageName>".
 class CC_EXPORT CompositorFrameReporter {
  public:
   enum FrameTerminationStatus {
@@ -47,20 +59,72 @@
     kUnknown
   };
 
-  CompositorFrameReporter();
-  CompositorFrameReporter(const CompositorFrameReporter& reporter) = delete;
+  enum class MissedFrameReportTypes {
+    kNonMissedFrame,
+    kMissedFrame,
+    kMissedFrameLatencyIncrease,
+    kMissedFrameReportTypeCount
+  };
+
+  enum class StageType {
+    kBeginImplFrameToSendBeginMainFrame,
+    kSendBeginMainFrameToCommit,
+    kCommit,
+    kEndCommitToActivation,
+    kActivation,
+    kEndActivateToSubmitCompositorFrame,
+    kTotalLatency,
+    kStageTypeCount
+  };
+
+  explicit CompositorFrameReporter(bool is_single_threaded = false);
   ~CompositorFrameReporter();
 
+  CompositorFrameReporter(const CompositorFrameReporter& reporter) = delete;
   CompositorFrameReporter& operator=(const CompositorFrameReporter& reporter) =
       delete;
 
-  void StartStage(const char* stage_name);
-  void SetFrameTerminationStatus(FrameTerminationStatus termination_status);
+  // Note that the started stage may be reported to UMA. If the histogram is
+  // intended to be reported then the histograms.xml file must be updated too.
+  void StartStage(StageType stage_type,
+                  base::TimeTicks start_time,
+                  RollingTimeDeltaHistory* stage_time_delta_history);
+  void TerminateFrame(FrameTerminationStatus termination_status,
+                      base::TimeTicks termination_time);
+
+  int StageHistorySizeForTesting() { return stage_history_.size(); }
+
+ protected:
+  struct StageData {
+    StageType stage_type;
+    base::TimeTicks start_time;
+    base::TimeTicks end_time;
+    RollingTimeDeltaHistory* time_delta_history;
+  };
+
+  StageData current_stage_;
+
+  // Stage data is recorded here. On destruction these stages will be reported
+  // to UMA if the termination status is kSubmittedFrame or
+  // kSubmittedFrameMissedDeadline.
+  std::vector<StageData> stage_history_;
 
  private:
+  void TerminateReporter();
+  void EndCurrentStage(base::TimeTicks end_time);
+  void ReportStageHistograms(bool missed_frame) const;
+  void ReportHistogram(
+      CompositorFrameReporter::MissedFrameReportTypes report_type,
+      StageType stage_type,
+      base::TimeDelta time_delta) const;
+  // Returns true if the stage duration is greater than |kAbnormalityPercentile|
+  // of its RollingTimeDeltaHistory.
+  base::TimeDelta GetStateNormalUpperLimit(const StageData& stage) const;
+
+  const bool is_single_threaded_;
+  base::TimeTicks frame_termination_time_;
   FrameTerminationStatus frame_termination_status_ =
       FrameTerminationStatus::kUnknown;
-  void TerminateFrame();
 };
 }  // namespace cc
 
diff --git a/cc/scheduler/compositor_frame_reporter_unittest.cc b/cc/scheduler/compositor_frame_reporter_unittest.cc
new file mode 100644
index 0000000..217a31d
--- /dev/null
+++ b/cc/scheduler/compositor_frame_reporter_unittest.cc
@@ -0,0 +1,301 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/scheduler/compositor_frame_reporter.h"
+
+#include "base/test/metrics/histogram_tester.h"
+#include "cc/scheduler/compositor_frame_reporting_controller.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cc {
+namespace {
+
+class CompositorFrameReporterTest;
+
+class CompositorFrameReporterTest : public testing::Test {
+ public:
+  CompositorFrameReporterTest()
+      : pipeline_reporter_(std::make_unique<CompositorFrameReporter>()) {
+    AdvanceNowByMs(1);
+  }
+
+  void AdvanceNowByMs(int advance_ms) {
+    now_ += base::TimeDelta::FromMicroseconds(advance_ms);
+  }
+
+  base::TimeTicks Now() { return now_; }
+
+ protected:
+  std::unique_ptr<CompositorFrameReporter> pipeline_reporter_;
+  base::TimeTicks now_;
+};
+
+TEST_F(CompositorFrameReporterTest, MainFrameAbortedReportingTest) {
+  base::HistogramTester histogram_tester;
+
+  pipeline_reporter_->StartStage(
+      CompositorFrameReporter::StageType::kBeginImplFrameToSendBeginMainFrame,
+      Now(), nullptr);
+  EXPECT_EQ(0, pipeline_reporter_->StageHistorySizeForTesting());
+
+  AdvanceNowByMs(3);
+  pipeline_reporter_->StartStage(
+      CompositorFrameReporter::StageType::kSendBeginMainFrameToCommit, Now(),
+      nullptr);
+  EXPECT_EQ(1, pipeline_reporter_->StageHistorySizeForTesting());
+
+  AdvanceNowByMs(2);
+  pipeline_reporter_->TerminateFrame(
+      CompositorFrameReporter::FrameTerminationStatus::kMainFrameAborted,
+      Now());
+  EXPECT_EQ(2, pipeline_reporter_->StageHistorySizeForTesting());
+
+  pipeline_reporter_ = nullptr;
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.BeginImplFrameToSendBeginMainFrame", 0);
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.SendBeginMainFrameToCommit", 0);
+}
+
+TEST_F(CompositorFrameReporterTest, ReplacedByNewReporterReportingTest) {
+  base::HistogramTester histogram_tester;
+
+  pipeline_reporter_->StartStage(CompositorFrameReporter::StageType::kCommit,
+                                 Now(), nullptr);
+  EXPECT_EQ(0, pipeline_reporter_->StageHistorySizeForTesting());
+
+  AdvanceNowByMs(3);
+  pipeline_reporter_->StartStage(
+      CompositorFrameReporter::StageType::kEndCommitToActivation, Now(),
+      nullptr);
+  EXPECT_EQ(1, pipeline_reporter_->StageHistorySizeForTesting());
+
+  AdvanceNowByMs(2);
+  pipeline_reporter_->TerminateFrame(
+      CompositorFrameReporter::FrameTerminationStatus::kReplacedByNewReporter,
+      Now());
+  EXPECT_EQ(2, pipeline_reporter_->StageHistorySizeForTesting());
+
+  pipeline_reporter_ = nullptr;
+  histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 0);
+  histogram_tester.ExpectTotalCount("CompositorLatency.EndCommitToActivation",
+                                    0);
+}
+
+TEST_F(CompositorFrameReporterTest, SubmittedFrameReportingTest) {
+  base::HistogramTester histogram_tester;
+
+  pipeline_reporter_->StartStage(
+      CompositorFrameReporter::StageType::kActivation, Now(), nullptr);
+  EXPECT_EQ(0, pipeline_reporter_->StageHistorySizeForTesting());
+
+  AdvanceNowByMs(3);
+  pipeline_reporter_->StartStage(
+      CompositorFrameReporter::StageType::kEndActivateToSubmitCompositorFrame,
+      Now(), nullptr);
+  EXPECT_EQ(1, pipeline_reporter_->StageHistorySizeForTesting());
+
+  AdvanceNowByMs(2);
+  pipeline_reporter_->TerminateFrame(
+      CompositorFrameReporter::FrameTerminationStatus::kSubmittedFrame, Now());
+  EXPECT_EQ(2, pipeline_reporter_->StageHistorySizeForTesting());
+
+  pipeline_reporter_ = nullptr;
+  histogram_tester.ExpectTotalCount("CompositorLatency.Activation", 1);
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.EndActivateToSubmitCompositorFrame", 1);
+  histogram_tester.ExpectTotalCount("CompositorLatency.TotalLatency", 1);
+  histogram_tester.ExpectTotalCount("CompositorLatency.MissedFrame.Activation",
+                                    0);
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.MissedFrame.EndActivateToSubmitCompositorFrame", 0);
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.MissedFrame.TotalLatency", 0);
+
+  histogram_tester.ExpectBucketCount("CompositorLatency.Activation", 3, 1);
+  histogram_tester.ExpectBucketCount(
+      "CompositorLatency.EndActivateToSubmitCompositorFrame", 2, 1);
+  histogram_tester.ExpectBucketCount("CompositorLatency.TotalLatency", 5, 1);
+}
+
+TEST_F(CompositorFrameReporterTest, SubmittedMissedFrameReportingTest) {
+  base::HistogramTester histogram_tester;
+
+  pipeline_reporter_->StartStage(
+      CompositorFrameReporter::StageType::kSendBeginMainFrameToCommit, Now(),
+      nullptr);
+  EXPECT_EQ(0, pipeline_reporter_->StageHistorySizeForTesting());
+
+  AdvanceNowByMs(3);
+  pipeline_reporter_->StartStage(CompositorFrameReporter::StageType::kCommit,
+                                 Now(), nullptr);
+  EXPECT_EQ(1, pipeline_reporter_->StageHistorySizeForTesting());
+
+  AdvanceNowByMs(2);
+  pipeline_reporter_->TerminateFrame(
+      CompositorFrameReporter::FrameTerminationStatus::
+          kSubmittedFrameMissedDeadline,
+      Now());
+  EXPECT_EQ(2, pipeline_reporter_->StageHistorySizeForTesting());
+
+  pipeline_reporter_ = nullptr;
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.MissedFrame.SendBeginMainFrameToCommit", 1);
+  histogram_tester.ExpectTotalCount("CompositorLatency.MissedFrame.Commit", 1);
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.MissedFrame.TotalLatency", 1);
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.SendBeginMainFrameToCommit", 0);
+  histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 0);
+  histogram_tester.ExpectTotalCount("CompositorLatency.TotalLatency", 0);
+
+  histogram_tester.ExpectBucketCount(
+      "CompositorLatency.MissedFrame.SendBeginMainFrameToCommit", 3, 1);
+  histogram_tester.ExpectBucketCount("CompositorLatency.MissedFrame.Commit", 2,
+                                     1);
+  histogram_tester.ExpectBucketCount(
+      "CompositorLatency.MissedFrame.TotalLatency", 5, 1);
+}
+
+TEST_F(CompositorFrameReporterTest, MissedFrameLatencyIncreaseReportingTest) {
+  base::HistogramTester histogram_tester;
+  RollingTimeDeltaHistory time_delta_history(50);
+  RollingTimeDeltaHistory time_delta_history2(50);
+
+  // Terminate this frame since it will get destroyed in the for loop.
+  pipeline_reporter_->TerminateFrame(
+      CompositorFrameReporter::FrameTerminationStatus::kDidNotProduceFrame,
+      Now());
+
+  // Submit 19 non-missed frames.
+  for (int i = 0; i < 19; ++i) {
+    pipeline_reporter_ = std::make_unique<CompositorFrameReporter>();
+    pipeline_reporter_->StartStage(CompositorFrameReporter::StageType::kCommit,
+                                   Now(), &time_delta_history);
+    AdvanceNowByMs(1);
+    pipeline_reporter_->StartStage(
+        CompositorFrameReporter::StageType::kEndCommitToActivation, Now(),
+        &time_delta_history2);
+    pipeline_reporter_->TerminateFrame(
+        CompositorFrameReporter::FrameTerminationStatus::kSubmittedFrame,
+        Now());
+  }
+  pipeline_reporter_ = nullptr;
+  EXPECT_EQ((size_t)19, time_delta_history.sample_count());
+  EXPECT_EQ((size_t)19, time_delta_history2.sample_count());
+  histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 19);
+  histogram_tester.ExpectTotalCount("CompositorLatency.EndCommitToActivation",
+                                    19);
+
+  // Submit 3 frames missed frames. This will remove 3 sample from the front of
+  // time delta history. And 16 sample will be in the time delta history.
+  for (int i = 0; i < 3; ++i) {
+    pipeline_reporter_ = std::make_unique<CompositorFrameReporter>();
+    pipeline_reporter_->StartStage(CompositorFrameReporter::StageType::kCommit,
+                                   Now(), &time_delta_history);
+    AdvanceNowByMs(100);
+    pipeline_reporter_->StartStage(
+        CompositorFrameReporter::StageType::kEndCommitToActivation, Now(),
+        &time_delta_history2);
+    pipeline_reporter_->TerminateFrame(
+        CompositorFrameReporter::FrameTerminationStatus::
+            kSubmittedFrameMissedDeadline,
+        Now());
+  }
+  pipeline_reporter_ = nullptr;
+  EXPECT_EQ((size_t)16, time_delta_history.sample_count());
+  EXPECT_EQ((size_t)16, time_delta_history2.sample_count());
+  DCHECK_EQ(time_delta_history.sample_count(), (size_t)16);
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.MissedFrameLatencyIncrease.Commit", 0);
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.MissedFrameLatencyIncrease.EndCommitToActivation", 0);
+  histogram_tester.ExpectTotalCount("CompositorLatency.MissedFrame.Commit", 3);
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.MissedFrame.EndCommitToActivation", 3);
+
+  // Submit 5 frame so that missed frame duration increases would be reported.
+  for (int i = 0; i < 5; ++i) {
+    pipeline_reporter_ = std::make_unique<CompositorFrameReporter>();
+    pipeline_reporter_->StartStage(CompositorFrameReporter::StageType::kCommit,
+                                   Now(), &time_delta_history);
+    AdvanceNowByMs(1);
+    pipeline_reporter_->StartStage(
+        CompositorFrameReporter::StageType::kEndCommitToActivation, Now(),
+        &time_delta_history2);
+    pipeline_reporter_->TerminateFrame(
+        CompositorFrameReporter::FrameTerminationStatus::kSubmittedFrame,
+        Now());
+  }
+  pipeline_reporter_ = nullptr;
+  EXPECT_EQ((size_t)21, time_delta_history.sample_count());
+  EXPECT_EQ((size_t)21, time_delta_history2.sample_count());
+
+  histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 24);
+  histogram_tester.ExpectTotalCount("CompositorLatency.EndCommitToActivation",
+                                    24);
+
+  // Submit missed frame that is not abnormal (more than 95 percentile of the
+  // frame history). This brings down the time delta history count to 20.
+  pipeline_reporter_ = std::make_unique<CompositorFrameReporter>();
+  pipeline_reporter_->StartStage(CompositorFrameReporter::StageType::kCommit,
+                                 Now(), &time_delta_history);
+  AdvanceNowByMs(1);
+  pipeline_reporter_->StartStage(
+      CompositorFrameReporter::StageType::kEndCommitToActivation, Now(),
+      &time_delta_history2);
+  pipeline_reporter_->TerminateFrame(
+      CompositorFrameReporter::FrameTerminationStatus::
+          kSubmittedFrameMissedDeadline,
+      Now());
+  pipeline_reporter_ = nullptr;
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.MissedFrameLatencyIncrease.Commit", 0);
+  histogram_tester.ExpectTotalCount("CompositorLatency.MissedFrame.Commit", 4);
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.MissedFrame.EndCommitToActivation", 4);
+
+  EXPECT_EQ((size_t)20, time_delta_history.sample_count());
+  EXPECT_EQ((size_t)20, time_delta_history2.sample_count());
+
+  // Submit missed frame that is abnormal (more than 95 percentile of the
+  // frame history).
+  pipeline_reporter_ = std::make_unique<CompositorFrameReporter>();
+  pipeline_reporter_->StartStage(CompositorFrameReporter::StageType::kCommit,
+                                 Now(), &time_delta_history);
+  AdvanceNowByMs(3);
+  pipeline_reporter_->StartStage(
+      CompositorFrameReporter::StageType::kEndCommitToActivation, Now(),
+      &time_delta_history2);
+  pipeline_reporter_->TerminateFrame(
+      CompositorFrameReporter::FrameTerminationStatus::
+          kSubmittedFrameMissedDeadline,
+      Now());
+  pipeline_reporter_ = nullptr;
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.MissedFrameLatencyIncrease.Commit", 1);
+  histogram_tester.ExpectTotalCount("CompositorLatency.MissedFrame.Commit", 5);
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.MissedFrame.EndCommitToActivation", 5);
+
+  // Submit not-missed frame with abnormal times.
+  pipeline_reporter_ = std::make_unique<CompositorFrameReporter>();
+  pipeline_reporter_->StartStage(CompositorFrameReporter::StageType::kCommit,
+                                 Now(), &time_delta_history);
+  AdvanceNowByMs(3);
+  pipeline_reporter_->StartStage(
+      CompositorFrameReporter::StageType::kEndCommitToActivation, Now(),
+      &time_delta_history2);
+  pipeline_reporter_->TerminateFrame(
+      CompositorFrameReporter::FrameTerminationStatus::kSubmittedFrame, Now());
+  pipeline_reporter_ = nullptr;
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.MissedFrameLatencyIncrease.Commit", 1);
+  histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 25);
+  histogram_tester.ExpectTotalCount("CompositorLatency.EndCommitToActivation",
+                                    25);
+}
+
+}  // namespace
+}  // namespace cc
diff --git a/cc/scheduler/compositor_frame_reporting_controller.cc b/cc/scheduler/compositor_frame_reporting_controller.cc
index 1b17021..23b95a2 100644
--- a/cc/scheduler/compositor_frame_reporting_controller.cc
+++ b/cc/scheduler/compositor_frame_reporting_controller.cc
@@ -7,34 +7,63 @@
 #include "cc/scheduler/compositor_frame_reporter.h"
 
 namespace cc {
-CompositorFrameReportingController::CompositorFrameReportingController() {}
+namespace {
+static constexpr size_t kMaxHistorySize = 50;
+}  // namespace
+
+CompositorFrameReportingController::CompositorFrameReportingController(
+    bool is_single_threaded)
+    : is_single_threaded_(is_single_threaded) {
+  for (int i = 0; i < static_cast<int>(
+                          CompositorFrameReporter::StageType::kStageTypeCount);
+       ++i) {
+    stage_history_[i] =
+        std::make_unique<RollingTimeDeltaHistory>(kMaxHistorySize);
+  }
+}
 
 CompositorFrameReportingController::~CompositorFrameReportingController() {
+  base::TimeTicks now = Now();
   for (int i = 0; i < PipelineStage::kNumPipelineStages; ++i) {
     if (reporters_[i]) {
-      reporters_[i]->SetFrameTerminationStatus(
-          CompositorFrameReporter::FrameTerminationStatus::kDidNotProduceFrame);
+      reporters_[i]->TerminateFrame(
+          CompositorFrameReporter::FrameTerminationStatus::kDidNotProduceFrame,
+          now);
     }
   }
 }
 
+base::TimeTicks CompositorFrameReportingController::Now() const {
+  return base::TimeTicks::Now();
+}
+
 void CompositorFrameReportingController::WillBeginImplFrame() {
+  base::TimeTicks begin_time = Now();
+  if (reporters_[PipelineStage::kBeginImplFrame]) {
+    reporters_[PipelineStage::kBeginImplFrame]->TerminateFrame(
+        CompositorFrameReporter::FrameTerminationStatus::kReplacedByNewReporter,
+        begin_time);
+  }
   std::unique_ptr<CompositorFrameReporter> reporter =
-      std::make_unique<CompositorFrameReporter>();
-  reporter->StartStage("BeginImplFrameToSendBeginMainFrame");
-  if (reporters_[PipelineStage::kBeginImplFrame])
-    reporters_[PipelineStage::kBeginImplFrame]->SetFrameTerminationStatus(
-        CompositorFrameReporter::FrameTerminationStatus::
-            kReplacedByNewReporter);
+      std::make_unique<CompositorFrameReporter>(is_single_threaded_);
+  reporter->StartStage(
+      CompositorFrameReporter::StageType::kBeginImplFrameToSendBeginMainFrame,
+      begin_time,
+      stage_history_[static_cast<int>(CompositorFrameReporter::StageType::
+                                          kBeginImplFrameToSendBeginMainFrame)]
+          .get());
   reporters_[PipelineStage::kBeginImplFrame] = std::move(reporter);
 }
 
 void CompositorFrameReportingController::WillBeginMainFrame() {
   DCHECK(reporters_[PipelineStage::kBeginImplFrame]);
-  DCHECK(reporters_[PipelineStage::kBeginMainFrame] !=
-         reporters_[PipelineStage::kBeginImplFrame]);
+  DCHECK_NE(reporters_[PipelineStage::kBeginMainFrame],
+            reporters_[PipelineStage::kBeginImplFrame]);
   reporters_[PipelineStage::kBeginImplFrame]->StartStage(
-      "SendBeginMainFrameToCommit");
+      CompositorFrameReporter::StageType::kSendBeginMainFrameToCommit, Now(),
+      stage_history_[static_cast<int>(CompositorFrameReporter::StageType::
+                                          kSendBeginMainFrameToCommit)]
+          .get());
   AdvanceReporterStage(PipelineStage::kBeginImplFrame,
                        PipelineStage::kBeginMainFrame);
 }
@@ -43,20 +72,27 @@
   DCHECK(reporters_[PipelineStage::kBeginMainFrame]);
   std::unique_ptr<CompositorFrameReporter> aborted_frame_reporter =
       std::move(reporters_[PipelineStage::kBeginMainFrame]);
-  aborted_frame_reporter->StartStage("BeginMainFrameAborted");
-  aborted_frame_reporter->SetFrameTerminationStatus(
-      CompositorFrameReporter::FrameTerminationStatus::kMainFrameAborted);
+  aborted_frame_reporter->TerminateFrame(
+      CompositorFrameReporter::FrameTerminationStatus::kMainFrameAborted,
+      Now());
 }
 
 void CompositorFrameReportingController::WillCommit() {
   DCHECK(reporters_[PipelineStage::kBeginMainFrame]);
-  reporters_[PipelineStage::kBeginMainFrame]->StartStage("Commit");
+  reporters_[PipelineStage::kBeginMainFrame]->StartStage(
+      CompositorFrameReporter::StageType::kCommit, Now(),
+      stage_history_[static_cast<int>(
+                         CompositorFrameReporter::StageType::kCommit)]
+          .get());
 }
 
 void CompositorFrameReportingController::DidCommit() {
   DCHECK(reporters_[PipelineStage::kBeginMainFrame]);
   reporters_[PipelineStage::kBeginMainFrame]->StartStage(
-      "EndCommitToActivation");
+      CompositorFrameReporter::StageType::kEndCommitToActivation, Now(),
+      stage_history_[static_cast<int>(CompositorFrameReporter::StageType::
+                                          kEndCommitToActivation)]
+          .get());
   AdvanceReporterStage(PipelineStage::kBeginMainFrame, PipelineStage::kCommit);
 }
 
@@ -65,11 +101,16 @@
   // TODO(alsan): Report latency of impl side invalidations.
   next_activate_has_invalidation_ = true;
 }
+
 void CompositorFrameReportingController::WillActivate() {
   DCHECK(reporters_[PipelineStage::kCommit] || next_activate_has_invalidation_);
   if (!reporters_[PipelineStage::kCommit])
     return;
-  reporters_[PipelineStage::kCommit]->StartStage("Activation");
+  reporters_[PipelineStage::kCommit]->StartStage(
+      CompositorFrameReporter::StageType::kActivation, Now(),
+      stage_history_[static_cast<int>(
+                         CompositorFrameReporter::StageType::kActivation)]
+          .get());
 }
 
 void CompositorFrameReportingController::DidActivate() {
@@ -78,35 +119,43 @@
   if (!reporters_[PipelineStage::kCommit])
     return;
   reporters_[PipelineStage::kCommit]->StartStage(
-      "EndActivateToSubmitCompositorFrame");
+      CompositorFrameReporter::StageType::kEndActivateToSubmitCompositorFrame,
+      Now(),
+      stage_history_[static_cast<int>(CompositorFrameReporter::StageType::
+                                          kEndActivateToSubmitCompositorFrame)]
+          .get());
   AdvanceReporterStage(PipelineStage::kCommit, PipelineStage::kActivate);
 }
 
 void CompositorFrameReportingController::DidSubmitCompositorFrame() {
   if (!reporters_[PipelineStage::kActivate])
     return;
+  base::TimeTicks submit_time = Now();
   std::unique_ptr<CompositorFrameReporter> submitted_reporter =
       std::move(reporters_[PipelineStage::kActivate]);
-  submitted_reporter->StartStage("SubmitCompositorFrame");
   // If there are any other reporters active on the other stages of the
   // pipeline then that means a new frame was started during the duration of
   // this reporter and therefore the frame being tracked missed the deadline.
   if (reporters_[PipelineStage::kBeginImplFrame] ||
       reporters_[PipelineStage::kBeginMainFrame] ||
       reporters_[PipelineStage::kCommit]) {
-    submitted_reporter->SetFrameTerminationStatus(
+    submitted_reporter->TerminateFrame(
         CompositorFrameReporter::FrameTerminationStatus::
-            kSubmittedFrameMissedDeadline);
+            kSubmittedFrameMissedDeadline,
+        submit_time);
   } else {
-    submitted_reporter->SetFrameTerminationStatus(
-        CompositorFrameReporter::FrameTerminationStatus::kSubmittedFrame);
+    submitted_reporter->TerminateFrame(
+        CompositorFrameReporter::FrameTerminationStatus::kSubmittedFrame,
+        submit_time);
   }
 }
 
 void CompositorFrameReportingController::DidNotProduceFrame() {
-  if (reporters_[PipelineStage::kActivate])
-    reporters_[PipelineStage::kActivate]->SetFrameTerminationStatus(
-        CompositorFrameReporter::FrameTerminationStatus::kDidNotProduceFrame);
+  if (!reporters_[PipelineStage::kActivate])
+    return;
+  reporters_[PipelineStage::kActivate]->TerminateFrame(
+      CompositorFrameReporter::FrameTerminationStatus::kDidNotProduceFrame,
+      Now());
   reporters_[PipelineStage::kActivate] = nullptr;
 }
 
@@ -114,9 +163,9 @@
     PipelineStage start,
     PipelineStage target) {
   if (reporters_[target]) {
-    reporters_[target]->SetFrameTerminationStatus(
-        CompositorFrameReporter::FrameTerminationStatus::
-            kReplacedByNewReporter);
+    reporters_[target]->TerminateFrame(
+        CompositorFrameReporter::FrameTerminationStatus::kReplacedByNewReporter,
+        Now());
   }
   reporters_[target] = std::move(reporters_[start]);
 }
diff --git a/cc/scheduler/compositor_frame_reporting_controller.h b/cc/scheduler/compositor_frame_reporting_controller.h
index 9b72cff..0251ec7 100644
--- a/cc/scheduler/compositor_frame_reporting_controller.h
+++ b/cc/scheduler/compositor_frame_reporting_controller.h
@@ -6,13 +6,16 @@
 #define CC_SCHEDULER_COMPOSITOR_FRAME_REPORTING_CONTROLLER_H_
 
 #include <memory>
+#include <vector>
 
 #include "base/time/time.h"
 #include "cc/base/base_export.h"
+#include "cc/base/rolling_time_delta_history.h"
 #include "cc/cc_export.h"
+#include "cc/scheduler/compositor_frame_reporter.h"
 
 namespace cc {
-class CompositorFrameReporter;
+class RollingTimeDeltaHistory;
 
 // This is used for managing simultaneous CompositorFrameReporter instances
 // in the case that the compositor has high latency. Calling one of the
@@ -31,7 +34,7 @@
     kNumPipelineStages
   };
 
-  CompositorFrameReportingController();
+  explicit CompositorFrameReportingController(bool is_single_threaded = false);
   virtual ~CompositorFrameReportingController();
 
   CompositorFrameReportingController(
@@ -52,13 +55,23 @@
   virtual void DidNotProduceFrame();
 
  protected:
+  base::TimeTicks Now() const;
   std::unique_ptr<CompositorFrameReporter>
       reporters_[PipelineStage::kNumPipelineStages];
 
  private:
   void AdvanceReporterStage(PipelineStage start, PipelineStage target);
 
+  // Used by the managed reporters to differentiate the histogram names when
+  // reporting to UMA.
+  const bool is_single_threaded_;
   bool next_activate_has_invalidation_ = false;
+
+  // These keep track of stage durations for when a frame did not miss a
+  // deadline. The history is used by reporter instances to determine if a
+  // missed frame had a stage duration that was abnormally large.
+  std::unique_ptr<RollingTimeDeltaHistory> stage_history_[static_cast<size_t>(
+      CompositorFrameReporter::StageType::kStageTypeCount)];
 };
 }  // namespace cc
 
diff --git a/cc/scheduler/compositor_frame_reporting_controller_unittest.cc b/cc/scheduler/compositor_frame_reporting_controller_unittest.cc
index 94f6ffd..60d27b4 100644
--- a/cc/scheduler/compositor_frame_reporting_controller_unittest.cc
+++ b/cc/scheduler/compositor_frame_reporting_controller_unittest.cc
@@ -5,6 +5,7 @@
 #include "cc/scheduler/compositor_frame_reporting_controller.h"
 
 #include "base/macros.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace cc {
@@ -108,24 +109,24 @@
   EXPECT_EQ(1, reporting_controller_.ActiveReporters());
 
   // BF -> BF
-  // Should replace previous reporter
+  // Should replace previous reporter.
   reporting_controller_.WillBeginImplFrame();
   EXPECT_EQ(1, reporting_controller_.ActiveReporters());
 
   // BF -> BMF -> BF
-  // Should add new reporter
+  // Should add new reporter.
   reporting_controller_.WillBeginMainFrame();
   reporting_controller_.WillBeginImplFrame();
   EXPECT_EQ(2, reporting_controller_.ActiveReporters());
 
   // BF -> BMF -> BF -> Commit
-  // Should stay same
+  // Should stay same.
   reporting_controller_.WillCommit();
   reporting_controller_.DidCommit();
   EXPECT_EQ(2, reporting_controller_.ActiveReporters());
 
   // BF -> BMF -> BF -> Commit -> BMF -> Activate -> Commit -> Activation
-  // Having two reporters at Activate phase should delete the older one
+  // Having two reporters at Activate phase should delete the older one.
   reporting_controller_.WillBeginMainFrame();
   reporting_controller_.WillActivate();
   reporting_controller_.DidActivate();
@@ -138,7 +139,7 @@
   reporting_controller_.DidSubmitCompositorFrame();
   EXPECT_EQ(0, reporting_controller_.ActiveReporters());
 
-  // 4 simultaneous reporters
+  // 4 simultaneous reporters active.
   SimulateActivate();
 
   SimulateCommit();
@@ -148,9 +149,75 @@
   SimulateBeginImplFrame();
   EXPECT_EQ(4, reporting_controller_.ActiveReporters());
 
-  // Any additional BeginImplFrame's would be ignored
+  // Any additional BeginImplFrame's would be ignored.
   SimulateBeginImplFrame();
   EXPECT_EQ(4, reporting_controller_.ActiveReporters());
 }
+
+TEST_F(CompositorFrameReportingControllerTest,
+       SubmittedFrameHistogramReporting) {
+  base::HistogramTester histogram_tester;
+
+  // 2 reporters active.
+  SimulateActivate();
+  SimulateBeginImplFrame();
+
+  // Submitting the next reporter should be missed.
+  SimulateSubmitCompositorFrame();
+
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.MissedFrame.BeginImplFrameToSendBeginMainFrame", 1);
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.MissedFrame.SendBeginMainFrameToCommit", 1);
+  histogram_tester.ExpectTotalCount("CompositorLatency.MissedFrame.Commit", 1);
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.MissedFrame.EndCommitToActivation", 1);
+  histogram_tester.ExpectTotalCount("CompositorLatency.MissedFrame.Activation",
+                                    1);
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.MissedFrame.EndActivateToSubmitCompositorFrame", 1);
+
+  // Other histograms should not be reported.
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.BeginImplFrameToSendBeginMainFrame", 0);
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.SendBeginMainFrameToCommit", 0);
+  histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 0);
+  histogram_tester.ExpectTotalCount("CompositorLatency.EndCommitToActivation",
+                                    0);
+  histogram_tester.ExpectTotalCount("CompositorLatency.Activation", 0);
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.EndActivateToSubmitCompositorFrame", 0);
+
+  // Submitting the next reporter will not be counted as missed.
+  // In practice this submitted frame should be considered as missed because a
+  // new BeginFrame would have been issued, which is the cause for this frame
+  // submission.
+  SimulateSubmitCompositorFrame();
+  // Other histograms should not be reported.
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.BeginImplFrameToSendBeginMainFrame", 1);
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.SendBeginMainFrameToCommit", 1);
+  histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 1);
+  histogram_tester.ExpectTotalCount("CompositorLatency.EndCommitToActivation",
+                                    1);
+  histogram_tester.ExpectTotalCount("CompositorLatency.Activation", 1);
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.EndActivateToSubmitCompositorFrame", 1);
+
+  // Missed frame histogram counts should not change.
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.MissedFrame.BeginImplFrameToSendBeginMainFrame", 1);
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.MissedFrame.SendBeginMainFrameToCommit", 1);
+  histogram_tester.ExpectTotalCount("CompositorLatency.MissedFrame.Commit", 1);
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.MissedFrame.EndCommitToActivation", 1);
+  histogram_tester.ExpectTotalCount("CompositorLatency.MissedFrame.Activation",
+                                    1);
+  histogram_tester.ExpectTotalCount(
+      "CompositorLatency.MissedFrame.EndActivateToSubmitCompositorFrame", 1);
+}
 }  // namespace
 }  // namespace cc
diff --git a/cc/test/fake_compositor_frame_reporting_controller.cc b/cc/test/fake_compositor_frame_reporting_controller.cc
index 905f3b4..a828263 100644
--- a/cc/test/fake_compositor_frame_reporting_controller.cc
+++ b/cc/test/fake_compositor_frame_reporting_controller.cc
@@ -5,8 +5,9 @@
 #include "cc/test/fake_compositor_frame_reporting_controller.h"
 
 namespace cc {
-FakeCompositorFrameReportingController::FakeCompositorFrameReportingController()
-    : CompositorFrameReportingController() {}
+FakeCompositorFrameReportingController::FakeCompositorFrameReportingController(
+    bool is_single_threaded)
+    : CompositorFrameReportingController(is_single_threaded) {}
 
 void FakeCompositorFrameReportingController::WillBeginMainFrame() {
   if (!reporters_[PipelineStage::kBeginImplFrame])
diff --git a/cc/test/fake_compositor_frame_reporting_controller.h b/cc/test/fake_compositor_frame_reporting_controller.h
index bd52323..4bf881d 100644
--- a/cc/test/fake_compositor_frame_reporting_controller.h
+++ b/cc/test/fake_compositor_frame_reporting_controller.h
@@ -15,7 +15,8 @@
 class FakeCompositorFrameReportingController
     : public CompositorFrameReportingController {
  public:
-  FakeCompositorFrameReportingController();
+  explicit FakeCompositorFrameReportingController(
+      bool is_single_threaded = false);
 
   FakeCompositorFrameReportingController(
       const FakeCompositorFrameReportingController& controller) = delete;
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index 85460b3..d43cf62 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -231,7 +231,8 @@
                           std::move(image_worker_task_runner)),
         test_hooks_(test_hooks) {
     compositor_frame_reporting_controller_ =
-        std::make_unique<FakeCompositorFrameReportingController>();
+        std::make_unique<FakeCompositorFrameReportingController>(
+            settings.single_thread_proxy_scheduler);
   }
 
   std::unique_ptr<RasterBufferProvider> CreateRasterBufferProvider() override {
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 10924d0..cc3f57d 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -323,7 +323,8 @@
       task_runner_provider_(task_runner_provider),
       current_begin_frame_tracker_(BEGINFRAMETRACKER_FROM_HERE),
       compositor_frame_reporting_controller_(
-          std::make_unique<CompositorFrameReportingController>()),
+          std::make_unique<CompositorFrameReportingController>(
+              settings.single_thread_proxy_scheduler)),
       settings_(settings),
       is_synchronous_single_threaded_(!task_runner_provider->HasImplThread() &&
                                       !settings_.single_thread_proxy_scheduler),
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml
index c152412..fd1cfc05 100644
--- a/chrome/android/java/res/values/colors.xml
+++ b/chrome/android/java/res/values/colors.xml
@@ -161,9 +161,6 @@
     <color name="light_background_color">@android:color/white</color>
     <color name="resizing_background_color">@android:color/white</color>
 
-    <!-- WebappActivity colors -->
-    <color name="webapp_default_bg">@color/modern_grey_50</color>
-
     <!-- Favicon colors -->
     <color name="default_favicon_background_color">#787878</color>
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
index 80e94f96..16d1573 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
@@ -23,7 +23,6 @@
 import android.widget.TextView;
 
 import org.chromium.base.ContextUtils;
-import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
@@ -57,7 +56,6 @@
 import org.chromium.ui.base.PageTransition;
 
 import java.util.List;
-import java.util.Set;
 
 /**
  * Displays and manages the UI for browsing history.
@@ -220,7 +218,6 @@
             mSelectionDelegate.clearSelection();
             return true;
         } else if (item.getItemId() == R.id.selection_mode_delete_menu_id) {
-            recordSelectionCountHistorgram("Remove");
             recordUserActionWithOptionalSearch("RemoveSelected");
 
             int numItemsRemoved = 0;
@@ -416,7 +413,6 @@
     }
 
     private void openItemsInNewTabs(List<HistoryItem> items, boolean isIncognito) {
-        recordSelectionCountHistorgram("Open");
         recordUserActionWithOptionalSearch("OpenSelected" + (isIncognito ? "Incognito" : ""));
 
         for (HistoryItem item : items) {
@@ -463,16 +459,6 @@
     }
 
     /**
-     * Records the number of selected items when a multi-select action is performed.
-     * @param action The multi-select action that was performed.
-     */
-    private void recordSelectionCountHistorgram(String action) {
-        Set<HistoryItem> selectedItems = mSelectionDelegate.getSelectedItems();
-        RecordHistogram.recordCount100Histogram(
-                METRICS_PREFIX + action + "Selected", selectedItems.size());
-    }
-
-    /**
      * @return True if info menu item should be shown on history toolbar, false otherwise.
      */
     boolean shouldShowInfoButton() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilter.java b/chrome/android/java/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilter.java
index ef9c7f9..582715b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilter.java
@@ -158,6 +158,7 @@
     private int mActualGroupCount;
     private Tab mAbsentSelectedTab;
     private boolean mShouldRecordUma = true;
+    private boolean mTabRestoreCompleted;
 
     public TabGroupModelFilter(TabModel tabModel) {
         super(tabModel);
@@ -170,6 +171,7 @@
                 RecordHistogram.recordCountHistogram("TabGroups.UserGroupCount", mActualGroupCount);
                 Tab currentTab = TabModelUtils.getCurrentTab(getTabModel());
                 if (currentTab != null) recordSessionsCount(currentTab);
+                mTabRestoreCompleted = true;
                 removeObserver(this);
             }
         });
@@ -541,6 +543,8 @@
 
     @Override
     public void didMoveTab(Tab tab, int newIndex, int curIndex) {
+        // Ignore didMoveTab calls in tab restoring stage.
+        if (!mTabRestoreCompleted) return;
         // Need to cache the flags before resetting the internal data map.
         boolean isMergeTabToGroup = isMergeTabToGroup(tab);
         boolean isMoveTabOutOfGroup = isMoveTabOutOfGroup(tab);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java
index a250b9d..b4bcfae 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.webapps;
 
+import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -32,6 +33,7 @@
 import org.chromium.webapk.lib.common.WebApkConstants;
 import org.chromium.webapk.lib.common.WebApkMetaDataKeys;
 import org.chromium.webapk.lib.common.WebApkMetaDataUtils;
+import org.chromium.webapk.lib.common.splash.SplashLayout;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -273,11 +275,10 @@
             return null;
         }
 
+        Context appContext = ContextUtils.getApplicationContext();
         Resources res = null;
         try {
-            res = ContextUtils.getApplicationContext()
-                          .getPackageManager()
-                          .getResourcesForApplication(webApkPackageName);
+            res = appContext.getPackageManager().getResourcesForApplication(webApkPackageName);
         } catch (PackageManager.NameNotFoundException e) {
             return null;
         }
@@ -304,6 +305,19 @@
                 WebApkMetaDataUtils.getLongFromMetaData(bundle, WebApkMetaDataKeys.BACKGROUND_COLOR,
                         ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING);
 
+        // Fetch the default background color from the WebAPK's resources. Fetching the default
+        // background color from the WebAPK is important for consistency when:
+        // - A new version of Chrome has changed the default background color.
+        // - Chrome has not yet requested an update for the WebAPK and the WebAPK still has the old
+        //   default background color in its resources.
+        // New-style WebAPKs use the background color and default background color in both the
+        // WebAPK and Chrome processes.
+        int defaultBackgroundColorId =
+                IntentUtils.safeGetInt(bundle, WebApkMetaDataKeys.DEFAULT_BACKGROUND_COLOR_ID, 0);
+        int defaultBackgroundColor = (defaultBackgroundColorId == 0)
+                ? SplashLayout.getDefaultBackgroundColor(appContext)
+                : ApiCompatibilityUtils.getColor(res, defaultBackgroundColorId);
+
         int shellApkVersion =
                 IntentUtils.safeGetInt(bundle, WebApkMetaDataKeys.SHELL_APK_VERSION, 0);
 
@@ -334,10 +348,10 @@
 
         return create(WebApkConstants.WEBAPK_ID_PREFIX + webApkPackageName, url, scope,
                 new Icon(primaryIcon), new Icon(badgeIcon), new Icon(splashIcon), name, shortName,
-                displayMode, orientation, source, themeColor, backgroundColor, webApkPackageName,
-                shellApkVersion, manifestUrl, manifestStartUrl, distributor,
-                iconUrlToMurmur2HashMap, shareTarget, shareTargetActivityName, forceNavigation,
-                isSplashProvidedByWebApk, shareData);
+                displayMode, orientation, source, themeColor, backgroundColor,
+                defaultBackgroundColor, webApkPackageName, shellApkVersion, manifestUrl,
+                manifestStartUrl, distributor, iconUrlToMurmur2HashMap, shareTarget,
+                shareTargetActivityName, forceNavigation, isSplashProvidedByWebApk, shareData);
     }
 
     /**
@@ -355,6 +369,8 @@
      * @param source                   Source that the WebAPK was launched from.
      * @param themeColor               The theme color of the WebAPK.
      * @param backgroundColor          The background color of the WebAPK.
+     * @param defaultBackgroundColor   The background color to use if the Web Manifest does not
+     *                                 provide a background color.
      * @param webApkPackageName        The package of the WebAPK.
      * @param shellApkVersion          Version of the code in //chrome/android/webapk/shell_apk.
      * @param manifestUrl              URL of the Web Manifest.
@@ -377,10 +393,10 @@
     public static WebApkInfo create(String id, String url, String scope, Icon primaryIcon,
             Icon badgeIcon, Icon splashIcon, String name, String shortName,
             @WebDisplayMode int displayMode, int orientation, int source, long themeColor,
-            long backgroundColor, String webApkPackageName, int shellApkVersion, String manifestUrl,
-            String manifestStartUrl, @WebApkDistributor int distributor,
-            Map<String, String> iconUrlToMurmur2HashMap, ShareTarget shareTarget,
-            String shareTargetActivityName, boolean forceNavigation,
+            long backgroundColor, int defaultBackgroundColor, String webApkPackageName,
+            int shellApkVersion, String manifestUrl, String manifestStartUrl,
+            @WebApkDistributor int distributor, Map<String, String> iconUrlToMurmur2HashMap,
+            ShareTarget shareTarget, String shareTargetActivityName, boolean forceNavigation,
             boolean isSplashProvidedByWebApk, ShareData shareData) {
         if (id == null || url == null || manifestStartUrl == null || webApkPackageName == null) {
             Log.e(TAG,
@@ -397,22 +413,22 @@
         }
 
         return new WebApkInfo(id, url, scope, primaryIcon, badgeIcon, splashIcon, name, shortName,
-                displayMode, orientation, source, themeColor, backgroundColor, webApkPackageName,
-                shellApkVersion, manifestUrl, manifestStartUrl, distributor,
-                iconUrlToMurmur2HashMap, shareTarget, shareTargetActivityName, forceNavigation,
-                isSplashProvidedByWebApk, shareData);
+                displayMode, orientation, source, themeColor, backgroundColor,
+                defaultBackgroundColor, webApkPackageName, shellApkVersion, manifestUrl,
+                manifestStartUrl, distributor, iconUrlToMurmur2HashMap, shareTarget,
+                shareTargetActivityName, forceNavigation, isSplashProvidedByWebApk, shareData);
     }
 
     protected WebApkInfo(String id, String url, String scope, Icon primaryIcon, Icon badgeIcon,
             Icon splashIcon, String name, String shortName, @WebDisplayMode int displayMode,
             int orientation, int source, long themeColor, long backgroundColor,
-            String webApkPackageName, int shellApkVersion, String manifestUrl,
-            String manifestStartUrl, @WebApkDistributor int distributor,
+            int defaultBackgroundColor, String webApkPackageName, int shellApkVersion,
+            String manifestUrl, String manifestStartUrl, @WebApkDistributor int distributor,
             Map<String, String> iconUrlToMurmur2HashMap, ShareTarget shareTarget,
             String shareTargetActivityName, boolean forceNavigation,
             boolean isSplashProvidedByWebApk, ShareData shareData) {
         super(id, url, scope, primaryIcon, name, shortName, displayMode, orientation, source,
-                themeColor, backgroundColor, false /* isIconGenerated */,
+                themeColor, backgroundColor, defaultBackgroundColor, false /* isIconGenerated */,
                 false /* isIconAdaptive */, forceNavigation);
         mBadgeIcon = badgeIcon;
         mSplashIcon = splashIcon;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcher.java
index 5a87979f..4ad4d92 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcher.java
@@ -4,14 +4,17 @@
 
 package org.chromium.chrome.browser.webapps;
 
+import android.content.Context;
 import android.graphics.Bitmap;
 import android.text.TextUtils;
 
+import org.chromium.base.ContextUtils;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.blink_public.platform.WebDisplayMode;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.content_public.browser.WebContents;
+import org.chromium.webapk.lib.common.splash.SplashLayout;
 
 import java.util.HashMap;
 
@@ -103,6 +106,8 @@
             String shareParamsTitle, String shareParamsText, String shareParamsUrl,
             boolean isShareMethodPost, boolean isShareEncTypeMultipart,
             String[] shareParamsFileNames, String[][] shareParamsAccepts) {
+        Context appContext = ContextUtils.getApplicationContext();
+
         HashMap<String, String> iconUrlToMurmur2HashMap = new HashMap<String, String>();
         for (String iconUrl : iconUrls) {
             String murmur2Hash = null;
@@ -121,13 +126,14 @@
                         shareParamsUrl, isShareMethodPost, isShareEncTypeMultipart,
                         shareParamsFileNames, shareParamsAccepts);
 
+        int defaultBackgroundColor = SplashLayout.getDefaultBackgroundColor(appContext);
         WebApkInfo info = WebApkInfo.create(mOldInfo.id(), mOldInfo.uri().toString(), scopeUrl,
                 new WebApkInfo.Icon(primaryIconBitmap), new WebApkInfo.Icon(badgeIconBitmap), null,
                 name, shortName, displayMode, orientation, mOldInfo.source(), themeColor,
-                backgroundColor, mOldInfo.webApkPackageName(), mOldInfo.shellApkVersion(),
-                mOldInfo.manifestUrl(), manifestStartUrl, WebApkInfo.WebApkDistributor.BROWSER,
-                iconUrlToMurmur2HashMap, shareTarget, null, mOldInfo.shouldForceNavigation(),
-                mOldInfo.isSplashProvidedByWebApk(), null);
+                backgroundColor, defaultBackgroundColor, mOldInfo.webApkPackageName(),
+                mOldInfo.shellApkVersion(), mOldInfo.manifestUrl(), manifestStartUrl,
+                WebApkInfo.WebApkDistributor.BROWSER, iconUrlToMurmur2HashMap, shareTarget, null,
+                mOldInfo.shouldForceNavigation(), mOldInfo.isSplashProvidedByWebApk(), null);
         mObserver.onGotManifestData(info, primaryIconUrl, badgeIconUrl);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java
index 224c559..2581093 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java
@@ -21,6 +21,7 @@
 import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
 import org.chromium.chrome.browser.util.IntentUtils;
 import org.chromium.content_public.common.ScreenOrientationValues;
+import org.chromium.webapk.lib.common.splash.SplashLayout;
 
 /**
  * Stores info about a web app.
@@ -71,6 +72,7 @@
     private int mSource;
     private long mThemeColor;
     private long mBackgroundColor;
+    private int mDefaultBackgroundColor;
     private boolean mIsIconGenerated;
     private boolean mIsIconAdaptive;
     private boolean mForceNavigation;
@@ -201,15 +203,17 @@
             return null;
         }
 
+        int defaultBackgroundColor =
+                SplashLayout.getDefaultBackgroundColor(ContextUtils.getApplicationContext());
         return new WebappInfo(id, url, scope, icon, name, shortName, displayMode, orientation,
-                source, themeColor, backgroundColor, isIconGenerated, isIconAdaptive,
-                forceNavigation);
+                source, themeColor, backgroundColor, defaultBackgroundColor, isIconGenerated,
+                isIconAdaptive, forceNavigation);
     }
 
     protected WebappInfo(String id, String url, String scope, Icon icon, String name,
             String shortName, @WebDisplayMode int displayMode, int orientation, int source,
-            long themeColor, long backgroundColor, boolean isIconGenerated, boolean isIconAdaptive,
-            boolean forceNavigation) {
+            long themeColor, long backgroundColor, int defaultBackgroundColor,
+            boolean isIconGenerated, boolean isIconAdaptive, boolean forceNavigation) {
         Uri uri = Uri.parse(url);
         if (TextUtils.isEmpty(scope)) {
             scope = ShortcutHelper.getScopeFromUrl(url);
@@ -227,6 +231,7 @@
         mSource = source;
         mThemeColor = themeColor;
         mBackgroundColor = backgroundColor;
+        mDefaultBackgroundColor = defaultBackgroundColor;
         mIsIconGenerated = isIconGenerated;
         mIsIconAdaptive = isIconAdaptive;
         mForceNavigation = forceNavigation;
@@ -327,10 +332,10 @@
 
     /**
      * Returns the background color specified by {@link #backgroundColor()} if
-     * the value is valid. Returns the specified fallback color otherwise.
+     * the value is valid. Returns the webapp's default background color otherwise.
      */
-    public int backgroundColor(int fallback) {
-        return hasValidBackgroundColor() ? (int) mBackgroundColor : fallback;
+    public int backgroundColorFallbackToDefault() {
+        return hasValidBackgroundColor() ? (int) mBackgroundColor : mDefaultBackgroundColor;
     }
 
     // This is needed for clients that want to send the icon through an intent.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappSplashDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappSplashDelegate.java
index c03b5d7..b2c577e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappSplashDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappSplashDelegate.java
@@ -15,12 +15,10 @@
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 
-import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.FileUtils;
 import org.chromium.base.StrictModeContext;
 import org.chromium.base.metrics.RecordHistogram;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.lifecycle.NativeInitObserver;
 import org.chromium.chrome.browser.metrics.WebappSplashUmaCache;
@@ -74,9 +72,8 @@
     @Override
     public View buildSplashView() {
         Context appContext = ContextUtils.getApplicationContext();
-        int backgroundColor = ColorUtils.getOpaqueColor(
-                mWebappInfo.backgroundColor(ApiCompatibilityUtils.getColor(
-                        appContext.getResources(), R.color.webapp_default_bg)));
+        int backgroundColor =
+                ColorUtils.getOpaqueColor(mWebappInfo.backgroundColorFallbackToDefault());
         if (mWebappInfo.isSplashProvidedByWebApk()) {
             return buildSplashWithWebApkProvidedScreenshot(appContext, backgroundColor);
         }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcherTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcherTest.java
index f2c7d63..a53b975 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcherTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcherTest.java
@@ -103,7 +103,7 @@
         final WebApkUpdateDataFetcher fetcher = new WebApkUpdateDataFetcher();
         PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> {
             WebApkInfo oldInfo = WebApkInfo.create("", "", scopeUrl, null, null, null, null, null,
-                    -1, -1, -1, -1, -1, "random.package", -1, manifestUrl, "",
+                    -1, -1, -1, -1, -1, -1, "random.package", -1, manifestUrl, "",
                     WebApkInfo.WebApkDistributor.BROWSER, new HashMap<String, String>(), null,
                     null /*shareTargetActivityName*/, false /* forceNavigation */,
                     false /* isSplashProvidedByWebApk */, null /* shareData */);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java
index a90af0c7..64b94bb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java
@@ -154,7 +154,7 @@
             WebApkInfo info = WebApkInfo.create(
                     WEBAPK_ID, "", creationData.scope, null, null, null, creationData.name,
                     creationData.shortName, creationData.displayMode, creationData.orientation, 0,
-                    creationData.themeColor, creationData.backgroundColor, "",
+                    creationData.themeColor, creationData.backgroundColor, 0, "",
                     WebApkVersion.REQUEST_UPDATE_FOR_SHELL_APK_VERSION, creationData.manifestUrl,
                     creationData.startUrl, WebApkInfo.WebApkDistributor.BROWSER,
                     creationData.iconUrlToMurmur2HashMap, null, null /*shareTargetActivityName*/,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappVisibilityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappVisibilityTest.java
index 18991d5..e8df4cc 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappVisibilityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappVisibilityTest.java
@@ -134,7 +134,7 @@
                         false /* isIconAdaptive */, false /* forceNavigation */)
                 : WebApkInfo.create(
                         "", "", webappStartUrlOrScopeUrl, null, null, null, null, null, displayMode,
-                        0, 0, 0, 0, "", 0, null, "", WebApkInfo.WebApkDistributor.BROWSER, null,
+                        0, 0, 0, 0, 0, "", 0, null, "", WebApkInfo.WebApkDistributor.BROWSER, null,
                         null, null /*shareTargetActivityName*/, false /* forceNavigation */,
                         false /* isSplashProvidedByWebApk */, null /* shareData */
 
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilterUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilterUnitTest.java
index 063f49b8..f6a51bf 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilterUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/tasks/tabgroup/TabGroupModelFilterUnitTest.java
@@ -176,6 +176,7 @@
         }).when(mTabModel).getCount();
 
         doReturn(0).when(mTabModel).index();
+        doNothing().when(mTabModel).addObserver(mTabModelObserverCaptor.capture());
     }
 
     private Tab addTabToTabModel() {
@@ -185,18 +186,7 @@
         return tab;
     }
 
-    @Before
-    public void setUp() {
-        RecordUserAction.setDisabledForTests(true);
-        RecordHistogram.setDisabledForTests(true);
-
-        MockitoAnnotations.initMocks(this);
-
-        setUpTab();
-        setUpTabModel();
-
-        doNothing().when(mTabModel).addObserver(mTabModelObserverCaptor.capture());
-
+    private void setupTabGroupModelFilter(boolean isTabRestoreCompleted) {
         mTabGroupModelFilter = new TabGroupModelFilter(mTabModel);
         mTabGroupModelFilter.addTabGroupObserver(mTabGroupModelFilterObserver);
 
@@ -217,6 +207,22 @@
 
         mTabModel.addTab(mTab6, -1, TabLaunchType.FROM_CHROME_UI);
         mTabModelObserverCaptor.getValue().didAddTab(mTab6, TabLaunchType.FROM_CHROME_UI);
+
+        if (isTabRestoreCompleted) {
+            mTabGroupModelFilter.restoreCompleted();
+        }
+    }
+
+    @Before
+    public void setUp() {
+        RecordUserAction.setDisabledForTests(true);
+        RecordHistogram.setDisabledForTests(true);
+
+        MockitoAnnotations.initMocks(this);
+
+        setUpTab();
+        setUpTabModel();
+        setupTabGroupModelFilter(true);
     }
 
     @After
@@ -463,4 +469,24 @@
         verify(mTabGroupModelFilterObserver).didMoveTabGroup(mTab6, POSITION6, startIndex + 2);
         assertArrayEquals(mTabs.toArray(), expectedTabModel.toArray());
     }
+
+    @Test
+    public void ignoreUnrelatedMoveTab() {
+        // Simulate that the tab restoring is not yet finished.
+        setupTabGroupModelFilter(false);
+
+        mTabModelObserverCaptor.getValue().didMoveTab(mTab1, POSITION1, POSITION6);
+        mTabModelObserverCaptor.getValue().didMoveTab(mTab1, POSITION6, POSITION1);
+        mTabModelObserverCaptor.getValue().didMoveTab(mTab2, POSITION2, POSITION5);
+        mTabModelObserverCaptor.getValue().didMoveTab(mTab2, POSITION5, POSITION2);
+
+        // No call should be made here.
+        verify(mTabGroupModelFilterObserver, never())
+                .didMoveTabOutOfGroup(any(Tab.class), anyInt());
+        verify(mTabGroupModelFilterObserver, never()).didMergeTabToGroup(any(Tab.class), anyInt());
+        verify(mTabGroupModelFilterObserver, never())
+                .didMoveWithinGroup(any(Tab.class), anyInt(), anyInt());
+        verify(mTabGroupModelFilterObserver, never())
+                .didMoveTabGroup(any(Tab.class), anyInt(), anyInt());
+    }
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkInfoTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkInfoTest.java
index 0308db5..5ef3ae8 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkInfoTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkInfoTest.java
@@ -25,6 +25,7 @@
 import org.chromium.content_public.common.ScreenOrientationValues;
 import org.chromium.webapk.lib.common.WebApkConstants;
 import org.chromium.webapk.lib.common.WebApkMetaDataKeys;
+import org.chromium.webapk.lib.common.splash.SplashLayout;
 import org.chromium.webapk.test.WebApkTestHelper;
 
 import java.util.HashMap;
@@ -84,6 +85,11 @@
             return mIdValueMap.get(id);
         }
 
+        @Override
+        public int getColor(int id, Resources.Theme theme) {
+            return Integer.parseInt(getString(id));
+        }
+
         public void addStringForTesting(
                 String name, String defType, String defPackage, int identifier, String value) {
             String key = getKey(name, defType, defPackage);
@@ -91,6 +97,10 @@
             mIdValueMap.put(identifier, value);
         }
 
+        public void addColorForTesting(String name, String defPackage, int identifier, int value) {
+            addStringForTesting(name, "color", defPackage, identifier, Integer.toString(value));
+        }
+
         private String getKey(String name, String defType, String defPackage) {
             return defPackage + ":" + defType + "/" + name;
         }
@@ -463,4 +473,57 @@
         Assert.assertNotNull(info.shareTarget());
         Assert.assertEquals("", info.shareTarget().getAction());
     }
+
+    /**
+     * Test that {@link WebApkInfo#backgroundColorFallbackToDefault()} uses
+     * {@link SplashLayout#getDefaultBackgroundColor()} as the default background color if there is
+     * no default background color in the WebAPK's resources.
+     */
+    @Test
+    public void testBackgroundColorFallbackToDefaultNoCustomDefault() {
+        Bundle bundle = new Bundle();
+        bundle.putString(WebApkMetaDataKeys.START_URL, START_URL);
+        bundle.putString(WebApkMetaDataKeys.BACKGROUND_COLOR,
+                ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING + "L");
+        WebApkTestHelper.registerWebApkWithMetaData(WEBAPK_PACKAGE_NAME, bundle, null);
+
+        Intent intent = new Intent();
+        intent.putExtra(WebApkConstants.EXTRA_WEBAPK_PACKAGE_NAME, WEBAPK_PACKAGE_NAME);
+        intent.putExtra(ShortcutHelper.EXTRA_URL, START_URL);
+
+        WebApkInfo info = WebApkInfo.create(intent);
+        Assert.assertEquals(SplashLayout.getDefaultBackgroundColor(RuntimeEnvironment.application),
+                info.backgroundColorFallbackToDefault());
+    }
+
+    /**
+     * Test that {@link WebApkInfo#backgroundColorFallbackToDefault()} uses the default
+     * background color from the WebAPK's resources if present.
+     */
+    @Test
+    public void testBackgroundColorFallbackToDefaultWebApkHasCustomDefault() {
+        final int defaultBackgroundColorResourceId = 1;
+        final int defaultBackgroundColorInWebApk = 42;
+
+        Bundle bundle = new Bundle();
+        bundle.putString(WebApkMetaDataKeys.START_URL, START_URL);
+        bundle.putString(WebApkMetaDataKeys.BACKGROUND_COLOR,
+                ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING + "L");
+        bundle.putInt(
+                WebApkMetaDataKeys.DEFAULT_BACKGROUND_COLOR_ID, defaultBackgroundColorResourceId);
+        WebApkTestHelper.registerWebApkWithMetaData(WEBAPK_PACKAGE_NAME, bundle, null);
+
+        FakeResources res = new FakeResources();
+        res.addColorForTesting("mockResource", WEBAPK_PACKAGE_NAME,
+                defaultBackgroundColorResourceId, defaultBackgroundColorInWebApk);
+        WebApkTestHelper.setResource(WEBAPK_PACKAGE_NAME, res);
+
+        Intent intent = new Intent();
+        intent.putExtra(WebApkConstants.EXTRA_WEBAPK_PACKAGE_NAME, WEBAPK_PACKAGE_NAME);
+        intent.putExtra(ShortcutHelper.EXTRA_URL, START_URL);
+
+        WebApkInfo info = WebApkInfo.create(intent);
+        Assert.assertEquals(
+                defaultBackgroundColorInWebApk, info.backgroundColorFallbackToDefault());
+    }
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java
index 08af551..7bd08e103 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java
@@ -6,6 +6,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
@@ -13,6 +14,8 @@
 import static org.chromium.webapk.lib.client.WebApkVersion.REQUEST_UPDATE_FOR_SHELL_APK_VERSION;
 
 import android.content.Intent;
+import android.content.res.AssetManager;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.os.Bundle;
@@ -24,6 +27,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mockito;
+import org.robolectric.RuntimeEnvironment;
 import org.robolectric.android.util.concurrent.RoboExecutorService;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowLooper;
@@ -43,6 +47,7 @@
 import org.chromium.content_public.common.ScreenOrientationValues;
 import org.chromium.webapk.lib.common.WebApkConstants;
 import org.chromium.webapk.lib.common.WebApkMetaDataKeys;
+import org.chromium.webapk.lib.common.splash.SplashLayout;
 import org.chromium.webapk.test.WebApkTestHelper;
 
 import java.io.File;
@@ -84,6 +89,7 @@
     private static final int ORIENTATION = ScreenOrientationValues.DEFAULT;
     private static final long THEME_COLOR = 1L;
     private static final long BACKGROUND_COLOR = 2L;
+    private static final int DEFAULT_BACKGROUND_COLOR = 3;
     private static final String SHARE_TARGET_ACTION = "/share_action.html";
     private static final String SHARE_TARGET_PARAM_TITLE = "share_params_title";
     private static final String SHARE_TARGET_METHOD_GET = "GET";
@@ -214,6 +220,7 @@
         public int orientation;
         public long themeColor;
         public long backgroundColor;
+        public int defaultBackgroundColor;
         public String shareTargetAction;
         public String shareTargetParamTitle;
         public String shareTargetMethod;
@@ -222,6 +229,24 @@
         public String[][] shareTargetFileAccepts;
     }
 
+    private static class FakeDefaultBackgroundColorResource extends Resources {
+        private static final int ID = 10;
+        private int mColorValue;
+
+        public FakeDefaultBackgroundColorResource(int colorValue) {
+            super(new AssetManager(), null, null);
+            mColorValue = colorValue;
+        }
+
+        @Override
+        public int getColor(int id, Resources.Theme theme) {
+            if (id != ID) {
+                throw new Resources.NotFoundException("id 0x" + Integer.toHexString(id));
+            }
+            return mColorValue;
+        }
+    }
+
     private static String getWebApkId(String packageName) {
         return WebApkConstants.WEBAPK_ID_PREFIX + packageName;
     }
@@ -246,6 +271,8 @@
         metaData.putString(WebApkMetaDataKeys.SHORT_NAME, manifestData.shortName);
         metaData.putString(WebApkMetaDataKeys.THEME_COLOR, manifestData.themeColor + "L");
         metaData.putString(WebApkMetaDataKeys.BACKGROUND_COLOR, manifestData.backgroundColor + "L");
+        metaData.putInt(WebApkMetaDataKeys.DEFAULT_BACKGROUND_COLOR_ID,
+                FakeDefaultBackgroundColorResource.ID);
         metaData.putString(WebApkMetaDataKeys.WEB_MANIFEST_URL, WEB_MANIFEST_URL);
 
         String iconUrlsAndIconMurmur2Hashes = "";
@@ -292,6 +319,8 @@
 
         WebApkTestHelper.registerWebApkWithMetaData(
                 packageName, metaData, new Bundle[] {shareTargetMetaData});
+        WebApkTestHelper.setResource(packageName,
+                new FakeDefaultBackgroundColorResource(manifestData.defaultBackgroundColor));
     }
 
     private static ManifestData defaultManifestData() {
@@ -313,6 +342,7 @@
         manifestData.orientation = ORIENTATION;
         manifestData.themeColor = THEME_COLOR;
         manifestData.backgroundColor = BACKGROUND_COLOR;
+        manifestData.defaultBackgroundColor = DEFAULT_BACKGROUND_COLOR;
         manifestData.shareTargetAction = SHARE_TARGET_ACTION;
         manifestData.shareTargetParamTitle = SHARE_TARGET_PARAM_TITLE;
 
@@ -332,8 +362,9 @@
                 new WebApkInfo.Icon(manifestData.primaryIcon),
                 new WebApkInfo.Icon(manifestData.badgeIcon), null, manifestData.name,
                 manifestData.shortName, manifestData.displayMode, manifestData.orientation, -1,
-                manifestData.themeColor, manifestData.backgroundColor, kPackageName, -1,
-                WEB_MANIFEST_URL, manifestData.startUrl, WebApkInfo.WebApkDistributor.BROWSER,
+                manifestData.themeColor, manifestData.backgroundColor,
+                manifestData.defaultBackgroundColor, kPackageName, -1, WEB_MANIFEST_URL,
+                manifestData.startUrl, WebApkInfo.WebApkDistributor.BROWSER,
                 manifestData.iconUrlToMurmur2HashMap,
                 new WebApkInfo.ShareTarget(manifestData.shareTargetAction,
                         manifestData.shareTargetParamTitle, null, null,
@@ -1007,6 +1038,30 @@
     }
 
     /**
+     * Test that an upgrade is not requested if the AndroidManifest does not have a valid background
+     * color and the default background color in the WebAPK's resources is different than
+     * {@link SplashLayout#getDefaultBackgroundColor()} (due to a change in the return value of
+     * {@link SplashLayout#getDefaultBackgroundColor()} in a new Chrome version).
+     */
+    @Test
+    public void testDefaultBackgroundColorHasChangedShouldUpgrade() {
+        int oldDefaultBackgroundColor = 3;
+        int splashLayoutDefaultBackgroundColor =
+                SplashLayout.getDefaultBackgroundColor(RuntimeEnvironment.application);
+        assertNotEquals(oldDefaultBackgroundColor, splashLayoutDefaultBackgroundColor);
+
+        ManifestData androidManifestData = defaultManifestData();
+        androidManifestData.backgroundColor = ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING;
+        androidManifestData.defaultBackgroundColor = oldDefaultBackgroundColor;
+
+        ManifestData fetchedManifestData = defaultManifestData();
+        fetchedManifestData.backgroundColor = ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING;
+        fetchedManifestData.defaultBackgroundColor = splashLayoutDefaultBackgroundColor;
+
+        assertFalse(checkUpdateNeededForFetchedManifest(androidManifestData, fetchedManifestData));
+    }
+
+    /**
      * Tests that a WebAPK update is requested immediately if:
      * the Shell APK is out of date,
      * AND
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessUiCoordinatorImpl.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessUiCoordinatorImpl.java
index 1a0c918..d0b0336 100644
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessUiCoordinatorImpl.java
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessUiCoordinatorImpl.java
@@ -87,7 +87,6 @@
 
     @Override
     public KeyEvent processKeyEvent(KeyEvent event) {
-        if (mProgressBarCoordinator != null) mProgressBarCoordinator.onKeyEvent();
         if (mModelCoordinator == null) return event;
         return mModelCoordinator.onKeyEvent(event);
     }
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarCoordinator.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarCoordinator.java
index 916c9f04..985781c4 100644
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarCoordinator.java
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarCoordinator.java
@@ -32,10 +32,6 @@
         mMediator.onActivityResume();
     }
 
-    public void onKeyEvent() {
-        mMediator.onKeyEvent();
-    }
-
     public void destroy() {
         mMediator.destroy();
     }
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarMediator.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarMediator.java
index ca11fde..29322243 100644
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarMediator.java
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarMediator.java
@@ -36,11 +36,6 @@
         if (mModel.get(ProgressBarProperties.IS_ENABLED)) show();
     }
 
-    void onKeyEvent() {
-        mCanHideProgressBar = true;
-        hide();
-    }
-
     private void show() {
         if (mHideTask != null) mHideTask.cancel(false);
         mHideTask = new FutureTask<Void>(() -> {
diff --git a/chrome/android/touchless/junit/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarMediatorTest.java b/chrome/android/touchless/junit/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarMediatorTest.java
index d259dcb..5db6699 100644
--- a/chrome/android/touchless/junit/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarMediatorTest.java
+++ b/chrome/android/touchless/junit/src/org/chromium/chrome/browser/touchless/ui/progressbar/ProgressBarMediatorTest.java
@@ -97,16 +97,11 @@
         Assert.assertEquals(mModel.get(ProgressBarProperties.IS_ENABLED), false);
         Assert.assertEquals(mModel.get(ProgressBarProperties.IS_VISIBLE), false);
 
-        // Mock key press before timeout and page load finish.
+        // Mock display timeout before page load finish.
         mTabObserver.getValue().onPageLoadStarted(mTab, SAMPLE_URL);
-        progressBarMediator.onKeyEvent();
-        Assert.assertEquals(mModel.get(ProgressBarProperties.IS_ENABLED), true);
-        Assert.assertEquals(mModel.get(ProgressBarProperties.IS_VISIBLE), true);
-
-        // Mock display timeout before page load finish, and after key press.
         ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
         Assert.assertEquals(mModel.get(ProgressBarProperties.IS_ENABLED), true);
-        Assert.assertEquals(mModel.get(ProgressBarProperties.IS_VISIBLE), false);
+        Assert.assertEquals(mModel.get(ProgressBarProperties.IS_VISIBLE), true);
     }
 
     @Test
diff --git a/chrome/android/webapk/libs/common/res_splash/values/common_colors.xml b/chrome/android/webapk/libs/common/res_splash/values/common_colors.xml
index 4867176..85cb897 100644
--- a/chrome/android/webapk/libs/common/res_splash/values/common_colors.xml
+++ b/chrome/android/webapk/libs/common/res_splash/values/common_colors.xml
@@ -4,6 +4,7 @@
      found in the LICENSE file. -->
 
 <resources xmlns:tools="http://schemas.android.com/tools">
+    <color name="webapp_default_bg">#F8F9FA</color>
     <color name="webapp_grey_900">#202124</color>
     <color name="webapp_splash_title_light">@android:color/white</color>
 </resources>
diff --git a/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/WebApkMetaDataKeys.java b/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/WebApkMetaDataKeys.java
index cb57851..190c027 100644
--- a/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/WebApkMetaDataKeys.java
+++ b/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/WebApkMetaDataKeys.java
@@ -22,6 +22,8 @@
     public static final String ORIENTATION = "org.chromium.webapk.shell_apk.orientation";
     public static final String THEME_COLOR = "org.chromium.webapk.shell_apk.themeColor";
     public static final String BACKGROUND_COLOR = "org.chromium.webapk.shell_apk.backgroundColor";
+    public static final String DEFAULT_BACKGROUND_COLOR_ID =
+            "org.chromium.webapk.shell_apk.defaultBackgroundColorId";
     public static final String ICON_ID = "org.chromium.webapk.shell_apk.iconId";
     public static final String SPLASH_ID = "org.chromium.webapk.shell_apk.splashId";
 
diff --git a/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/splash/SplashLayout.java b/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/splash/SplashLayout.java
index 4b60512..0fc21f2 100644
--- a/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/splash/SplashLayout.java
+++ b/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/splash/SplashLayout.java
@@ -33,6 +33,10 @@
         int LARGE = 2;
     }
 
+    public static int getDefaultBackgroundColor(Context appContext) {
+        return getColorCompatibility(appContext.getResources(), R.color.webapp_default_bg);
+    }
+
     /**
      * Classifies the icon based on:
      * - Whether it is appropriate to display on the splash screen.
diff --git a/chrome/android/webapk/shell_apk/AndroidManifest.xml b/chrome/android/webapk/shell_apk/AndroidManifest.xml
index 45cd24e..0061613 100644
--- a/chrome/android/webapk/shell_apk/AndroidManifest.xml
+++ b/chrome/android/webapk/shell_apk/AndroidManifest.xml
@@ -123,7 +123,11 @@
         <meta-data android:name="org.chromium.webapk.shell_apk.displayMode" android:value="{{{display_mode}}}" />
         <meta-data android:name="org.chromium.webapk.shell_apk.orientation" android:value="{{{orientation}}}" />
         <meta-data android:name="org.chromium.webapk.shell_apk.themeColor" android:value="{{{theme_color}}}" />
+
+        <!-- Empty if the Web Manifest does not provide a background color. -->
         <meta-data android:name="org.chromium.webapk.shell_apk.backgroundColor" android:value="{{{background_color}}}" />
+
+        <meta-data android:name="org.chromium.webapk.shell_apk.defaultBackgroundColorId" android:resource="@color/webapp_default_bg" />
         <meta-data android:name="org.chromium.webapk.shell_apk.iconId" android:resource="@mipmap/app_icon" />
         <meta-data android:name="org.chromium.webapk.shell_apk.splashId" android:resource="@drawable/splash_icon" />
         <meta-data android:name="org.chromium.webapk.shell_apk.distributor" android:value="{{{distributor}}}" />
diff --git a/chrome/android/webapk/shell_apk/current_version/current_version.gni b/chrome/android/webapk/shell_apk/current_version/current_version.gni
index 1b53c34e..fe83047 100644
--- a/chrome/android/webapk/shell_apk/current_version/current_version.gni
+++ b/chrome/android/webapk/shell_apk/current_version/current_version.gni
@@ -12,4 +12,4 @@
 # //chrome/android/webapk/shell_apk:webapk is changed. This includes
 # Java files, Android resource files and AndroidManifest.xml. Does not affect
 # Chrome.apk
-current_shell_apk_version = 95
+current_shell_apk_version = 96
diff --git a/chrome/android/webapk/shell_apk/res/values-v17/styles.xml b/chrome/android/webapk/shell_apk/res/values-v17/styles.xml
index cf80bab7..65ebb8e2 100644
--- a/chrome/android/webapk/shell_apk/res/values-v17/styles.xml
+++ b/chrome/android/webapk/shell_apk/res/values-v17/styles.xml
@@ -7,6 +7,6 @@
   <style name="SplashTheme" parent="@android:style/Theme.Holo">
     <item name="android:windowActionBar">false</item>
     <item name="android:windowNoTitle">true</item>
-    <item name="android:windowBackground">@color/background_color</item>
+    <item name="android:windowBackground">@color/background_color_non_empty</item>
   </style>
 </resources>
diff --git a/chrome/android/webapk/shell_apk/res_template/values/background_color.xml b/chrome/android/webapk/shell_apk/res_template/values/background_color.xml
index c087ef02..8b06b059 100644
--- a/chrome/android/webapk/shell_apk/res_template/values/background_color.xml
+++ b/chrome/android/webapk/shell_apk/res_template/values/background_color.xml
@@ -4,5 +4,5 @@
      found in the LICENSE file. -->
 
 <resources>
-  <color name="background_color">{{{background_color_xml}}}</color>
+  <color name="background_color_non_empty">{{{background_color_xml}}}</color>
 </resources>
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/h2o/SplashUtils.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/h2o/SplashUtils.java
index 06716b3..e909f0c 100644
--- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/h2o/SplashUtils.java
+++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/h2o/SplashUtils.java
@@ -24,7 +24,7 @@
         Bitmap icon = WebApkUtils.decodeBitmapFromDrawable(resources, R.drawable.splash_icon);
         @SplashLayout.IconClassification
         int iconClassification = SplashLayout.classifyIcon(resources, icon, false);
-        int backgroundColor = WebApkUtils.getColor(resources, R.color.background_color);
+        int backgroundColor = WebApkUtils.getColor(resources, R.color.background_color_non_empty);
 
         FrameLayout layout = new FrameLayout(context);
         SplashLayout.createLayout(context, layout, icon, false /* isIconAdaptive */,
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index da5304d..383a259 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -4821,7 +4821,6 @@
     sources += [
       "spellchecker/spell_check_host_chrome_impl.cc",
       "spellchecker/spell_check_host_chrome_impl.h",
-      "spellchecker/spell_check_host_chrome_impl_mac.cc",
       "spellchecker/spellcheck_custom_dictionary.cc",
       "spellchecker/spellcheck_custom_dictionary.h",
       "spellchecker/spellcheck_factory.cc",
@@ -4836,6 +4835,13 @@
       "spellchecker/spellcheck_service.h",
     ]
 
+    if (use_browser_spellchecker) {
+      sources += [
+        "spellchecker/spelling_request.cc",
+        "spellchecker/spelling_request.h",
+      ]
+    }
+
     if (has_spellcheck_panel) {
       sources += [
         "spellchecker/spell_check_panel_host_impl.cc",
diff --git a/chrome/browser/accessibility/accessibility_extension_api.cc b/chrome/browser/accessibility/accessibility_extension_api.cc
index 9973a6b2..6dd7be5 100644
--- a/chrome/browser/accessibility/accessibility_extension_api.cc
+++ b/chrome/browser/accessibility/accessibility_extension_api.cc
@@ -25,7 +25,7 @@
 #include "components/infobars/core/confirm_infobar_delegate.h"
 #include "components/infobars/core/infobar.h"
 #include "content/public/browser/browser_accessibility_state.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/error_utils.h"
@@ -61,9 +61,8 @@
 ash::mojom::AccessibilityControllerPtr GetAccessibilityController() {
   // Connect to the accessibility mojo interface in ash.
   ash::mojom::AccessibilityControllerPtr accessibility_controller;
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(ash::mojom::kServiceName, &accessibility_controller);
+  content::GetSystemConnector()->BindInterface(ash::mojom::kServiceName,
+                                               &accessibility_controller);
   return accessibility_controller;
 }
 #endif
diff --git a/chrome/browser/android/download/download_media_parser.cc b/chrome/browser/android/download/download_media_parser.cc
index 4d72b46..34cd7ea9 100644
--- a/chrome/browser/android/download/download_media_parser.cc
+++ b/chrome/browser/android/download/download_media_parser.cc
@@ -14,7 +14,7 @@
 #include "cc/paint/skia_paint_canvas.h"
 #include "chrome/browser/android/download/local_media_data_source_factory.h"
 #include "content/public/browser/android/gpu_video_accelerator_factories_provider.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "media/base/overlay_info.h"
 #include "media/base/video_thumbnail_decoder.h"
 #include "media/mojo/clients/mojo_video_decoder.h"
@@ -97,8 +97,7 @@
   }
 
   size_ = file_size;
-  RetrieveMediaParser(
-      content::ServiceManagerConnection::GetForProcess()->GetConnector());
+  RetrieveMediaParser(content::GetSystemConnector());
 }
 
 void DownloadMediaParser::OnMediaParserCreated() {
@@ -269,9 +268,8 @@
     media_interface_provider_ = std::make_unique<media::MediaInterfaceProvider>(
         mojo::MakeRequest(&interfaces));
     media::mojom::MediaServicePtr media_service;
-    content::ServiceManagerConnection::GetForProcess()
-        ->GetConnector()
-        ->BindInterface(media::mojom::kMediaServiceName, &media_service);
+    content::GetSystemConnector()->BindInterface(
+        media::mojom::kMediaServiceName, &media_service);
     media_service->CreateInterfaceFactory(
         MakeRequest(&media_interface_factory_), std::move(interfaces));
     media_interface_factory_.set_connection_error_handler(
diff --git a/chrome/browser/android/explore_sites/image_helper.cc b/chrome/browser/android/explore_sites/image_helper.cc
index 3593ca9..57d624c9 100644
--- a/chrome/browser/android/explore_sites/image_helper.cc
+++ b/chrome/browser/android/explore_sites/image_helper.cc
@@ -8,7 +8,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/metrics/histogram_macros.h"
 #include "chrome/browser/android/explore_sites/explore_sites_types.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/data_decoder/public/cpp/decode_image.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -95,11 +95,7 @@
 }
 
 void ImageHelper::Job::SetupConnector() {
-  service_manager::mojom::ConnectorRequest connector_request;
-  connector_ = service_manager::Connector::Create(&connector_request);
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindConnectorRequest(std::move(connector_request));
+  connector_ = content::GetSystemConnector()->Clone();
 }
 
 void ImageHelper::Job::DecodeImageBytes(
diff --git a/chrome/browser/android/explore_sites/ntp_json_fetcher.cc b/chrome/browser/android/explore_sites/ntp_json_fetcher.cc
index ff7d4d8..56f446e 100644
--- a/chrome/browser/android/explore_sites/ntp_json_fetcher.cc
+++ b/chrome/browser/android/explore_sites/ntp_json_fetcher.cc
@@ -15,7 +15,7 @@
 #include "chrome/browser/android/explore_sites/url_util_experimental.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/storage_partition.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "net/base/load_flags.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "net/url_request/url_fetcher.h"
@@ -98,8 +98,7 @@
 
   // The parser will call us back via one of the callbacks.
   data_decoder::SafeJsonParser::Parse(
-      content::ServiceManagerConnection::GetForProcess()->GetConnector(),
-      *response_body,
+      content::GetSystemConnector(), *response_body,
       base::BindOnce(&NTPJsonFetcher::OnJsonParseSuccess,
                      weak_factory_.GetWeakPtr()),
       base::BindOnce(&NTPJsonFetcher::OnJsonParseError,
diff --git a/chrome/browser/android/vr/vr_shell.cc b/chrome/browser/android/vr/vr_shell.cc
index 2d7424c..992cc781 100644
--- a/chrome/browser/android/vr/vr_shell.cc
+++ b/chrome/browser/android/vr/vr_shell.cc
@@ -60,9 +60,9 @@
 #include "content/public/browser/render_widget_host_iterator.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/storage_partition.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/referrer.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/common/url_constants.h"
 #include "device/vr/android/gvr/cardboard_gamepad_data_fetcher.h"
 #include "device/vr/android/gvr/gvr_device.h"
@@ -193,9 +193,8 @@
 
   UpdateVrAssetsComponent(g_browser_process->component_updater());
 
-  auto* connector =
-      content::ServiceManagerConnection::GetForProcess()->GetConnector();
-  connector->BindInterface(device::mojom::kServiceName, &geolocation_config_);
+  content::GetSystemConnector()->BindInterface(device::mojom::kServiceName,
+                                               &geolocation_config_);
 }
 
 void VrShell::Destroy(JNIEnv* env, const JavaParamRef<jobject>& obj) {
diff --git a/chrome/browser/apps/app_service/app_icon_factory.cc b/chrome/browser/apps/app_service/app_icon_factory.cc
index f2cf630..2f9473a 100644
--- a/chrome/browser/apps/app_service/app_icon_factory.cc
+++ b/chrome/browser/apps/app_service/app_icon_factory.cc
@@ -17,7 +17,7 @@
 #include "chrome/browser/extensions/chrome_app_icon.h"
 #include "chrome/browser/extensions/chrome_app_icon_loader.h"
 #include "chrome/browser/extensions/extension_service.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/browser/component_extension_resource_manager.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/browser/extensions_browser_client.h"
@@ -166,7 +166,7 @@
     return;
   }
   data_decoder::DecodeImage(
-      content::ServiceManagerConnection::GetForProcess()->GetConnector(), data,
+      content::GetSystemConnector(), data,
       data_decoder::mojom::ImageCodec::DEFAULT, false,
       data_decoder::kDefaultMaxSizeInBytes, gfx::Size(),
       base::BindOnce(&RunCallbackWithUncompressedSkBitmap, size_hint_in_dip,
diff --git a/chrome/browser/apps/app_service/arc_apps.cc b/chrome/browser/apps/app_service/arc_apps.cc
index 71c65ab..02f978e 100644
--- a/chrome/browser/apps/app_service/arc_apps.cc
+++ b/chrome/browser/apps/app_service/arc_apps.cc
@@ -25,7 +25,7 @@
 #include "components/arc/common/app.mojom.h"
 #include "components/arc/common/app_permissions.mojom.h"
 #include "components/arc/session/arc_bridge_service.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/grit/extensions_browser_resources.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "services/data_decoder/public/cpp/decode_image.h"
@@ -83,8 +83,8 @@
 
     case apps::mojom::IconCompression::kUncompressed:
       data_decoder::DecodeImage(
-          content::ServiceManagerConnection::GetForProcess()->GetConnector(),
-          icon_png_data, data_decoder::mojom::ImageCodec::DEFAULT, false,
+          content::GetSystemConnector(), icon_png_data,
+          data_decoder::mojom::ImageCodec::DEFAULT, false,
           data_decoder::kDefaultMaxSizeInBytes, gfx::Size(),
           base::BindOnce(&LoadIcon2, std::move(callback)));
       break;
diff --git a/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc
index 7775727..9e5063c 100644
--- a/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc
+++ b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc
@@ -51,8 +51,8 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/service_manager_connection.h"
 #include "extensions/browser/api/file_system/file_system_api.h"
 #include "extensions/browser/app_window/app_window.h"
 #include "extensions/browser/app_window/app_window_registry.h"
@@ -679,7 +679,7 @@
       std::move(media_data_source_factory));
   SafeMediaMetadataParser* parser_ptr = parser.get();
   parser_ptr->Start(
-      content::ServiceManagerConnection::GetForProcess()->GetConnector(),
+      content::GetSystemConnector(),
       base::BindOnce(
           &MediaGalleriesGetMetadataFunction::OnSafeMediaMetadataParserDone,
           this, std::move(parser)));
diff --git a/chrome/browser/autofill/risk_util.cc b/chrome/browser/autofill/risk_util.cc
index e9e853f..25170c1 100644
--- a/chrome/browser/autofill/risk_util.cc
+++ b/chrome/browser/autofill/risk_util.cc
@@ -23,8 +23,8 @@
 #include "components/prefs/pref_service.h"
 #include "components/version_info/version_info.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/service_manager_connection.h"
 #include "services/service_manager/public/cpp/connector.h"
 
 #if !defined(OS_ANDROID)
@@ -89,15 +89,12 @@
       g_browser_process->metrics_service()->GetInstallDate());
 
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  DCHECK(content::ServiceManagerConnection::GetForProcess());
-  service_manager::Connector* connector =
-      content::ServiceManagerConnection::GetForProcess()->GetConnector();
-
   risk::GetFingerprint(
       obfuscated_gaia_id, window_bounds, web_contents,
       version_info::GetVersionNumber(), charset, accept_languages, install_time,
       g_browser_process->GetApplicationLocale(), GetUserAgent(),
-      base::BindOnce(PassRiskData, std::move(callback)), connector);
+      base::BindOnce(PassRiskData, std::move(callback)),
+      content::GetSystemConnector());
 }
 
 }  // namespace autofill
diff --git a/chrome/browser/battery/battery_metrics.cc b/chrome/browser/battery/battery_metrics.cc
index 08c61a2..f5639184 100644
--- a/chrome/browser/battery/battery_metrics.cc
+++ b/chrome/browser/battery/battery_metrics.cc
@@ -10,7 +10,7 @@
 #include "base/bind.h"
 #include "base/metrics/histogram_macros.h"
 #include "build/build_config.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -36,9 +36,7 @@
 
   // Don't create a long lived BatteryMonitor on windows. crbug.com/794105.
 #if !defined(OS_WIN)
-  content::ServiceManagerConnection* connection =
-      content::ServiceManagerConnection::GetForProcess();
-  connection->GetConnector()->BindInterface(
+  content::GetSystemConnector()->BindInterface(
       service_manager::ServiceFilter::ByName(device::mojom::kServiceName),
       mojo::MakeRequest(&battery_monitor_));
   QueryNextStatus();
diff --git a/chrome/browser/browser_switcher/ieem_sitelist_parser.cc b/chrome/browser/browser_switcher/ieem_sitelist_parser.cc
index 436d5597..ec95bf515b 100644
--- a/chrome/browser/browser_switcher/ieem_sitelist_parser.cc
+++ b/chrome/browser/browser_switcher/ieem_sitelist_parser.cc
@@ -6,7 +6,7 @@
 
 #include "base/bind.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/data_decoder/public/cpp/safe_xml_parser.h"
 #include "services/data_decoder/public/mojom/constants.mojom.h"
 #include "services/data_decoder/public/mojom/xml_parser.mojom.h"
@@ -163,9 +163,8 @@
 
 void ParseIeemXml(const std::string& xml,
                   base::OnceCallback<void(ParsedXml)> callback) {
-  data_decoder::ParseXml(
-      content::ServiceManagerConnection::GetForProcess()->GetConnector(), xml,
-      base::BindOnce(&RawXmlParsed, std::move(callback)));
+  data_decoder::ParseXml(content::GetSystemConnector(), xml,
+                         base::BindOnce(&RawXmlParsed, std::move(callback)));
 }
 
 }  // namespace browser_switcher
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 9675f039..828ad687 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -169,13 +169,13 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/site_instance.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/webvr_service_provider.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/main_function_params.h"
 #include "content/public/common/profiling.h"
-#include "content/public/common/service_manager_connection.h"
 #include "device/vr/buildflags/buildflags.h"
 #include "extensions/buildflags/buildflags.h"
 #include "media/base/localized_strings.h"
@@ -1558,9 +1558,7 @@
       language::GetOverrideLanguageModel() ==
           language::OverrideLanguageModel::GEO) {
     language::GeoLanguageProvider::GetInstance()->StartUp(
-        content::ServiceManagerConnection::GetForProcess()
-            ->GetConnector()
-            ->Clone(),
+        content::GetSystemConnector()->Clone(),
         browser_process_->local_state());
   }
 
diff --git a/chrome/browser/chrome_browser_main_win.cc b/chrome/browser/chrome_browser_main_win.cc
index 0a40f3a..62963a1 100644
--- a/chrome/browser/chrome_browser_main_win.cc
+++ b/chrome/browser/chrome_browser_main_win.cc
@@ -80,9 +80,9 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_process_host.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/main_function_params.h"
-#include "content/public/common/service_manager_connection.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "ui/base/cursor/cursor_loader_win.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -416,12 +416,9 @@
 #endif
 
   ModuleDatabase::GetTaskRunner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(&InitializeModuleDatabase,
-                     content::ServiceManagerConnection::GetForProcess()
-                         ->GetConnector()
-                         ->Clone(),
-                     third_party_blocking_policy_enabled));
+      FROM_HERE, base::BindOnce(&InitializeModuleDatabase,
+                                content::GetSystemConnector()->Clone(),
+                                third_party_blocking_policy_enabled));
 
   *module_watcher = ModuleWatcher::Create(base::BindRepeating(&OnModuleEvent));
 }
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 4955932..eb48506 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -5465,8 +5465,8 @@
   if (previews_triggering_logic_already_ran) {
     // Copy the server state that was used before the redirect for the initial
     // URL.
-    previews_state |= (previews_data->allowed_previews_state() &
-                       server_previews_enabled_state);
+    previews_state |=
+        (previews_data->AllowedPreviewsState() & server_previews_enabled_state);
   } else {
     if (previews_decider_impl->ShouldAllowPreviewAtNavigationStart(
             previews_data, current_navigation_url, is_reload,
@@ -5654,7 +5654,7 @@
            ? previews::PreviewsEligibilityReason::CACHE_CONTROL_NO_TRANSFORM
            : previews::PreviewsEligibilityReason::COMMITTED),
       navigation_handle->GetURL(), base::Time::Now(),
-      previews_user_data->committed_previews_type(), std::move(passed_reasons),
+      previews_user_data->CommittedPreviewsType(), std::move(passed_reasons),
       previews_user_data);
 
   return committed_state;
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 9688e570..d5ddd87 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -2527,6 +2527,7 @@
     "login/screens/network_screen_unittest.cc",
     "login/screens/recommend_apps/recommend_apps_fetcher_impl_unittest.cc",
     "login/screens/update_screen_unittest.cc",
+    "login/session/user_session_manager_test.cc",
     "login/signin_partition_manager_unittest.cc",
     "login/supervised/supervised_user_authentication_unittest.cc",
     "login/ui/login_screen_extension_ui/login_screen_extension_ui_dialog_delegate_unittest.cc",
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
index 977131e..ccbe703 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -72,10 +72,10 @@
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_source.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/tts_controller.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/common/content_switches.h"
-#include "content/public/common/service_manager_connection.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/extension.h"
@@ -323,15 +323,12 @@
                           weak_ptr_factory_.GetWeakPtr())));
 
   // Connect to ash's AccessibilityController interface.
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(ash::mojom::kServiceName, &accessibility_controller_);
+  content::GetSystemConnector()->BindInterface(ash::mojom::kServiceName,
+                                               &accessibility_controller_);
 
   // Connect to the media session service.
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(media_session::mojom::kServiceName,
-                      &audio_focus_manager_ptr_);
+  content::GetSystemConnector()->BindInterface(
+      media_session::mojom::kServiceName, &audio_focus_manager_ptr_);
 
   ash::AcceleratorController::SetVolumeAdjustmentSoundCallback(
       base::BindRepeating(&AccessibilityManager::PlayVolumeAdjustSound,
diff --git a/chrome/browser/chromeos/accessibility/accessibility_panel.cc b/chrome/browser/chromeos/accessibility/accessibility_panel.cc
index 1241c80c..10da9944 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_panel.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_panel.cc
@@ -10,8 +10,8 @@
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
 #include "chrome/browser/ui/ash/ash_util.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/service_manager_connection.h"
 #include "extensions/browser/view_type_utils.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "ui/display/display.h"
@@ -78,9 +78,8 @@
 AccessibilityPanel::GetAccessibilityController() {
   // Connect to the accessibility mojo interface in ash.
   ash::mojom::AccessibilityControllerPtr accessibility_controller;
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(ash::mojom::kServiceName, &accessibility_controller);
+  content::GetSystemConnector()->BindInterface(ash::mojom::kServiceName,
+                                               &accessibility_controller);
   return accessibility_controller;
 }
 
diff --git a/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc b/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc
index 78cc880c..255c2e0d 100644
--- a/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc
+++ b/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc
@@ -29,7 +29,7 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_service.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/test/browser_test_utils.h"
 #include "extensions/browser/extension_host.h"
 #include "extensions/browser/notification_types.h"
@@ -63,10 +63,8 @@
     ASSERT_FALSE(AccessibilityManager::Get()->IsSelectToSpeakEnabled());
 
     // Connect to the ash test interface for the StatusAreaWidget.
-    content::ServiceManagerConnection::GetForProcess()
-        ->GetConnector()
-        ->BindInterface(ash::mojom::kServiceName,
-                        &status_area_widget_test_api_);
+    content::GetSystemConnector()->BindInterface(ash::mojom::kServiceName,
+                                                 &status_area_widget_test_api_);
 
     content::WindowedNotificationObserver extension_load_waiter(
         extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD,
diff --git a/chrome/browser/chromeos/accessibility/select_to_speak_event_handler_delegate.cc b/chrome/browser/chromeos/accessibility/select_to_speak_event_handler_delegate.cc
index f6c5a52c..ee7603d 100644
--- a/chrome/browser/chromeos/accessibility/select_to_speak_event_handler_delegate.cc
+++ b/chrome/browser/chromeos/accessibility/select_to_speak_event_handler_delegate.cc
@@ -13,8 +13,8 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/service_manager_connection.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_host.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -29,9 +29,8 @@
     : binding_(this) {
   // Connect to ash's AccessibilityController interface.
   ash::mojom::AccessibilityControllerPtr accessibility_controller;
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(ash::mojom::kServiceName, &accessibility_controller);
+  content::GetSystemConnector()->BindInterface(ash::mojom::kServiceName,
+                                               &accessibility_controller);
 
   // Set this object as the SelectToSpeakEventHandlerDelegate.
   ash::mojom::SelectToSpeakEventHandlerDelegatePtr ptr;
diff --git a/chrome/browser/chromeos/accessibility/switch_access_browsertest.cc b/chrome/browser/chromeos/accessibility/switch_access_browsertest.cc
index bd4c1ce..a57f8a2 100644
--- a/chrome/browser/chromeos/accessibility/switch_access_browsertest.cc
+++ b/chrome/browser/chromeos/accessibility/switch_access_browsertest.cc
@@ -9,7 +9,7 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/interactive_test_utils.h"
 #include "chromeos/constants/chromeos_switches.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/test/browser_test_utils.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "ui/accessibility/accessibility_switches.h"
@@ -21,9 +21,8 @@
 ash::mojom::AccessibilityControllerPtr GetAccessibilityController() {
   // Connect to the accessibility mojo interface in ash.
   ash::mojom::AccessibilityControllerPtr controller;
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(ash::mojom::kServiceName, &controller);
+  content::GetSystemConnector()->BindInterface(ash::mojom::kServiceName,
+                                               &controller);
   return controller;
 }
 
diff --git a/chrome/browser/chromeos/accessibility/switch_access_event_handler_delegate.cc b/chrome/browser/chromeos/accessibility/switch_access_event_handler_delegate.cc
index 8ff054a..9052380 100644
--- a/chrome/browser/chromeos/accessibility/switch_access_event_handler_delegate.cc
+++ b/chrome/browser/chromeos/accessibility/switch_access_event_handler_delegate.cc
@@ -4,22 +4,50 @@
 
 #include "chrome/browser/chromeos/accessibility/switch_access_event_handler_delegate.h"
 
+#include <utility>
+
 #include "ash/public/interfaces/constants.mojom.h"
+#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
 #include "chrome/browser/chromeos/accessibility/event_handler_common.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/common/extensions/api/accessibility_private.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
+#include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_host.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "ui/events/event.h"
 
+namespace {
+
+std::string AccessibilityPrivateEnumForCommand(
+    ash::mojom::SwitchAccessCommand command) {
+  switch (command) {
+    case ash::mojom::SwitchAccessCommand::kSelect:
+      return extensions::api::accessibility_private::ToString(
+          extensions::api::accessibility_private::SWITCH_ACCESS_COMMAND_SELECT);
+    case ash::mojom::SwitchAccessCommand::kNext:
+      return extensions::api::accessibility_private::ToString(
+          extensions::api::accessibility_private::SWITCH_ACCESS_COMMAND_NEXT);
+    case ash::mojom::SwitchAccessCommand::kPrevious:
+      return extensions::api::accessibility_private::ToString(
+          extensions::api::accessibility_private::
+              SWITCH_ACCESS_COMMAND_PREVIOUS);
+    case ash::mojom::SwitchAccessCommand::kNone:
+      NOTREACHED();
+      return "";
+  }
+}
+
+}  // namespace
+
 SwitchAccessEventHandlerDelegate::SwitchAccessEventHandlerDelegate()
     : binding_(this) {
   // Connect to ash's AccessibilityController interface.
   ash::mojom::AccessibilityControllerPtr accessibility_controller;
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(ash::mojom::kServiceName, &accessibility_controller);
+  content::GetSystemConnector()->BindInterface(ash::mojom::kServiceName,
+                                               &accessibility_controller);
 
   // Set this object as the SwitchAccessEventHandlerDelegate.
   ash::mojom::SwitchAccessEventHandlerDelegatePtr ptr;
@@ -44,3 +72,20 @@
   const ui::KeyEvent* key_event = event->AsKeyEvent();
   chromeos::ForwardKeyToExtension(*key_event, host);
 }
+
+void SwitchAccessEventHandlerDelegate::SendSwitchAccessCommand(
+    ash::mojom::SwitchAccessCommand command) {
+  extensions::EventRouter* event_router = extensions::EventRouter::Get(
+      chromeos::AccessibilityManager::Get()->profile());
+
+  auto event_args = std::make_unique<base::ListValue>();
+  event_args->AppendString(AccessibilityPrivateEnumForCommand(command));
+
+  auto event = std::make_unique<extensions::Event>(
+      extensions::events::ACCESSIBILITY_PRIVATE_ON_SWITCH_ACCESS_COMMAND,
+      extensions::api::accessibility_private::OnSwitchAccessCommand::kEventName,
+      std::move(event_args));
+
+  event_router->DispatchEventWithLazyListener(
+      extension_misc::kSwitchAccessExtensionId, std::move(event));
+}
diff --git a/chrome/browser/chromeos/accessibility/switch_access_event_handler_delegate.h b/chrome/browser/chromeos/accessibility/switch_access_event_handler_delegate.h
index a2141ae..07af077 100644
--- a/chrome/browser/chromeos/accessibility/switch_access_event_handler_delegate.h
+++ b/chrome/browser/chromeos/accessibility/switch_access_event_handler_delegate.h
@@ -23,6 +23,8 @@
  private:
   // ash::mojom::SwitchAccessEventHandlerDelegate:
   void DispatchKeyEvent(std::unique_ptr<ui::Event> event) override;
+  void SendSwitchAccessCommand(
+      ash::mojom::SwitchAccessCommand command) override;
 
   mojo::Binding<ash::mojom::SwitchAccessEventHandlerDelegate> binding_;
 
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_data.cc b/chrome/browser/chromeos/app_mode/kiosk_app_data.cc
index db55438e..d851043 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_app_data.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_data.cc
@@ -26,7 +26,7 @@
 #include "components/prefs/scoped_user_pref_update.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/browser/image_loader.h"
 #include "extensions/browser/sandboxed_unpacker.h"
@@ -91,9 +91,7 @@
              base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) {}
 
   void Start() {
-    auto connector = content::ServiceManagerConnection::GetForProcess()
-                         ->GetConnector()
-                         ->Clone();
+    auto connector = content::GetSystemConnector()->Clone();
     task_runner_->PostTask(FROM_HERE,
                            base::BindOnce(&CrxLoader::StartInThreadPool, this,
                                           std::move(connector)));
diff --git a/chrome/browser/chromeos/app_mode/kiosk_external_update_validator.cc b/chrome/browser/chromeos/app_mode/kiosk_external_update_validator.cc
index b796291..973473c 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_external_update_validator.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_external_update_validator.cc
@@ -9,7 +9,7 @@
 #include "base/task/post_task.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/manifest_constants.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -32,9 +32,7 @@
 
 void KioskExternalUpdateValidator::Start() {
   auto unpacker = base::MakeRefCounted<extensions::SandboxedUnpacker>(
-      content::ServiceManagerConnection::GetForProcess()
-          ->GetConnector()
-          ->Clone(),
+      content::GetSystemConnector()->Clone(),
       extensions::Manifest::EXTERNAL_PREF, extensions::Extension::NO_FLAGS,
       crx_unpack_dir_, backend_task_runner_.get(), this);
   if (!backend_task_runner_->PostTask(
diff --git a/chrome/browser/chromeos/apps/apk_web_app_installer.cc b/chrome/browser/chromeos/apps/apk_web_app_installer.cc
index caf0747..3874881 100644
--- a/chrome/browser/chromeos/apps/apk_web_app_installer.cc
+++ b/chrome/browser/chromeos/apps/apk_web_app_installer.cc
@@ -16,7 +16,7 @@
 #include "chrome/browser/web_applications/components/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/data_decoder/public/cpp/decode_image.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -44,9 +44,8 @@
   // CompleteInstallation().
   auto* installer =
       new ApkWebAppInstaller(profile, std::move(callback), weak_owner);
-  installer->Start(
-      content::ServiceManagerConnection::GetForProcess()->GetConnector(),
-      std::move(web_app_info), icon_png_data);
+  installer->Start(content::GetSystemConnector(), std::move(web_app_info),
+                   icon_png_data);
 }
 
 ApkWebAppInstaller::ApkWebAppInstaller(Profile* profile,
diff --git a/chrome/browser/chromeos/arc/arc_service_launcher.cc b/chrome/browser/chromeos/arc/arc_service_launcher.cc
index f25f393..5350ac17 100644
--- a/chrome/browser/chromeos/arc/arc_service_launcher.cc
+++ b/chrome/browser/chromeos/arc/arc_service_launcher.cc
@@ -76,7 +76,7 @@
 #include "components/arc/volume_mounter/arc_volume_mounter_bridge.h"
 #include "components/arc/wake_lock/arc_wake_lock_bridge.h"
 #include "components/prefs/pref_member.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/service_manager/public/cpp/connector.h"
 
 namespace arc {
@@ -111,9 +111,8 @@
                      arc::IsArcVmEnabled() ? "1" : "0", 1));
 
   ash::mojom::CrosDisplayConfigControllerPtr cros_display_config;
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(ash::mojom::kServiceName, &cros_display_config);
+  content::GetSystemConnector()->BindInterface(ash::mojom::kServiceName,
+                                               &cros_display_config);
   default_scale_factor_retriever_.Start(std::move(cros_display_config));
 }
 
diff --git a/chrome/browser/chromeos/arc/policy/arc_policy_bridge.cc b/chrome/browser/chromeos/arc/policy/arc_policy_bridge.cc
index 3468fc7..5492b01 100644
--- a/chrome/browser/chromeos/arc/policy/arc_policy_bridge.cc
+++ b/chrome/browser/chromeos/arc/policy/arc_policy_bridge.cc
@@ -34,7 +34,7 @@
 #include "components/policy/policy_constants.h"
 #include "components/prefs/pref_service.h"
 #include "components/user_manager/user.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "crypto/sha2.h"
 #include "services/data_decoder/public/cpp/safe_json_parser.h"
 
@@ -434,8 +434,7 @@
   auto repeating_callback =
       base::AdaptCallbackForRepeating(std::move(callback));
   data_decoder::SafeJsonParser::Parse(
-      content::ServiceManagerConnection::GetForProcess()->GetConnector(),
-      request,
+      content::GetSystemConnector(), request,
       base::BindOnce(&ArcPolicyBridge::OnReportComplianceParseSuccess,
                      weak_ptr_factory_.GetWeakPtr(), repeating_callback),
       base::BindOnce(&OnReportComplianceParseFailure, repeating_callback));
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index 97b4d28a..8f384fe2 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -173,9 +173,9 @@
 #include "content/public/browser/media_capture_devices.h"
 #include "content/public/browser/network_service_instance.h"
 #include "content/public/browser/notification_service.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/main_function_params.h"
-#include "content/public/common/service_manager_connection.h"
 #include "crypto/nss_util_internal.h"
 #include "crypto/scoped_nss_types.h"
 #include "dbus/object_path.h"
@@ -625,7 +625,7 @@
   system_token_certdb_initializer_->Initialize();
 
   CrasAudioHandler::Initialize(
-      content::ServiceManagerConnection::GetForProcess()->GetConnector(),
+      content::GetSystemConnector(),
       new AudioDevicesPrefHandlerImpl(g_browser_process->local_state()));
 
   content::MediaCaptureDevices::GetInstance()->AddVideoCaptureObserver(
@@ -741,10 +741,7 @@
         new default_app_order::ExternalLoader(true /* async */));
   }
 
-  audio::SoundsManager::Create(
-      content::ServiceManagerConnection::GetForProcess()
-          ->GetConnector()
-          ->Clone());
+  audio::SoundsManager::Create(content::GetSystemConnector()->Clone());
 
   // |arc_service_launcher_| must be initialized before NoteTakingHelper.
   NoteTakingHelper::Initialize();
@@ -1043,7 +1040,7 @@
   }
 
   dark_resume_controller_ = std::make_unique<system::DarkResumeController>(
-      content::ServiceManagerConnection::GetForProcess()->GetConnector());
+      content::GetSystemConnector());
 
   ChromeBrowserMainPartsLinux::PostBrowserStart();
 }
diff --git a/chrome/browser/chromeos/drive/drive_integration_service.cc b/chrome/browser/chromeos/drive/drive_integration_service.cc
index 76d81c8..5152c62 100644
--- a/chrome/browser/chromeos/drive/drive_integration_service.cc
+++ b/chrome/browser/chromeos/drive/drive_integration_service.cc
@@ -62,7 +62,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/network_service_instance.h"
 #include "content/public/browser/notification_service.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/user_agent.h"
 #include "google_apis/drive/auth_service.h"
 #include "mojo/public/cpp/bindings/callback_helpers.h"
@@ -713,11 +713,8 @@
   }
 
   device::mojom::WakeLockProviderPtr wake_lock_provider;
-  DCHECK(content::ServiceManagerConnection::GetForProcess());
-  auto* connector =
-      content::ServiceManagerConnection::GetForProcess()->GetConnector();
-  connector->BindInterface(device::mojom::kServiceName,
-                           mojo::MakeRequest(&wake_lock_provider));
+  content::GetSystemConnector()->BindInterface(
+      device::mojom::kServiceName, mojo::MakeRequest(&wake_lock_provider));
 
   scheduler_ = std::make_unique<JobScheduler>(
       profile_->GetPrefs(), logger_.get(), drive_service_.get(),
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
index c69b3ba..5470d3ba 100644
--- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
+++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
@@ -67,7 +67,7 @@
 #include "components/arc/metrics/arc_metrics_constants.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/histogram_fetcher.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/browser/extension_function_registry.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
@@ -1320,8 +1320,7 @@
 
 AutotestPrivateSetAssistantEnabledFunction::
     AutotestPrivateSetAssistantEnabledFunction() {
-  auto* connection = content::ServiceManagerConnection::GetForProcess();
-  assistant_state_.Init(connection->GetConnector());
+  assistant_state_.Init(content::GetSystemConnector());
   assistant_state_.AddObserver(this);
 }
 
diff --git a/chrome/browser/chromeos/extensions/external_cache_impl.cc b/chrome/browser/chromeos/extensions/external_cache_impl.cc
index a383bea0..312f4167 100644
--- a/chrome/browser/chromeos/extensions/external_cache_impl.cc
+++ b/chrome/browser/chromeos/extensions/external_cache_impl.cc
@@ -24,7 +24,7 @@
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_source.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/browser/notification_types.h"
 #include "extensions/browser/updater/extension_downloader.h"
 #include "extensions/common/extension.h"
@@ -254,7 +254,7 @@
 service_manager::Connector* ExternalCacheImpl::GetConnector() {
   if (use_null_connector_)
     return nullptr;
-  return content::ServiceManagerConnection::GetForProcess()->GetConnector();
+  return content::GetSystemConnector();
 }
 
 void ExternalCacheImpl::UpdateExtensionLoader() {
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc
index f349404..643d9ee 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc
@@ -64,9 +64,9 @@
 #include "components/prefs/pref_service.h"
 #include "components/user_manager/user_manager.h"
 #include "components/zoom/page_zoom.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/page_zoom.h"
-#include "content/public/common/service_manager_connection.h"
 #include "extensions/browser/api/file_handlers/mime_util.h"
 #include "extensions/browser/app_window/app_window.h"
 #include "extensions/browser/app_window/app_window_registry.h"
@@ -341,8 +341,7 @@
        base::Bind(&FileManagerPrivateInternalZipSelectionFunction::OnZipDone,
                   this),
        src_dir, src_relative_paths, dest_file))
-      ->Start(
-          content::ServiceManagerConnection::GetForProcess()->GetConnector());
+      ->Start(content::GetSystemConnector());
   return RespondLater();
 }
 
diff --git a/chrome/browser/chromeos/hats/hats_finch_helper.cc b/chrome/browser/chromeos/hats/hats_finch_helper.cc
index cbda70b..43787d4 100644
--- a/chrome/browser/chromeos/hats/hats_finch_helper.cc
+++ b/chrome/browser/chromeos/hats/hats_finch_helper.cc
@@ -4,15 +4,13 @@
 
 #include "chrome/browser/chromeos/hats/hats_finch_helper.h"
 
+#include "base/metrics/field_trial_params.h"
 #include "base/rand_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
 #include "components/prefs/pref_service.h"
-#include "components/variations/variations_associated_data.h"
 
 namespace chromeos {
 
@@ -48,35 +46,30 @@
 HatsFinchHelper::~HatsFinchHelper() {}
 
 void HatsFinchHelper::LoadFinchParamValues() {
-  if (!base::FeatureList::IsEnabled(features::kHappinessTrackingSystem))
+  const auto& feature = features::kHappinessTrackingSystem;
+  if (!base::FeatureList::IsEnabled(feature))
     return;
 
-  std::string study_name(features::kHappinessTrackingSystem.name);
+  probability_of_pick_ = base::GetFieldTrialParamByFeatureAsDouble(
+      feature, kProbabilityParam, -1.0);
 
-  std::string value =
-      variations::GetVariationParamValue(study_name, kProbabilityParam);
-
-  if (!base::StringToDouble(value, &probability_of_pick_) ||
-      (probability_of_pick_ < 0.0 || probability_of_pick_ > 1.0)) {
+  if (probability_of_pick_ < 0.0 || probability_of_pick_ > 1.0) {
     LOG(ERROR) << "Invalid value for probability: " << probability_of_pick_;
     probability_of_pick_ = 0;
   }
 
-  value =
-      variations::GetVariationParamValue(study_name, kSurveyCycleLengthParam);
+  survey_cycle_length_ = base::GetFieldTrialParamByFeatureAsInt(
+      feature, kSurveyCycleLengthParam, 0);
 
-  if (!base::StringToInt(value, &survey_cycle_length_) ||
-      survey_cycle_length_ <= 0) {
+  if (survey_cycle_length_ <= 0) {
     LOG(ERROR) << "Invalid value for survey cycle length: "
                << survey_cycle_length_;
     survey_cycle_length_ = INT_MAX;
   }
 
-  value =
-      variations::GetVariationParamValue(study_name, kSurveyStartDateMsParam);
-  double first_survey_start_date_ms;
-  if (!base::StringToDouble(value, &first_survey_start_date_ms) ||
-      first_survey_start_date_ms < 0) {
+  double first_survey_start_date_ms = base::GetFieldTrialParamByFeatureAsDouble(
+      feature, kSurveyStartDateMsParam, -1.0);
+  if (first_survey_start_date_ms < 0) {
     LOG(ERROR) << "Invalid timestamp for survey start date: "
                << first_survey_start_date_ms;
     // Set a random date in the distant future so that the survey never starts
@@ -86,12 +79,11 @@
   first_survey_start_date_ =
       base::Time().FromJsTime(first_survey_start_date_ms);
 
-  value =
-      variations::GetVariationParamValue(study_name, kResetSurveyCycleParam);
-  reset_survey_cycle_ = base::ToLowerASCII(value) == "true";
+  reset_survey_cycle_ = base::GetFieldTrialParamByFeatureAsBool(
+      feature, kResetSurveyCycleParam, false);
 
-  value = variations::GetVariationParamValue(study_name, kResetAllParam);
-  reset_hats_ = base::ToLowerASCII(value) == "true";
+  reset_hats_ =
+      base::GetFieldTrialParamByFeatureAsBool(feature, kResetAllParam, false);
 
   // Set every property to no op values if this is a reset finch seed.
   if (reset_survey_cycle_ || reset_hats_) {
diff --git a/chrome/browser/chromeos/hats/hats_finch_helper_unittest.cc b/chrome/browser/chromeos/hats/hats_finch_helper_unittest.cc
index 26f3d38..1a45ca3 100644
--- a/chrome/browser/chromeos/hats/hats_finch_helper_unittest.cc
+++ b/chrome/browser/chromeos/hats/hats_finch_helper_unittest.cc
@@ -14,37 +14,26 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/prefs/pref_service.h"
-#include "components/variations/variations_associated_data.h"
-#include "components/variations/variations_params_manager.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chromeos {
 
-namespace {
-
-const std::string kFeatureAndTrialName(features::kHappinessTrackingSystem.name);
-
-}  // namespace
-
 class HatsFinchHelperTest : public testing::Test {
  public:
-  using ParamMap = std::map<std::string, std::string>;
-
   HatsFinchHelperTest() {}
 
-  void SetFinchSeedParams(ParamMap params) {
-    params_manager_.SetVariationParamsWithFeatureAssociations(
-        kFeatureAndTrialName /* trial name */, params,
-        std::set<std::string>{kFeatureAndTrialName} /*features to switch on */);
+  void SetFeatureParams(const base::FieldTrialParams& params) {
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        features::kHappinessTrackingSystem, params);
   }
 
-  ParamMap CreateParamMap(std::string prob,
-                          std::string cycle_length,
-                          std::string start_date,
-                          std::string reset_survey,
-                          std::string reset) {
-    ParamMap params;
+  base::FieldTrialParams CreateParamMap(std::string prob,
+                                        std::string cycle_length,
+                                        std::string start_date,
+                                        std::string reset_survey,
+                                        std::string reset) {
+    base::FieldTrialParams params;
     params[HatsFinchHelper::kProbabilityParam] = prob;
     params[HatsFinchHelper::kSurveyCycleLengthParam] = cycle_length;
     params[HatsFinchHelper::kSurveyStartDateMsParam] = start_date;
@@ -61,15 +50,15 @@
   TestingProfile profile_;
 
  private:
-  variations::testing::VariationParamsManager params_manager_;
+  base::test::ScopedFeatureList scoped_feature_list_;
 
   DISALLOW_COPY_AND_ASSIGN(HatsFinchHelperTest);
 };
 
 TEST_F(HatsFinchHelperTest, InitFinchSeed_ValidValues) {
-  ParamMap params =
+  base::FieldTrialParams params =
       CreateParamMap("1.0", "7", "1475613895337", "false", "false");
-  SetFinchSeedParams(params);
+  SetFeatureParams(params);
 
   HatsFinchHelper hats_finch_helper(&profile_);
 
@@ -82,8 +71,9 @@
 }
 
 TEST_F(HatsFinchHelperTest, InitFinchSeed_Invalidalues) {
-  ParamMap params = CreateParamMap("-0.1", "-1", "-1000", "false", "false");
-  SetFinchSeedParams(params);
+  base::FieldTrialParams params =
+      CreateParamMap("-0.1", "-1", "-1000", "false", "false");
+  SetFeatureParams(params);
 
   base::Time current_time = base::Time::Now();
   HatsFinchHelper hats_finch_helper(&profile_);
@@ -95,11 +85,12 @@
 }
 
 TEST_F(HatsFinchHelperTest, TestComputeNextDate) {
-  ParamMap params = CreateParamMap("0",
-                                   "7",  // 7 Days survey cycle length
-                                   "0", "false", "false");
+  base::FieldTrialParams params =
+      CreateParamMap("0",
+                     "7",  // 7 Days survey cycle length
+                     "0", "false", "false");
 
-  SetFinchSeedParams(params);
+  SetFeatureParams(params);
 
   base::Time current_time = base::Time::Now();
 
@@ -124,8 +115,9 @@
 }
 
 TEST_F(HatsFinchHelperTest, ResetSurveyCycle) {
-  ParamMap params = CreateParamMap("0.5", "7", "1475613895337", "TruE", "0");
-  SetFinchSeedParams(params);
+  base::FieldTrialParams params =
+      CreateParamMap("0.5", "7", "1475613895337", "true", "0");
+  SetFeatureParams(params);
 
   int64_t initial_timestamp = base::Time::Now().ToInternalValue();
   PrefService* pref_service = profile_.GetPrefs();
@@ -147,8 +139,9 @@
 }
 
 TEST_F(HatsFinchHelperTest, ResetHats) {
-  ParamMap params = CreateParamMap("0.5", "7", "1475613895337", "0", "TrUe");
-  SetFinchSeedParams(params);
+  base::FieldTrialParams params =
+      CreateParamMap("0.5", "7", "1475613895337", "0", "true");
+  SetFeatureParams(params);
 
   int64_t initial_timestamp = base::Time::Now().ToInternalValue();
   PrefService* pref_service = profile_.GetPrefs();
diff --git a/chrome/browser/chromeos/input_method/ime_service_connector.cc b/chrome/browser/chromeos/input_method/ime_service_connector.cc
index 8013d84..d155cb1 100644
--- a/chrome/browser/chromeos/input_method/ime_service_connector.cc
+++ b/chrome/browser/chromeos/input_method/ime_service_connector.cc
@@ -9,7 +9,7 @@
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "chromeos/services/ime/public/mojom/constants.mojom.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 
 namespace chromeos {
 namespace input_method {
@@ -56,8 +56,7 @@
 
 void ImeServiceConnector::SetupImeService(
     mojo::PendingReceiver<chromeos::ime::mojom::InputEngineManager> receiver) {
-  auto* connector =
-      content::ServiceManagerConnection::GetForProcess()->GetConnector();
+  auto* connector = content::GetSystemConnector();
   auto per_id_filter = service_manager::ServiceFilter::ByNameWithId(
       chromeos::ime::mojom::kServiceName, instance_id_);
 
diff --git a/chrome/browser/chromeos/kiosk_next_home/intent_config_helper.cc b/chrome/browser/chromeos/kiosk_next_home/intent_config_helper.cc
index 3121bd1..3b8b48c 100644
--- a/chrome/browser/chromeos/kiosk_next_home/intent_config_helper.cc
+++ b/chrome/browser/chromeos/kiosk_next_home/intent_config_helper.cc
@@ -14,7 +14,7 @@
 #include "base/stl_util.h"
 #include "base/task/post_task.h"
 #include "base/task/task_traits.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/data_decoder/public/cpp/safe_json_parser.h"
 #include "url/url_constants.h"
 
@@ -118,14 +118,14 @@
 }
 
 void IntentConfigHelper::ParseConfig(const std::string& json_config) {
-  auto* connection = content::ServiceManagerConnection::GetForProcess();
-  // Service manager connection may not be bound in tests.
-  if (!connection)
+  auto* connector = content::GetSystemConnector();
+  // Service manager may not be initialized in tests.
+  if (!connector)
     return;
 
   // Parse JSON in utility process via Data Decoder Service.
   data_decoder::SafeJsonParser::Parse(
-      connection->GetConnector(), json_config,
+      connector, json_config,
       base::BindOnce(&IntentConfigHelper::ParseConfigDone,
                      weak_factory_.GetWeakPtr()),
       base::BindOnce(&IntentConfigHelper::ParseConfigFailed,
diff --git a/chrome/browser/chromeos/lock_screen_apps/state_controller.cc b/chrome/browser/chromeos/lock_screen_apps/state_controller.cc
index a322bf6..d57bcba 100644
--- a/chrome/browser/chromeos/lock_screen_apps/state_controller.cc
+++ b/chrome/browser/chromeos/lock_screen_apps/state_controller.cc
@@ -31,8 +31,8 @@
 #include "components/prefs/pref_service.h"
 #include "components/session_manager/core/session_manager.h"
 #include "components/user_manager/user.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/service_manager_connection.h"
 #include "crypto/symmetric_key.h"
 #include "extensions/browser/api/lock_screen_data/lock_screen_item_storage.h"
 #include "extensions/browser/app_window/app_window.h"
@@ -136,9 +136,8 @@
   // The tray action ptr might be set previously if the client was being created
   // for testing.
   if (!tray_action_ptr_) {
-    service_manager::Connector* connector =
-        content::ServiceManagerConnection::GetForProcess()->GetConnector();
-    connector->BindInterface(ash::mojom::kServiceName, &tray_action_ptr_);
+    content::GetSystemConnector()->BindInterface(ash::mojom::kServiceName,
+                                                 &tray_action_ptr_);
   }
   ash::mojom::TrayActionClientPtr client;
   binding_.Bind(mojo::MakeRequest(&client));
diff --git a/chrome/browser/chromeos/lock_screen_apps/state_controller_unittest.cc b/chrome/browser/chromeos/lock_screen_apps/state_controller_unittest.cc
index e26a770..38aa51b 100644
--- a/chrome/browser/chromeos/lock_screen_apps/state_controller_unittest.cc
+++ b/chrome/browser/chromeos/lock_screen_apps/state_controller_unittest.cc
@@ -388,7 +388,6 @@
     SetUpStylusAvailability();
 
     session_manager_ = std::make_unique<session_manager::SessionManager>();
-    session_manager_->SessionStarted();
     session_manager_->SetSessionState(
         session_manager::SessionState::LOGIN_PRIMARY);
 
diff --git a/chrome/browser/chromeos/login/active_directory_login_browsertest.cc b/chrome/browser/chromeos/login/active_directory_login_browsertest.cc
index c5f27494..4f9d36b 100644
--- a/chrome/browser/chromeos/login/active_directory_login_browsertest.cc
+++ b/chrome/browser/chromeos/login/active_directory_login_browsertest.cc
@@ -18,8 +18,8 @@
 #include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chromeos/dbus/auth_policy/fake_auth_policy_client.h"
 #include "components/user_manager/user_names.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/network_service_util.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/test/test_utils.h"
 #include "mojo/public/cpp/bindings/sync_call_restrictions.h"
@@ -41,10 +41,8 @@
   std::string value;
   if (content::IsOutOfProcessNetworkService()) {
     network::mojom::NetworkServiceTestPtr network_service_test;
-    content::ServiceManagerConnection::GetForProcess()
-        ->GetConnector()
-        ->BindInterface(content::mojom::kNetworkServiceName,
-                        &network_service_test);
+    content::GetSystemConnector()->BindInterface(
+        content::mojom::kNetworkServiceName, &network_service_test);
     mojo::ScopedAllowSyncCallForTesting allow_sync_call;
     network_service_test->GetEnvironmentVariableValue(name, &value);
   } else {
diff --git a/chrome/browser/chromeos/login/kiosk_browsertest.cc b/chrome/browser/chromeos/login/kiosk_browsertest.cc
index dbd880ca..4028813 100644
--- a/chrome/browser/chromeos/login/kiosk_browsertest.cc
+++ b/chrome/browser/chromeos/login/kiosk_browsertest.cc
@@ -75,8 +75,8 @@
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/notification_service.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_ui.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "extensions/browser/app_window/app_window.h"
@@ -2421,10 +2421,7 @@
     }
 
     auto handler = std::make_unique<audio::AudioStreamHandler>(
-        content::ServiceManagerConnection::GetForProcess()
-            ->GetConnector()
-            ->Clone(),
-        iter->second);
+        content::GetSystemConnector()->Clone(), iter->second);
     if (!handler->IsInitialized()) {
       LOG(WARNING) << "Can't initialize AudioStreamHandler for key = " << key;
       return false;
diff --git a/chrome/browser/chromeos/login/lock/screen_locker.cc b/chrome/browser/chromeos/login/lock/screen_locker.cc
index 65807e3..902eb69 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker.cc
+++ b/chrome/browser/chromeos/login/lock/screen_locker.cc
@@ -65,10 +65,10 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_service.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/url_data_source.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
-#include "content/public/common/service_manager_connection.h"
 #include "services/audio/public/cpp/sounds/sounds_manager.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -180,9 +180,8 @@
                       bundle.GetRawDataResource(IDR_SOUND_LOCK_WAV));
   manager->Initialize(SOUND_UNLOCK,
                       bundle.GetRawDataResource(IDR_SOUND_UNLOCK_WAV));
-  service_manager::Connector* connector =
-      content::ServiceManagerConnection::GetForProcess()->GetConnector();
-  connector->BindInterface(device::mojom::kServiceName, &fp_service_);
+  content::GetSystemConnector()->BindInterface(device::mojom::kServiceName,
+                                               &fp_service_);
 
   device::mojom::FingerprintObserverPtr observer;
   fingerprint_observer_binding_.Bind(mojo::MakeRequest(&observer));
diff --git a/chrome/browser/chromeos/login/lock/screen_locker_unittest.cc b/chrome/browser/chromeos/login/lock/screen_locker_unittest.cc
index 5f25041..6752bf4 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker_unittest.cc
+++ b/chrome/browser/chromeos/login/lock/screen_locker_unittest.cc
@@ -37,7 +37,7 @@
 #include "components/account_id/account_id.h"
 #include "components/session_manager/core/session_manager.h"
 #include "components/user_manager/scoped_user_manager.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_service_manager_context.h"
 #include "device/bluetooth/dbus/bluez_dbus_manager.h"
@@ -77,10 +77,7 @@
     observer_ = std::make_unique<audio::TestObserver>((base::DoNothing()));
     audio::AudioStreamHandler::SetObserverForTesting(observer_.get());
 
-    audio::SoundsManager::Create(
-        content::ServiceManagerConnection::GetForProcess()
-            ->GetConnector()
-            ->Clone());
+    audio::SoundsManager::Create(content::GetSystemConnector()->Clone());
     input_method::InputMethodManager::Initialize(
         // Owned by InputMethodManager
         new input_method::MockInputMethodManagerImpl());
diff --git a/chrome/browser/chromeos/login/screens/hid_detection_screen.cc b/chrome/browser/chromeos/login/screens/hid_detection_screen.cc
index ac0f1fda..7beb588b 100644
--- a/chrome/browser/chromeos/login/screens/hid_detection_screen.cc
+++ b/chrome/browser/chromeos/login/screens/hid_detection_screen.cc
@@ -15,7 +15,7 @@
 #include "chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.h"
 #include "chrome/grit/generated_resources.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "services/device/public/mojom/constants.mojom.h"
@@ -485,9 +485,8 @@
 
 void HIDDetectionScreen::ConnectToInputDeviceManager() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  DCHECK(content::ServiceManagerConnection::GetForProcess());
-  service_manager::Connector* connector =
-      content::ServiceManagerConnection::GetForProcess()->GetConnector();
+  service_manager::Connector* connector = content::GetSystemConnector();
+  DCHECK(connector);
   connector->BindInterface(device::mojom::kServiceName,
                            mojo::MakeRequest(&input_device_manager_));
 }
diff --git a/chrome/browser/chromeos/login/screens/recommend_apps/recommend_apps_fetcher.cc b/chrome/browser/chromeos/login/screens/recommend_apps/recommend_apps_fetcher.cc
index c138b55..c1b90e4d 100644
--- a/chrome/browser/chromeos/login/screens/recommend_apps/recommend_apps_fetcher.cc
+++ b/chrome/browser/chromeos/login/screens/recommend_apps/recommend_apps_fetcher.cc
@@ -9,7 +9,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "content/public/browser/storage_partition.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 
 namespace chromeos {
 
@@ -28,8 +28,7 @@
   if (g_factory_callback)
     return g_factory_callback->Run(delegate);
   return std::make_unique<RecommendAppsFetcherImpl>(
-      delegate,
-      content::ServiceManagerConnection::GetForProcess()->GetConnector(),
+      delegate, content::GetSystemConnector(),
       content::BrowserContext::GetDefaultStoragePartition(
           ProfileManager::GetActiveUserProfile())
           ->GetURLLoaderFactoryForBrowserProcess()
diff --git a/chrome/browser/chromeos/login/session/chrome_session_manager.cc b/chrome/browser/chromeos/login/session/chrome_session_manager.cc
index f65dce5..5038abb 100644
--- a/chrome/browser/chromeos/login/session/chrome_session_manager.cc
+++ b/chrome/browser/chromeos/login/session/chrome_session_manager.cc
@@ -169,6 +169,8 @@
         chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
         content::NotificationService::AllSources(),
         content::Details<Profile>(user_profile));
+    session_manager::SessionManager::Get()->NotifyUserProfileLoaded(
+        ProfileHelper::Get()->GetUserByProfile(user_profile)->GetAccountId());
 
     // This call will set session state to SESSION_STATE_ACTIVE (same one).
     session_manager::SessionManager::Get()->SessionStarted();
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc
index 53115ff7..0ec141e3 100644
--- a/chrome/browser/chromeos/login/session/user_session_manager.cc
+++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -172,10 +172,6 @@
 #include "components/rlz/rlz_tracker.h"
 #endif
 
-#if BUILDFLAG(ENABLE_CROS_ASSISTANT)
-#include "chrome/browser/ui/ash/assistant/assistant_client.h"
-#endif
-
 namespace chromeos {
 
 namespace {
@@ -1114,17 +1110,33 @@
   btl->AddLoginTimeMarker("StartSession-End", false);
 }
 
-void UserSessionManager::OnUserNetworkPolicyParsed(bool send_password) {
-  if (send_password) {
-    if (user_context_.GetPasswordKey()->GetSecret().size() > 0) {
-      SessionManagerClient::Get()->SaveLoginPassword(
-          user_context_.GetPasswordKey()->GetSecret());
+void UserSessionManager::VoteForSavingLoginPassword(
+    PasswordConsumingService service,
+    bool save_password) {
+  DCHECK_LT(service, PasswordConsumingService::kCount);
+
+  // Prevent this code from being called twice from two services or else the
+  // second service would trigger the warning below (since the password has been
+  // cleared).
+  if (save_password && !password_was_saved_) {
+    password_was_saved_ = true;
+    const std::string& password = user_context_.GetPasswordKey()->GetSecret();
+    if (!password.empty()) {
+      VLOG(1) << "Saving login password for service "
+              << static_cast<size_t>(service);
+      SessionManagerClient::Get()->SaveLoginPassword(password);
     } else {
       LOG(WARNING) << "Not saving password because password is empty.";
     }
   }
 
-  user_context_.GetMutablePasswordKey()->ClearSecret();
+  // If we've already sent the password or if all services voted 'no', forget
+  // the password again, it's not needed anymore.
+  password_service_voted_.set(static_cast<size_t>(service), true);
+  if (save_password || password_service_voted_.all()) {
+    VLOG(1) << "Clearing login password";
+    user_context_.GetMutablePasswordKey()->ClearSecret();
+  }
 }
 
 void UserSessionManager::InitDemoSessionIfNeeded(base::OnceClosure callback) {
@@ -1538,9 +1550,12 @@
       content::NotificationService::AllSources(),
       content::Details<Profile>(profile));
 
-  // Initialize various services only for primary user.
   const user_manager::User* user =
       ProfileHelper::Get()->GetUserByProfile(profile);
+  session_manager::SessionManager::Get()->NotifyUserProfileLoaded(
+      user->GetAccountId());
+
+  // Initialize various services only for primary user.
   if (user_manager->GetPrimaryUser() == user) {
     InitRlz(profile);
     InitializeCerts(profile);
@@ -1696,14 +1711,6 @@
   ProfileHelper::Get()->ProfileStartup(profile);
 
   if (start_session_type_ == PRIMARY_USER_SESSION) {
-#if BUILDFLAG(ENABLE_CROS_ASSISTANT)
-    // Initialize Assistant early to be used in post login Oobe steps.
-    // Note: AssistantClient::MaybeInit is also called in
-    // SessionControllerClient::OnSessionStateChanged, which happends after the
-    // post login Oobe steps. Therefore Assistant is initialized here.
-    if (chromeos::switches::IsAssistantEnabled())
-      AssistantClient::Get()->MaybeInit(profile);
-#endif
     UserFlow* user_flow = ChromeUserManager::Get()->GetCurrentUserFlow();
     WizardController* oobe_controller = WizardController::default_controller();
     base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.h b/chrome/browser/chromeos/login/session/user_session_manager.h
index ed6318e0..f01c06c 100644
--- a/chrome/browser/chromeos/login/session/user_session_manager.h
+++ b/chrome/browser/chromeos/login/session/user_session_manager.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SESSION_USER_SESSION_MANAGER_H_
 #define CHROME_BROWSER_CHROMEOS_LOGIN_SESSION_USER_SESSION_MANAGER_H_
 
+#include <bitset>
 #include <map>
 #include <memory>
 #include <set>
@@ -141,6 +142,17 @@
     base::TimeDelta time_since_oobe_completion;
   };
 
+  // To keep track of which systems need the login password to be stored in the
+  // kernel keyring.
+  enum class PasswordConsumingService {
+    // Shill needs the login password if ${PASSWORD} is specified somewhere in
+    // the OpenNetworkConfiguration policy.
+    kNetwork = 0,
+
+    // Should be last. All enum values must be consecutive starting from 0.
+    kCount = 1,
+  };
+
   // Returns UserSessionManager instance.
   static UserSessionManager* GetInstance();
 
@@ -307,11 +319,20 @@
                           CommandLineSwitchesType switches_type,
                           const std::vector<std::string>& switches);
 
-  // Called when the user network policy has been parsed. If |send_password| is
-  // true, the user's password will be sent over dbus to the session manager to
-  // save in a keyring. Before the function exits, it will clear the user
-  // password from the UserContext regardless of the value of |send_password|.
-  void OnUserNetworkPolicyParsed(bool send_password);
+  // Notify whether |service| wants session manager to save the user's login
+  // password. If |save_password| is true, the login password is sent over D-Bus
+  // to the session manager to save in a keyring. Once this method has been
+  // called from all services defined in |PasswordConsumingService|, or if
+  // |save_password| is true, the method clears the user password from the
+  // UserContext before exiting.
+  // Should be called for each |service| in |PasswordConsumingService| as soon
+  // as the service knows whether it needs the login password. Must be called
+  // before user_context_.ClearSecrets() (see .cc), where Chrome 'forgets' the
+  // password.
+  void VoteForSavingLoginPassword(PasswordConsumingService service,
+                                  bool save_password);
+
+  UserContext* mutable_user_context_for_testing() { return &user_context_; }
 
   // Shows U2F notification if necessary.
   void MaybeShowU2FNotification();
@@ -576,10 +597,17 @@
   std::map<Profile*, std::unique_ptr<EolNotification>, ProfileCompare>
       eol_notification_handler_;
 
-  // Maps command-line switch types to the currently set command-line switches
-  // for that type. Note: This is not per Profile/AccountId, because session
-  // manager currently doesn't support setting command-line switches per
-  // AccountId.
+  // Keeps track of which password-requiring-service has already told us whether
+  // they need the login password or not.
+  std::bitset<static_cast<size_t>(PasswordConsumingService::kCount)>
+      password_service_voted_;
+  // Whether the login password was saved in the kernel keyring.
+  bool password_was_saved_ = false;
+
+  // Maps command-line switch types to the currently set command-line
+  // switches for that type. Note: This is not per Profile/AccountId,
+  // because session manager currently doesn't support setting command-line
+  // switches per AccountId.
   base::flat_map<CommandLineSwitchesType, std::vector<std::string>>
       command_line_switches_;
 
diff --git a/chrome/browser/chromeos/login/session/user_session_manager_test.cc b/chrome/browser/chromeos/login/session/user_session_manager_test.cc
new file mode 100644
index 0000000..1504e7e
--- /dev/null
+++ b/chrome/browser/chromeos/login/session/user_session_manager_test.cc
@@ -0,0 +1,85 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/session/user_session_manager.h"
+
+#include "base/macros.h"
+#include "chromeos/dbus/session_manager/fake_session_manager_client.h"
+#include "chromeos/dbus/session_manager/session_manager_client.h"
+#include "chromeos/login/auth/key.h"
+#include "chromeos/login/auth/user_context.h"
+#include "components/user_manager/fake_user_manager.h"
+#include "components/user_manager/scoped_user_manager.h"
+#include "content/public/browser/network_service_instance.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+
+namespace {
+constexpr char kFakePassword[] = "p4zzw0r(|";
+}
+
+class UserSessionManagerTest : public testing::Test {
+ public:
+  UserSessionManagerTest() {
+    SessionManagerClient::InitializeFake();
+    user_session_manager_ = UserSessionManager::GetInstance();
+  }
+
+  ~UserSessionManagerTest() override { SessionManagerClient::Shutdown(); }
+
+ protected:
+  void InitLoginPassword() {
+    user_session_manager_->mutable_user_context_for_testing()->SetPasswordKey(
+        Key(kFakePassword));
+    EXPECT_FALSE(user_session_manager_->user_context()
+                     .GetPasswordKey()
+                     ->GetSecret()
+                     .empty());
+    EXPECT_TRUE(FakeSessionManagerClient::Get()->login_password().empty());
+  }
+
+  // Convenience pointer to the singleton, not owned.
+  UserSessionManager* user_session_manager_;
+
+  // Allows UserSessionManager to request the NetworkConnectionTracker in its
+  // constructor.
+  content::TestBrowserThreadBundle thread_bundle_;
+
+  user_manager::ScopedUserManager scoped_user_manager_{
+      std::make_unique<user_manager::FakeUserManager>()};
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(UserSessionManagerTest);
+};
+
+// Calling VoteForSavingLoginPassword() with |save_password| set to false for
+// all |PasswordConsumerService|s should not send the password to SessionManager
+// and clear it from the user context.
+TEST_F(UserSessionManagerTest, PasswordConsumerService_NoSave) {
+  InitLoginPassword();
+  user_session_manager_->VoteForSavingLoginPassword(
+      UserSessionManager::PasswordConsumingService::kNetwork, false);
+  EXPECT_TRUE(FakeSessionManagerClient::Get()->login_password().empty());
+  EXPECT_TRUE(user_session_manager_->user_context()
+                  .GetPasswordKey()
+                  ->GetSecret()
+                  .empty());
+}
+
+// Calling VoteForSavingLoginPassword() with |save_password| set to true should
+// send the password to SessionManager and clear it from the user context.
+TEST_F(UserSessionManagerTest, PasswordConsumerService_Save) {
+  InitLoginPassword();
+  user_session_manager_->VoteForSavingLoginPassword(
+      UserSessionManager::PasswordConsumingService::kNetwork, true);
+  EXPECT_EQ(kFakePassword, FakeSessionManagerClient::Get()->login_password());
+  EXPECT_TRUE(user_session_manager_->user_context()
+                  .GetPasswordKey()
+                  ->GetSecret()
+                  .empty());
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc b/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
index 45dc21c..1053bf3 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
@@ -316,19 +316,8 @@
   user_context.SetIsUsingPin(authenticated_by_pin);
   user_context.SetKey(
       Key(chromeos::Key::KEY_TYPE_PASSWORD_PLAIN, "" /*salt*/, password));
-  // Save the user's plaintext password for possible authentication to a
-  // network. If the user's OpenNetworkConfiguration policy contains a
-  // ${PASSWORD} variable, then the user's password will be used to authenticate
-  // to the specified network.
-  //
-  // The user's password needs to be saved in memory until the policy can be
-  // examined. When the policy comes in, if it does not contain the ${PASSWORD}
-  // variable, the user's password will be discarded. If it contains the
-  // password, it will be sent to the session manager, which will then save it
-  // in a keyring so it can be retrieved for authenticating to the network.
-  //
-  // More details can be found in https://crbug.com/386606
   user_context.SetPasswordKey(Key(password));
+
   if (account_id.GetAccountType() == AccountType::ACTIVE_DIRECTORY) {
     if (user_context.GetUserType() !=
         user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY) {
diff --git a/chrome/browser/chromeos/night_light/night_light_client.cc b/chrome/browser/chromeos/night_light/night_light_client.cc
index 61c93a5..559dacbb 100644
--- a/chrome/browser/chromeos/night_light/night_light_client.cc
+++ b/chrome/browser/chromeos/night_light/night_light_client.cc
@@ -10,7 +10,7 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/time/clock.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/service_manager/public/cpp/connector.h"
 
@@ -50,10 +50,8 @@
   timezone_settings->AddObserver(this);
 
   if (!night_light_controller_) {
-    service_manager::Connector* connector =
-        content::ServiceManagerConnection::GetForProcess()->GetConnector();
-    connector->BindInterface(ash::mojom::kServiceName,
-                             &night_light_controller_);
+    content::GetSystemConnector()->BindInterface(ash::mojom::kServiceName,
+                                                 &night_light_controller_);
   }
   ash::mojom::NightLightClientPtr client;
   binding_.Bind(mojo::MakeRequest(&client));
diff --git a/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl.cc b/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl.cc
index 7cf8362b..1c496f0 100644
--- a/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl.cc
+++ b/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl.cc
@@ -42,6 +42,7 @@
 #include "content/public/browser/network_service_instance.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_service.h"
+#include "content/public/browser/system_connector.h"
 #include "services/data_decoder/public/cpp/safe_json_parser.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/mojom/network_context.mojom.h"
@@ -410,10 +411,8 @@
         std::make_unique<invalidation::FCMInvalidationService>(
             device_identity_provider_.get(), g_browser_process->gcm_driver(),
             device_instance_id_driver_.get(), g_browser_process->local_state(),
-            base::BindRepeating(
-                data_decoder::SafeJsonParser::Parse,
-                content::ServiceManagerConnection::GetForProcess()
-                    ->GetConnector()),
+            base::BindRepeating(data_decoder::SafeJsonParser::Parse,
+                                content::GetSystemConnector()),
             url_loader_factory.get(), policy::kPolicyFCMInvalidationSenderID);
     device_invalidation_service->Init();
     return device_invalidation_service;
diff --git a/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl_unittest.cc b/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl_unittest.cc
index 35ab0fd6..dada62f 100644
--- a/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl_unittest.cc
+++ b/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl_unittest.cc
@@ -41,7 +41,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_service.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "services/data_decoder/public/cpp/safe_json_parser.h"
 #include "services/data_decoder/public/cpp/testing_json_parser.h"
@@ -255,20 +255,18 @@
                                      is_fcm_enabled());
 
   if (is_fcm_enabled()) {
+    service_manager::mojom::ConnectorRequest conector_request;
+    content::SetSystemConnectorForTesting(
+        service_manager::Connector::Create(&conector_request));
     data_decoder::SafeJsonParser::SetFactoryForTesting(
         &CreateTestingJsonParser);
-
-    content::ServiceManagerConnection::SetForProcess(
-        content::ServiceManagerConnection::Create(
-            nullptr, base::CreateSingleThreadTaskRunnerWithTraits(
-                         {content::BrowserThread::IO})));
   }
 }
 
 AffiliatedInvalidationServiceProviderImplTest::
     ~AffiliatedInvalidationServiceProviderImplTest() {
   if (is_fcm_enabled()) {
-    content::ServiceManagerConnection::DestroyForProcess();
+    content::SetSystemConnectorForTesting(nullptr);
     data_decoder::SafeJsonParser::SetFactoryForTesting(nullptr);
   }
 }
diff --git a/chrome/browser/chromeos/policy/display_settings_handler.cc b/chrome/browser/chromeos/policy/display_settings_handler.cc
index 04ed0b4..c7398f39 100644
--- a/chrome/browser/chromeos/policy/display_settings_handler.cc
+++ b/chrome/browser/chromeos/policy/display_settings_handler.cc
@@ -15,15 +15,14 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chromeos/settings/cros_settings_names.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/service_manager/public/cpp/connector.h"
 
 namespace policy {
 
 DisplaySettingsHandler::DisplaySettingsHandler() {
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(ash::mojom::kServiceName, &cros_display_config_);
+  content::GetSystemConnector()->BindInterface(ash::mojom::kServiceName,
+                                               &cros_display_config_);
 }
 
 DisplaySettingsHandler::~DisplaySettingsHandler() = default;
diff --git a/chrome/browser/chromeos/policy/user_network_configuration_updater.cc b/chrome/browser/chromeos/policy/user_network_configuration_updater.cc
index 82bb1b4..41fff31 100644
--- a/chrome/browser/chromeos/policy/user_network_configuration_updater.cc
+++ b/chrome/browser/chromeos/policy/user_network_configuration_updater.cc
@@ -76,8 +76,7 @@
   // call, which is not safe before the profile initialization is finalized.
   // Thus, listen for PROFILE_ADDED notification, on which |cert_importer_|
   // creation should start.
-  registrar_.Add(this,
-                 chrome::NOTIFICATION_PROFILE_ADDED,
+  registrar_.Add(this, chrome::NOTIFICATION_PROFILE_ADDED,
                  content::Source<Profile>(profile));
 
   // Make sure that the |NetworkCertLoader| which makes certificates available
@@ -110,13 +109,13 @@
 
   // Call on UserSessionManager to send the user's password to session manager
   // if the password substitution variable exists in the ONC.
-  bool send_password =
+  bool save_password =
       chromeos::onc::HasUserPasswordSubsitutionVariable(network_configs_onc);
-  chromeos::UserSessionManager::GetInstance()->OnUserNetworkPolicyParsed(
-      send_password);
+  chromeos::UserSessionManager::GetInstance()->VoteForSavingLoginPassword(
+      chromeos::UserSessionManager::PasswordConsumingService::kNetwork,
+      save_password);
 
-  network_config_handler_->SetPolicy(onc_source_,
-                                     user_->username_hash(),
+  network_config_handler_->SetPolicy(onc_source_, user_->username_hash(),
                                      *network_configs_onc,
                                      *global_network_config);
 }
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc
index f0d4faec9..d13a4b0 100644
--- a/chrome/browser/chromeos/preferences.cc
+++ b/chrome/browser/chromeos/preferences.cc
@@ -56,7 +56,7 @@
 #include "components/user_manager/user.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "third_party/blink/public/platform/web_speech_synthesis_constants.h"
 #include "third_party/cros_system_api/dbus/update_engine/dbus-constants.h"
@@ -143,11 +143,8 @@
       input_method_manager_(input_method_manager),
       user_(NULL),
       user_is_primary_(false) {
-  // |manager_connection| or |connector| may be null in tests.
-  content::ServiceManagerConnection* manager_connection =
-      content::ServiceManagerConnection::GetForProcess();
-  service_manager::Connector* connector =
-      manager_connection ? manager_connection->GetConnector() : nullptr;
+  // |connector| may be null in tests.
+  service_manager::Connector* connector = content::GetSystemConnector();
   if (connector) {
     connector->BindInterface(ash::mojom::kServiceName,
                              &cros_display_config_ptr_);
diff --git a/chrome/browser/chromeos/printing/cups_proxy_service_manager.cc b/chrome/browser/chromeos/printing/cups_proxy_service_manager.cc
index 237e4164a..c2e3f9d 100644
--- a/chrome/browser/chromeos/printing/cups_proxy_service_manager.cc
+++ b/chrome/browser/chromeos/printing/cups_proxy_service_manager.cc
@@ -6,7 +6,7 @@
 
 #include "chrome/services/cups_proxy/public/mojom/constants.mojom.h"
 #include "chromeos/dbus/cups_proxy/cups_proxy_client.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/service_manager/public/cpp/connector.h"
 
 namespace chromeos {
@@ -29,7 +29,7 @@
   // Note: The service does not support BindInterface calls, so we
   // intentionally leave out a connection_error_handler, since it would
   // called immediately.
-  content::ServiceManagerConnection::GetForProcess()->GetConnector()->Connect(
+  content::GetSystemConnector()->Connect(
       printing::mojom::kCupsProxyServiceName,
       service_handle_.BindNewPipeAndPassReceiver());
 }
diff --git a/chrome/browser/chromeos/printing/usb_printer_detector.cc b/chrome/browser/chromeos/printing/usb_printer_detector.cc
index db93a4f..0e5de53 100644
--- a/chrome/browser/chromeos/printing/usb_printer_detector.cc
+++ b/chrome/browser/chromeos/printing/usb_printer_detector.cc
@@ -29,7 +29,7 @@
 #include "chromeos/printing/ppd_provider.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/device/public/mojom/usb_manager_client.mojom.h"
@@ -175,11 +175,8 @@
 std::unique_ptr<UsbPrinterDetector> UsbPrinterDetector::Create() {
   // Bind to the DeviceService for USB device manager.
   device::mojom::UsbDeviceManagerPtrInfo usb_manager_info;
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(device::mojom::kServiceName,
-                      mojo::MakeRequest(&usb_manager_info));
-
+  content::GetSystemConnector()->BindInterface(
+      device::mojom::kServiceName, mojo::MakeRequest(&usb_manager_info));
   return std::make_unique<UsbPrinterDetectorImpl>(std::move(usb_manager_info));
 }
 
diff --git a/chrome/browser/chromeos/secure_channel/secure_channel_client_provider.cc b/chrome/browser/chromeos/secure_channel/secure_channel_client_provider.cc
index 6fa979d..b19c0df 100644
--- a/chrome/browser/chromeos/secure_channel/secure_channel_client_provider.cc
+++ b/chrome/browser/chromeos/secure_channel/secure_channel_client_provider.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/chromeos/secure_channel/secure_channel_client_provider.h"
 
 #include "chromeos/services/secure_channel/public/cpp/client/secure_channel_client_impl.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 
 namespace chromeos {
 
@@ -23,14 +23,9 @@
 
 SecureChannelClient* SecureChannelClientProvider::GetClient() {
   if (!secure_channel_client_) {
-    // ServiceManagerConnection::GetForProcess() returns null in tests.
-    service_manager::Connector* connector =
-        content::ServiceManagerConnection::GetForProcess()
-            ? content::ServiceManagerConnection::GetForProcess()->GetConnector()
-            : nullptr;
-
     secure_channel_client_ =
-        SecureChannelClientImpl::Factory::Get()->BuildInstance(connector);
+        SecureChannelClientImpl::Factory::Get()->BuildInstance(
+            content::GetSystemConnector());
   }
 
   return secure_channel_client_.get();
diff --git a/chrome/browser/chromeos/usb/cros_usb_detector.cc b/chrome/browser/chromeos/usb/cros_usb_detector.cc
index 6e6d071..9bfa069 100644
--- a/chrome/browser/chromeos/usb/cros_usb_detector.cc
+++ b/chrome/browser/chromeos/usb/cros_usb_detector.cc
@@ -20,7 +20,7 @@
 #include "chromeos/constants/chromeos_features.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "components/vector_icons/vector_icons.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/device/public/cpp/usb/usb_utils.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/device/public/mojom/usb_enumeration_options.mojom.h"
@@ -256,10 +256,7 @@
 void CrosUsbDetector::ConnectToDeviceManager() {
   // Tests may set a fake manager.
   if (!device_manager_) {
-    // Request UsbDeviceManagerPtr from DeviceService.
-    auto* connection = content::ServiceManagerConnection::GetForProcess();
-    DCHECK(connection);
-    connection->GetConnector()->BindInterface(
+    content::GetSystemConnector()->BindInterface(
         device::mojom::kServiceName, mojo::MakeRequest(&device_manager_));
   }
   DCHECK(device_manager_);
diff --git a/chrome/browser/component_updater/chrome_component_updater_configurator.cc b/chrome/browser/component_updater/chrome_component_updater_configurator.cc
index eba8eb7c..ffa9b9e 100644
--- a/chrome/browser/component_updater/chrome_component_updater_configurator.cc
+++ b/chrome/browser/component_updater/chrome_component_updater_configurator.cc
@@ -35,7 +35,7 @@
 #include "components/update_client/unzipper.h"
 #include "components/update_client/update_query_params.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/service_manager/public/cpp/connector.h"
 
@@ -193,9 +193,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!unzip_factory_) {
     unzip_factory_ = base::MakeRefCounted<update_client::UnzipChromiumFactory>(
-        content::ServiceManagerConnection::GetForProcess()
-            ->GetConnector()
-            ->Clone());
+        content::GetSystemConnector()->Clone());
   }
   return unzip_factory_;
 }
@@ -205,9 +203,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!patch_factory_) {
     patch_factory_ = base::MakeRefCounted<update_client::PatchChromiumFactory>(
-        content::ServiceManagerConnection::GetForProcess()
-            ->GetConnector()
-            ->Clone());
+        content::GetSystemConnector()->Clone());
   }
   return patch_factory_;
 }
diff --git a/chrome/browser/component_updater/component_patcher_operation_browsertest.cc b/chrome/browser/component_updater/component_patcher_operation_browsertest.cc
index 30b129b..952c70d 100644
--- a/chrome/browser/component_updater/component_patcher_operation_browsertest.cc
+++ b/chrome/browser/component_updater/component_patcher_operation_browsertest.cc
@@ -21,7 +21,7 @@
 #include "components/update_client/component_patcher_operation.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "courgette/courgette.h"
 #include "courgette/third_party/bsdiff/bsdiff.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -96,9 +96,7 @@
     done_called_ = false;
 
     std::unique_ptr<service_manager::Connector> connector =
-        content::ServiceManagerConnection::GetForProcess()
-            ->GetConnector()
-            ->Clone();
+        content::GetSystemConnector()->Clone();
     base::CreateSequencedTaskRunnerWithTraits(kTaskTraits)
         ->PostTask(
             FROM_HERE,
diff --git a/chrome/browser/component_updater/supervised_user_whitelist_installer.cc b/chrome/browser/component_updater/supervised_user_whitelist_installer.cc
index a65d7c7..2c2a5a5 100644
--- a/chrome/browser/component_updater/supervised_user_whitelist_installer.cc
+++ b/chrome/browser/component_updater/supervised_user_whitelist_installer.cc
@@ -44,7 +44,7 @@
 #include "components/prefs/scoped_user_pref_update.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/data_decoder/public/cpp/json_sanitizer.h"
 
 namespace component_updater {
@@ -180,8 +180,7 @@
   }
 
   data_decoder::JsonSanitizer::Sanitize(
-      content::ServiceManagerConnection::GetForProcess()->GetConnector(),
-      unsafe_json,
+      content::GetSystemConnector(), unsafe_json,
       base::BindOnce(&OnWhitelistSanitizationResult, crx_id, task_runner,
                      callback),
       base::BindOnce(&OnWhitelistSanitizationError, whitelist_path));
diff --git a/chrome/browser/component_updater/sw_reporter_installer_win_unittest.cc b/chrome/browser/component_updater/sw_reporter_installer_win_unittest.cc
index 8ec5409..9485cbc6 100644
--- a/chrome/browser/component_updater/sw_reporter_installer_win_unittest.cc
+++ b/chrome/browser/component_updater/sw_reporter_installer_win_unittest.cc
@@ -29,7 +29,6 @@
 #include "chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.h"
 #include "components/chrome_cleaner/public/constants/constants.h"
 #include "components/component_updater/mock_component_updater_service.h"
-#include "components/variations/variations_params_manager.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -71,26 +70,19 @@
   }
 
   void CreateFeatureWithoutTag() {
-    std::map<std::string, std::string> params;
+    base::FieldTrialParams params;
     CreateFeatureWithParams(params);
   }
 
   void CreateFeatureWithTag(const std::string& tag) {
-    std::map<std::string, std::string> params{{"reporter_omaha_tag", tag}};
+    base::FieldTrialParams params{{"reporter_omaha_tag", tag}};
     CreateFeatureWithParams(params);
   }
 
-  void CreateFeatureWithParams(
-      const std::map<std::string, std::string>& params) {
-    // Assign the given variation params to the experiment group until
-    // |variations_| goes out of scope when the test exits. This will also
-    // create a FieldTrial for this group and associate the params with the
-    // feature. For the test just re-use the feature name as the trial name.
-    variations_ = std::make_unique<variations::testing::VariationParamsManager>(
-        "SwReporterInstallerTestTrialName", params,
-        /*associated_features=*/
-        std::set<std::string>{
-            safe_browsing::kChromeCleanupDistributionFeature.name});
+  void CreateFeatureWithParams(const base::FieldTrialParams& params) {
+    scoped_feature_list_.Reset();
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        safe_browsing::kChromeCleanupDistributionFeature, params);
   }
 
   void ExpectAttributesWithTag(const SwReporterInstallerPolicy& policy,
@@ -204,7 +196,6 @@
                                    SW_REPORTER_EXPERIMENT_ERROR_BAD_PARAMS, 1);
   }
 
-  std::unique_ptr<variations::testing::VariationParamsManager> variations_;
   base::test::ScopedFeatureList scoped_feature_list_;
   base::HistogramTester histograms_;
 
diff --git a/chrome/browser/content_settings/sound_content_setting_observer_unittest.cc b/chrome/browser/content_settings/sound_content_setting_observer_unittest.cc
index 3ef95ad..4673479 100644
--- a/chrome/browser/content_settings/sound_content_setting_observer_unittest.cc
+++ b/chrome/browser/content_settings/sound_content_setting_observer_unittest.cc
@@ -110,9 +110,8 @@
   HostContentSettingsMap* host_content_settings_map_;
   std::unique_ptr<ukm::TestUkmRecorder> test_ukm_recorder_;
 
-  // WebContentsImpl accesses
-  // content::ServiceManagerConnection::GetForProcess(), so
-  // we must make sure it is instantiated.
+  // WebContentsImpl accesses the system Connector, so make sure the Service
+  // Manager is initialized.
   std::unique_ptr<content::TestServiceManagerContext>
       test_service_manager_context_;
 
diff --git a/chrome/browser/data_reduction_proxy/data_reduction_proxy_browsertest.cc b/chrome/browser/data_reduction_proxy/data_reduction_proxy_browsertest.cc
index e09d3570..837d697 100644
--- a/chrome/browser/data_reduction_proxy/data_reduction_proxy_browsertest.cc
+++ b/chrome/browser/data_reduction_proxy/data_reduction_proxy_browsertest.cc
@@ -42,8 +42,8 @@
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/network_service_instance.h"
 #include "content/public/browser/storage_partition.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/network_service_util.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test.h"
@@ -117,10 +117,8 @@
 void SimulateNetworkChange(network::mojom::ConnectionType type) {
   if (!content::IsInProcessNetworkService()) {
     network::mojom::NetworkServiceTestPtr network_service_test;
-    content::ServiceManagerConnection::GetForProcess()
-        ->GetConnector()
-        ->BindInterface(content::mojom::kNetworkServiceName,
-                        &network_service_test);
+    content::GetSystemConnector()->BindInterface(
+        content::mojom::kNetworkServiceName, &network_service_test);
     base::RunLoop run_loop;
     network_service_test->SimulateNetworkChange(type, run_loop.QuitClosure());
     run_loop.Run();
diff --git a/chrome/browser/devtools/device/usb/usb_device_manager_helper.cc b/chrome/browser/devtools/device/usb/usb_device_manager_helper.cc
index 8703dbc..fd87477 100644
--- a/chrome/browser/devtools/device/usb/usb_device_manager_helper.cc
+++ b/chrome/browser/devtools/device/usb/usb_device_manager_helper.cc
@@ -13,7 +13,7 @@
 #include "base/task/post_task.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "mojo/public/cpp/bindings/callback_helpers.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/device/public/mojom/usb_enumeration_options.mojom.h"
@@ -107,9 +107,8 @@
     device::mojom::UsbDeviceManagerRequest request) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   // Bind to the DeviceService for USB device manager.
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(device::mojom::kServiceName, std::move(request));
+  content::GetSystemConnector()->BindInterface(device::mojom::kServiceName,
+                                               std::move(request));
 }
 
 }  // namespace
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc
index 90e3af6..53178fa 100644
--- a/chrome/browser/download/download_browsertest.cc
+++ b/chrome/browser/download/download_browsertest.cc
@@ -102,11 +102,11 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/resource_context.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/context_menu_params.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/download_test_observer.h"
 #include "content/public/test/slow_download_http_response.h"
@@ -1199,9 +1199,7 @@
   DownloadWakeLockTest() = default;
 
   void Initialize() {
-    auto* connection = content::ServiceManagerConnection::GetForProcess();
-    auto* connector = connection->GetConnector();
-    connector_ = connector->Clone();
+    connector_ = content::GetSystemConnector()->Clone();
     connector_->BindInterface(device::mojom::kServiceName,
                               &wake_lock_provider_);
   }
diff --git a/chrome/browser/download/download_manager_utils.cc b/chrome/browser/download/download_manager_utils.cc
index 9d1b3bf204..2378e43f 100644
--- a/chrome/browser/download/download_manager_utils.cc
+++ b/chrome/browser/download/download_manager_utils.cc
@@ -17,7 +17,7 @@
 #include "components/download/public/common/simple_download_manager_coordinator.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/download_request_utils.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 
 #if defined(OS_ANDROID)
 #include "chrome/browser/android/download/download_manager_service.h"
@@ -50,13 +50,6 @@
   DCHECK(manager);
 }
 
-service_manager::Connector* GetServiceConnector() {
-  auto* connection = content::ServiceManagerConnection::GetForProcess();
-  if (!connection)
-    return nullptr;
-  return connection->GetConnector();
-}
-
 void CreateInProgressDownloadManager(SimpleFactoryKey* key) {
   auto& map = GetInProgressManagerMap();
   auto it = map.find(key);
@@ -67,7 +60,7 @@
             nullptr, key->IsOffTheRecord() ? base::FilePath() : key->GetPath(),
             base::BindRepeating(&IgnoreOriginSecurityCheck),
             base::BindRepeating(&content::DownloadRequestUtils::IsURLSafe),
-            GetServiceConnector());
+            content::GetSystemConnector());
     download::SimpleDownloadManagerCoordinator* coordinator =
         SimpleDownloadManagerCoordinatorFactory::GetForKey(key);
     coordinator->SetSimpleDownloadManager(in_progress_manager.get(), false);
diff --git a/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc b/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc
index 90d56ba..c288b10 100644
--- a/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc
+++ b/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc
@@ -36,6 +36,7 @@
 #include "components/undo/bookmark_undo_service.h"
 #include "components/user_prefs/user_prefs.h"
 #include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
 #include "extensions/browser/extension_function_dispatcher.h"
@@ -411,12 +412,9 @@
     source = ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH;
 
   chrome::DragBookmarks(GetProfile(),
-                        {
-                            std::move(nodes), params->drag_node_index,
-                            platform_util::GetViewForWindow(
-                                web_contents->GetTopLevelNativeWindow()),
-                            source,
-                        });
+                        {std::move(nodes), params->drag_node_index,
+                         web_contents->GetContentNativeView(), source,
+                         gfx::Point(params->x, params->y)});
 
   return true;
 }
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
index 99e4494..1b3f833 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -61,9 +61,9 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/storage_partition.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/drop_data.h"
-#include "content/public/common/service_manager_connection.h"
 #include "extensions/browser/api/file_handlers/app_file_handler_util.h"
 #include "extensions/browser/app_window/app_window.h"
 #include "extensions/browser/app_window/app_window_registry.h"
@@ -1220,9 +1220,8 @@
 
   ExtensionService* service = GetExtensionService(browser_context());
   if (path.MatchesExtension(FILE_PATH_LITERAL(".zip"))) {
-    ZipFileInstaller::Create(
-        content::ServiceManagerConnection::GetForProcess()->GetConnector(),
-        MakeRegisterInExtensionServiceCallback(service))
+    ZipFileInstaller::Create(content::GetSystemConnector(),
+                             MakeRegisterInExtensionServiceCallback(service))
         ->LoadFromZipFile(path);
   } else {
     auto prompt = std::make_unique<ExtensionInstallPrompt>(web_contents);
diff --git a/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc b/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc
index 3dddc11..7447bbc 100644
--- a/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc
+++ b/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc
@@ -19,7 +19,7 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/service_manager/public/cpp/connector.h"
 
 namespace extensions {
@@ -103,9 +103,7 @@
 
  private:
   void SetUpOnMainThread() override {
-    connector_ = content::ServiceManagerConnection::GetForProcess()
-                     ->GetConnector()
-                     ->Clone();
+    connector_ = content::GetSystemConnector()->Clone();
   }
 
   void StartWriteTest() {
diff --git a/chrome/browser/extensions/api/image_writer_private/operation_manager.cc b/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
index dffe7832..82fe44e4 100644
--- a/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
+++ b/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
@@ -20,7 +20,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/storage_partition.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_host.h"
 #include "extensions/browser/extension_registry.h"
@@ -247,9 +247,7 @@
 
 std::unique_ptr<service_manager::Connector>
 OperationManager::CreateConnector() {
-  return content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->Clone();
+  return content::GetSystemConnector()->Clone();
 }
 
 void OperationManager::Observe(int type,
diff --git a/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_unittest.cc b/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_unittest.cc
index 743b339..a35e419d 100644
--- a/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_unittest.cc
+++ b/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_unittest.cc
@@ -93,7 +93,7 @@
   std::unique_ptr<base::RunLoop> run_loop_;
 };
 
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#if BUILDFLAG(USE_RENDERER_SPELLCHECKER)
 
 TEST_F(LanguageSettingsPrivateDelegateTest,
        RetryDownloadHunspellDictionaryTest) {
@@ -116,6 +116,6 @@
   EXPECT_FALSE(afterStatuses.front().download_failed);
 }
 
-#endif  // !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#endif  // BUILDFLAG(USE_RENDERER_SPELLCHECKER)
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc b/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc
index c67db6d..356b2aae 100644
--- a/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc
+++ b/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc
@@ -39,8 +39,8 @@
 #include "chrome/common/web_application_info.h"
 #include "components/favicon/core/favicon_service.h"
 #include "content/public/browser/browser_context.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/service_manager_connection.h"
 #include "extensions/browser/api/management/management_api.h"
 #include "extensions/browser/api/management/management_api_constants.h"
 #include "extensions/browser/disable_reason.h"
@@ -288,8 +288,7 @@
         extensions::ManagementGetPermissionWarningsByManifestFunction* function,
         const std::string& manifest_str) const {
   data_decoder::SafeJsonParser::Parse(
-      content::ServiceManagerConnection::GetForProcess()->GetConnector(),
-      manifest_str,
+      content::GetSystemConnector(), manifest_str,
       base::BindOnce(
           &extensions::ManagementGetPermissionWarningsByManifestFunction::
               OnParseSuccess,
diff --git a/chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.cc b/chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.cc
index 9f241e7..633d8ff 100644
--- a/chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.cc
+++ b/chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.cc
@@ -13,7 +13,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/chromeos/delegate_to_browser_gpu_service_accelerator_factory.h"
 #include "content/public/browser/render_frame_host.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/video_capture/public/mojom/constants.mojom.h"
@@ -73,11 +73,7 @@
         video_capture::mojom::DeviceFactoryProviderPtr* provider) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   // In unit test environments, there may not be any connector.
-  content::ServiceManagerConnection* connection =
-      content::ServiceManagerConnection::GetForProcess();
-  if (!connection)
-    return;
-  service_manager::Connector* connector = connection->GetConnector();
+  service_manager::Connector* connector = content::GetSystemConnector();
   if (!connector)
     return;
   connector->BindInterface(video_capture::mojom::kServiceName, provider);
diff --git a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
index f067d4c..7f27757 100644
--- a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
+++ b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
@@ -26,7 +26,7 @@
 #include "chromeos/constants/chromeos_features.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/common/api/virtual_keyboard.h"
 #include "extensions/common/api/virtual_keyboard_private.h"
@@ -172,11 +172,10 @@
 void ChromeVirtualKeyboardDelegate::GetKeyboardConfig(
     OnKeyboardSettingsCallback on_settings_callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  if (!audio_system_)
-    audio_system_ = audio::CreateAudioSystem(
-        content::ServiceManagerConnection::GetForProcess()
-            ->GetConnector()
-            ->Clone());
+  if (!audio_system_) {
+    audio_system_ =
+        audio::CreateAudioSystem(content::GetSystemConnector()->Clone());
+  }
   audio_system_->HasInputDevices(
       base::BindOnce(&ChromeVirtualKeyboardDelegate::OnHasInputDevices,
                      weak_this_, std::move(on_settings_callback)));
diff --git a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc
index 0799d4a..9d920b10 100644
--- a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc
+++ b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc
@@ -19,8 +19,8 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/media_device_id.h"
 #include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/service_manager_connection.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/error_utils.h"
@@ -135,10 +135,8 @@
 media::AudioSystem* WebrtcAudioPrivateFunction::GetAudioSystem() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (!audio_system_) {
-    audio_system_ = audio::CreateAudioSystem(
-        content::ServiceManagerConnection::GetForProcess()
-            ->GetConnector()
-            ->Clone());
+    audio_system_ =
+        audio::CreateAudioSystem(content::GetSystemConnector()->Clone());
   }
   return audio_system_.get();
 }
diff --git a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc
index 37f2157..50073312 100644
--- a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc
+++ b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc
@@ -33,8 +33,8 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/media_device_id.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/test/browser_test_utils.h"
 #include "extensions/common/permissions/permission_set.h"
 #include "extensions/common/permissions/permissions_data.h"
@@ -71,10 +71,8 @@
 void GetAudioDeviceDescriptions(bool for_input,
                                 AudioDeviceDescriptions* device_descriptions) {
   base::RunLoop run_loop;
-  std::unique_ptr<media::AudioSystem> audio_system = audio::CreateAudioSystem(
-      content::ServiceManagerConnection::GetForProcess()
-          ->GetConnector()
-          ->Clone());
+  std::unique_ptr<media::AudioSystem> audio_system =
+      audio::CreateAudioSystem(content::GetSystemConnector()->Clone());
   audio_system->GetDeviceDescriptions(
       for_input,
       base::BindOnce(
diff --git a/chrome/browser/extensions/chrome_extensions_interface_registration.cc b/chrome/browser/extensions/chrome_extensions_interface_registration.cc
index 8d6d170..be64883 100644
--- a/chrome/browser/extensions/chrome_extensions_interface_registration.cc
+++ b/chrome/browser/extensions/chrome_extensions_interface_registration.cc
@@ -28,7 +28,7 @@
 #include "chromeos/services/media_perception/public/mojom/media_perception.mojom.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/media_device_id.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/browser/api/extensions_api_client.h"
 #include "extensions/browser/api/media_perception_private/media_perception_api_delegate.h"
 #include "media/capture/video/chromeos/mojo/cros_image_capture.mojom.h"
@@ -111,10 +111,8 @@
   auto proxy_request = mojo::MakeRequest(&proxy_ptr);
 
   // Bind proxy request to video_capture service.
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(video_capture::mojom::kServiceName,
-                      std::move(proxy_request));
+  content::GetSystemConnector()->BindInterface(
+      video_capture::mojom::kServiceName, std::move(proxy_request));
 
   auto security_origin = source->GetLastCommittedOrigin();
   auto media_device_id_salt =
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc
index 3b5b4e3..6d292f4e 100644
--- a/chrome/browser/extensions/crx_installer.cc
+++ b/chrome/browser/extensions/crx_installer.cc
@@ -43,7 +43,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/resource_dispatcher_host.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/browser/extension_file_task_runner.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
@@ -1089,10 +1089,8 @@
 }
 
 service_manager::Connector* CrxInstaller::GetConnector() const {
-  return connector_for_test_
-             ? connector_for_test_
-             : content::ServiceManagerConnection::GetForProcess()
-                   ->GetConnector();
+  return connector_for_test_ ? connector_for_test_
+                             : content::GetSystemConnector();
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/startup_helper.cc b/chrome/browser/extensions/startup_helper.cc
index 1f20d9fa..fc818d3 100644
--- a/chrome/browser/extensions/startup_helper.cc
+++ b/chrome/browser/extensions/startup_helper.cc
@@ -17,7 +17,7 @@
 #include "chrome/common/initialize_extensions_client.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/browser/extension_file_task_runner.h"
 #include "extensions/browser/sandboxed_unpacker.h"
 #include "extensions/common/extension.h"
@@ -94,13 +94,10 @@
   const base::string16& error() const { return error_; }
 
   void Start() {
-    std::unique_ptr<::service_manager::Connector> connector =
-        content::ServiceManagerConnection::GetForProcess()
-            ->GetConnector()
-            ->Clone();
     GetExtensionFileTaskRunner()->PostTask(
-        FROM_HERE, base::BindOnce(&ValidateCrxHelper::StartOnBlockingThread,
-                                  this, std::move(connector)));
+        FROM_HERE,
+        base::BindOnce(&ValidateCrxHelper::StartOnBlockingThread, this,
+                       content::GetSystemConnector()->Clone()));
   }
 
  protected:
diff --git a/chrome/browser/extensions/system_display/display_info_provider_chromeos.cc b/chrome/browser/extensions/system_display/display_info_provider_chromeos.cc
index 0487f96..a14bfc5 100644
--- a/chrome/browser/extensions/system_display/display_info_provider_chromeos.cc
+++ b/chrome/browser/extensions/system_display/display_info_provider_chromeos.cc
@@ -14,7 +14,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/ui/ash/tablet_mode_client.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/common/api/system_display.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "ui/display/display.h"
@@ -623,11 +623,7 @@
 
 // static
 DisplayInfoProvider* DisplayInfoProvider::Create() {
-  std::unique_ptr<service_manager::Connector> connector =
-      content::ServiceManagerConnection::GetForProcess()
-          ->GetConnector()
-          ->Clone();
-  return new DisplayInfoProviderChromeOS(connector.get());
+  return new DisplayInfoProviderChromeOS(content::GetSystemConnector());
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/updater/chrome_extension_downloader_factory.cc b/chrome/browser/extensions/updater/chrome_extension_downloader_factory.cc
index 29e2916..35a7e666 100644
--- a/chrome/browser/extensions/updater/chrome_extension_downloader_factory.cc
+++ b/chrome/browser/extensions/updater/chrome_extension_downloader_factory.cc
@@ -15,7 +15,7 @@
 #include "components/crx_file/crx_verifier.h"
 #include "components/update_client/update_query_params.h"
 #include "content/public/browser/storage_partition.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/updater/extension_downloader.h"
 #include "extensions/common/verifier_formats.h"
@@ -58,12 +58,10 @@
 ChromeExtensionDownloaderFactory::CreateForProfile(
     Profile* profile,
     ExtensionDownloaderDelegate* delegate) {
-  service_manager::Connector* connector =
-      content::ServiceManagerConnection::GetForProcess()->GetConnector();
   std::unique_ptr<ExtensionDownloader> downloader = CreateForURLLoaderFactory(
       content::BrowserContext::GetDefaultStoragePartition(profile)
           ->GetURLLoaderFactoryForBrowserProcess(),
-      delegate, connector,
+      delegate, content::GetSystemConnector(),
       extensions::GetPolicyVerifierFormat(
           extensions::ExtensionPrefs::Get(profile)
               ->InsecureExtensionUpdatesEnabled()),
diff --git a/chrome/browser/extensions/updater/chrome_update_client_config.cc b/chrome/browser/extensions/updater/chrome_update_client_config.cc
index a29c4b6..9c24598 100644
--- a/chrome/browser/extensions/updater/chrome_update_client_config.cc
+++ b/chrome/browser/extensions/updater/chrome_update_client_config.cc
@@ -27,7 +27,7 @@
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/storage_partition.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/browser/extension_prefs.h"
 #include "services/service_manager/public/cpp/connector.h"
 
@@ -186,9 +186,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!unzip_factory_) {
     unzip_factory_ = base::MakeRefCounted<update_client::UnzipChromiumFactory>(
-        content::ServiceManagerConnection::GetForProcess()
-            ->GetConnector()
-            ->Clone());
+        content::GetSystemConnector()->Clone());
   }
   return unzip_factory_;
 }
@@ -198,9 +196,7 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!patch_factory_) {
     patch_factory_ = base::MakeRefCounted<update_client::PatchChromiumFactory>(
-        content::ServiceManagerConnection::GetForProcess()
-            ->GetConnector()
-            ->Clone());
+        content::GetSystemConnector()->Clone());
   }
   return patch_factory_;
 }
diff --git a/chrome/browser/extensions/webstore_data_fetcher.cc b/chrome/browser/extensions/webstore_data_fetcher.cc
index 7a46a2a4..c52ed25 100644
--- a/chrome/browser/extensions/webstore_data_fetcher.cc
+++ b/chrome/browser/extensions/webstore_data_fetcher.cc
@@ -14,7 +14,7 @@
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/storage_partition.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/common/extension_urls.h"
 #include "net/base/load_flags.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
@@ -122,8 +122,7 @@
 
   // The parser will call us back via one of the callbacks.
   data_decoder::SafeJsonParser::Parse(
-      content::ServiceManagerConnection::GetForProcess()->GetConnector(),
-      *response_body,
+      content::GetSystemConnector(), *response_body,
       base::BindOnce(&WebstoreDataFetcher::OnJsonParseSuccess, AsWeakPtr()),
       base::BindOnce(&WebstoreDataFetcher::OnJsonParseFailure, AsWeakPtr()));
 }
diff --git a/chrome/browser/extensions/webstore_install_helper.cc b/chrome/browser/extensions/webstore_install_helper.cc
index d12a3b1..ab583085 100644
--- a/chrome/browser/extensions/webstore_install_helper.cc
+++ b/chrome/browser/extensions/webstore_install_helper.cc
@@ -8,7 +8,7 @@
 #include "base/values.h"
 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "net/base/load_flags.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "net/url_request/url_request.h"
@@ -43,8 +43,7 @@
   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   data_decoder::SafeJsonParser::Parse(
-      content::ServiceManagerConnection::GetForProcess()->GetConnector(),
-      manifest_,
+      content::GetSystemConnector(), manifest_,
       base::BindOnce(&WebstoreInstallHelper::OnJSONParseSucceeded, this),
       base::BindOnce(&WebstoreInstallHelper::OnJSONParseFailed, this));
 
diff --git a/chrome/browser/feature_engagement/bookmark/bookmark_tracker_unittest.cc b/chrome/browser/feature_engagement/bookmark/bookmark_tracker_unittest.cc
index d734353..c8e3c1b 100644
--- a/chrome/browser/feature_engagement/bookmark/bookmark_tracker_unittest.cc
+++ b/chrome/browser/feature_engagement/bookmark/bookmark_tracker_unittest.cc
@@ -6,10 +6,6 @@
 
 #include <memory>
 
-#include "base/feature_list.h"
-#include "base/metrics/field_trial.h"
-#include "base/metrics/field_trial_param_associator.h"
-#include "base/metrics/field_trial_params.h"
 #include "base/run_loop.h"
 #include "base/sequenced_task_runner.h"
 #include "base/strings/string_number_conversions.h"
@@ -28,7 +24,6 @@
 #include "components/feature_engagement/test/mock_tracker.h"
 #include "components/feature_engagement/test/test_tracker.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
-#include "components/variations/variations_params_manager.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -37,8 +32,6 @@
 
 namespace {
 
-constexpr char kBookmarkTrialName[] = "BookmarkTrial";
-constexpr char kGroupName[] = "Enabled";
 constexpr char kTestProfileName[] = "test-profile";
 
 class FakeBookmarkTracker : public BookmarkTracker {
@@ -118,26 +111,8 @@
 
 class BookmarkTrackerTest : public testing::Test {
  public:
-  BookmarkTrackerTest() = default;
-  ~BookmarkTrackerTest() override = default;
-
-  void SetUp() override {
-    // Set up the kBookmarkTrialName field trial.
-    base::FieldTrial* bookmark_trial =
-        base::FieldTrialList::CreateFieldTrial(kBookmarkTrialName, kGroupName);
-    trials_[kIPHBookmarkFeature.name] = bookmark_trial;
-
-    std::unique_ptr<base::FeatureList> feature_list =
-        std::make_unique<base::FeatureList>();
-    feature_list->RegisterFieldTrialOverride(
-        kIPHBookmarkFeature.name, base::FeatureList::OVERRIDE_ENABLE_FEATURE,
-        bookmark_trial);
-
-    scoped_feature_list_.InitWithFeatureList(std::move(feature_list));
-    ASSERT_EQ(bookmark_trial,
-              base::FeatureList::GetFieldTrial(kIPHBookmarkFeature));
-
-    std::map<std::string, std::string> bookmark_params;
+  BookmarkTrackerTest() {
+    base::FieldTrialParams bookmark_params;
     bookmark_params["event_bookmark_added"] =
         "name:bookmark_added;comparator:==0;window:3650;storage:3650";
     bookmark_params["event_bookmark_session_time_met"] =
@@ -153,8 +128,12 @@
         base::NumberToString(static_cast<int64_t>(
             first_run::GetFirstRunSentinelCreationTime().ToDoubleT()));
 
-    SetFeatureParams(kIPHBookmarkFeature, bookmark_params);
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(kIPHBookmarkFeature,
+                                                            bookmark_params);
+  }
+  ~BookmarkTrackerTest() override = default;
 
+  void SetUp() override {
     // Start the DesktopSessionDurationTracker to track active session time.
     metrics::DesktopSessionDurationTracker::Initialize();
 
@@ -183,28 +162,14 @@
     base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
   }
 
-  void SetFeatureParams(const base::Feature& feature,
-                        std::map<std::string, std::string> params) {
-    ASSERT_TRUE(
-        base::FieldTrialParamAssociator::GetInstance()
-            ->AssociateFieldTrialParams(trials_[feature.name]->trial_name(),
-                                        kGroupName, params));
-
-    std::map<std::string, std::string> actualParams;
-    EXPECT_TRUE(base::GetFieldTrialParamsByFeature(feature, &actualParams));
-    EXPECT_EQ(params, actualParams);
-  }
-
  protected:
   std::unique_ptr<FakeBookmarkTracker> bookmark_tracker_;
   std::unique_ptr<Tracker> feature_engagement_tracker_;
-  variations::testing::VariationParamsManager params_manager_;
 
  private:
   std::unique_ptr<TestingProfileManager> testing_profile_manager_;
   base::test::ScopedFeatureList scoped_feature_list_;
   content::TestBrowserThreadBundle thread_bundle_;
-  std::map<std::string, base::FieldTrial*> trials_;
 
   DISALLOW_COPY_AND_ASSIGN(BookmarkTrackerTest);
 };
diff --git a/chrome/browser/feature_engagement/feature_tracker_unittest.cc b/chrome/browser/feature_engagement/feature_tracker_unittest.cc
index 2132fef..82a0bfd 100644
--- a/chrome/browser/feature_engagement/feature_tracker_unittest.cc
+++ b/chrome/browser/feature_engagement/feature_tracker_unittest.cc
@@ -6,11 +6,7 @@
 
 #include <memory>
 
-#include "base/feature_list.h"
 #include "base/files/file_util.h"
-#include "base/metrics/field_trial.h"
-#include "base/metrics/field_trial_param_associator.h"
-#include "base/metrics/field_trial_params.h"
 #include "base/run_loop.h"
 #include "base/sequenced_task_runner.h"
 #include "base/strings/string_number_conversions.h"
@@ -26,7 +22,6 @@
 #include "components/feature_engagement/public/event_constants.h"
 #include "components/feature_engagement/public/feature_constants.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
-#include "components/variations/variations_params_manager.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -38,8 +33,6 @@
 constexpr int kTestTimeDeltaInMinutes = 100;
 constexpr int kTestTimeSufficentInMinutes = 110;
 constexpr int kTestTimeInsufficientInMinutes = 90;
-constexpr char kGroupName[] = "Enabled";
-constexpr char kNewTabFieldTrialName[] = "NewTabFieldTrial";
 constexpr char kTestProfileName[] = "test-profile";
 constexpr char kTestObservedSessionTimeKey[] = "test_observed_session_time_key";
 
@@ -150,21 +143,6 @@
     testing_profile_manager_ = std::make_unique<TestingProfileManager>(
         TestingBrowserProcess::GetGlobal());
     ASSERT_TRUE(testing_profile_manager_->SetUp());
-
-    // Set up the NewTabInProductHelp field trial.
-    base::FieldTrial* new_tab_trial = base::FieldTrialList::CreateFieldTrial(
-        kNewTabFieldTrialName, kGroupName);
-    trials_[kIPHNewTabFeature.name] = new_tab_trial;
-
-    std::unique_ptr<base::FeatureList> feature_list =
-        std::make_unique<base::FeatureList>();
-    feature_list->RegisterFieldTrialOverride(
-        kIPHNewTabFeature.name, base::FeatureList::OVERRIDE_ENABLE_FEATURE,
-        new_tab_trial);
-
-    scoped_feature_list_.InitWithFeatureList(std::move(feature_list));
-    ASSERT_EQ(new_tab_trial,
-              base::FeatureList::GetFieldTrial(kIPHNewTabFeature));
   }
 
   void TearDown() override {
@@ -174,22 +152,14 @@
   }
 
   void SetFeatureParams(const base::Feature& feature,
-                        std::map<std::string, std::string> params) {
-    ASSERT_TRUE(
-        base::FieldTrialParamAssociator::GetInstance()
-            ->AssociateFieldTrialParams(trials_[feature.name]->trial_name(),
-                                        kGroupName, params));
-    std::map<std::string, std::string> actualParams;
-    EXPECT_TRUE(
-        base::GetFieldTrialParamsByFeature(kIPHNewTabFeature, &actualParams));
-    EXPECT_EQ(params, actualParams);
+                        const FieldTrialParams& params) {
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(kIPHNewTabFeature,
+                                                            params);
   }
 
  protected:
   std::unique_ptr<TestingProfileManager> testing_profile_manager_;
   base::test::ScopedFeatureList scoped_feature_list_;
-  std::map<std::string, base::FieldTrial*> trials_;
-  variations::testing::VariationParamsManager params_manager_;
 
  private:
   content::TestBrowserThreadBundle thread_bundle_;
diff --git a/chrome/browser/feature_engagement/incognito_window/incognito_window_tracker_unittest.cc b/chrome/browser/feature_engagement/incognito_window/incognito_window_tracker_unittest.cc
index 120b50c0..63c27d0 100644
--- a/chrome/browser/feature_engagement/incognito_window/incognito_window_tracker_unittest.cc
+++ b/chrome/browser/feature_engagement/incognito_window/incognito_window_tracker_unittest.cc
@@ -6,10 +6,6 @@
 
 #include <memory>
 
-#include "base/feature_list.h"
-#include "base/metrics/field_trial.h"
-#include "base/metrics/field_trial_param_associator.h"
-#include "base/metrics/field_trial_params.h"
 #include "base/run_loop.h"
 #include "base/sequenced_task_runner.h"
 #include "base/strings/string_number_conversions.h"
@@ -28,7 +24,6 @@
 #include "components/feature_engagement/test/mock_tracker.h"
 #include "components/feature_engagement/test/test_tracker.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
-#include "components/variations/variations_params_manager.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -37,8 +32,6 @@
 
 namespace {
 
-constexpr char kIncognitoWindowTrialName[] = "IncognitoWindowTrial";
-constexpr char kGroupName[] = "Enabled";
 constexpr char kTestProfileName[] = "test-profile";
 
 class FakeIncognitoWindowTracker : public IncognitoWindowTracker {
@@ -120,27 +113,8 @@
 
 class IncognitoWindowTrackerTest : public testing::Test {
  public:
-  IncognitoWindowTrackerTest() = default;
-  ~IncognitoWindowTrackerTest() override = default;
-
-  void SetUp() override {
-    // Set up the kIncognitoWindowTrialName field trial.
-    base::FieldTrial* incognito_window_trial =
-        base::FieldTrialList::CreateFieldTrial(kIncognitoWindowTrialName,
-                                               kGroupName);
-    trials_[kIPHIncognitoWindowFeature.name] = incognito_window_trial;
-
-    std::unique_ptr<base::FeatureList> feature_list =
-        std::make_unique<base::FeatureList>();
-    feature_list->RegisterFieldTrialOverride(
-        kIPHIncognitoWindowFeature.name,
-        base::FeatureList::OVERRIDE_ENABLE_FEATURE, incognito_window_trial);
-
-    scoped_feature_list_.InitWithFeatureList(std::move(feature_list));
-    ASSERT_EQ(incognito_window_trial,
-              base::FeatureList::GetFieldTrial(kIPHIncognitoWindowFeature));
-
-    std::map<std::string, std::string> incognito_window_params;
+  IncognitoWindowTrackerTest() {
+    base::FieldTrialParams incognito_window_params;
     incognito_window_params["event_incognito_window_opened"] =
         "name:incognito_window_opened;comparator:==0;window:3650;storage:3650";
     incognito_window_params["event_incognito_window_session_time_met"] =
@@ -155,8 +129,13 @@
     incognito_window_params["x_date_released_in_seconds"] =
         base::NumberToString(static_cast<int64_t>(
             first_run::GetFirstRunSentinelCreationTime().ToDoubleT()));
-    SetFeatureParams(kIPHIncognitoWindowFeature, incognito_window_params);
 
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        kIPHIncognitoWindowFeature, incognito_window_params);
+  }
+  ~IncognitoWindowTrackerTest() override = default;
+
+  void SetUp() override {
     // Start the DesktopSessionDurationTracker to track active session time.
     metrics::DesktopSessionDurationTracker::Initialize();
 
@@ -181,33 +160,16 @@
     // Need to invoke the reset method as TearDown is on the UI thread.
     testing_profile_manager_.reset();
     metrics::DesktopSessionDurationTracker::CleanupForTesting();
-
-    // This is required to ensure each test can define its own params.
-    base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
-  }
-
-  void SetFeatureParams(const base::Feature& feature,
-                        std::map<std::string, std::string> params) {
-    ASSERT_TRUE(
-        base::FieldTrialParamAssociator::GetInstance()
-            ->AssociateFieldTrialParams(trials_[feature.name]->trial_name(),
-                                        kGroupName, params));
-
-    std::map<std::string, std::string> actualParams;
-    EXPECT_TRUE(base::GetFieldTrialParamsByFeature(feature, &actualParams));
-    EXPECT_EQ(params, actualParams);
   }
 
  protected:
   std::unique_ptr<FakeIncognitoWindowTracker> incognito_window_tracker_;
   std::unique_ptr<Tracker> feature_engagement_tracker_;
-  variations::testing::VariationParamsManager params_manager_;
 
  private:
   std::unique_ptr<TestingProfileManager> testing_profile_manager_;
   base::test::ScopedFeatureList scoped_feature_list_;
   content::TestBrowserThreadBundle thread_bundle_;
-  std::map<std::string, base::FieldTrial*> trials_;
 
   DISALLOW_COPY_AND_ASSIGN(IncognitoWindowTrackerTest);
 };
diff --git a/chrome/browser/feature_engagement/new_tab/new_tab_tracker_unittest.cc b/chrome/browser/feature_engagement/new_tab/new_tab_tracker_unittest.cc
index c6829da..b42f773 100644
--- a/chrome/browser/feature_engagement/new_tab/new_tab_tracker_unittest.cc
+++ b/chrome/browser/feature_engagement/new_tab/new_tab_tracker_unittest.cc
@@ -6,10 +6,6 @@
 
 #include <memory>
 
-#include "base/feature_list.h"
-#include "base/metrics/field_trial.h"
-#include "base/metrics/field_trial_param_associator.h"
-#include "base/metrics/field_trial_params.h"
 #include "base/run_loop.h"
 #include "base/sequenced_task_runner.h"
 #include "base/strings/string_number_conversions.h"
@@ -28,7 +24,6 @@
 #include "components/feature_engagement/test/mock_tracker.h"
 #include "components/feature_engagement/test/test_tracker.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
-#include "components/variations/variations_params_manager.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -126,27 +121,8 @@
 
 class NewTabTrackerTest : public testing::Test {
  public:
-  NewTabTrackerTest() = default;
-  ~NewTabTrackerTest() override = default;
-
-  // testing::Test:
-  void SetUp() override {
-    // Set up the NewTabInProductHelp field trial.
-    base::FieldTrial* new_tab_trial =
-        base::FieldTrialList::CreateFieldTrial(kNewTabTrialName, kGroupName);
-    trials_[kIPHNewTabFeature.name] = new_tab_trial;
-
-    std::unique_ptr<base::FeatureList> feature_list =
-        std::make_unique<base::FeatureList>();
-    feature_list->RegisterFieldTrialOverride(
-        kIPHNewTabFeature.name, base::FeatureList::OVERRIDE_ENABLE_FEATURE,
-        new_tab_trial);
-
-    scoped_feature_list_.InitWithFeatureList(std::move(feature_list));
-    ASSERT_EQ(new_tab_trial,
-              base::FeatureList::GetFieldTrial(kIPHNewTabFeature));
-
-    std::map<std::string, std::string> new_tab_params;
+  NewTabTrackerTest() {
+    base::FieldTrialParams new_tab_params;
     new_tab_params["event_new_tab_opened"] =
         "name:new_tab_opened;comparator:==0;window:3650;storage:3650";
     new_tab_params["event_omnibox_used"] =
@@ -163,8 +139,13 @@
         base::NumberToString(static_cast<int64_t>(
             first_run::GetFirstRunSentinelCreationTime().ToDoubleT()));
 
-    SetFeatureParams(kIPHNewTabFeature, new_tab_params);
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(kIPHNewTabFeature,
+                                                            new_tab_params);
+  }
+  ~NewTabTrackerTest() override = default;
 
+  // testing::Test:
+  void SetUp() override {
     // Start the DesktopSessionDurationTracker to track active session time.
     metrics::DesktopSessionDurationTracker::Initialize();
 
@@ -187,33 +168,16 @@
     new_tab_tracker_->RemoveSessionDurationObserver();
     testing_profile_manager_->DeleteTestingProfile(kTestProfileName);
     metrics::DesktopSessionDurationTracker::CleanupForTesting();
-
-    // This is required to ensure each test can define its own params.
-    base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
-  }
-
-  void SetFeatureParams(const base::Feature& feature,
-                        std::map<std::string, std::string> params) {
-    ASSERT_TRUE(
-        base::FieldTrialParamAssociator::GetInstance()
-            ->AssociateFieldTrialParams(trials_[feature.name]->trial_name(),
-                                        kGroupName, params));
-
-    std::map<std::string, std::string> actualParams;
-    EXPECT_TRUE(base::GetFieldTrialParamsByFeature(feature, &actualParams));
-    EXPECT_EQ(params, actualParams);
   }
 
  protected:
   std::unique_ptr<FakeNewTabTracker> new_tab_tracker_;
   std::unique_ptr<Tracker> feature_engagement_tracker_;
-  variations::testing::VariationParamsManager params_manager_;
 
  private:
   std::unique_ptr<TestingProfileManager> testing_profile_manager_;
   base::test::ScopedFeatureList scoped_feature_list_;
   content::TestBrowserThreadBundle thread_bundle_;
-  std::map<std::string, base::FieldTrial*> trials_;
 
   DISALLOW_COPY_AND_ASSIGN(NewTabTrackerTest);
 };
diff --git a/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc b/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc
index 00fb583b..3bd2516 100644
--- a/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc
+++ b/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc
@@ -40,7 +40,7 @@
 #include "chromeos/dbus/util/version_loader.h"
 #include "chromeos/system/statistics_provider.h"
 #include "components/user_manager/user_manager.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/service_manager/public/cpp/connector.h"
 #endif
 
@@ -199,9 +199,8 @@
 ChromeInternalLogSource::ChromeInternalLogSource()
     : SystemLogsSource("ChromeInternal") {
 #if defined(OS_CHROMEOS)
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(ash::mojom::kServiceName, &cros_display_config_ptr_);
+  content::GetSystemConnector()->BindInterface(ash::mojom::kServiceName,
+                                               &cros_display_config_ptr_);
 #endif
 }
 
diff --git a/chrome/browser/geolocation/geolocation_permission_context.cc b/chrome/browser/geolocation/geolocation_permission_context.cc
index d3538bcc..aebeecbb 100644
--- a/chrome/browser/geolocation/geolocation_permission_context.cc
+++ b/chrome/browser/geolocation/geolocation_permission_context.cc
@@ -10,8 +10,8 @@
 #include "chrome/browser/profiles/profile.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/service_manager_connection.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "url/origin.h"
@@ -87,11 +87,8 @@
     return geolocation_control_.get();
 
   auto request = mojo::MakeRequest(&geolocation_control_);
-  if (!content::ServiceManagerConnection::GetForProcess())
-    return geolocation_control_.get();
-
-  service_manager::Connector* connector =
-      content::ServiceManagerConnection::GetForProcess()->GetConnector();
-  connector->BindInterface(device::mojom::kServiceName, std::move(request));
+  service_manager::Connector* connector = content::GetSystemConnector();
+  if (connector)
+    connector->BindInterface(device::mojom::kServiceName, std::move(request));
   return geolocation_control_.get();
 }
diff --git a/chrome/browser/hid/hid_chooser_context.cc b/chrome/browser/hid/hid_chooser_context.cc
index ed93ce5de..d56893b 100644
--- a/chrome/browser/hid/hid_chooser_context.cc
+++ b/chrome/browser/hid/hid_chooser_context.cc
@@ -9,7 +9,7 @@
 #include "base/values.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/content_settings/core/common/content_settings_types.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 
@@ -181,9 +181,8 @@
     return;
 
   device::mojom::HidManagerPtr manager;
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(device::mojom::kServiceName, mojo::MakeRequest(&manager));
+  content::GetSystemConnector()->BindInterface(device::mojom::kServiceName,
+                                               mojo::MakeRequest(&manager));
   SetUpHidManagerConnection(std::move(manager));
 }
 
diff --git a/chrome/browser/image_decoder.cc b/chrome/browser/image_decoder.cc
index 96cb124..5842bbc2 100644
--- a/chrome/browser/image_decoder.cc
+++ b/chrome/browser/image_decoder.cc
@@ -13,7 +13,7 @@
 #include "build/build_config.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "ipc/ipc_channel.h"
 #include "services/data_decoder/public/cpp/decode_image.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -40,9 +40,7 @@
 
 void BindToBrowserConnector(service_manager::mojom::ConnectorRequest request) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  content::ServiceManagerConnection::GetForProcess()->GetConnector()
-      ->BindConnectorRequest(std::move(request));
+  content::GetSystemConnector()->BindConnectorRequest(std::move(request));
 }
 
 void RunDecodeCallbackOnTaskRunner(
diff --git a/chrome/browser/importer/external_process_importer_client.cc b/chrome/browser/importer/external_process_importer_client.cc
index 7320911..d6f6de3 100644
--- a/chrome/browser/importer/external_process_importer_client.cc
+++ b/chrome/browser/importer/external_process_importer_client.cc
@@ -15,7 +15,7 @@
 #include "chrome/common/importer/imported_bookmark_entry.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/strings/grit/components_strings.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -39,10 +39,8 @@
 void ExternalProcessImporterClient::Start() {
   AddRef();  // balanced in Cleanup.
 
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(chrome::mojom::kProfileImportServiceName,
-                      &profile_import_);
+  content::GetSystemConnector()->BindInterface(
+      chrome::mojom::kProfileImportServiceName, &profile_import_);
 
   profile_import_.set_connection_error_handler(
       base::BindOnce(&ExternalProcessImporterClient::OnProcessCrashed, this));
diff --git a/chrome/browser/invalidation/profile_invalidation_provider_factory.cc b/chrome/browser/invalidation/profile_invalidation_provider_factory.cc
index 1417d6a..f7e3586 100644
--- a/chrome/browser/invalidation/profile_invalidation_provider_factory.cc
+++ b/chrome/browser/invalidation/profile_invalidation_provider_factory.cc
@@ -28,7 +28,7 @@
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_registry.h"
 #include "content/public/browser/storage_partition.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "services/data_decoder/public/cpp/safe_json_parser.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -55,9 +55,8 @@
       instance_id::InstanceIDProfileServiceFactory::GetForProfile(profile)
           ->driver(),
       profile->GetPrefs(),
-      base::BindRepeating(
-          &data_decoder::SafeJsonParser::Parse,
-          content::ServiceManagerConnection::GetForProcess()->GetConnector()),
+      base::BindRepeating(&data_decoder::SafeJsonParser::Parse,
+                          content::GetSystemConnector()),
       content::BrowserContext::GetDefaultStoragePartition(profile)
           ->GetURLLoaderFactoryForBrowserProcess()
           .get(),
diff --git a/chrome/browser/media/cast_mirroring_service_host.cc b/chrome/browser/media/cast_mirroring_service_host.cc
index f587d9f..d3033e7 100644
--- a/chrome/browser/media/cast_mirroring_service_host.cc
+++ b/chrome/browser/media/cast_mirroring_service_host.cc
@@ -30,9 +30,9 @@
 #include "content/public/browser/network_service_instance.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/video_capture_device_launcher.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/service_manager_connection.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/network/public/mojom/network_service.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -187,9 +187,8 @@
   }
 
   // Connect to the Mirroring Service.
-  service_manager::Connector* connector =
-      content::ServiceManagerConnection::GetForProcess()->GetConnector();
-  connector->BindInterface(mojom::kServiceName, &mirroring_service_);
+  content::GetSystemConnector()->BindInterface(mojom::kServiceName,
+                                               &mirroring_service_);
   mojom::ResourceProviderPtr provider;
   resource_provider_binding_.Bind(mojo::MakeRequest(&provider));
   mirroring_service_->Start(
diff --git a/chrome/browser/media/cast_transport_host_filter.cc b/chrome/browser/media/cast_transport_host_filter.cc
index 5dbad65..3326bc0 100644
--- a/chrome/browser/media/cast_transport_host_filter.cc
+++ b/chrome/browser/media/cast_transport_host_filter.cc
@@ -13,7 +13,7 @@
 #include "chrome/common/cast_messages.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "media/cast/net/cast_transport.h"
 #include "media/cast/net/udp_transport_impl.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
@@ -109,11 +109,8 @@
 void CastBindConnectorRequest(
     service_manager::mojom::ConnectorRequest connector_request) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  DCHECK(content::ServiceManagerConnection::GetForProcess());
-
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindConnectorRequest(std::move(connector_request));
+  content::GetSystemConnector()->BindConnectorRequest(
+      std::move(connector_request));
 }
 
 }  // namespace
@@ -404,8 +401,6 @@
 
   device::mojom::WakeLockRequest request = mojo::MakeRequest(&wake_lock_);
 
-  DCHECK(content::ServiceManagerConnection::GetForProcess());
-
   service_manager::mojom::ConnectorRequest connector_request;
   auto connector = service_manager::Connector::Create(&connector_request);
   base::PostTaskWithTraits(
diff --git a/chrome/browser/media/media_engagement_contents_observer_unittest.cc b/chrome/browser/media/media_engagement_contents_observer_unittest.cc
index 0031b09..c3d9b38 100644
--- a/chrome/browser/media/media_engagement_contents_observer_unittest.cc
+++ b/chrome/browser/media/media_engagement_contents_observer_unittest.cc
@@ -461,9 +461,8 @@
       MediaEngagementContentsObserver::kSignificantMediaPlaybackTime +
       base::TimeDelta::FromSeconds(2);
 
-  // WebContentsImpl accesses
-  // content::ServiceManagerConnection::GetForProcess(), so
-  // we must make sure it is instantiated.
+  // WebContentsImpl accesses the system Connector so the Service Manager must
+  // be initialized.
   std::unique_ptr<content::TestServiceManagerContext>
       test_service_manager_context_;
 };
diff --git a/chrome/browser/media/router/discovery/dial/dial_media_sink_service.cc b/chrome/browser/media/router/discovery/dial/dial_media_sink_service.cc
index 858cd7b..876fc39 100644
--- a/chrome/browser/media/router/discovery/dial/dial_media_sink_service.cc
+++ b/chrome/browser/media/router/discovery/dial/dial_media_sink_service.cc
@@ -12,7 +12,7 @@
 #include "chrome/common/media_router/media_source.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/service_manager/public/cpp/connector.h"
 
 namespace media_router {
@@ -46,8 +46,7 @@
 std::unique_ptr<DialMediaSinkServiceImpl, base::OnTaskRunnerDeleter>
 DialMediaSinkService::CreateImpl(
     const OnSinksDiscoveredCallback& sink_discovery_cb) {
-  service_manager::Connector* connector =
-      content::ServiceManagerConnection::GetForProcess()->GetConnector();
+  service_manager::Connector* connector = content::GetSystemConnector();
 
   // Note: The SequencedTaskRunner needs to be IO thread because DialRegistry
   // runs on IO thread.
diff --git a/chrome/browser/media/router/mojo/media_router_desktop.cc b/chrome/browser/media/router/mojo/media_router_desktop.cc
index db0f2ab..f265cf1 100644
--- a/chrome/browser/media/router/mojo/media_router_desktop.cc
+++ b/chrome/browser/media/router/mojo/media_router_desktop.cc
@@ -20,7 +20,7 @@
 #include "chrome/common/media_router/media_source.h"
 #include "components/cast_channel/cast_socket_service.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/common/extension.h"
 #include "services/service_manager/public/cpp/connector.h"
 #if defined(OS_WIN)
@@ -31,11 +31,12 @@
 
 namespace {
 
-// Returns the Connector object for the current process. It is the caller's
-// responsibility to clone the returned object to be used in another thread.
+// Returns the system Connector object for the browser process. It is the
+// caller's responsibility to clone the returned object to be used in another
+// thread.
 service_manager::Connector* GetConnector() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  return content::ServiceManagerConnection::GetForProcess()->GetConnector();
+  return content::GetSystemConnector();
 }
 
 }  // namespace
diff --git a/chrome/browser/media/router/providers/cast/chrome_cast_message_handler.cc b/chrome/browser/media/router/providers/cast/chrome_cast_message_handler.cc
index ab473ee..5a5cf7f 100644
--- a/chrome/browser/media/router/providers/cast/chrome_cast_message_handler.cc
+++ b/chrome/browser/media/router/providers/cast/chrome_cast_message_handler.cc
@@ -11,7 +11,7 @@
 #include "components/cast_channel/cast_socket_service.h"
 #include "components/version_info/version_info.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/service_manager/public/cpp/connector.h"
 
 namespace media_router {
@@ -21,11 +21,8 @@
   static cast_channel::CastMessageHandler* instance =
       new cast_channel::CastMessageHandler(
           cast_channel::CastSocketService::GetInstance(),
-          content::ServiceManagerConnection::GetForProcess()
-              ->GetConnector()
-              ->Clone(),
-          kDataDecoderServiceBatchId, GetUserAgent(),
-          version_info::GetVersionNumber(),
+          content::GetSystemConnector()->Clone(), kDataDecoderServiceBatchId,
+          GetUserAgent(), version_info::GetVersionNumber(),
           g_browser_process->GetApplicationLocale());
   return instance;
 }
diff --git a/chrome/browser/media/unified_autoplay_config_unittest.cc b/chrome/browser/media/unified_autoplay_config_unittest.cc
index 9b950e4..d1a82e0e 100644
--- a/chrome/browser/media/unified_autoplay_config_unittest.cc
+++ b/chrome/browser/media/unified_autoplay_config_unittest.cc
@@ -76,9 +76,8 @@
 
   base::test::ScopedFeatureList scoped_feature_list_;
 
-  // WebContentsImpl accesses
-  // content::ServiceManagerConnection::GetForProcess(), so
-  // we must make sure it is instantiated.
+  // WebContentsImpl accesses the system Connector, so the Service Manager must
+  // be initialized.
   std::unique_ptr<content::TestServiceManagerContext>
       test_service_manager_context_;
 };
diff --git a/chrome/browser/media/webrtc/audio_debug_recordings_handler.cc b/chrome/browser/media/webrtc/audio_debug_recordings_handler.cc
index fc8575b..5c55e50 100644
--- a/chrome/browser/media/webrtc/audio_debug_recordings_handler.cc
+++ b/chrome/browser/media/webrtc/audio_debug_recordings_handler.cc
@@ -18,7 +18,7 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_process_host.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "media/audio/audio_debug_recording_session.h"
 #include "services/audio/public/cpp/debug_recording_session_factory.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -111,9 +111,7 @@
   host->EnableAudioDebugRecordings(prefix_path);
 
   audio_debug_recording_session_ = audio::CreateAudioDebugRecordingSession(
-      prefix_path, content::ServiceManagerConnection::GetForProcess()
-                       ->GetConnector()
-                       ->Clone());
+      prefix_path, content::GetSystemConnector()->Clone());
 
   if (delay.is_zero()) {
     const bool is_stopped = false, is_manual_stop = false;
diff --git a/chrome/browser/media/webrtc/webrtc_browsertest.cc b/chrome/browser/media/webrtc/webrtc_browsertest.cc
index cfd82bb..da6dc26 100644
--- a/chrome/browser/media/webrtc/webrtc_browsertest.cc
+++ b/chrome/browser/media/webrtc/webrtc_browsertest.cc
@@ -15,11 +15,11 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/network_service_instance.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/buildflags.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/feature_h264_with_openh264_ffmpeg.h"
 #include "content/public/common/network_service_util.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/test/browser_test_utils.h"
 #include "media/base/media_switches.h"
@@ -126,10 +126,8 @@
     }
 
     network::mojom::NetworkServiceTestPtr network_service_test;
-    content::ServiceManagerConnection::GetForProcess()
-        ->GetConnector()
-        ->BindInterface(content::mojom::kNetworkServiceName,
-                        &network_service_test);
+    content::GetSystemConnector()->BindInterface(
+        content::mojom::kNetworkServiceName, &network_service_test);
     // TODO(crbug.com/901026): Make sure the network process is started to avoid
     // a deadlock on Android.
     network_service_test.FlushForTesting();
diff --git a/chrome/browser/media_galleries/fileapi/supported_audio_video_checker.cc b/chrome/browser/media_galleries/fileapi/supported_audio_video_checker.cc
index 52c116d..9eee9cd 100644
--- a/chrome/browser/media_galleries/fileapi/supported_audio_video_checker.cc
+++ b/chrome/browser/media_galleries/fileapi/supported_audio_video_checker.cc
@@ -22,7 +22,7 @@
 #include "chrome/services/media_gallery_util/public/cpp/safe_audio_video_checker.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "net/base/mime_util.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "third_party/blink/public/common/mime_util/mime_util.h"
@@ -95,17 +95,13 @@
 void SupportedAudioVideoChecker::RetrieveConnectorOnUIThread(
     base::WeakPtr<SupportedAudioVideoChecker> this_ptr) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  std::unique_ptr<service_manager::Connector> connector =
-      content::ServiceManagerConnection::GetForProcess()
-          ->GetConnector()
-          ->Clone();
   // We need a fresh connector so that we can use it on the IO thread. It has
   // to be retrieved from the UI thread. We must use static method and pass a
   // WeakPtr around as WeakPtrs are not thread-safe.
   base::PostTaskWithTraits(
       FROM_HERE, {content::BrowserThread::IO},
       base::BindOnce(&SupportedAudioVideoChecker::OnConnectorRetrieved,
-                     this_ptr, std::move(connector)));
+                     this_ptr, content::GetSystemConnector()->Clone()));
 }
 
 // static
diff --git a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
index b5652de..f60c66f8 100644
--- a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
+++ b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
@@ -28,8 +28,8 @@
 #include "chrome/browser/shell_integration.h"
 #include "chrome/browser/vr/service/xr_runtime_manager.h"
 #include "components/flags_ui/pref_service_flags_storage.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/content_switches.h"
-#include "content/public/common/service_manager_connection.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "ui/base/pointer/pointer_device.h"
 #include "ui/base/ui_base_switches.h"
@@ -608,8 +608,7 @@
   // TODO(isherman): The delay below is currently needed to avoid (flakily)
   // breaking some tests, including all of the ProcessMemoryMetricsEmitterTest
   // tests. Figure out why there is a dependency and fix the tests.
-  service_manager::Connector* connector =
-      content::ServiceManagerConnection::GetForProcess()->GetConnector();
+  service_manager::Connector* connector = content::GetSystemConnector();
 
   auto background_task_runner =
       base::CreateSequencedTaskRunnerWithTraits(background_task_traits);
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc
index 4d0b915..aa906a2 100644
--- a/chrome/browser/metrics/chrome_metrics_service_client.cc
+++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -147,7 +147,7 @@
 #include "chrome/install_static/install_util.h"
 #include "chrome/notification_helper/notification_helper_constants.h"
 #include "components/browser_watcher/watcher_metrics_provider_win.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #endif
 
 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_ANDROID)
@@ -654,7 +654,7 @@
 
   metrics_service_->RegisterMetricsProvider(
       std::make_unique<AntiVirusMetricsProvider>(
-          content::ServiceManagerConnection::GetForProcess()->GetConnector()));
+          content::GetSystemConnector()));
 #endif  // defined(OS_WIN)
 
 #if defined(OS_WIN) || defined(OS_MACOSX) || \
diff --git a/chrome/browser/net/chrome_mojo_proxy_resolver_factory.cc b/chrome/browser/net/chrome_mojo_proxy_resolver_factory.cc
index 1fe2edc..f76feaa 100644
--- a/chrome/browser/net/chrome_mojo_proxy_resolver_factory.cc
+++ b/chrome/browser/net/chrome_mojo_proxy_resolver_factory.cc
@@ -10,7 +10,7 @@
 #include "base/logging.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
 
@@ -40,7 +40,7 @@
   // create a ProxyResolverFactory and then destroy the factory, to avoid
   // keeping the service alive after all resolvers have been destroyed.
   mojo::Remote<proxy_resolver::mojom::ProxyResolverFactory> resolver_factory;
-  content::ServiceManagerConnection::GetForProcess()->GetConnector()->Connect(
+  content::GetSystemConnector()->Connect(
       proxy_resolver::mojom::kProxyResolverServiceName,
       resolver_factory.BindNewPipeAndPassReceiver());
   resolver_factory->CreateResolver(pac_script, std::move(receiver),
diff --git a/chrome/browser/net/chrome_mojo_proxy_resolver_factory_browsertest.cc b/chrome/browser/net/chrome_mojo_proxy_resolver_factory_browsertest.cc
index d76edb3..d60d1a95 100644
--- a/chrome/browser/net/chrome_mojo_proxy_resolver_factory_browsertest.cc
+++ b/chrome/browser/net/chrome_mojo_proxy_resolver_factory_browsertest.cc
@@ -17,7 +17,7 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h"
@@ -165,7 +165,7 @@
   void SetUpOnMainThread() override {
     // Access the service manager so a listener for service creation/destruction
     // can be set-up.
-    content::ServiceManagerConnection::GetForProcess()->GetConnector()->Connect(
+    content::GetSystemConnector()->Connect(
         service_manager::mojom::kServiceName,
         service_manager_.BindNewPipeAndPassReceiver());
 
diff --git a/chrome/browser/net/network_connection_tracker_browsertest.cc b/chrome/browser/net/network_connection_tracker_browsertest.cc
index b769ce3..b12722d3 100644
--- a/chrome/browser/net/network_connection_tracker_browsertest.cc
+++ b/chrome/browser/net/network_connection_tracker_browsertest.cc
@@ -17,8 +17,8 @@
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/network_service_instance.h"
 #include "content/public/browser/storage_partition.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/network_service_util.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
@@ -94,10 +94,8 @@
   void SimulateNetworkChange(network::mojom::ConnectionType type) {
     if (!content::IsInProcessNetworkService()) {
       network::mojom::NetworkServiceTestPtr network_service_test;
-      content::ServiceManagerConnection::GetForProcess()
-          ->GetConnector()
-          ->BindInterface(content::mojom::kNetworkServiceName,
-                          &network_service_test);
+      content::GetSystemConnector()->BindInterface(
+          content::mojom::kNetworkServiceName, &network_service_test);
       base::RunLoop run_loop;
       network_service_test->SimulateNetworkChange(
           type, base::Bind([](base::RunLoop* run_loop) { run_loop->Quit(); },
diff --git a/chrome/browser/net/network_quality_estimator_prefs_browsertest.cc b/chrome/browser/net/network_quality_estimator_prefs_browsertest.cc
index a6d7bf3..115b2af 100644
--- a/chrome/browser/net/network_quality_estimator_prefs_browsertest.cc
+++ b/chrome/browser/net/network_quality_estimator_prefs_browsertest.cc
@@ -33,8 +33,8 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/network_service_instance.h"
 #include "content/public/browser/storage_partition.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/network_service_util.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_base.h"
@@ -164,10 +164,8 @@
     DCHECK(content::GetNetworkService());
 
     network::mojom::NetworkServiceTestPtr network_service_test;
-    content::ServiceManagerConnection::GetForProcess()
-        ->GetConnector()
-        ->BindInterface(content::mojom::kNetworkServiceName,
-                        &network_service_test);
+    content::GetSystemConnector()->BindInterface(
+        content::mojom::kNetworkServiceName, &network_service_test);
     base::RunLoop run_loop;
     network_service_test->SimulateNetworkQualityChange(
         type, base::BindOnce([](base::RunLoop* run_loop) { run_loop->Quit(); },
diff --git a/chrome/browser/net/network_quality_tracker_browsertest.cc b/chrome/browser/net/network_quality_tracker_browsertest.cc
index e4b50b8f..0a20d6f5d 100644
--- a/chrome/browser/net/network_quality_tracker_browsertest.cc
+++ b/chrome/browser/net/network_quality_tracker_browsertest.cc
@@ -19,8 +19,8 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/network_service_instance.h"
 #include "content/public/browser/storage_partition.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/network_service_util.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_base.h"
@@ -142,10 +142,8 @@
     DCHECK(content::GetNetworkService());
 
     network::mojom::NetworkServiceTestPtr network_service_test;
-    content::ServiceManagerConnection::GetForProcess()
-        ->GetConnector()
-        ->BindInterface(content::mojom::kNetworkServiceName,
-                        &network_service_test);
+    content::GetSystemConnector()->BindInterface(
+        content::mojom::kNetworkServiceName, &network_service_test);
     base::RunLoop run_loop;
     network_service_test->SimulateNetworkQualityChange(
         type, base::BindOnce([](base::RunLoop* run_loop) { run_loop->Quit(); },
diff --git a/chrome/browser/notifications/scheduler/BUILD.gn b/chrome/browser/notifications/scheduler/BUILD.gn
index 59b3088..9802aec 100644
--- a/chrome/browser/notifications/scheduler/BUILD.gn
+++ b/chrome/browser/notifications/scheduler/BUILD.gn
@@ -33,6 +33,7 @@
     "//chrome/browser/notifications/scheduler/public",
     "//components/keyed_service/core",
     "//components/leveldb_proto",
+    "//skia",
   ]
 }
 
diff --git a/chrome/browser/notifications/scheduler/internal/notification_scheduler_context.cc b/chrome/browser/notifications/scheduler/internal/notification_scheduler_context.cc
index f67c8d90..0121503d 100644
--- a/chrome/browser/notifications/scheduler/internal/notification_scheduler_context.cc
+++ b/chrome/browser/notifications/scheduler/internal/notification_scheduler_context.cc
@@ -14,7 +14,6 @@
 #include "chrome/browser/notifications/scheduler/internal/impression_history_tracker.h"
 #include "chrome/browser/notifications/scheduler/internal/scheduled_notification_manager.h"
 #include "chrome/browser/notifications/scheduler/internal/scheduler_config.h"
-#include "chrome/browser/notifications/scheduler/internal/webui_client.h"
 #include "chrome/browser/notifications/scheduler/public/notification_background_task_scheduler.h"
 #include "chrome/browser/notifications/scheduler/public/notification_scheduler_client.h"
 #include "chrome/browser/notifications/scheduler/public/notification_scheduler_client_registrar.h"
@@ -37,10 +36,7 @@
       background_task_coordinator_(std::make_unique<BackgroundTaskCoordinator>(
           std::move(background_task),
           config_.get(),
-          base::DefaultClock::GetInstance())) {
-  client_registrar_->RegisterClient(SchedulerClientType::kWebUI,
-                                    std::make_unique<WebUIClient>());
-}
+          base::DefaultClock::GetInstance())) {}
 
 NotificationSchedulerContext::~NotificationSchedulerContext() = default;
 
diff --git a/chrome/browser/notifications/scheduler/schedule_service_factory_helper.cc b/chrome/browser/notifications/scheduler/schedule_service_factory_helper.cc
index 71b953d..52344f5 100644
--- a/chrome/browser/notifications/scheduler/schedule_service_factory_helper.cc
+++ b/chrome/browser/notifications/scheduler/schedule_service_factory_helper.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/notifications/scheduler/internal/notification_store.h"
 #include "chrome/browser/notifications/scheduler/internal/scheduled_notification_manager.h"
 #include "chrome/browser/notifications/scheduler/internal/scheduler_config.h"
+#include "chrome/browser/notifications/scheduler/internal/webui_client.h"
 #include "chrome/browser/notifications/scheduler/public/notification_background_task_scheduler.h"
 #include "chrome/browser/notifications/scheduler/public/notification_scheduler_client_registrar.h"
 #include "components/leveldb_proto/public/proto_database_provider.h"
@@ -43,6 +44,8 @@
   auto config = SchedulerConfig::Create();
   auto task_runner = base::CreateSequencedTaskRunnerWithTraits(
       {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
+  client_registrar->RegisterClient(SchedulerClientType::kWebUI,
+                                   std::make_unique<WebUIClient>());
 
   // Build icon store.
   base::FilePath icon_store_dir = storage_dir.Append(kIconDBName);
diff --git a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
index 00b93837..c2e3227 100644
--- a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
+++ b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
@@ -49,7 +49,7 @@
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/storage_partition.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "google_apis/google_api_keys.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "services/data_decoder/public/cpp/safe_json_parser.h"
@@ -170,9 +170,8 @@
 #endif  // BUILDFLAG(ENABLE_OFFLINE_PAGES)
   auto suggestions_fetcher = std::make_unique<RemoteSuggestionsFetcherImpl>(
       identity_manager, url_loader_factory, pref_service, language_histogram,
-      base::BindRepeating(
-          &data_decoder::SafeJsonParser::Parse,
-          content::ServiceManagerConnection::GetForProcess()->GetConnector()),
+      base::BindRepeating(&data_decoder::SafeJsonParser::Parse,
+                          content::GetSystemConnector()),
       GetFetchEndpoint(), api_key, user_classifier);
 
   auto provider = std::make_unique<RemoteSuggestionsProviderImpl>(
diff --git a/chrome/browser/ntp_tiles/chrome_popular_sites_factory.cc b/chrome/browser/ntp_tiles/chrome_popular_sites_factory.cc
index 6f3c5db..7864b9b 100644
--- a/chrome/browser/ntp_tiles/chrome_popular_sites_factory.cc
+++ b/chrome/browser/ntp_tiles/chrome_popular_sites_factory.cc
@@ -12,7 +12,7 @@
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/storage_partition.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/data_decoder/public/cpp/safe_json_parser.h"
 
 std::unique_ptr<ntp_tiles::PopularSites>
@@ -22,7 +22,6 @@
       g_browser_process->variations_service(),
       content::BrowserContext::GetDefaultStoragePartition(profile)
           ->GetURLLoaderFactoryForBrowserProcess(),
-      base::BindRepeating(
-          &data_decoder::SafeJsonParser::Parse,
-          content::ServiceManagerConnection::GetForProcess()->GetConnector()));
+      base::BindRepeating(&data_decoder::SafeJsonParser::Parse,
+                          content::GetSystemConnector()));
 }
diff --git a/chrome/browser/offline_pages/background_loader_offliner.cc b/chrome/browser/offline_pages/background_loader_offliner.cc
index 3b565d8b..de53bb8 100644
--- a/chrome/browser/offline_pages/background_loader_offliner.cc
+++ b/chrome/browser/offline_pages/background_loader_offliner.cc
@@ -403,7 +403,7 @@
     previews::PreviewsUserData* previews_user_data =
         previews_tab_helper->GetPreviewsUserData(navigation_handle);
     if (previews_user_data)
-      previews_state = previews_user_data->committed_previews_state();
+      previews_state = previews_user_data->CommittedPreviewsState();
   }
 
   RecordOffliningPreviewsUMA(pending_request_->client_id(), previews_state);
diff --git a/chrome/browser/page_load_metrics/observers/previews_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/previews_page_load_metrics_observer.cc
index 2a4a2b4..e255bec9 100644
--- a/chrome/browser/page_load_metrics/observers/previews_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/previews_page_load_metrics_observer.cc
@@ -123,7 +123,7 @@
     return STOP_OBSERVING;
 
   previews_type_ = previews::GetMainFramePreviewsType(
-      previews_user_data->committed_previews_state());
+      previews_user_data->PreHoldbackCommittedPreviewsState());
   if (previews_type_ != previews::PreviewsType::NOSCRIPT &&
       previews_type_ != previews::PreviewsType::RESOURCE_LOADING_HINTS) {
     return STOP_OBSERVING;
diff --git a/chrome/browser/page_load_metrics/observers/previews_ukm_observer.cc b/chrome/browser/page_load_metrics/observers/previews_ukm_observer.cc
index e73ad14..cc253b620 100644
--- a/chrome/browser/page_load_metrics/observers/previews_ukm_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/previews_ukm_observer.cc
@@ -72,22 +72,23 @@
   if (!previews_user_data)
     return STOP_OBSERVING;
 
-  committed_preview_ = previews_user_data->committed_previews_type();
+  committed_preview_ = previews_user_data->PreHoldbackCommittedPreviewsType();
 
   // Only check for preview types that are decided before commit in the
   // |allowed_previews_state|.
-  previews_likely_ = HasEnabledPreviews(
-      previews_user_data->allowed_previews_state() & kPreCommitPreviews);
+  previews_likely_ =
+      HasEnabledPreviews(previews_user_data->PreHoldbackAllowedPreviewsState() &
+                         kPreCommitPreviews);
 
   // Check all preview types in the |committed_previews_state|. In practice
   // though, this will only set |previews_likely_| if it wasn't before for an
   // Optimization Hints preview.
-  previews_likely_ |=
-      HasEnabledPreviews(previews_user_data->committed_previews_state());
+  previews_likely_ |= HasEnabledPreviews(
+      previews_user_data->PreHoldbackCommittedPreviewsState());
 
   coin_flip_result_ = previews_user_data->coin_flip_holdback_result();
   content::PreviewsState previews_state =
-      previews_user_data->committed_previews_state();
+      previews_user_data->PreHoldbackCommittedPreviewsState();
 
   DCHECK(coin_flip_result_ == CoinFlipHoldbackResult::kNotSet ||
          previews_likely_);
diff --git a/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc
index 12d9321..5b5ebfe 100644
--- a/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc
@@ -86,35 +86,35 @@
 
     if (noscript_on_) {
       content::PreviewsState previews_state =
-          user_data->committed_previews_state();
+          user_data->CommittedPreviewsState();
       user_data->set_committed_previews_state(previews_state |=
                                               content::NOSCRIPT_ON);
     }
 
     if (resource_loading_hints_on_) {
       content::PreviewsState previews_state =
-          user_data->committed_previews_state();
+          user_data->CommittedPreviewsState();
       user_data->set_committed_previews_state(
           previews_state |= content::RESOURCE_LOADING_HINTS_ON);
     }
 
     if (lite_page_received_) {
       content::PreviewsState previews_state =
-          user_data->committed_previews_state();
+          user_data->CommittedPreviewsState();
       user_data->set_committed_previews_state(previews_state |=
                                               content::SERVER_LITE_PAGE_ON);
     }
 
     if (lite_page_redirect_received_) {
       content::PreviewsState previews_state =
-          user_data->committed_previews_state();
+          user_data->CommittedPreviewsState();
       user_data->set_committed_previews_state(previews_state |=
                                               content::LITE_PAGE_REDIRECT_ON);
     }
 
     if (is_offline_preview_) {
       content::PreviewsState previews_state =
-          user_data->committed_previews_state();
+          user_data->CommittedPreviewsState();
       user_data->set_committed_previews_state(previews_state |=
                                               content::OFFLINE_PAGE_ON);
     }
diff --git a/chrome/browser/performance_manager/performance_manager.cc b/chrome/browser/performance_manager/performance_manager.cc
index 0bed066..75a83825 100644
--- a/chrome/browser/performance_manager/performance_manager.cc
+++ b/chrome/browser/performance_manager/performance_manager.cc
@@ -22,7 +22,7 @@
 #include "chrome/browser/performance_manager/observers/isolation_context_metrics.h"
 #include "chrome/browser/performance_manager/observers/metrics_collector.h"
 #include "chrome/browser/performance_manager/observers/working_set_trimmer_win.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/resource_coordinator/public/cpp/resource_coordinator_features.h"
 
 namespace performance_manager {
@@ -247,12 +247,11 @@
 void PerformanceManager::OnStart() {
   // Some tests don't initialize the service manager connection, so this class
   // tolerates its absence for tests.
-  auto* connection = content::ServiceManagerConnection::GetForProcess();
+  auto* connector = content::GetSystemConnector();
   task_runner_->PostTask(
       FROM_HERE,
-      base::BindOnce(
-          &PerformanceManager::OnStartImpl, base::Unretained(this),
-          connection ? connection->GetConnector()->Clone() : nullptr));
+      base::BindOnce(&PerformanceManager::OnStartImpl, base::Unretained(this),
+                     connector ? connector->Clone() : nullptr));
 }
 
 void PerformanceManager::CallOnGraphImpl(GraphCallback graph_callback) {
diff --git a/chrome/browser/plugins/plugins_resource_service.cc b/chrome/browser/plugins/plugins_resource_service.cc
index d7c3801..85003dd 100644
--- a/chrome/browser/plugins/plugins_resource_service.cc
+++ b/chrome/browser/plugins/plugins_resource_service.cc
@@ -15,7 +15,7 @@
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/network_service_instance.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/data_decoder/public/cpp/safe_json_parser.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "url/gurl.h"
@@ -88,8 +88,7 @@
               ->GetSharedURLLoaderFactory(),
           switches::kDisableBackgroundNetworking,
           base::BindRepeating(&data_decoder::SafeJsonParser::Parse,
-                              content::ServiceManagerConnection::GetForProcess()
-                                  ->GetConnector()),
+                              content::GetSystemConnector()),
           kPluginResourceServiceTrafficAnnotation,
           base::BindOnce(&content::GetNetworkConnectionTracker)) {}
 
diff --git a/chrome/browser/policy/browser_signin_policy_handler.cc b/chrome/browser/policy/browser_signin_policy_handler.cc
index 35b47eb..a7be7da 100644
--- a/chrome/browser/policy/browser_signin_policy_handler.cc
+++ b/chrome/browser/policy/browser_signin_policy_handler.cc
@@ -19,7 +19,7 @@
     : SchemaValidatingPolicyHandler(
           key::kBrowserSignin,
           chrome_schema.GetKnownProperty(key::kBrowserSignin),
-          SCHEMA_STRICT) {}
+          SCHEMA_ALLOW_UNKNOWN) {}
 
 BrowserSigninPolicyHandler::~BrowserSigninPolicyHandler() {}
 
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index 07848b7..770697d 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -1129,24 +1129,22 @@
   handlers->AddHandler(std::make_unique<ProxyPolicyHandler>());
   handlers->AddHandler(std::make_unique<URLBlacklistPolicyHandler>());
 
-  // TODO(https://crbug.com/953615): Consider switching from SCHEMA_STRICT to
-  // SCHEMA_ALLOW_UNKNOWN for all schema validating policy handlers.
   handlers->AddHandler(std::make_unique<SimpleSchemaValidatingPolicyHandler>(
       key::kCertificateTransparencyEnforcementDisabledForUrls,
       certificate_transparency::prefs::kCTExcludedHosts, chrome_schema,
-      SCHEMA_STRICT,
+      SCHEMA_ALLOW_UNKNOWN,
       SimpleSchemaValidatingPolicyHandler::RECOMMENDED_PROHIBITED,
       SimpleSchemaValidatingPolicyHandler::MANDATORY_ALLOWED));
   handlers->AddHandler(std::make_unique<SimpleSchemaValidatingPolicyHandler>(
       key::kCertificateTransparencyEnforcementDisabledForCas,
       certificate_transparency::prefs::kCTExcludedSPKIs, chrome_schema,
-      SCHEMA_STRICT,
+      SCHEMA_ALLOW_UNKNOWN,
       SimpleSchemaValidatingPolicyHandler::RECOMMENDED_PROHIBITED,
       SimpleSchemaValidatingPolicyHandler::MANDATORY_ALLOWED));
   handlers->AddHandler(std::make_unique<SimpleSchemaValidatingPolicyHandler>(
       key::kCertificateTransparencyEnforcementDisabledForLegacyCas,
       certificate_transparency::prefs::kCTExcludedLegacySPKIs, chrome_schema,
-      SCHEMA_STRICT,
+      SCHEMA_ALLOW_UNKNOWN,
       SimpleSchemaValidatingPolicyHandler::RECOMMENDED_PROHIBITED,
       SimpleSchemaValidatingPolicyHandler::MANDATORY_ALLOWED));
   handlers->AddHandler(
@@ -1221,11 +1219,9 @@
   handlers->AddHandler(
       std::make_unique<extensions::ExtensionSettingsPolicyHandler>(
           chrome_schema));
-  // TODO(https://crbug.com/953615): Consider switching from SCHEMA_STRICT to
-  // SCHEMA_ALLOW_UNKNOWN for all schema validating policy handlers.
   handlers->AddHandler(std::make_unique<SimpleSchemaValidatingPolicyHandler>(
       key::kWebAppInstallForceList, prefs::kWebAppInstallForceList,
-      chrome_schema, SCHEMA_STRICT,
+      chrome_schema, SCHEMA_ALLOW_UNKNOWN,
       SimpleSchemaValidatingPolicyHandler::RECOMMENDED_PROHIBITED,
       SimpleSchemaValidatingPolicyHandler::MANDATORY_ALLOWED));
 #endif
@@ -1248,11 +1244,10 @@
   handlers->AddHandler(std::make_unique<DownloadDirPolicyHandler>());
   handlers->AddHandler(std::make_unique<LocalSyncPolicyHandler>());
 
-  // TODO(https://crbug.com/953615): Consider switching from SCHEMA_STRICT to
-  // SCHEMA_ALLOW_UNKNOWN for all schema validating policy handlers.
   handlers->AddHandler(std::make_unique<SimpleSchemaValidatingPolicyHandler>(
       key::kRegisteredProtocolHandlers,
-      prefs::kPolicyRegisteredProtocolHandlers, chrome_schema, SCHEMA_STRICT,
+      prefs::kPolicyRegisteredProtocolHandlers, chrome_schema,
+      SCHEMA_ALLOW_UNKNOWN,
       SimpleSchemaValidatingPolicyHandler::RECOMMENDED_ALLOWED,
       SimpleSchemaValidatingPolicyHandler::MANDATORY_PROHIBITED));
 
@@ -1263,14 +1258,12 @@
       key::kSafeBrowsingExtendedReportingOptInAllowed,
       prefs::kSafeBrowsingExtendedReportingOptInAllowed,
       base::Value::Type::BOOLEAN));
-  // TODO(https://crbug.com/953615): Consider switching from SCHEMA_STRICT to
-  // SCHEMA_ALLOW_UNKNOWN for all schema validating policy handlers.
   handlers->AddHandler(std::make_unique<LegacyPoliciesDeprecatingPolicyHandler>(
       std::move(sber_legacy_policy),
       std::make_unique<SimpleSchemaValidatingPolicyHandler>(
           key::kSafeBrowsingExtendedReportingEnabled,
           prefs::kSafeBrowsingScoutReportingEnabled, chrome_schema,
-          SCHEMA_STRICT,
+          SCHEMA_ALLOW_UNKNOWN,
           SimpleSchemaValidatingPolicyHandler::RECOMMENDED_ALLOWED,
           SimpleSchemaValidatingPolicyHandler::MANDATORY_ALLOWED)));
 
@@ -1432,10 +1425,8 @@
       key::kNativePrintersBulkConfiguration));
   handlers->AddHandler(std::make_unique<ExternalDataPolicyHandler>(
       key::kDeviceWilcoDtcConfiguration));
-  // TODO(https://crbug.com/953615): Consider switching from SCHEMA_STRICT to
-  // SCHEMA_ALLOW_UNKNOWN for all schema validating policy handlers.
   handlers->AddHandler(std::make_unique<SimpleSchemaValidatingPolicyHandler>(
-      key::kSessionLocales, nullptr, chrome_schema, SCHEMA_STRICT,
+      key::kSessionLocales, nullptr, chrome_schema, SCHEMA_ALLOW_UNKNOWN,
       SimpleSchemaValidatingPolicyHandler::RECOMMENDED_ALLOWED,
       SimpleSchemaValidatingPolicyHandler::MANDATORY_PROHIBITED));
   handlers->AddHandler(
@@ -1447,11 +1438,9 @@
   handlers->AddHandler(
       std::make_unique<SecondaryGoogleAccountSigninPolicyHandler>());
   if (base::FeatureList::IsEnabled(features::kUsageTimeLimitPolicy)) {
-    // TODO(https://crbug.com/953615): Consider switching from SCHEMA_STRICT to
-    // SCHEMA_ALLOW_UNKNOWN for all schema validating policy handlers.
     handlers->AddHandler(std::make_unique<SimpleSchemaValidatingPolicyHandler>(
         key::kUsageTimeLimit, prefs::kUsageTimeLimit, chrome_schema,
-        SCHEMA_STRICT,
+        SCHEMA_ALLOW_UNKNOWN,
         SimpleSchemaValidatingPolicyHandler::RECOMMENDED_PROHIBITED,
         SimpleSchemaValidatingPolicyHandler::MANDATORY_ALLOWED));
   }
@@ -1473,17 +1462,15 @@
   handlers->AddHandler(std::make_unique<PrintingDuplexDefaultPolicyHandler>());
   handlers->AddHandler(std::make_unique<PrintingPinDefaultPolicyHandler>());
   handlers->AddHandler(std::make_unique<PrintingSizeDefaultPolicyHandler>());
-  // TODO(https://crbug.com/953615): Consider switching from SCHEMA_STRICT to
-  // SCHEMA_ALLOW_UNKNOWN for all schema validating policy handlers.
   handlers->AddHandler(std::make_unique<SimpleSchemaValidatingPolicyHandler>(
       key::kNetworkFileSharesPreconfiguredShares,
       prefs::kNetworkFileSharesPreconfiguredShares, chrome_schema,
-      SCHEMA_STRICT,
+      SCHEMA_ALLOW_UNKNOWN,
       SimpleSchemaValidatingPolicyHandler::RECOMMENDED_PROHIBITED,
       SimpleSchemaValidatingPolicyHandler::MANDATORY_ALLOWED));
   handlers->AddHandler(std::make_unique<SimpleSchemaValidatingPolicyHandler>(
       key::kParentAccessCodeConfig, prefs::kParentAccessCodeConfig,
-      chrome_schema, SCHEMA_STRICT,
+      chrome_schema, SCHEMA_ALLOW_UNKNOWN,
       SimpleSchemaValidatingPolicyHandler::RECOMMENDED_PROHIBITED,
       SimpleSchemaValidatingPolicyHandler::MANDATORY_ALLOWED));
   handlers->AddHandler(
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index 1f65ff0..8d2cda8 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -183,6 +183,7 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/storage_partition.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_constants.h"
 #include "content/public/common/content_features.h"
@@ -190,7 +191,6 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/common/network_service_util.h"
 #include "content/public/common/result_codes.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/common/web_preferences.h"
@@ -813,10 +813,8 @@
   void SetShouldRequireCTForTesting(bool* required) {
     if (content::IsOutOfProcessNetworkService()) {
       network::mojom::NetworkServiceTestPtr network_service_test;
-      content::ServiceManagerConnection::GetForProcess()
-          ->GetConnector()
-          ->BindInterface(content::mojom::kNetworkServiceName,
-                          &network_service_test);
+      content::GetSystemConnector()->BindInterface(
+          content::mojom::kNetworkServiceName, &network_service_test);
       network::mojom::NetworkServiceTest::ShouldRequireCT required_ct;
       if (!required) {
         required_ct =
diff --git a/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.cc b/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.cc
index aee799e..1b6bbb77 100644
--- a/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.cc
+++ b/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.cc
@@ -69,9 +69,10 @@
     const char* policy_name,
     const char* pref_path,
     const Schema& chrome_schema)
-    : SchemaValidatingPolicyHandler(policy_name,
-                                    chrome_schema.GetKnownProperty(policy_name),
-                                    SchemaOnErrorStrategy::SCHEMA_STRICT),
+    : SchemaValidatingPolicyHandler(
+          policy_name,
+          chrome_schema.GetKnownProperty(policy_name),
+          SchemaOnErrorStrategy::SCHEMA_ALLOW_UNKNOWN),
       pref_path_(pref_path) {}
 
 WebUsbAllowDevicesForUrlsPolicyHandler::
diff --git a/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler_unittest.cc b/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler_unittest.cc
index 2bc6dba..4cb2d29c 100644
--- a/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler_unittest.cc
+++ b/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler_unittest.cc
@@ -146,6 +146,24 @@
         ]
       }
     ])";
+// Same as |kInvalidPolicyUnknownProperty| without the unknown property
+// "serialNumber". This serves as expected pref value of applying the policy
+// with |kInvalidPolicyUnknownProperty|.
+constexpr char kInvalidPolicyUnknownPropertyAfterCleanup[] = R"(
+    [
+      {
+        "devices": [
+          {
+            "vendor_id": 1234,
+            "product_id": 5678
+          }
+        ],
+        "urls": [
+          "https://google.com,https://google.com",
+          "https://www.youtube.com"
+        ]
+      }
+    ])";
 // A device containing a |product_id| must also have a |vendor_id|.
 constexpr char kInvalidPolicyProductIdWithoutVendorId[] = R"(
     [
@@ -336,12 +354,11 @@
       base::JSONReader::ReadDeprecated(kInvalidPolicyUnknownProperty), nullptr);
 
   ASSERT_TRUE(errors.empty());
-  EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
+  EXPECT_TRUE(handler()->CheckPolicySettings(policy, &errors));
   EXPECT_EQ(errors.size(), 1ul);
 
   const base::string16 kExpected = base::ASCIIToUTF16(
-      "Schema validation error at \"items[0].devices.items[0]\": Unknown "
-      "property: serialNumber");
+      "Schema validation error at \"(ROOT)\": Unknown property: serialNumber");
   EXPECT_EQ(errors.GetErrors(policy_name_), kExpected);
 }
 
@@ -627,8 +644,13 @@
       base::JSONReader::ReadDeprecated(kInvalidPolicyUnknownProperty), nullptr);
   UpdateProviderPolicy(policy);
   const base::Value* pref_value = nullptr;
-  EXPECT_FALSE(store_->GetValue(pref_name_, &pref_value));
-  EXPECT_FALSE(pref_value);
+  EXPECT_TRUE(store_->GetValue(pref_name_, &pref_value));
+  EXPECT_TRUE(pref_value);
+
+  base::Optional<base::Value> expected_pref_value =
+      base::JSONReader::Read(kInvalidPolicyUnknownPropertyAfterCleanup);
+  ASSERT_TRUE(expected_pref_value);
+  EXPECT_EQ(*expected_pref_value, *pref_value);
 }
 
 TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
diff --git a/chrome/browser/previews/android/previews_android_bridge.cc b/chrome/browser/previews/android/previews_android_bridge.cc
index 21f2c52..d711798d 100644
--- a/chrome/browser/previews/android/previews_android_bridge.cc
+++ b/chrome/browser/previews/android/previews_android_bridge.cc
@@ -123,6 +123,5 @@
 
   return base::android::ScopedJavaLocalRef<jstring>(
       base::android::ConvertUTF8ToJavaString(
-          env,
-          previews::GetStringNameForType(data->committed_previews_type())));
+          env, previews::GetStringNameForType(data->CommittedPreviewsType())));
 }
diff --git a/chrome/browser/previews/previews_lite_page_browsertest.cc b/chrome/browser/previews/previews_lite_page_browsertest.cc
index eb86ba9..721c441 100644
--- a/chrome/browser/previews/previews_lite_page_browsertest.cc
+++ b/chrome/browser/previews/previews_lite_page_browsertest.cc
@@ -394,7 +394,7 @@
     previews::PreviewsUserData* previews_data =
         ui_tab_helper->previews_user_data();
     EXPECT_TRUE(previews_data->HasCommittedPreviewsType());
-    EXPECT_EQ(previews_data->committed_previews_type(),
+    EXPECT_EQ(previews_data->CommittedPreviewsType(),
               previews::PreviewsType::LITE_PAGE_REDIRECT);
 
     const GURL loaded_url = GetLoadedURL();
@@ -446,7 +446,7 @@
     previews::PreviewsUserData* previews_data =
         ui_tab_helper->previews_user_data();
     EXPECT_FALSE(previews_data->HasCommittedPreviewsType());
-    EXPECT_NE(previews_data->committed_previews_type(),
+    EXPECT_NE(previews_data->CommittedPreviewsType(),
               previews::PreviewsType::LITE_PAGE_REDIRECT);
 
     const GURL loaded_url = GetLoadedURL();
@@ -2007,7 +2007,7 @@
   previews::PreviewsUserData* previews_data =
       ui_tab_helper->previews_user_data();
   EXPECT_TRUE(previews_data->HasCommittedPreviewsType());
-  EXPECT_EQ(previews_data->committed_previews_type(),
+  EXPECT_EQ(previews_data->CommittedPreviewsType(),
             previews::PreviewsType::RESOURCE_LOADING_HINTS);
 
   ClearDeciderState();
@@ -2108,10 +2108,8 @@
     }
 
     if (want_resource_loading_committed) {
-      EXPECT_EQ(previews_data->committed_previews_type(),
+      EXPECT_EQ(previews_data->CommittedPreviewsType(),
                 previews::PreviewsType::RESOURCE_LOADING_HINTS);
-      EXPECT_NE(previews_data->coin_flip_holdback_result(),
-                previews::CoinFlipHoldbackResult::kHoldback);
     }
 
     EXPECT_EQ(want_ukm_coin_flip_holdback_result,
diff --git a/chrome/browser/previews/previews_lite_page_navigation_throttle.cc b/chrome/browser/previews/previews_lite_page_navigation_throttle.cc
index 1995729..553a3d1d 100644
--- a/chrome/browser/previews/previews_lite_page_navigation_throttle.cc
+++ b/chrome/browser/previews/previews_lite_page_navigation_throttle.cc
@@ -318,11 +318,8 @@
       tab_helper ? (tab_helper->GetPreviewsUserData(navigation_handle()))
                  : nullptr;
 
-  if (!previews_data ||
-      !(previews_data->allowed_previews_state() &
-        content::LITE_PAGE_REDIRECT_ON) ||
-      previews_data->coin_flip_holdback_result() ==
-          previews::CoinFlipHoldbackResult::kHoldback) {
+  if (!previews_data || !(previews_data->AllowedPreviewsState() &
+                          content::LITE_PAGE_REDIRECT_ON)) {
     return false;
   }
 
diff --git a/chrome/browser/previews/previews_ui_tab_helper.cc b/chrome/browser/previews/previews_ui_tab_helper.cc
index e4f58a4..04b7bef 100644
--- a/chrome/browser/previews/previews_ui_tab_helper.cc
+++ b/chrome/browser/previews/previews_ui_tab_helper.cc
@@ -188,7 +188,7 @@
 
 void PreviewsUITabHelper::ReloadWithoutPreviews() {
   DCHECK(previews_user_data_);
-  ReloadWithoutPreviews(previews_user_data_->committed_previews_type());
+  ReloadWithoutPreviews(previews_user_data_->CommittedPreviewsType());
 }
 
 void PreviewsUITabHelper::ReloadWithoutPreviews(
@@ -345,7 +345,7 @@
 
   if (tab_helper && tab_helper->GetOfflinePreviewItem()) {
     DCHECK_EQ(previews::PreviewsType::OFFLINE,
-              previews_user_data_->committed_previews_type());
+              previews_user_data_->CommittedPreviewsType());
     UMA_HISTOGRAM_BOOLEAN("Previews.Offline.CommittedErrorPage",
                           navigation_handle->IsErrorPage());
     if (navigation_handle->IsErrorPage()) {
@@ -388,11 +388,9 @@
 #endif  // BUILDFLAG(ENABLE_OFFLINE_PAGES)
 
   // Check for committed main frame preview.
-  if (previews_user_data_ && previews_user_data_->HasCommittedPreviewsType() &&
-      previews_user_data_->coin_flip_holdback_result() !=
-          previews::CoinFlipHoldbackResult::kHoldback) {
+  if (previews_user_data_ && previews_user_data_->HasCommittedPreviewsType()) {
     previews::PreviewsType main_frame_preview =
-        previews_user_data_->committed_previews_type();
+        previews_user_data_->CommittedPreviewsType();
     if (main_frame_preview != previews::PreviewsType::NONE) {
       if (main_frame_preview == previews::PreviewsType::LITE_PAGE) {
         const net::HttpResponseHeaders* headers =
diff --git a/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc b/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc
index e903595..b092c4b 100644
--- a/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc
+++ b/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc
@@ -93,6 +93,14 @@
     https_url_ = https_server_->GetURL("/resource_loading_hints.html");
     ASSERT_TRUE(https_url_.SchemeIs(url::kHttpsScheme));
 
+    https_url_iframe_ =
+        https_server_->GetURL("/resource_loading_hints_iframe.html");
+    ASSERT_TRUE(https_url_.SchemeIs(url::kHttpsScheme));
+
+    https_url_iframe_preload_ =
+        https_server_->GetURL("/resource_loading_hints_iframe_preload.html");
+    ASSERT_TRUE(https_url_.SchemeIs(url::kHttpsScheme));
+
     https_url_preload_ =
         https_server_->GetURL("/resource_loading_hints_preload.html");
 
@@ -255,7 +263,19 @@
   }
 
   virtual const GURL& https_url() const { return https_url_; }
+
+  // URL that loads blocked resources uses link-rel preload in <head>.
   const GURL& https_url_preload() const { return https_url_preload_; }
+
+  // URL that loads a woff2 resource and https_url() webpage in an iframe.
+  virtual const GURL& https_url_iframe() const { return https_url_iframe_; }
+
+  // URL that loads a woff2 resource and https_url_preload() webpage in an
+  // iframe.
+  virtual const GURL& https_url_iframe_preload() const {
+    return https_url_iframe_preload_;
+  }
+
   const GURL& https_second_url() const { return https_second_url_; }
   const GURL& https_no_transform_url() const { return https_no_transform_url_; }
   const GURL& https_hint_setup_url() const { return https_hint_setup_url_; }
@@ -271,6 +291,10 @@
     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
     subresource_expected_["/bar.jpg"] = expect_bar_jpg_requested;
   }
+  void SetExpectedBazWoff2Request(bool expect_woff_requested) {
+    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+    subresource_expected_["/baz.woff2"] = expect_woff_requested;
+  }
 
   bool resource_loading_hint_intervention_header_seen() const {
     return resource_loading_hint_intervention_header_seen_;
@@ -327,7 +351,9 @@
       if (gurl.path() == expect.first) {
         // Verify that |gurl| is expected to be fetched. This ensures that a
         // resource whose loading is blocked is not loaded.
-        EXPECT_TRUE(expect.second);
+        EXPECT_TRUE(expect.second)
+            << " GURL " << gurl
+            << " was expected to be blocked, but was actually fetched";
         // Subresource should not be fetched again.
         subresource_expected_[gurl.path()] = false;
         return;
@@ -342,6 +368,8 @@
   std::unique_ptr<net::EmbeddedTestServer> http_server_;
   GURL https_url_;
   GURL https_url_preload_;
+  GURL https_url_iframe_;
+  GURL https_url_iframe_preload_;
   GURL https_second_url_;
   GURL https_no_transform_url_;
   GURL https_hint_setup_url_;
@@ -390,6 +418,12 @@
     return ResourceLoadingNoFeaturesBrowserTest::https_url();
   }
 
+  const GURL& https_url_iframe() const override {
+    if (GetParam())
+      return ResourceLoadingNoFeaturesBrowserTest::https_url_iframe_preload();
+    return ResourceLoadingNoFeaturesBrowserTest::https_url_iframe();
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(ResourceLoadingHintsBrowserTest);
 };
@@ -473,6 +507,80 @@
   EXPECT_TRUE(resource_loading_hint_intervention_header_seen());
 }
 
+// The test loads https_url_iframe() which is whitelisted for resource blocking.
+// This webpage loads a woff2 resource whose loading should be blocked.
+// https_url_iframe() also loads https_url() in an iframe. https_url()
+// contains two resources whose URL match blocked patterns. However, since
+// https_url() is inside an iframe, loading of those two resources should not
+// be blocked.
+IN_PROC_BROWSER_TEST_P(
+    ResourceLoadingHintsBrowserTest,
+    DISABLE_ON_WIN_MAC_CHROMESOS(ResourceLoadingHintsHttpsWhitelisted_Iframe)) {
+  GURL url = https_url_iframe();
+
+  // Whitelist resource loading hints for https_url_iframe()'s' host.
+  SetDefaultOnlyResourceLoadingHints(https_url_iframe());
+
+  // Loading of these two resources should not be blocked since they are loaded
+  // by a webpage inside an iframe.
+  SetExpectedFooJpgRequest(true);
+  SetExpectedBarJpgRequest(true);
+
+  // Woff2 subresource is loaded by the https_url_iframe() and its loading
+  // should be blocked.
+  SetExpectedBazWoff2Request(false);
+  ResetResourceLoadingHintInterventionHeaderSeen();
+
+  base::HistogramTester histogram_tester;
+
+  ui_test_utils::NavigateToURL(browser(), url);
+
+  histogram_tester.ExpectBucketCount(
+      "Previews.EligibilityReason.ResourceLoadingHints",
+      static_cast<int>(previews::PreviewsEligibilityReason::ALLOWED), 1);
+  histogram_tester.ExpectTotalCount(
+      "Previews.PreviewShown.ResourceLoadingHints", 1);
+  histogram_tester.ExpectTotalCount(
+      "ResourceLoadingHints.CountBlockedSubresourcePatterns", 0);
+  EXPECT_TRUE(resource_loading_hint_intervention_header_seen());
+}
+
+// The test loads https_url_iframe() which is NOT whitelisted for resource
+// blocking. This webpage loads a woff2 resource whose loading should NOT be
+// blocked. https_url_iframe() also loads https_url() in an iframe. https_url()
+// contains two resources whose URL match blocked patterns. Loading of those two
+// resources should not be blocked either since https_url_iframe() is not
+// whitelisted.
+IN_PROC_BROWSER_TEST_P(ResourceLoadingHintsBrowserTest,
+                       DISABLE_ON_WIN_MAC_CHROMESOS(
+                           ResourceLoadingHintsHttpsNotWhitelisted_Iframe)) {
+  GURL url = https_url_iframe();
+
+  // Do not whitelist resource loading hints for https_url_iframe()'s' host.
+
+  SetExpectedFooJpgRequest(true);
+  SetExpectedBarJpgRequest(true);
+
+  // Woff2 subresource is loaded by the https_url_iframe(). The other two
+  // resources are loaded by the webpage inside the iframe. None of these
+  // resources should be blocked from loading.
+  SetExpectedBazWoff2Request(true);
+  ResetResourceLoadingHintInterventionHeaderSeen();
+
+  base::HistogramTester histogram_tester;
+
+  ui_test_utils::NavigateToURL(browser(), url);
+
+  histogram_tester.ExpectBucketCount(
+      "Previews.EligibilityReason.ResourceLoadingHints",
+      static_cast<int>(previews::PreviewsEligibilityReason::ALLOWED), 1);
+  histogram_tester.ExpectTotalCount(
+      "Previews.PreviewShown.ResourceLoadingHints", 0);
+  histogram_tester.ExpectTotalCount(
+      "ResourceLoadingHints.CountBlockedSubresourcePatterns", 0);
+  EXPECT_FALSE(resource_loading_hint_intervention_header_seen());
+}
+
 // Sets only the experimental hints, but does not enable the matching
 // experiment. Verifies that the hints are not used, and the resource loading is
 // not blocked.
diff --git a/chrome/browser/previews/resource_loading_hints/resource_loading_hints_web_contents_observer.cc b/chrome/browser/previews/resource_loading_hints/resource_loading_hints_web_contents_observer.cc
index e4bfecb..ffb3240 100644
--- a/chrome/browser/previews/resource_loading_hints/resource_loading_hints_web_contents_observer.cc
+++ b/chrome/browser/previews/resource_loading_hints/resource_loading_hints_web_contents_observer.cc
@@ -53,17 +53,10 @@
       ui_tab_helper->GetPreviewsUserData(navigation_handle);
 
   if (!previews_user_data ||
-      previews_user_data->committed_previews_type() !=
+      previews_user_data->CommittedPreviewsType() !=
           previews::PreviewsType::RESOURCE_LOADING_HINTS) {
     return;
   }
-  // The committed previews type can sometimes not be cleared out if there were
-  // no pre-commit previews allowed, so make sure we are not in the coin flip
-  // holdback before proceeding with sending resource loading hints.
-  if (previews_user_data->coin_flip_holdback_result() ==
-      previews::CoinFlipHoldbackResult::kHoldback) {
-    return;
-  }
 
   DCHECK(previews::params::IsResourceLoadingHintsEnabled());
   SendResourceLoadingHints(navigation_handle,
diff --git a/chrome/browser/printing/pdf_nup_converter_client.cc b/chrome/browser/printing/pdf_nup_converter_client.cc
index 60cbd7c..7f1bc0b 100644
--- a/chrome/browser/printing/pdf_nup_converter_client.cc
+++ b/chrome/browser/printing/pdf_nup_converter_client.cc
@@ -9,7 +9,7 @@
 #include "base/bind.h"
 #include "chrome/services/printing/public/mojom/constants.mojom.h"
 #include "chrome/services/printing/public/mojom/pdf_nup_converter.mojom.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/service_manager/public/cpp/connector.h"
 
 namespace printing {
@@ -77,13 +77,8 @@
 
 mojom::PdfNupConverterPtr
 PdfNupConverterClient::CreatePdfNupConverterRequest() {
-  if (!connector_) {
-    service_manager::mojom::ConnectorRequest connector_request;
-    connector_ = service_manager::Connector::Create(&connector_request);
-    content::ServiceManagerConnection::GetForProcess()
-        ->GetConnector()
-        ->BindConnectorRequest(std::move(connector_request));
-  }
+  if (!connector_)
+    connector_ = content::GetSystemConnector()->Clone();
   mojom::PdfNupConverterPtr pdf_nup_converter;
   connector_->BindInterface(printing::mojom::kChromePrintingServiceName,
                             &pdf_nup_converter);
diff --git a/chrome/browser/printing/pdf_to_emf_converter.cc b/chrome/browser/printing/pdf_to_emf_converter.cc
index 90f43cf3..6c5f6cf8 100644
--- a/chrome/browser/printing/pdf_to_emf_converter.cc
+++ b/chrome/browser/printing/pdf_to_emf_converter.cc
@@ -28,7 +28,7 @@
 #include "chrome/services/printing/public/mojom/pdf_to_emf_converter.mojom.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/child_process_data.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "printing/emf_win.h"
 #include "printing/pdf_render_settings.h"
@@ -272,10 +272,9 @@
 
   memcpy(memory.mapping.memory(), data->front(), data->size());
 
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(printing::mojom::kChromePrintingServiceName,
-                      &pdf_to_emf_converter_factory_);
+  content::GetSystemConnector()->BindInterface(
+      printing::mojom::kChromePrintingServiceName,
+      &pdf_to_emf_converter_factory_);
   pdf_to_emf_converter_factory_.set_connection_error_handler(base::BindOnce(
       &PdfConverterImpl::OnFailed, weak_ptr_factory_.GetWeakPtr(),
       std::string("Connection to PdfToEmfConverterFactory error.")));
diff --git a/chrome/browser/printing/pwg_raster_converter.cc b/chrome/browser/printing/pwg_raster_converter.cc
index fa1827f..67dd930 100644
--- a/chrome/browser/printing/pwg_raster_converter.cc
+++ b/chrome/browser/printing/pwg_raster_converter.cc
@@ -20,7 +20,7 @@
 #include "components/cloud_devices/common/printer_description.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/child_process_data.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 #include "printing/pdf_render_settings.h"
 #include "printing/pwg_raster_settings.h"
@@ -80,10 +80,9 @@
 
   callback_ = std::move(callback);
 
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(printing::mojom::kChromePrintingServiceName,
-                      &pdf_to_pwg_raster_converter_ptr_);
+  content::GetSystemConnector()->BindInterface(
+      printing::mojom::kChromePrintingServiceName,
+      &pdf_to_pwg_raster_converter_ptr_);
 
   pdf_to_pwg_raster_converter_ptr_.set_connection_error_handler(
       base::BindOnce(&PwgRasterConverterHelper::RunCallback, this,
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index a9dbd34..7d0a88d 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -146,7 +146,7 @@
 #include "ui/gfx/text_elider.h"
 #include "ui/strings/grit/ui_strings.h"
 
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#if BUILDFLAG(USE_RENDERER_SPELLCHECKER)
 #include "chrome/browser/renderer_context_menu/spelling_options_submenu_observer.h"
 #endif
 
diff --git a/chrome/browser/renderer_context_menu/spelling_menu_observer.cc b/chrome/browser/renderer_context_menu/spelling_menu_observer.cc
index 616642e6..3b0f45fc 100644
--- a/chrome/browser/renderer_context_menu/spelling_menu_observer.cc
+++ b/chrome/browser/renderer_context_menu/spelling_menu_observer.cc
@@ -26,6 +26,7 @@
 #include "components/spellcheck/browser/spellcheck_platform.h"
 #include "components/spellcheck/browser/spelling_service_client.h"
 #include "components/spellcheck/common/spellcheck_common.h"
+#include "components/spellcheck/common/spellcheck_features.h"
 #include "components/spellcheck/common/spellcheck_result.h"
 #include "components/spellcheck/spellcheck_buildflags.h"
 #include "content/public/browser/browser_thread.h"
@@ -267,7 +268,9 @@
       }
     }
 #if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
-    spellcheck_platform::AddWord(misspelled_word_);
+    if (spellcheck::UseBrowserSpellChecker()) {
+      spellcheck_platform::AddWord(misspelled_word_);
+    }
 #endif
   }
 
diff --git a/chrome/browser/renderer_host/pepper/pepper_flash_browser_host.cc b/chrome/browser/renderer_host/pepper/pepper_flash_browser_host.cc
index 9d249be9..016007f 100644
--- a/chrome/browser/renderer_host/pepper/pepper_flash_browser_host.cc
+++ b/chrome/browser/renderer_host/pepper/pepper_flash_browser_host.cc
@@ -16,7 +16,7 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_process_host.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "ipc/ipc_message_macros.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "ppapi/c/pp_errors.h"
@@ -39,7 +39,6 @@
 using content::BrowserPpapiHost;
 using content::BrowserThread;
 using content::RenderProcessHost;
-using content::ServiceManagerConnection;
 
 namespace {
 
@@ -60,11 +59,9 @@
 void PepperBindConnectorRequest(
     service_manager::mojom::ConnectorRequest connector_request) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK(ServiceManagerConnection::GetForProcess());
-
-  ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindConnectorRequest(std::move(connector_request));
+  DCHECK(content::GetSystemConnector());
+  content::GetSystemConnector()->BindConnectorRequest(
+      std::move(connector_request));
 }
 
 }  // namespace
@@ -184,9 +181,8 @@
 
   device::mojom::WakeLockRequest request = mojo::MakeRequest(&wake_lock_);
 
-  // Service manager connection might be not initialized in some testing
-  // contexts.
-  if (!ServiceManagerConnection::GetForProcess())
+  // The system Connector might be not initialized in some testing environments.
+  if (!content::GetSystemConnector())
     return wake_lock_.get();
 
   service_manager::mojom::ConnectorRequest connector_request;
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.cc b/chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.cc
index 00f289f..6b3b1d5 100644
--- a/chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.cc
+++ b/chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.cc
@@ -14,8 +14,8 @@
 #include "chrome/browser/resource_coordinator/tab_manager_features.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/service_manager_connection.h"
 #include "services/resource_coordinator/public/cpp/resource_coordinator_features.h"
 
 namespace resource_coordinator {
@@ -110,20 +110,16 @@
   LocalSiteCharacteristicsDataStoreFactory::EnableForTesting();
 
   // TODO(siggi): Can this die now?
-  content::ServiceManagerConnection::SetForProcess(
-      content::ServiceManagerConnection::Create(
-          mojo::MakeRequest(&service_),
-          base::CreateSingleThreadTaskRunnerWithTraits(
-              {content::BrowserThread::IO})));
-
+  service_manager::mojom::ConnectorRequest connector_request;
+  content::SetSystemConnectorForTesting(
+      service_manager::Connector::Create(&connector_request));
   ChromeRenderViewHostTestHarness::SetUp();
 }
 
 void ChromeTestHarnessWithLocalDB::TearDown() {
   performance_manager::PerformanceManager::Destroy(
       std::move(performance_manager_));
-
-  content::ServiceManagerConnection::DestroyForProcess();
+  content::SetSystemConnectorForTesting(nullptr);
   ChromeRenderViewHostTestHarness::TearDown();
 }
 
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h b/chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h
index e8c438a8..96676169 100644
--- a/chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h
+++ b/chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h
@@ -14,8 +14,6 @@
 #include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory.h"
 #include "chrome/browser/resource_coordinator/local_site_characteristics_database.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
-#include "content/public/common/service_manager_connection.h"
-#include "services/service_manager/public/mojom/service.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace content {
@@ -101,7 +99,6 @@
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
-  service_manager::mojom::ServicePtr service_;
   std::unique_ptr<performance_manager::PerformanceManager> performance_manager_;
 };
 
diff --git a/chrome/browser/resource_coordinator/tab_manager_features_unittest.cc b/chrome/browser/resource_coordinator/tab_manager_features_unittest.cc
index 582bab8..17939e9 100644
--- a/chrome/browser/resource_coordinator/tab_manager_features_unittest.cc
+++ b/chrome/browser/resource_coordinator/tab_manager_features_unittest.cc
@@ -7,7 +7,7 @@
 #include "base/macros.h"
 #include "base/metrics/field_trial.h"
 #include "base/strings/string_piece.h"
-#include "components/variations/variations_params_manager.h"
+#include "base/test/scoped_feature_list.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace resource_coordinator {
@@ -19,19 +19,17 @@
   // Enables the proactive tab discarding feature, and sets up the associated
   // variations parameter values.
   void EnableProactiveTabFreezeAndDiscard() {
-    std::set<std::string> features;
-    features.insert(features::kProactiveTabFreezeAndDiscard.name);
-    variations_manager_.SetVariationParamsWithFeatureAssociations(
-        "DummyTrial", params_, features);
+    scoped_feature_list_.Reset();
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        features::kProactiveTabFreezeAndDiscard, params_);
   }
 
   // Enables the site characteristics database feature, and sets up the
   // associated variations parameter values.
   void EnableSiteCharacteristicsDatabase() {
-    std::set<std::string> features;
-    features.insert(features::kSiteCharacteristicsDatabase.name);
-    variations_manager_.SetVariationParamsWithFeatureAssociations(
-        "DummyTrial", params_, features);
+    scoped_feature_list_.Reset();
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        features::kSiteCharacteristicsDatabase, params_);
   }
 
   void SetParam(base::StringPiece key, base::StringPiece value) {
@@ -162,8 +160,8 @@
   }
 
  private:
-  std::map<std::string, std::string> params_;
-  variations::testing::VariationParamsManager variations_manager_;
+  base::FieldTrialParams params_;
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 }  // namespace
diff --git a/chrome/browser/resources/bookmarks/dnd_manager.js b/chrome/browser/resources/bookmarks/dnd_manager.js
index 0c9bf741..4db582fcd 100644
--- a/chrome/browser/resources/bookmarks/dnd_manager.js
+++ b/chrome/browser/resources/bookmarks/dnd_manager.js
@@ -330,6 +330,9 @@
        * @private {!Object}
        */
       this.timerProxy_ = window;
+
+      /** @private {boolean} */
+      this.lastPointerWasTouch_ = false;
     }
 
     init() {
@@ -344,7 +347,8 @@
         'dragleave': this.onDragLeave_.bind(this),
         'drop': this.onDrop_.bind(this),
         'dragend': this.clearDragData_.bind(this),
-        // TODO(calamity): Add touch support.
+        'mousedown': this.onMouseDown_.bind(this),
+        'touchstart': this.onTouchStart_.bind(this),
       };
       for (const event in this.documentListeners_) {
         document.addEventListener(event, this.documentListeners_[event]);
@@ -407,9 +411,9 @@
       const dragNodeIndex = draggedNodes.indexOf(dragElement.itemId);
       assert(dragNodeIndex != -1);
 
-      // TODO(calamity): account for touch.
       chrome.bookmarkManagerPrivate.startDrag(
-          draggedNodes, dragNodeIndex, false);
+          draggedNodes, dragNodeIndex, this.lastPointerWasTouch_, e.clientX,
+          e.clientY);
     }
 
     /** @private */
@@ -496,6 +500,16 @@
       this.dropIndicator_.update(this.dropDestination_);
     }
 
+    /** @private */
+    onMouseDown_() {
+      this.lastPointerWasTouch_ = false;
+    }
+
+    /** @private */
+    onTouchStart_() {
+      this.lastPointerWasTouch_ = true;
+    }
+
     /**
      * @private
      * @param {DragData} dragData
diff --git a/chrome/browser/resources/bookmarks/item.js b/chrome/browser/resources/bookmarks/item.js
index 1b9ee64..e4d8147 100644
--- a/chrome/browser/resources/bookmarks/item.js
+++ b/chrome/browser/resources/bookmarks/item.js
@@ -37,6 +37,9 @@
 
     /** @private */
     isFolder_: Boolean,
+
+    /** @private */
+    lastTouchPoints_: Number,
   },
 
   hostAttributes: {
@@ -55,6 +58,7 @@
     'auxclick': 'onMiddleClick_',
     'mousedown': 'cancelMiddleMouseBehavior_',
     'mouseup': 'cancelMiddleMouseBehavior_',
+    'touchstart': 'onTouchStart_',
   },
 
   /** @override */
@@ -82,6 +86,14 @@
   onContextMenu_: function(e) {
     e.preventDefault();
     e.stopPropagation();
+
+    // Prevent context menu from appearing after a drag, but allow opening the
+    // context menu through 2 taps
+    if (e.sourceCapabilities && e.sourceCapabilities.firesTouchEvents &&
+        this.lastTouchPoints_ !== 2) {
+      return;
+    }
+
     this.focus();
     if (!this.isSelectedItem_) {
       this.selectThisItem_();
@@ -210,6 +222,14 @@
   },
 
   /**
+   * @param {TouchEvent} e
+   * @private
+   */
+  onTouchStart_: function(e) {
+    this.lastTouchPoints_ = e.touches.length;
+  },
+
+  /**
    * Prevent default middle-mouse behavior. On Windows, this prevents autoscroll
    * (during mousedown), and on Linux this prevents paste (during mouseup).
    * @param {MouseEvent} e
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs
index ed469a24..bf0f2fdb 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs
@@ -250,24 +250,44 @@
 });
 
 /** Tests that individual buttons are stops for move-by-word functionality. */
-TEST_F('ChromeVoxBackgroundTest', 'CaretNavigationTreatsButtonAsWord', function() {
+TEST_F('ChromeVoxBackgroundTest', 'CaretNavigationMoveThroughButtonByWord', function() {
   var mockFeedback = this.createMockFeedback();
   this.runWithLoadedTree(this.buttonDoc, function() {
     mockFeedback.expectSpeech('start');
-    mockFeedback.call(doCmd('nextWord'))
+    mockFeedback.call(doCmd('nextObject'))
         .expectSpeech('hello button one', 'Button');
+    mockFeedback.call(doCmd('previousWord'))
+        .expectSpeech('start');
+    mockFeedback.call(doCmd('nextWord'))
+        .expectSpeech('hello');
+    mockFeedback.call(doCmd('nextWord'))
+        .expectSpeech('button');
+    mockFeedback.call(doCmd('nextWord'))
+        .expectSpeech('one');
     mockFeedback.call(doCmd('nextWord'))
         .expectSpeech('cats');
     mockFeedback.call(doCmd('nextWord'))
-        .expectSpeech('hello button two', 'Button');
+        .expectSpeech('hello');
+    mockFeedback.call(doCmd('nextWord'))
+        .expectSpeech('button');
+    mockFeedback.call(doCmd('nextWord'))
+        .expectSpeech('two');
     mockFeedback.call(doCmd('nextWord'))
         .expectSpeech('end');
     mockFeedback.call(doCmd('previousWord'))
-        .expectSpeech('hello button two', 'Button');
+        .expectSpeech('two');
+    mockFeedback.call(doCmd('previousWord'))
+        .expectSpeech('button');
+    mockFeedback.call(doCmd('previousWord'))
+        .expectSpeech('hello');
     mockFeedback.call(doCmd('previousWord'))
         .expectSpeech('cats');
     mockFeedback.call(doCmd('previousWord'))
-        .expectSpeech('hello button one', 'Button');
+        .expectSpeech('one');
+    mockFeedback.call(doCmd('previousWord'))
+        .expectSpeech('button');
+    mockFeedback.call(doCmd('previousWord'))
+        .expectSpeech('hello');
     mockFeedback.replay();
   });
 });
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/cursors.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/cursors.js
index ce725dc..4e48d74 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/cursors.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/cursors.js
@@ -333,33 +333,41 @@
 
         switch (movement) {
           case Movement.BOUND:
+            var wordStarts, wordEnds;
             if (newNode.role == RoleType.INLINE_TEXT_BOX) {
-              var start, end;
-              for (var i = 0; i < newNode.wordStarts.length; i++) {
-                if (newIndex >= newNode.wordStarts[i] &&
-                    newIndex <= newNode.wordEnds[i]) {
-                  start = newNode.wordStarts[i];
-                  end = newNode.wordEnds[i];
-                  break;
-                }
-              }
-              if (goog.isDef(start) && goog.isDef(end))
-                newIndex = dir == Dir.FORWARD ? end : start;
+              wordStarts = newNode.wordStarts;
+              wordEnds = newNode.wordEnds;
             } else {
-              newIndex = cursors.NODE_INDEX;
+              wordStarts = newNode.nonInlineTextWordStarts;
+              wordEnds = newNode.nonInlineTextWordEnds;
             }
+            var start, end;
+            for (var i = 0; i < wordStarts.length; i++) {
+              if (newIndex >= wordStarts[i] && newIndex <= wordEnds[i]) {
+                start = wordStarts[i];
+                end = wordEnds[i];
+                break;
+              }
+            }
+            if (goog.isDef(start) && goog.isDef(end))
+              newIndex = dir == Dir.FORWARD ? end : start;
             break;
           case Movement.DIRECTIONAL:
+            var wordStarts, wordEnds;
             var start;
             if (newNode.role == RoleType.INLINE_TEXT_BOX) {
-              // Go to the next word stop in the same piece of text.
-              for (var i = 0; i < newNode.wordStarts.length; i++) {
-                if (newIndex >= newNode.wordStarts[i] &&
-                    newIndex <= newNode.wordEnds[i]) {
-                  var nextIndex = dir == Dir.FORWARD ? i + 1 : i - 1;
-                  start = newNode.wordStarts[nextIndex];
-                  break;
-                }
+              wordStarts = newNode.wordStarts;
+              wordEnds = newNode.wordEnds;
+            } else {
+              wordStarts = newNode.nonInlineTextWordStarts;
+              wordEnds = newNode.nonInlineTextWordEnds;
+            }
+            // Go to the next word stop in the same piece of text.
+            for (var i = 0; i < wordStarts.length; i++) {
+              if (newIndex >= wordStarts[i] && newIndex <= wordEnds[i]) {
+                var nextIndex = dir == Dir.FORWARD ? i + 1 : i - 1;
+                start = wordStarts[nextIndex];
+                break;
               }
             }
             if (goog.isDef(start)) {
@@ -374,16 +382,14 @@
                 newNode = AutomationUtil.findNextNode(
                     newNode, dir, AutomationPredicate.leafWithWordStop);
                 if (newNode) {
-                  if (newNode.role == RoleType.INLINE_TEXT_BOX) {
-                    var starts = newNode.wordStarts;
-                    if (starts.length) {
-                      newIndex = dir == Dir.BACKWARD ?
-                          starts[starts.length - 1] :
-                          starts[0];
-                    }
-                  } else {
-                    // For non-text nodes, move by word = by object.
-                    newIndex = cursors.NODE_INDEX;
+                  var starts;
+                  if (newNode.role == RoleType.INLINE_TEXT_BOX)
+                    starts = newNode.wordStarts;
+                  else
+                    starts = newNode.nonInlineTextWordStarts;
+                  if (starts.length) {
+                    newIndex = dir == Dir.BACKWARD ? starts[starts.length - 1] :
+                                                     starts[0];
                   }
                 }
               }
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/cursors_test.extjs b/chrome/browser/resources/chromeos/chromevox/cvox2/background/cursors_test.extjs
index 97d21f8..5882679 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/cursors_test.extjs
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/cursors_test.extjs
@@ -126,6 +126,11 @@
   multiInlineDoc: function() {/*!
     <p style='max-width: 5px'>start diff line</p>
     <p>end
+  */},
+
+  buttonAndInlineTextDoc: function() {/*!
+    <div>Inline text content</div>
+    <div role="button">Button example content</div>
   */}
 };
 
@@ -596,3 +601,35 @@
 
   });
 });
+
+TEST_F('ChromeVoxCursorsTest', 'MovementByWordThroughNonInlineText',
+  function() {this.runCursorMovesOnDocument(this.buttonAndInlineTextDoc,
+    [
+    // Move forward by word.
+    // 'text' start and end indices.
+    [WORD, DIRECTIONAL, FORWARD, {index: 7, value: 'Inline text content'}],
+    [WORD, BOUND, FORWARD, {index: 11, value: 'Inline text content'}],
+    // 'content' start and end incies.
+    [WORD, DIRECTIONAL, FORWARD, {index: 12, value: 'Inline text content'}],
+    [WORD, BOUND, FORWARD, {index: 19, value: 'Inline text content'}],
+    // 'Button' start and end indices.
+    [WORD, DIRECTIONAL, FORWARD, {index: 0, value: 'Button example content'}],
+    [WORD, BOUND, FORWARD, {index: 6, value: 'Button example content'}],
+    // 'example' start and end indices.
+    [WORD, DIRECTIONAL, FORWARD, {index: 7, value: 'Button example content'}],
+    [WORD, BOUND, FORWARD, {index: 14, value: 'Button example content'}],
+    // 'content' start index. Reached last word of last object.
+    [WORD, DIRECTIONAL, FORWARD, {index: 15, value: 'Button example content'}],
+    [WORD, DIRECTIONAL, FORWARD, {index: 15, value: 'Button example content'}],
+
+    // Move backward by word.
+    // Only test start indices.
+    [WORD, DIRECTIONAL, BACKWARD, {index: 7, value: 'Button example content'}],
+    [WORD, DIRECTIONAL, BACKWARD, {index: 0, value: 'Button example content'}],
+    [WORD, DIRECTIONAL, BACKWARD, {index: 12, value: 'Inline text content'}],
+    [WORD, DIRECTIONAL, BACKWARD, {index: 7, value: 'Inline text content'}],
+    [WORD, DIRECTIONAL, BACKWARD, {index: 0, value: 'Inline text content'}],
+    // Reached first word of first object.
+    [WORD, DIRECTIONAL, BACKWARD, {index: 0, value: 'Inline text content'}]
+    ]);
+});
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_page.html b/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_page.html
index 4d101f0..f41b1bf 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_page.html
@@ -140,7 +140,7 @@
         display: none;
       }
 
-      .restart-button {
+      #restartButton {
         margin-inline-start: var(--settings-controlled-by-spacing);
       }
     </style>
@@ -177,8 +177,9 @@
                   </div>
                 </div>
                 <template is="dom-if" if="[[isRestartRequired_(
-                        item.language.code, languages.prospectiveUILanguage)]]">
-                  <cr-button class="restart-button" on-click="onRestartTap_">
+                    item.language.code, languages.prospectiveUILanguage)]]"
+                    restamp>
+                  <cr-button id="restartButton" on-click="onRestartTap_">
                     $i18n{restart}
                   </cr-button>
                 </template>
@@ -240,8 +241,7 @@
         </iron-collapse>
         <cr-lazy-render id="menu">
           <template>
-            <cr-action-menu
-                class="complex">
+            <cr-action-menu class="complex" on-close="onCloseMenu_">
               <cr-checkbox id="uiLanguageItem"
                   class="dropdown-item"
                   checked="[[isProspectiveUILanguage_(
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_page.js b/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_page.js
index fe8484f..34ea3f1f 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_page.js
@@ -85,6 +85,9 @@
     },
   },
 
+  /** @private {boolean} */
+  isChangeInProgress_: false,
+
   /**
    * Stamps and opens the Add Languages dialog, registering a listener to
    * disable the dialog's dom-if again on close.
@@ -239,6 +242,20 @@
         this.languageHelper.requiresRestart();
   },
 
+  /** @private */
+  onCloseMenu_() {
+    if (!this.isChangeInProgress_) {
+      return;
+    }
+    Polymer.dom.flush();
+    this.isChangeInProgress_ = false;
+    const restartButton = this.$$('#restartButton');
+    if (!restartButton) {
+      return;
+    }
+    cr.ui.focusWithoutInk(restartButton);
+  },
+
   /**
    * @param {!LanguageState} languageState
    * @param {string} prospectiveUILanguage The chosen UI language.
@@ -286,9 +303,9 @@
     // We don't support unchecking this checkbox. TODO(michaelpg): Ask for a
     // simpler widget.
     assert(e.target.checked);
+    this.isChangeInProgress_ = true;
     this.languageHelper.setProspectiveUILanguage(
         this.detailLanguage_.language.code);
-
     this.closeMenuSoon_();
   },
 
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.html b/chrome/browser/resources/settings/languages_page/languages_page.html
index c220332e..c36a93d 100644
--- a/chrome/browser/resources/settings/languages_page/languages_page.html
+++ b/chrome/browser/resources/settings/languages_page/languages_page.html
@@ -171,7 +171,7 @@
         display: none;
       }
 
-      .restart-button {
+      #restartButton {
         margin-inline-start: var(--settings-controlled-by-spacing);
       }
 
@@ -230,8 +230,9 @@
                 </div>
 <if expr="chromeos or is_win">
                 <template is="dom-if" if="[[isRestartRequired_(
-                        item.language.code, languages.prospectiveUILanguage)]]">
-                  <cr-button class="restart-button"
+                    item.language.code, languages.prospectiveUILanguage)]]"
+                    restamp>
+                  <cr-button id="restartButton"
                       hidden="[[!pageVisibility.uiDisplayedInThisLanguage]]"
                       on-click="onRestartTap_">
                     $i18n{restart}
@@ -402,7 +403,7 @@
 </if> <!-- _google_chrome or not is_macosx -->
         <cr-lazy-render id="menu">
           <template>
-            <cr-action-menu
+            <cr-action-menu on-close="onCloseMenu_"
                 class$="[[getMenuClass_(prefs.translate.enabled.value)]]">
 <if expr="chromeos or is_win">
               <cr-checkbox id="uiLanguageItem"
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.js b/chrome/browser/resources/settings/languages_page/languages_page.js
index b1dc3d7..3bf2ad24 100644
--- a/chrome/browser/resources/settings/languages_page/languages_page.js
+++ b/chrome/browser/resources/settings/languages_page/languages_page.js
@@ -125,7 +125,12 @@
         'languages.forcedSpellCheckLanguages.*)',
     'updateSpellcheckEnabled_(prefs.browser.enable_spellchecking.*)',
   ],
+  // </if>
 
+  /** @private {boolean} */
+  isChangeInProgress_: false,
+
+  // <if expr="not is_macosx">
   /**
    * Checks if there are any errors downloading the spell check dictionary. This
    * is used for showing/hiding error messages, spell check toggle and retry.
@@ -331,6 +336,20 @@
         this.languageHelper.requiresRestart();
   },
 
+  /** @private */
+  onCloseMenu_() {
+    if (!this.isChangeInProgress_) {
+      return;
+    }
+    Polymer.dom.flush();
+    this.isChangeInProgress_ = false;
+    const restartButton = this.$$('#restartButton');
+    if (!restartButton) {
+      return;
+    }
+    cr.ui.focusWithoutInk(restartButton);
+  },
+
   /**
    * @param {!LanguageState} languageState
    * @param {string} prospectiveUILanguage The chosen UI language.
@@ -378,9 +397,9 @@
     // We don't support unchecking this checkbox. TODO(michaelpg): Ask for a
     // simpler widget.
     assert(e.target.checked);
+    this.isChangeInProgress_ = true;
     this.languageHelper.setProspectiveUILanguage(
         this.detailLanguage_.language.code);
-
     this.closeMenuSoon_();
   },
   // </if>
diff --git a/chrome/browser/resources/settings/people_page/people_page.html b/chrome/browser/resources/settings/people_page/people_page.html
index 076be7e3..c73ed57 100644
--- a/chrome/browser/resources/settings/people_page/people_page.html
+++ b/chrome/browser/resources/settings/people_page/people_page.html
@@ -332,26 +332,26 @@
       </template>
 
 <if expr="chromeos">
-      <template is="dom-if" if="[[!pageVisibility.people.lockScreen]]"
-          route-path="/lockScreen">
-        <settings-subpage
-            page-title="[[selectLockScreenTitleString(hasPinLogin)]]"
-            associated-control="[[$$('#lock-screen-subpage-trigger')]]">
-          <settings-lock-screen
-              prefs="{{prefs}}" auth-token="{{authToken_}}">
-          </settings-lock-screen>
-        </settings-subpage>
-      </template>
-      <template is="dom-if" if="[[fingerprintUnlockEnabled_
-          && !pageVisibility.people.lockScreen]]">
-        <template is="dom-if" route-path="/lockScreen/fingerprint" no-search>
-          <settings-subpage page-title="$i18n{lockScreenFingerprintTitle}">
-            <settings-fingerprint-list auth-token="[[authToken_]]">
-            </settings-fingerprint-list>
+      <template is="dom-if" if="[[pageVisibility.people.lockScreen]]">
+        <template is="dom-if" route-path="/lockScreen">
+          <settings-subpage
+              page-title="[[selectLockScreenTitleString(hasPinLogin)]]"
+              associated-control="[[$$('#lock-screen-subpage-trigger')]]">
+            <settings-lock-screen
+                prefs="{{prefs}}" auth-token="{{authToken_}}">
+            </settings-lock-screen>
           </settings-subpage>
         </template>
+        <template is="dom-if" if="[[fingerprintUnlockEnabled_]]">
+          <template is="dom-if" route-path="/lockScreen/fingerprint" no-search>
+            <settings-subpage page-title="$i18n{lockScreenFingerprintTitle}">
+              <settings-fingerprint-list auth-token="[[authToken_]]">
+              </settings-fingerprint-list>
+            </settings-subpage>
+          </template>
+        </template>
       </template>
-      <template is="dom-if" if="[!pageVisibility.people.manageUsers]]">
+      <template is="dom-if" if="[[pageVisibility.people.manageUsers]]">
         <template is="dom-if" route-path="/accounts">
           <settings-subpage
               associated-control=
diff --git a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_elements.html b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_elements.html
index b46c8ca..f7ed42a8 100644
--- a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_elements.html
+++ b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_elements.html
@@ -2,6 +2,7 @@
 
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="cups_printer_dialog_util.html">
 <link rel="import" href="cups_printer_shared_css.html">
 <link rel="import" href="cups_printers_browser_proxy.html">
 
@@ -16,7 +17,7 @@
       <array-selector id="arraySelector" items="[[printers]]"
           selected="{{selectedPrinter}}">
       </array-selector>
-      <template is="dom-repeat" items="[[printers]]">
+      <template is="dom-repeat" items="[[printers]]" sort="sort_">
         <button class="list-item" on-click="onSelect_">
           [[item.printerName]]
         </button>
diff --git a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_elements.js b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_elements.js
index d27c65f5..724c9cc9 100644
--- a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_elements.js
+++ b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_elements.js
@@ -27,6 +27,16 @@
   onSelect_: function(event) {
     this.selectedPrinter = event.model.item;
   },
+
+  /**
+   * @param {!CupsPrinterInfo} first
+   * @param {!CupsPrinterInfo} second
+   * @return {number} The result of the comparison.
+   * @private
+   */
+  sort_: function(first, second) {
+    return settings.printing.alphabeticalSort(first, second);
+  },
 });
 
 /** 'add-printer-dialog' is the template of the Add Printer dialog. */
diff --git a/chrome/browser/resources/settings/printing_page/cups_printer_dialog_util.js b/chrome/browser/resources/settings/printing_page/cups_printer_dialog_util.js
index d448aa6..7ebb5a6c 100644
--- a/chrome/browser/resources/settings/printing_page/cups_printer_dialog_util.js
+++ b/chrome/browser/resources/settings/printing_page/cups_printer_dialog_util.js
@@ -96,10 +96,23 @@
     return '';
   }
 
+  /**
+   * A function used for sorting printer names based on the current locale's
+   * collation order.
+   * @param {!CupsPrinterInfo} first
+   * @param {!CupsPrinterInfo} second
+   * @return {number} The result of the comparison.
+   */
+  function alphabeticalSort(first, second) {
+    return first.printerName.toLocaleLowerCase().localeCompare(
+        second.printerName.toLocaleLowerCase());
+  }
+
   return {
     isNetworkProtocol: isNetworkProtocol,
     isNameAndAddressValid: isNameAndAddressValid,
     isPPDInfoValid: isPPDInfoValid,
     getBaseName: getBaseName,
+    alphabeticalSort: alphabeticalSort,
   };
 });
diff --git a/chrome/browser/resources/settings/printing_page/cups_printers_list.html b/chrome/browser/resources/settings/printing_page/cups_printers_list.html
index c6f1c093..c0e8208c6 100644
--- a/chrome/browser/resources/settings/printing_page/cups_printers_list.html
+++ b/chrome/browser/resources/settings/printing_page/cups_printers_list.html
@@ -3,6 +3,7 @@
 <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="cups_printer_dialog_util.html">
 <link rel="import" href="cups_printers_browser_proxy.html">
 <link rel="import" href="../settings_shared_css.html">
 
@@ -24,7 +25,8 @@
     </cr-action-menu>
     <div class="list-frame vertical-list">
       <template is="dom-repeat" items="[[printers]]"
-          filter="[[filterPrinter_(searchTerm)]]">
+          filter="[[filterPrinter_(searchTerm)]]"
+          sort="sort_">
         <div class="list-item">
           <div class="printer-name text-elide">[[item.printerName]]</div>
           <!--TODO(xdai): Add icon for enterprise CUPS printer. -->
diff --git a/chrome/browser/resources/settings/printing_page/cups_printers_list.js b/chrome/browser/resources/settings/printing_page/cups_printers_list.js
index 0e266c7f..df422ff 100644
--- a/chrome/browser/resources/settings/printing_page/cups_printers_list.js
+++ b/chrome/browser/resources/settings/printing_page/cups_printers_list.js
@@ -93,4 +93,14 @@
           searchTerm.toLowerCase());
     };
   },
+
+  /**
+   * @param {!CupsPrinterInfo} first
+   * @param {!CupsPrinterInfo} second
+   * @return {number} The result of the comparison.
+   * @private
+   */
+  sort_: function(first, second) {
+    return settings.printing.alphabeticalSort(first, second);
+  },
 });
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc b/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
index 570d7ca..845adc36 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
@@ -33,7 +33,6 @@
 #include "components/strings/grit/components_strings.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "components/sync_user_events/fake_user_event_service.h"
-#include "components/variations/variations_params_manager.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/mock_navigation_handle.h"
diff --git a/chrome/browser/safe_browsing/download_protection/file_analyzer.cc b/chrome/browser/safe_browsing/download_protection/file_analyzer.cc
index d41df53..4da27ff3 100644
--- a/chrome/browser/safe_browsing/download_protection/file_analyzer.cc
+++ b/chrome/browser/safe_browsing/download_protection/file_analyzer.cc
@@ -15,7 +15,7 @@
 #include "chrome/common/safe_browsing/file_type_policies.h"
 #include "components/safe_browsing/features.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 
 namespace safe_browsing {
 
@@ -151,7 +151,7 @@
       tmp_path_,
       base::BindRepeating(&FileAnalyzer::OnZipAnalysisFinished,
                           weakptr_factory_.GetWeakPtr()),
-      content::ServiceManagerConnection::GetForProcess()->GetConnector());
+      content::GetSystemConnector());
   zip_analyzer_->Start();
 }
 
@@ -224,7 +224,7 @@
       tmp_path_,
       base::BindRepeating(&FileAnalyzer::OnRarAnalysisFinished,
                           weakptr_factory_.GetWeakPtr()),
-      content::ServiceManagerConnection::GetForProcess()->GetConnector());
+      content::GetSystemConnector());
   rar_analyzer_->Start();
 }
 
@@ -287,7 +287,7 @@
       FileTypePolicies::GetInstance()->GetMaxFileSizeToAnalyze("dmg"),
       base::BindRepeating(&FileAnalyzer::OnDmgAnalysisFinished,
                           weakptr_factory_.GetWeakPtr()),
-      content::ServiceManagerConnection::GetForProcess()->GetConnector());
+      content::GetSystemConnector());
   dmg_analyzer_->Start();
   dmg_analysis_start_time_ = base::TimeTicks::Now();
 }
diff --git a/chrome/browser/safe_json_parser_browsertest.cc b/chrome/browser/safe_json_parser_browsertest.cc
index 8c04612..0af13b17 100644
--- a/chrome/browser/safe_json_parser_browsertest.cc
+++ b/chrome/browser/safe_json_parser_browsertest.cc
@@ -14,7 +14,7 @@
 #include "base/values.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/test_service_manager_listener.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_utils.h"
 #include "services/data_decoder/public/cpp/safe_json_parser.h"
@@ -78,14 +78,13 @@
     }
 
     if (batch_id) {
-      SafeJsonParser::ParseBatch(
-          content::ServiceManagerConnection::GetForProcess()->GetConnector(),
-          json, std::move(success_callback), std::move(error_callback),
-          *batch_id);
+      SafeJsonParser::ParseBatch(content::GetSystemConnector(), json,
+                                 std::move(success_callback),
+                                 std::move(error_callback), *batch_id);
     } else {
-      SafeJsonParser::Parse(
-          content::ServiceManagerConnection::GetForProcess()->GetConnector(),
-          json, std::move(success_callback), std::move(error_callback));
+      SafeJsonParser::Parse(content::GetSystemConnector(), json,
+                            std::move(success_callback),
+                            std::move(error_callback));
     }
 
     message_loop_runner_->Run();
diff --git a/chrome/browser/safe_xml_parser_browsertest.cc b/chrome/browser/safe_xml_parser_browsertest.cc
index 039c1a0..1ad4bfb78 100644
--- a/chrome/browser/safe_xml_parser_browsertest.cc
+++ b/chrome/browser/safe_xml_parser_browsertest.cc
@@ -12,7 +12,7 @@
 #include "base/values.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/test_service_manager_listener.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/test/test_utils.h"
 #include "services/data_decoder/public/cpp/safe_xml_parser.h"
 #include "services/data_decoder/public/mojom/constants.mojom.h"
@@ -60,8 +60,7 @@
     }
 
     data_decoder::ParseXml(
-        content::ServiceManagerConnection::GetForProcess()->GetConnector(),
-        xml.as_string(),
+        content::GetSystemConnector(), xml.as_string(),
         base::BindOnce(&SafeXmlParserTest::XmlParsingDone,
                        base::Unretained(this), run_loop.QuitClosure(),
                        std::move(expected_value)),
diff --git a/chrome/browser/search/one_google_bar/one_google_bar_loader_impl.cc b/chrome/browser/search/one_google_bar/one_google_bar_loader_impl.cc
index 216ca39..0861281 100644
--- a/chrome/browser/search/one_google_bar/one_google_bar_loader_impl.cc
+++ b/chrome/browser/search/one_google_bar/one_google_bar_loader_impl.cc
@@ -20,7 +20,7 @@
 #include "components/signin/core/browser/chrome_connected_header_helper.h"
 #include "components/signin/core/browser/signin_header_helper.h"
 #include "components/variations/net/variations_http_headers.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "net/base/load_flags.h"
 #include "net/base/url_util.h"
 #include "net/http/http_status_code.h"
@@ -334,8 +334,7 @@
   }
 
   data_decoder::SafeJsonParser::Parse(
-      content::ServiceManagerConnection::GetForProcess()->GetConnector(),
-      response,
+      content::GetSystemConnector(), response,
       base::BindOnce(&OneGoogleBarLoaderImpl::JsonParsed,
                      weak_ptr_factory_.GetWeakPtr()),
       base::BindOnce(&OneGoogleBarLoaderImpl::JsonParseFailed,
diff --git a/chrome/browser/search/promos/promo_service.cc b/chrome/browser/search/promos/promo_service.cc
index 1ec7488a..7e84010 100644
--- a/chrome/browser/search/promos/promo_service.cc
+++ b/chrome/browser/search/promos/promo_service.cc
@@ -12,7 +12,7 @@
 #include "chrome/common/webui_url_constants.h"
 #include "components/google/core/browser/google_url_tracker.h"
 #include "components/google/core/common/google_util.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "net/base/load_flags.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/data_decoder/public/cpp/safe_json_parser.h"
@@ -159,8 +159,7 @@
   }
 
   data_decoder::SafeJsonParser::Parse(
-      content::ServiceManagerConnection::GetForProcess()->GetConnector(),
-      response,
+      content::GetSystemConnector(), response,
       base::BindOnce(&PromoService::OnJsonParsed,
                      weak_ptr_factory_.GetWeakPtr()),
       base::BindOnce(&PromoService::OnJsonParseFailed,
diff --git a/chrome/browser/search/search_suggest/search_suggest_loader_impl.cc b/chrome/browser/search/search_suggest/search_suggest_loader_impl.cc
index e7ca4dc..3f629833 100644
--- a/chrome/browser/search/search_suggest/search_suggest_loader_impl.cc
+++ b/chrome/browser/search/search_suggest/search_suggest_loader_impl.cc
@@ -20,7 +20,7 @@
 #include "components/signin/core/browser/chrome_connected_header_helper.h"
 #include "components/signin/core/browser/signin_header_helper.h"
 #include "components/variations/net/variations_http_headers.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "net/base/load_flags.h"
 #include "net/base/url_util.h"
 #include "net/http/http_status_code.h"
@@ -269,8 +269,7 @@
   }
 
   data_decoder::SafeJsonParser::Parse(
-      content::ServiceManagerConnection::GetForProcess()->GetConnector(),
-      response,
+      content::GetSystemConnector(), response,
       base::BindOnce(&SearchSuggestLoaderImpl::JsonParsed,
                      weak_ptr_factory_.GetWeakPtr()),
       base::BindOnce(&SearchSuggestLoaderImpl::JsonParseFailed,
diff --git a/chrome/browser/serial/serial_chooser_context.cc b/chrome/browser/serial/serial_chooser_context.cc
index 348995ed5..5f0ac95 100644
--- a/chrome/browser/serial/serial_chooser_context.cc
+++ b/chrome/browser/serial/serial_chooser_context.cc
@@ -9,7 +9,7 @@
 #include "base/base64.h"
 #include "base/values.h"
 #include "chrome/browser/profiles/profile.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 
@@ -188,9 +188,8 @@
     return;
 
   device::mojom::SerialPortManagerPtr manager;
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(device::mojom::kServiceName, mojo::MakeRequest(&manager));
+  content::GetSystemConnector()->BindInterface(device::mojom::kServiceName,
+                                               mojo::MakeRequest(&manager));
   SetUpPortManagerConnection(std::move(manager));
 }
 
diff --git a/chrome/browser/services_unittest.cc b/chrome/browser/services_unittest.cc
index 96d723b..2807bd6 100644
--- a/chrome/browser/services_unittest.cc
+++ b/chrome/browser/services_unittest.cc
@@ -11,7 +11,7 @@
 #include "components/services/patch/public/interfaces/file_patcher.mojom.h"
 #include "components/services/unzip/public/interfaces/constants.mojom.h"
 #include "components/services/unzip/public/interfaces/unzipper.mojom.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_utils.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -24,10 +24,6 @@
   ServicesTest()
       : thread_bundle_(content::TestBrowserThreadBundle::MainThreadType::IO) {}
 
-  ~ServicesTest() override {
-    content::ServiceManagerConnection::DestroyForProcess();
-  }
-
   template <typename Interface>
   bool CanAccessInterfaceFromBrowser(const std::string& service_name) {
     mojo::InterfacePtr<Interface> interface;
@@ -46,7 +42,7 @@
 
  private:
   service_manager::Connector* connector() {
-    return content::ServiceManagerConnection::GetForProcess()->GetConnector();
+    return content::GetSystemConnector();
   }
 
   content::TestBrowserThreadBundle thread_bundle_;
diff --git a/chrome/browser/sessions/tab_loader_unittest.cc b/chrome/browser/sessions/tab_loader_unittest.cc
index 4f79c90..1dd4a9a 100644
--- a/chrome/browser/sessions/tab_loader_unittest.cc
+++ b/chrome/browser/sessions/tab_loader_unittest.cc
@@ -15,7 +15,6 @@
 #include "chrome/browser/sessions/session_restore_test_utils.h"
 #include "chrome/browser/sessions/tab_loader_tester.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/variations/variations_params_manager.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/shell_integration_win.cc b/chrome/browser/shell_integration_win.cc
index 8844ee4..74b5b38 100644
--- a/chrome/browser/shell_integration_win.cc
+++ b/chrome/browser/shell_integration_win.cc
@@ -54,7 +54,6 @@
 #include "chrome/services/util_win/public/mojom/constants.mojom.h"
 #include "chrome/services/util_win/public/mojom/util_win.mojom.h"
 #include "components/variations/variations_associated_data.h"
-#include "content/public/common/service_manager_connection.h"
 #include "services/service_manager/public/cpp/connector.h"
 
 namespace shell_integration {
@@ -471,9 +470,7 @@
   void OnIsPinnedToTaskbarResult(bool succeeded, bool is_pinned_to_taskbar);
 
   chrome::mojom::UtilWinPtr util_win_ptr_;
-  // The connector used to retrieve the Patch service. We can't simply use
-  // content::ServiceManagerConnection::GetForProcess()->GetConnector() as this
-  // is called on a background thread.
+  // The connector used to retrieve the Patch service.
   std::unique_ptr<service_manager::Connector> connector_;
 
   ErrorCallback error_callback_;
diff --git a/chrome/browser/site_isolation/chrome_site_per_process_browsertest.cc b/chrome/browser/site_isolation/chrome_site_per_process_browsertest.cc
index d4894c4..bea9c25 100644
--- a/chrome/browser/site_isolation/chrome_site_per_process_browsertest.cc
+++ b/chrome/browser/site_isolation/chrome_site_per_process_browsertest.cc
@@ -927,7 +927,7 @@
   void RequestDictionary() override {}
   void NotifyChecked(const base::string16& word, bool misspelled) override {}
 
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#if BUILDFLAG(USE_RENDERER_SPELLCHECKER)
   void CallSpellingService(const base::string16& text,
                            CallSpellingServiceCallback callback) override {
     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
diff --git a/chrome/browser/spellchecker/spell_check_host_chrome_impl.cc b/chrome/browser/spellchecker/spell_check_host_chrome_impl.cc
index 0832417a9..afd0999 100644
--- a/chrome/browser/spellchecker/spell_check_host_chrome_impl.cc
+++ b/chrome/browser/spellchecker/spell_check_host_chrome_impl.cc
@@ -10,20 +10,20 @@
 #include "chrome/browser/spellchecker/spellcheck_factory.h"
 #include "chrome/browser/spellchecker/spellcheck_service.h"
 #include "components/spellcheck/browser/spellcheck_host_metrics.h"
-#include "components/spellcheck/common/spellcheck_result.h"
+#include "components/spellcheck/browser/spellcheck_platform.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 
-#if !defined(OS_MACOSX)
-// Mac needs different constructor and destructor for Mac-only members.
+#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#include "chrome/browser/spellchecker/spelling_request.h"
+#endif
 
 SpellCheckHostChromeImpl::SpellCheckHostChromeImpl(
     const service_manager::Identity& renderer_identity)
     : renderer_identity_(renderer_identity), weak_factory_(this) {}
 
 SpellCheckHostChromeImpl::~SpellCheckHostChromeImpl() = default;
-#endif
 
 // static
 void SpellCheckHostChromeImpl::Create(
@@ -64,7 +64,7 @@
     spellcheck->GetMetrics()->RecordCheckedWordStats(word, misspelled);
 }
 
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#if BUILDFLAG(USE_RENDERER_SPELLCHECKER)
 void SpellCheckHostChromeImpl::CallSpellingService(
     const base::string16& text,
     CallSpellingServiceCallback callback) {
@@ -123,7 +123,74 @@
 
   return results;
 }
-#endif  // !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#endif  // BUILDFLAG(USE_RENDERER_SPELLCHECKER)
+
+#if defined(OS_MACOSX) || defined(OS_WIN)
+
+void SpellCheckHostChromeImpl::CheckSpelling(const base::string16& word,
+                                             int route_id,
+                                             CheckSpellingCallback callback) {
+  bool correct = spellcheck_platform::CheckSpelling(word, route_id);
+  std::move(callback).Run(correct);
+}
+
+void SpellCheckHostChromeImpl::FillSuggestionList(
+    const base::string16& word,
+    FillSuggestionListCallback callback) {
+  std::vector<base::string16> suggestions;
+  spellcheck_platform::FillSuggestionList(word, &suggestions);
+  std::move(callback).Run(suggestions);
+}
+
+void SpellCheckHostChromeImpl::RequestTextCheck(
+    const base::string16& text,
+    int route_id,
+    RequestTextCheckCallback callback) {
+  DCHECK(!text.empty());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  // Initialize the spellcheck service if needed. The service will send the
+  // language code for text breaking to the renderer. (Text breaking is required
+  // for the context menu to show spelling suggestions.) Initialization must
+  // happen on UI thread.
+  GetSpellcheckService();
+
+  // |SpellingRequest| self-destructs on completion.
+  // OK to store unretained |this| in a |SpellingRequest| owned by |this|.
+  requests_.insert(std::make_unique<SpellingRequest>(
+      &client_, text, renderer_identity_, route_id, std::move(callback),
+      base::BindOnce(&SpellCheckHostChromeImpl::OnRequestFinished,
+                     base::Unretained(this))));
+}
+
+void SpellCheckHostChromeImpl::OnRequestFinished(SpellingRequest* request) {
+  auto iterator = requests_.find(request);
+  requests_.erase(iterator);
+}
+
+// static
+void SpellCheckHostChromeImpl::CombineResultsForTesting(
+    std::vector<SpellCheckResult>* remote_results,
+    const std::vector<SpellCheckResult>& local_results) {
+  SpellingRequest::CombineResults(remote_results, local_results);
+}
+#endif  // defined(OS_MACOSX) || defined(OS_WIN)
+
+#if defined(OS_MACOSX)
+int SpellCheckHostChromeImpl::ToDocumentTag(int route_id) {
+  if (!tag_map_.count(route_id))
+    tag_map_[route_id] = spellcheck_platform::GetDocumentTag();
+  return tag_map_[route_id];
+}
+
+// TODO(groby): We are currently not notified of retired tags. We need
+// to track destruction of RenderViewHosts on the browser process side
+// to update our mappings when a document goes away.
+void SpellCheckHostChromeImpl::RetireDocumentTag(int route_id) {
+  spellcheck_platform::CloseDocumentWithTag(ToDocumentTag(route_id));
+  tag_map_.erase(route_id);
+}
+#endif  // defined(OS_MACOSX)
 
 SpellcheckService* SpellCheckHostChromeImpl::GetSpellcheckService() const {
   return SpellcheckServiceFactory::GetForRenderer(renderer_identity_);
diff --git a/chrome/browser/spellchecker/spell_check_host_chrome_impl.h b/chrome/browser/spellchecker/spell_check_host_chrome_impl.h
index be996ad2..f5ce9f1 100644
--- a/chrome/browser/spellchecker/spell_check_host_chrome_impl.h
+++ b/chrome/browser/spellchecker/spell_check_host_chrome_impl.h
@@ -35,7 +35,7 @@
   void RequestDictionary() override;
   void NotifyChecked(const base::string16& word, bool misspelled) override;
 
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#if BUILDFLAG(USE_RENDERER_SPELLCHECKER)
   void CallSpellingService(const base::string16& text,
                            CallSpellingServiceCallback callback) override;
 
@@ -55,9 +55,9 @@
       const std::vector<SpellCheckResult>& service_results);
 #endif
 
-#if defined(OS_MACOSX)
-  // Non-Mac (i.e., Android) implementations of the following APIs are in the
-  // base class SpellCheckHostImpl.
+#if defined(OS_MACOSX) || defined(OS_WIN)
+  // Non-Mac and non-Win(i.e., Android) implementations of the following APIs
+  // are in the base class SpellCheckHostImpl.
   void CheckSpelling(const base::string16& word,
                      int route_id,
                      CheckSpellingCallback callback) override;
@@ -75,13 +75,15 @@
       std::vector<SpellCheckResult>* remote_results,
       const std::vector<SpellCheckResult>& local_results);
 
-  int ToDocumentTag(int route_id);
-  void RetireDocumentTag(int route_id);
-  std::map<int, int> tag_map_;
-
   // All pending requests.
   std::set<std::unique_ptr<SpellingRequest>, base::UniquePtrComparator>
       requests_;
+#endif  // defined(OS_MACOSX) || defined(OS_WIN)
+
+#if defined(OS_MACOSX)
+  int ToDocumentTag(int route_id);
+  void RetireDocumentTag(int route_id);
+  std::map<int, int> tag_map_;
 #endif  // defined(OS_MACOSX)
 
   // Returns the SpellcheckService of our |render_process_id_|. The return
diff --git a/chrome/browser/spellchecker/spell_check_host_chrome_impl_mac.cc b/chrome/browser/spellchecker/spell_check_host_chrome_impl_mac.cc
deleted file mode 100644
index 6ab03af..0000000
--- a/chrome/browser/spellchecker/spell_check_host_chrome_impl_mac.cc
+++ /dev/null
@@ -1,272 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/spellchecker/spell_check_host_chrome_impl.h"
-
-#include "base/barrier_closure.h"
-#include "base/bind.h"
-#include "base/task/post_task.h"
-#include "chrome/browser/spellchecker/spellcheck_factory.h"
-#include "chrome/browser/spellchecker/spellcheck_service.h"
-#include "components/spellcheck/browser/spellcheck_platform.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/render_process_host.h"
-#include "services/service_manager/public/cpp/identity.h"
-
-using content::BrowserThread;
-using content::BrowserContext;
-
-namespace {
-
-bool CompareLocation(const SpellCheckResult& r1, const SpellCheckResult& r2) {
-  return r1.location < r2.location;
-}
-
-// Adjusts remote_results by examining local_results. Any result that's both
-// local and remote stays type SPELLING, all others are flagged GRAMMAR.
-// (This is needed to force gray underline for remote-only results.)
-void CombineResults(std::vector<SpellCheckResult>* remote_results,
-                    const std::vector<SpellCheckResult>& local_results) {
-  std::vector<SpellCheckResult>::const_iterator local_iter(
-      local_results.begin());
-  std::vector<SpellCheckResult>::iterator remote_iter;
-
-  for (remote_iter = remote_results->begin();
-       remote_iter != remote_results->end(); ++remote_iter) {
-    // Discard all local results occurring before remote result.
-    while (local_iter != local_results.end() &&
-           local_iter->location < remote_iter->location) {
-      local_iter++;
-    }
-
-    // Unless local and remote result coincide, result is GRAMMAR.
-    remote_iter->decoration = SpellCheckResult::GRAMMAR;
-    if (local_iter != local_results.end() &&
-        local_iter->location == remote_iter->location &&
-        local_iter->length == remote_iter->length) {
-      remote_iter->decoration = SpellCheckResult::SPELLING;
-    }
-  }
-}
-
-}  // namespace
-
-// SpellingRequest is owned by SpellCheckHostChromeImpl.
-class SpellingRequest {
- public:
-  using RequestTextCheckCallback =
-      spellcheck::mojom::SpellCheckHost::RequestTextCheckCallback;
-  using DestructionCallback = base::OnceCallback<void(SpellingRequest*)>;
-
-  SpellingRequest(SpellingServiceClient* client,
-                  const base::string16& text,
-                  const service_manager::Identity& renderer_identity,
-                  int document_tag,
-                  RequestTextCheckCallback callback,
-                  DestructionCallback destruction_callback);
-
- private:
-  // Request server-side checking for |text_|.
-  void RequestRemoteCheck(SpellingServiceClient* client,
-                          const service_manager::Identity& renderer_identity);
-
-  // Request a check for |text_| from local spell checker.
-  void RequestLocalCheck(int document_tag);
-
-  // Check if all pending requests are done, send reply to render process if so.
-  void OnCheckCompleted();
-
-  // Called when server-side checking is complete. Must be called on UI thread.
-  void OnRemoteCheckCompleted(bool success,
-                              const base::string16& text,
-                              const std::vector<SpellCheckResult>& results);
-
-  // Called when local checking is complete. Must be called on UI thread.
-  void OnLocalCheckCompleted(const std::vector<SpellCheckResult>& results);
-
-  // Forwards the results back to UI thread when local checking completes.
-  static void OnLocalCheckCompletedOnAnyThread(
-      base::WeakPtr<SpellingRequest> request,
-      const std::vector<SpellCheckResult>& results);
-
-  std::vector<SpellCheckResult> local_results_;
-  std::vector<SpellCheckResult> remote_results_;
-
-  // Barrier closure for completion of both remote and local check.
-  base::RepeatingClosure completion_barrier_;
-  bool remote_success_;
-
-  // The string to be spell-checked.
-  base::string16 text_;
-
-  // Callback to send the results to renderer.
-  RequestTextCheckCallback callback_;
-
-  // Callback to delete |this|. Called on |this| after everything is done.
-  DestructionCallback destruction_callback_;
-
-  base::WeakPtrFactory<SpellingRequest> weak_factory_;
-};
-
-SpellingRequest::SpellingRequest(
-    SpellingServiceClient* client,
-    const base::string16& text,
-    const service_manager::Identity& renderer_identity,
-    int document_tag,
-    RequestTextCheckCallback callback,
-    DestructionCallback destruction_callback)
-    : remote_success_(false),
-      text_(text),
-      callback_(std::move(callback)),
-      destruction_callback_(std::move(destruction_callback)),
-      weak_factory_(this) {
-  DCHECK(!text_.empty());
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  completion_barrier_ =
-      BarrierClosure(2, base::BindOnce(&SpellingRequest::OnCheckCompleted,
-                                       weak_factory_.GetWeakPtr()));
-  RequestRemoteCheck(client, renderer_identity);
-  RequestLocalCheck(document_tag);
-}
-
-void SpellingRequest::RequestRemoteCheck(
-    SpellingServiceClient* client,
-    const service_manager::Identity& renderer_identity) {
-  BrowserContext* context =
-      content::BrowserContext::GetBrowserContextForServiceInstanceGroup(
-          renderer_identity.instance_group());
-
-  // |this| may be gone at callback invocation if the owner has been removed.
-  client->RequestTextCheck(
-      context, SpellingServiceClient::SPELLCHECK, text_,
-      base::BindOnce(&SpellingRequest::OnRemoteCheckCompleted,
-                     weak_factory_.GetWeakPtr()));
-}
-
-void SpellingRequest::RequestLocalCheck(int document_tag) {
-  // |this| may be gone at callback invocation if the owner has been removed.
-  spellcheck_platform::RequestTextCheck(
-      document_tag, text_,
-      base::BindOnce(&SpellingRequest::OnLocalCheckCompletedOnAnyThread,
-                     weak_factory_.GetWeakPtr()));
-}
-
-void SpellingRequest::OnCheckCompleted() {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  std::vector<SpellCheckResult>* check_results = &local_results_;
-  if (remote_success_) {
-    std::sort(remote_results_.begin(), remote_results_.end(), CompareLocation);
-    std::sort(local_results_.begin(), local_results_.end(), CompareLocation);
-    CombineResults(&remote_results_, local_results_);
-    check_results = &remote_results_;
-  }
-
-  std::move(callback_).Run(*check_results);
-
-  std::move(destruction_callback_).Run(this);
-
-  // |destruction_callback_| removes |this|. No more operations allowed.
-}
-
-void SpellingRequest::OnRemoteCheckCompleted(
-    bool success,
-    const base::string16& text,
-    const std::vector<SpellCheckResult>& results) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  remote_success_ = success;
-  remote_results_ = results;
-  completion_barrier_.Run();
-}
-
-// static
-void SpellingRequest::OnLocalCheckCompletedOnAnyThread(
-    base::WeakPtr<SpellingRequest> request,
-    const std::vector<SpellCheckResult>& results) {
-  // Local checking can happen on any thread - don't DCHECK thread.
-  base::PostTaskWithTraits(
-      FROM_HERE, {content::BrowserThread::UI},
-      base::BindOnce(&SpellingRequest::OnLocalCheckCompleted, request,
-                     results));
-}
-
-void SpellingRequest::OnLocalCheckCompleted(
-    const std::vector<SpellCheckResult>& results) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  local_results_ = results;
-  completion_barrier_.Run();
-}
-
-SpellCheckHostChromeImpl::SpellCheckHostChromeImpl(
-    const service_manager::Identity& renderer_identity)
-    : renderer_identity_(renderer_identity), weak_factory_(this) {}
-
-SpellCheckHostChromeImpl::~SpellCheckHostChromeImpl() = default;
-
-// static
-void SpellCheckHostChromeImpl::CombineResultsForTesting(
-    std::vector<SpellCheckResult>* remote_results,
-    const std::vector<SpellCheckResult>& local_results) {
-  CombineResults(remote_results, local_results);
-}
-
-void SpellCheckHostChromeImpl::CheckSpelling(const base::string16& word,
-                                             int route_id,
-                                             CheckSpellingCallback callback) {
-  bool correct =
-      spellcheck_platform::CheckSpelling(word, ToDocumentTag(route_id));
-  std::move(callback).Run(correct);
-}
-
-void SpellCheckHostChromeImpl::FillSuggestionList(
-    const base::string16& word,
-    FillSuggestionListCallback callback) {
-  std::vector<base::string16> suggestions;
-  spellcheck_platform::FillSuggestionList(word, &suggestions);
-  std::move(callback).Run(suggestions);
-}
-
-void SpellCheckHostChromeImpl::RequestTextCheck(
-    const base::string16& text,
-    int route_id,
-    RequestTextCheckCallback callback) {
-  DCHECK(!text.empty());
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  // Initialize the spellcheck service if needed. The service will send the
-  // language code for text breaking to the renderer. (Text breaking is required
-  // for the context menu to show spelling suggestions.) Initialization must
-  // happen on UI thread.
-  GetSpellcheckService();
-
-  // |SpellingRequest| self-destructs on completion.
-  // OK to store unretained |this| in a |SpellingRequest| owned by |this|.
-  requests_.insert(std::make_unique<SpellingRequest>(
-      &client_, text, renderer_identity_, ToDocumentTag(route_id),
-      std::move(callback),
-      base::BindOnce(&SpellCheckHostChromeImpl::OnRequestFinished,
-                     base::Unretained(this))));
-}
-
-void SpellCheckHostChromeImpl::OnRequestFinished(SpellingRequest* request) {
-  auto iterator = requests_.find(request);
-  requests_.erase(iterator);
-}
-
-int SpellCheckHostChromeImpl::ToDocumentTag(int route_id) {
-  if (!tag_map_.count(route_id))
-    tag_map_[route_id] = spellcheck_platform::GetDocumentTag();
-  return tag_map_[route_id];
-}
-
-// TODO(groby): We are currently not notified of retired tags. We need
-// to track destruction of RenderViewHosts on the browser process side
-// to update our mappings when a document goes away.
-void SpellCheckHostChromeImpl::RetireDocumentTag(int route_id) {
-  spellcheck_platform::CloseDocumentWithTag(ToDocumentTag(route_id));
-  tag_map_.erase(route_id);
-}
diff --git a/chrome/browser/spellchecker/spell_check_host_chrome_impl_unittest.cc b/chrome/browser/spellchecker/spell_check_host_chrome_impl_unittest.cc
index 8f777b5..83cf0cb 100644
--- a/chrome/browser/spellchecker/spell_check_host_chrome_impl_unittest.cc
+++ b/chrome/browser/spellchecker/spell_check_host_chrome_impl_unittest.cc
@@ -14,8 +14,8 @@
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
-#error !BUILDFLAG(USE_BROWSER_SPELLCHECKER) is required for these tests.
+#if !BUILDFLAG(USE_RENDERER_SPELLCHECKER)
+#error BUILDFLAG(USE_RENDERER_SPELLCHECKER) is required for these tests.
 #endif
 
 class TestSpellCheckHostChromeImpl {
diff --git a/chrome/browser/spellchecker/spell_check_host_chrome_impl_win_browsertest.cc b/chrome/browser/spellchecker/spell_check_host_chrome_impl_win_browsertest.cc
new file mode 100644
index 0000000..f1c65ad
--- /dev/null
+++ b/chrome/browser/spellchecker/spell_check_host_chrome_impl_win_browsertest.cc
@@ -0,0 +1,97 @@
+// Copyright 2019 The Chromium 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/spellchecker/spell_check_host_chrome_impl.h"
+
+#include "base/bind.h"
+#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/win/windows_version.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "components/spellcheck/browser/spellcheck_platform.h"
+#include "components/spellcheck/common/spellcheck_features.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/test/mock_render_process_host.h"
+
+class SpellCheckHostChromeImplWinBrowserTest : public InProcessBrowserTest {
+ public:
+  void SetUpOnMainThread() override {
+    content::BrowserContext* context = browser()->profile();
+    renderer_.reset(new content::MockRenderProcessHost(context));
+
+    service_manager::BindSourceInfo source_info;
+    source_info.identity = renderer_->GetChildIdentity();
+
+    base::test::ScopedFeatureList feature_list;
+    feature_list.InitAndEnableFeature(spellcheck::kWinUseBrowserSpellChecker);
+
+    SpellCheckHostChromeImpl::Create(mojo::MakeRequest(&spell_check_host_),
+                                     source_info);
+  }
+
+  void TearDownOnMainThread() override { renderer_.reset(); }
+
+  void LogResult(const std::vector<SpellCheckResult>& result) {
+    received_result_ = true;
+    result_ = result;
+    if (quit_)
+      std::move(quit_).Run();
+  }
+
+  void SetLanguageCompletionCallback(bool result) {
+    received_result_ = true;
+    if (quit_)
+      std::move(quit_).Run();
+  }
+
+  void RunUntilResultReceived() {
+    if (received_result_)
+      return;
+    base::RunLoop run_loop;
+    quit_ = run_loop.QuitClosure();
+    run_loop.Run();
+
+    // reset status
+    received_result_ = false;
+  }
+
+ protected:
+  std::unique_ptr<content::MockRenderProcessHost> renderer_;
+  spellcheck::mojom::SpellCheckHostPtr spell_check_host_;
+
+  bool received_result_ = false;
+  std::vector<SpellCheckResult> result_;
+  base::OnceClosure quit_;
+};
+
+// Uses browsertest to setup chrome threads.
+IN_PROC_BROWSER_TEST_F(SpellCheckHostChromeImplWinBrowserTest,
+                       SpellCheckReturnMessage) {
+  if (base::win::GetVersion() < base::win::Version::WIN8)
+    return;
+
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(spellcheck::kWinUseBrowserSpellChecker);
+
+  spellcheck_platform::SetLanguage(
+      "en-US", base::BindOnce(&SpellCheckHostChromeImplWinBrowserTest::
+                                  SetLanguageCompletionCallback,
+                              base::Unretained(this)));
+
+  RunUntilResultReceived();
+
+  spell_check_host_->RequestTextCheck(
+      base::UTF8ToUTF16("zz."), 123,
+      base::BindOnce(&SpellCheckHostChromeImplWinBrowserTest::LogResult,
+                     base::Unretained(this)));
+  RunUntilResultReceived();
+
+  ASSERT_EQ(1U, result_.size());
+  EXPECT_EQ(result_[0].location, 0);
+  EXPECT_EQ(result_[0].length, 2);
+  EXPECT_EQ(result_[0].decoration, SpellCheckResult::SPELLING);
+}
diff --git a/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc b/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc
index 5c22d2c..5f9f076b 100644
--- a/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc
+++ b/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc
@@ -24,6 +24,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "components/spellcheck/browser/spellcheck_platform.h"
 #include "components/spellcheck/common/spellcheck_common.h"
+#include "components/spellcheck/common/spellcheck_features.h"
 #include "components/spellcheck/spellcheck_buildflags.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
@@ -127,27 +128,31 @@
         FROM_HERE,
         base::BindOnce(&CloseDictionary, std::move(dictionary_file_.file)));
   }
+
+#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+  // Disable the language from platform spellchecker.
+  if (spellcheck::UseBrowserSpellChecker())
+    spellcheck_platform::DisableLanguage(language_);
+#endif
 }
 
 void SpellcheckHunspellDictionary::Load() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
 #if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
-  if (spellcheck_platform::SpellCheckerAvailable() &&
-      spellcheck_platform::PlatformSupportsLanguage(language_)) {
-    use_browser_spellchecker_ = true;
-    spellcheck_platform::SetLanguage(language_);
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::BindOnce(
-            &SpellcheckHunspellDictionary::InformListenersOfInitialization,
-            weak_ptr_factory_.GetWeakPtr()));
+  if (spellcheck::UseBrowserSpellChecker()) {
+    if (spellcheck_platform::SpellCheckerAvailable() &&
+        spellcheck_platform::PlatformSupportsLanguage(language_)) {
+      spellcheck_platform::SetLanguage(
+          language_, base::BindOnce(&SpellcheckHunspellDictionary::
+                                        SpellCheckPlatformSetLanguageCompleted,
+                                    base::Unretained(this)));
+    }
     return;
   }
 #endif  // USE_BROWSER_SPELLCHECKER
 
-// Mac falls back on hunspell if its platform spellchecker isn't available.
-// However, Android does not support hunspell.
+// Android does not support hunspell.
 #if !defined(OS_ANDROID)
   base::PostTaskAndReplyWithResult(
       task_runner_.get(), FROM_HERE,
@@ -441,3 +446,20 @@
   for (Observer& observer : observers_)
     observer.OnHunspellDictionaryDownloadFailure(language_);
 }
+
+#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+void SpellcheckHunspellDictionary::SpellCheckPlatformSetLanguageCompleted(
+    bool result) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  if (!result)
+    return;
+
+  use_browser_spellchecker_ = true;
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          &SpellcheckHunspellDictionary::InformListenersOfInitialization,
+          weak_ptr_factory_.GetWeakPtr()));
+}
+#endif
diff --git a/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h b/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h
index 715378b..d2a8492 100644
--- a/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h
+++ b/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h
@@ -17,6 +17,7 @@
 #include "base/sequenced_task_runner.h"
 #include "build/build_config.h"
 #include "components/spellcheck/browser/spellcheck_dictionary.h"
+#include "components/spellcheck/spellcheck_buildflags.h"
 #include "services/network/public/cpp/simple_url_loader.h"
 
 class GURL;
@@ -134,6 +135,10 @@
   void InitializeDictionaryLocationComplete(DictionaryFile file);
 #endif
 
+#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+  void SpellCheckPlatformSetLanguageCompleted(bool result);
+#endif
+
   // The reply point for PostTaskAndReplyWithResult, called after the dictionary
   // file has been saved.
   void SaveDictionaryDataComplete(bool dictionary_saved);
diff --git a/chrome/browser/spellchecker/spellcheck_service.cc b/chrome/browser/spellchecker/spellcheck_service.cc
index f3791a0..5299574f 100644
--- a/chrome/browser/spellchecker/spellcheck_service.cc
+++ b/chrome/browser/spellchecker/spellcheck_service.cc
@@ -30,6 +30,7 @@
 #include "components/spellcheck/browser/spelling_service_client.h"
 #include "components/spellcheck/common/spellcheck.mojom.h"
 #include "components/spellcheck/common/spellcheck_common.h"
+#include "components/spellcheck/common/spellcheck_features.h"
 #include "components/spellcheck/spellcheck_buildflags.h"
 #include "components/user_prefs/user_prefs.h"
 #include "content/public/browser/browser_context.h"
@@ -60,12 +61,11 @@
   dictionaries_pref.Init(spellcheck::prefs::kSpellCheckDictionaries, prefs);
   std::string first_of_dictionaries;
 
-#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
-  // Ensure that the renderer always knows the platform spellchecking language.
-  // This language is used for initialization of the text iterator. If the
-  // iterator is not initialized, then the context menu does not show spellcheck
-  // suggestions.
-  //
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
+  // Ensure that the renderer always knows the platform spellchecking
+  // language. This language is used for initialization of the text iterator.
+  // If the iterator is not initialized, then the context menu does not show
+  // spellcheck suggestions.
   // No migration is necessary, because the spellcheck language preference is
   // not user visible or modifiable in Chrome on Mac.
   dictionaries_pref.SetValue(std::vector<std::string>(
@@ -87,7 +87,7 @@
   }
 
   single_dictionary_pref.SetValue("");
-#endif  // BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#endif  // defined(OS_MACOSX) || defined(OS_ANDROID)
 
   pref_change_registrar_.Add(
       spellcheck::prefs::kSpellCheckDictionaries,
diff --git a/chrome/browser/spellchecker/spellcheck_service_browsertest.cc b/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
index 8d5ebe0..38b5207 100644
--- a/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
+++ b/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
@@ -443,13 +443,13 @@
   tester.ExpectTotalCount(kMisspellRatio, 1);
 }
 
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#if BUILDFLAG(USE_RENDERER_SPELLCHECKER)
 // When the renderer requests the spelling service for correcting text, the
 // render process host should call the remote spelling service.
 IN_PROC_BROWSER_TEST_F(SpellcheckServiceHostBrowserTest, CallSpellingService) {
   CallSpellingService();
 }
-#endif  // !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#endif  // BUILDFLAG(USE_RENDERER_SPELLCHECKER)
 
 // Tests that we can delete a corrupted BDICT file used by hunspell. We do not
 // run this test on Mac because Mac does not use hunspell by default.
diff --git a/chrome/browser/spellchecker/spelling_request.cc b/chrome/browser/spellchecker/spelling_request.cc
new file mode 100644
index 0000000..74536510
--- /dev/null
+++ b/chrome/browser/spellchecker/spelling_request.cc
@@ -0,0 +1,144 @@
+// Copyright 2019 The Chromium 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/spellchecker/spelling_request.h"
+
+#include "base/barrier_closure.h"
+#include "base/bind.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
+#include "chrome/browser/spellchecker/spellcheck_custom_dictionary.h"
+#include "chrome/browser/spellchecker/spellcheck_factory.h"
+#include "components/spellcheck/browser/spellcheck_platform.h"
+#include "components/spellcheck/common/spellcheck_result.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+
+namespace {
+
+bool CompareLocation(const SpellCheckResult& r1, const SpellCheckResult& r2) {
+  return r1.location < r2.location;
+}
+
+}  // namespace
+
+SpellingRequest::SpellingRequest(
+    SpellingServiceClient* client,
+    const base::string16& text,
+    const service_manager::Identity& renderer_identity,
+    int document_tag,
+    RequestTextCheckCallback callback,
+    DestructionCallback destruction_callback)
+    : remote_success_(false),
+      text_(text),
+      callback_(std::move(callback)),
+      destruction_callback_(std::move(destruction_callback)),
+      weak_factory_(this) {
+  DCHECK(!text_.empty());
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  completion_barrier_ =
+      BarrierClosure(2, base::BindOnce(&SpellingRequest::OnCheckCompleted,
+                                       weak_factory_.GetWeakPtr()));
+  RequestRemoteCheck(client, renderer_identity);
+  RequestLocalCheck(document_tag);
+}
+
+SpellingRequest::~SpellingRequest() = default;
+
+// static
+void SpellingRequest::CombineResults(
+    std::vector<SpellCheckResult>* remote_results,
+    const std::vector<SpellCheckResult>& local_results) {
+  std::vector<SpellCheckResult>::const_iterator local_iter(
+      local_results.begin());
+  std::vector<SpellCheckResult>::iterator remote_iter;
+
+  for (remote_iter = remote_results->begin();
+       remote_iter != remote_results->end(); ++remote_iter) {
+    // Discard all local results occurring before remote result.
+    while (local_iter != local_results.end() &&
+           local_iter->location < remote_iter->location) {
+      local_iter++;
+    }
+
+    // Unless local and remote result coincide, result is GRAMMAR.
+    remote_iter->decoration = SpellCheckResult::GRAMMAR;
+    if (local_iter != local_results.end() &&
+        local_iter->location == remote_iter->location &&
+        local_iter->length == remote_iter->length) {
+      remote_iter->decoration = SpellCheckResult::SPELLING;
+    }
+  }
+}
+
+void SpellingRequest::RequestRemoteCheck(
+    SpellingServiceClient* client,
+    const service_manager::Identity& renderer_identity) {
+  content::BrowserContext* context =
+      content::BrowserContext::GetBrowserContextForServiceInstanceGroup(
+          renderer_identity.instance_group());
+
+  // |this| may be gone at callback invocation if the owner has been removed.
+  client->RequestTextCheck(
+      context, SpellingServiceClient::SPELLCHECK, text_,
+      base::BindOnce(&SpellingRequest::OnRemoteCheckCompleted,
+                     weak_factory_.GetWeakPtr()));
+}
+
+void SpellingRequest::RequestLocalCheck(int document_tag) {
+  // |this| may be gone at callback invocation if the owner has been removed.
+  spellcheck_platform::RequestTextCheck(
+      document_tag, text_,
+      base::BindOnce(&SpellingRequest::OnLocalCheckCompletedOnAnyThread,
+                     weak_factory_.GetWeakPtr()));
+}
+
+void SpellingRequest::OnCheckCompleted() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  std::vector<SpellCheckResult>* check_results = &local_results_;
+  if (remote_success_) {
+    std::sort(remote_results_.begin(), remote_results_.end(), CompareLocation);
+    std::sort(local_results_.begin(), local_results_.end(), CompareLocation);
+    CombineResults(&remote_results_, local_results_);
+    check_results = &remote_results_;
+  }
+
+  std::move(callback_).Run(*check_results);
+
+  std::move(destruction_callback_).Run(this);
+
+  // |destruction_callback_| removes |this|. No more operations allowed.
+}
+
+void SpellingRequest::OnRemoteCheckCompleted(
+    bool success,
+    const base::string16& text,
+    const std::vector<SpellCheckResult>& results) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  remote_success_ = success;
+  remote_results_ = results;
+  completion_barrier_.Run();
+}
+
+// static
+void SpellingRequest::OnLocalCheckCompletedOnAnyThread(
+    base::WeakPtr<SpellingRequest> request,
+    const std::vector<SpellCheckResult>& results) {
+  // Local checking can happen on any thread - don't DCHECK thread.
+  base::PostTaskWithTraits(
+      FROM_HERE, {content::BrowserThread::UI},
+      base::BindOnce(&SpellingRequest::OnLocalCheckCompleted, request,
+                     results));
+}
+
+void SpellingRequest::OnLocalCheckCompleted(
+    const std::vector<SpellCheckResult>& results) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  local_results_ = results;
+  completion_barrier_.Run();
+}
diff --git a/chrome/browser/spellchecker/spelling_request.h b/chrome/browser/spellchecker/spelling_request.h
new file mode 100644
index 0000000..7877e93
--- /dev/null
+++ b/chrome/browser/spellchecker/spelling_request.h
@@ -0,0 +1,83 @@
+// Copyright 2019 The Chromium 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_SPELLCHECKER_SPELLING_REQUEST_H_
+#define CHROME_BROWSER_SPELLCHECKER_SPELLING_REQUEST_H_
+
+#include "base/containers/unique_ptr_adapters.h"
+#include "components/spellcheck/browser/spell_check_host_impl.h"
+#include "components/spellcheck/browser/spelling_service_client.h"
+#include "services/service_manager/public/cpp/bind_source_info.h"
+
+class SpellingRequest;
+
+struct SpellCheckResult;
+
+// SpellingRequest is owned by SpellCheckHostChromeImpl.
+class SpellingRequest {
+ public:
+  using RequestTextCheckCallback =
+      spellcheck::mojom::SpellCheckHost::RequestTextCheckCallback;
+  using DestructionCallback = base::OnceCallback<void(SpellingRequest*)>;
+
+  SpellingRequest(SpellingServiceClient* client,
+                  const base::string16& text,
+                  const service_manager::Identity& renderer_identity,
+                  int document_tag,
+                  RequestTextCheckCallback callback,
+                  DestructionCallback destruction_callback);
+
+  ~SpellingRequest();
+
+  // Exposed to tests only.
+  static void CombineResults(
+      std::vector<SpellCheckResult>* remote_results,
+      const std::vector<SpellCheckResult>& local_results);
+
+ private:
+  // Request server-side checking for |text_|.
+  void RequestRemoteCheck(SpellingServiceClient* client,
+                          const service_manager::Identity& renderer_identity);
+
+  // Request a check for |text_| from local spell checker.
+  void RequestLocalCheck(int document_tag);
+
+  // Check if all pending requests are done, send reply to render process if so.
+  void OnCheckCompleted();
+
+  // Called when server-side checking is complete. Must be called on UI thread.
+  void OnRemoteCheckCompleted(bool success,
+                              const base::string16& text,
+                              const std::vector<SpellCheckResult>& results);
+
+  // Called when local checking is complete. Must be called on UI thread.
+  void OnLocalCheckCompleted(const std::vector<SpellCheckResult>& results);
+
+  // Forwards the results back to UI thread when local checking completes.
+  static void OnLocalCheckCompletedOnAnyThread(
+      base::WeakPtr<SpellingRequest> request,
+      const std::vector<SpellCheckResult>& results);
+
+  std::vector<SpellCheckResult> local_results_;
+  std::vector<SpellCheckResult> remote_results_;
+
+  // Barrier closure for completion of both remote and local check.
+  base::RepeatingClosure completion_barrier_;
+  bool remote_success_;
+
+  // The string to be spell-checked.
+  base::string16 text_;
+
+  // Callback to send the results to renderer.
+  RequestTextCheckCallback callback_;
+
+  // Callback to delete |this|. Called on |this| after everything is done.
+  DestructionCallback destruction_callback_;
+
+  base::WeakPtrFactory<SpellingRequest> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(SpellingRequest);
+};
+
+#endif  // CHROME_BROWSER_SPELLCHECKER_SPELLING_REQUEST_H_
diff --git a/chrome/browser/ssl/secure_origin_policy_handler.cc b/chrome/browser/ssl/secure_origin_policy_handler.cc
index 84264a0..7bfb3b9 100644
--- a/chrome/browser/ssl/secure_origin_policy_handler.cc
+++ b/chrome/browser/ssl/secure_origin_policy_handler.cc
@@ -19,7 +19,7 @@
                                                      Schema schema)
     : SchemaValidatingPolicyHandler(policy_name,
                                     schema.GetKnownProperty(policy_name),
-                                    SCHEMA_STRICT) {
+                                    SCHEMA_ALLOW_UNKNOWN) {
   DCHECK(policy_name == key::kUnsafelyTreatInsecureOriginAsSecure ||
          policy_name == key::kOverrideSecurityRestrictionsOnInsecureOrigin);
 }
diff --git a/chrome/browser/ssl/security_state_tab_helper_browsertest.cc b/chrome/browser/ssl/security_state_tab_helper_browsertest.cc
index 0173fa1..ef97b3b7 100644
--- a/chrome/browser/ssl/security_state_tab_helper_browsertest.cc
+++ b/chrome/browser/ssl/security_state_tab_helper_browsertest.cc
@@ -59,11 +59,11 @@
 #include "content/public/browser/security_style_explanations.h"
 #include "content/public/browser/ssl_status.h"
 #include "content/public/browser/storage_partition.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_delegate.h"
 #include "content/public/common/page_type.h"
 #include "content/public/common/referrer.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_navigation_observer.h"
@@ -1124,10 +1124,8 @@
     mojo::ScopedAllowSyncCallForTesting allow_sync_call;
 
     network::mojom::NetworkServiceTestPtr network_service_test;
-    content::ServiceManagerConnection::GetForProcess()
-        ->GetConnector()
-        ->BindInterface(content::mojom::kNetworkServiceName,
-                        &network_service_test);
+    content::GetSystemConnector()->BindInterface(
+        content::mojom::kNetworkServiceName, &network_service_test);
     network_service_test->SetTransportSecurityStateSource(0);
 
     // This test class intentionally does not call the parent
@@ -1139,10 +1137,8 @@
     mojo::ScopedAllowSyncCallForTesting allow_sync_call;
 
     network::mojom::NetworkServiceTestPtr network_service_test;
-    content::ServiceManagerConnection::GetForProcess()
-        ->GetConnector()
-        ->BindInterface(content::mojom::kNetworkServiceName,
-                        &network_service_test);
+    content::GetSystemConnector()->BindInterface(
+        content::mojom::kNetworkServiceName, &network_service_test);
     // The tests don't depend on reporting, so the port doesn't matter.
     network_service_test->SetTransportSecurityStateSource(80);
 
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc
index 12c9e4e..d81a9b4f 100644
--- a/chrome/browser/ssl/ssl_browsertest.cc
+++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -120,12 +120,12 @@
 #include "content/public/browser/restore_type.h"
 #include "content/public/browser/ssl_status.h"
 #include "content/public/browser/storage_partition.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/network_service_util.h"
 #include "content/public/common/page_state.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/common/web_preferences.h"
@@ -6819,10 +6819,8 @@
 void SetShouldNotRequireCTForTesting() {
   if (content::IsOutOfProcessNetworkService()) {
     network::mojom::NetworkServiceTestPtr network_service_test;
-    content::ServiceManagerConnection::GetForProcess()
-        ->GetConnector()
-        ->BindInterface(content::mojom::kNetworkServiceName,
-                        &network_service_test);
+    content::GetSystemConnector()->BindInterface(
+        content::mojom::kNetworkServiceName, &network_service_test);
     network::mojom::NetworkServiceTest::ShouldRequireCT required_ct =
         network::mojom::NetworkServiceTest::ShouldRequireCT::DONT_REQUIRE;
 
@@ -7452,10 +7450,8 @@
       mojo::ScopedAllowSyncCallForTesting allow_sync_call;
 
       network::mojom::NetworkServiceTestPtr network_service_test;
-      content::ServiceManagerConnection::GetForProcess()
-          ->GetConnector()
-          ->BindInterface(content::mojom::kNetworkServiceName,
-                          &network_service_test);
+      content::GetSystemConnector()->BindInterface(
+          content::mojom::kNetworkServiceName, &network_service_test);
       network_service_test->SetTransportSecurityStateSource(0);
     } else {
       RunOnIOThreadBlocking(base::BindOnce(
@@ -7475,10 +7471,8 @@
       mojo::ScopedAllowSyncCallForTesting allow_sync_call;
 
       network::mojom::NetworkServiceTestPtr network_service_test;
-      content::ServiceManagerConnection::GetForProcess()
-          ->GetConnector()
-          ->BindInterface(content::mojom::kNetworkServiceName,
-                          &network_service_test);
+      content::GetSystemConnector()->BindInterface(
+          content::mojom::kNetworkServiceName, &network_service_test);
       network_service_test->SetTransportSecurityStateSource(reporting_port);
     } else {
       RunOnIOThreadBlocking(base::BindOnce(
diff --git a/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc b/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc
index f4b614fdc..c16b9ae 100644
--- a/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc
+++ b/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc
@@ -14,7 +14,6 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "components/prefs/testing_pref_service.h"
-#include "components/variations/variations_params_manager.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "net/cert/cert_verifier.h"
 #include "net/ssl/ssl_config.h"
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine.cc b/chrome/browser/sync_file_system/drive_backend/sync_engine.cc
index 769eaeb4..50bceb85 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_engine.cc
+++ b/chrome/browser/sync_file_system/drive_backend/sync_engine.cc
@@ -48,7 +48,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/network_service_instance.h"
 #include "content/public/browser/storage_partition.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/browser/extension_system_provider.h"
 #include "extensions/browser/extensions_browser_client.h"
@@ -275,11 +275,9 @@
           identity_manager_, url_loader_factory_, drive_task_runner_.get());
 
   device::mojom::WakeLockProviderPtr wake_lock_provider(nullptr);
-  DCHECK(content::ServiceManagerConnection::GetForProcess());
-  auto* connector =
-      content::ServiceManagerConnection::GetForProcess()->GetConnector();
-  connector->BindInterface(device::mojom::kServiceName,
-                           mojo::MakeRequest(&wake_lock_provider));
+  DCHECK(content::GetSystemConnector());
+  content::GetSystemConnector()->BindInterface(
+      device::mojom::kServiceName, mojo::MakeRequest(&wake_lock_provider));
 
   std::unique_ptr<drive::DriveUploaderInterface> drive_uploader(
       new drive::DriveUploader(drive_service.get(), drive_task_runner_.get(),
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 9a19015..917dedb 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -2433,6 +2433,7 @@
       deps += [
         "//ui/events/devices",
         "//ui/events/devices/x11",
+        "//ui/events/platform/x11",
       ]
     }
     if (use_ozone) {
diff --git a/chrome/browser/ui/ash/accessibility/accessibility_controller_client.cc b/chrome/browser/ui/ash/accessibility/accessibility_controller_client.cc
index 8d08bf4..befb4ee95 100644
--- a/chrome/browser/ui/ash/accessibility/accessibility_controller_client.cc
+++ b/chrome/browser/ui/ash/accessibility/accessibility_controller_client.cc
@@ -9,8 +9,8 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/aura/accessibility/automation_manager_aura.h"
 #include "chrome/grit/generated_resources.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/tts_controller.h"
-#include "content/public/common/service_manager_connection.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -34,9 +34,8 @@
 AccessibilityControllerClient::~AccessibilityControllerClient() = default;
 
 void AccessibilityControllerClient::Init() {
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(ash::mojom::kServiceName, &accessibility_controller_);
+  content::GetSystemConnector()->BindInterface(ash::mojom::kServiceName,
+                                               &accessibility_controller_);
   BindAndSetClient();
 }
 
diff --git a/chrome/browser/ui/ash/accessibility/fake_accessibility_controller.cc b/chrome/browser/ui/ash/accessibility/fake_accessibility_controller.cc
index c602ad5..36798cc 100644
--- a/chrome/browser/ui/ash/accessibility/fake_accessibility_controller.cc
+++ b/chrome/browser/ui/ash/accessibility/fake_accessibility_controller.cc
@@ -8,29 +8,25 @@
 
 #include "ash/public/interfaces/constants.mojom.h"
 #include "base/bind.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/service_filter.h"
 
 FakeAccessibilityController::FakeAccessibilityController() {
-  CHECK(content::ServiceManagerConnection::GetForProcess())
+  CHECK(content::GetSystemConnector())
       << "ServiceManager is uninitialized. Did you forget to create a "
          "content::TestServiceManagerContext?";
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->OverrideBinderForTesting(
-          service_manager::ServiceFilter::ByName(ash::mojom::kServiceName),
-          ash::mojom::AccessibilityController::Name_,
-          base::BindRepeating(&FakeAccessibilityController::Bind,
-                              base::Unretained(this)));
+  content::GetSystemConnector()->OverrideBinderForTesting(
+      service_manager::ServiceFilter::ByName(ash::mojom::kServiceName),
+      ash::mojom::AccessibilityController::Name_,
+      base::BindRepeating(&FakeAccessibilityController::Bind,
+                          base::Unretained(this)));
 }
 
 FakeAccessibilityController::~FakeAccessibilityController() {
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->ClearBinderOverrideForTesting(
-          service_manager::ServiceFilter::ByName(ash::mojom::kServiceName),
-          ash::mojom::AccessibilityController::Name_);
+  content::GetSystemConnector()->ClearBinderOverrideForTesting(
+      service_manager::ServiceFilter::ByName(ash::mojom::kServiceName),
+      ash::mojom::AccessibilityController::Name_);
 }
 
 void FakeAccessibilityController::SetClient(
diff --git a/chrome/browser/ui/ash/ash_shell_init.cc b/chrome/browser/ui/ash/ash_shell_init.cc
index b3b359d..8560b62 100644
--- a/chrome/browser/ui/ash/ash_shell_init.cc
+++ b/chrome/browser/ui/ash/ash_shell_init.cc
@@ -13,7 +13,7 @@
 #include "chrome/browser/ui/ash/keyboard/chrome_keyboard_ui_factory.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "content/public/browser/context_factory.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "ui/aura/window_tree_host.h"
 
 namespace {
@@ -24,8 +24,7 @@
   shell_init_params.context_factory = content::GetContextFactory();
   shell_init_params.context_factory_private =
       content::GetContextFactoryPrivate();
-  shell_init_params.connector =
-      content::ServiceManagerConnection::GetForProcess()->GetConnector();
+  shell_init_params.connector = content::GetSystemConnector();
   DCHECK(shell_init_params.connector);
   shell_init_params.local_state = g_browser_process->local_state();
   shell_init_params.keyboard_ui_factory =
diff --git a/chrome/browser/ui/ash/ash_util.cc b/chrome/browser/ui/ash/ash_util.cc
index 1041756..30b62fb 100644
--- a/chrome/browser/ui/ash/ash_util.cc
+++ b/chrome/browser/ui/ash/ash_util.cc
@@ -7,7 +7,6 @@
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/shell.h"
 #include "components/session_manager/core/session_manager.h"
-#include "content/public/common/service_manager_connection.h"
 #include "ui/wm/core/shadow_types.h"
 #include "ui/wm/core/window_animations.h"
 
@@ -29,14 +28,6 @@
              : ash::kShellWindowId_LockSystemModalContainer;
 }
 
-service_manager::Connector* GetServiceManagerConnector() {
-  content::ServiceManagerConnection* manager_connection =
-      content::ServiceManagerConnection::GetForProcess();
-  if (!manager_connection)
-    return nullptr;
-  return manager_connection->GetConnector();
-}
-
 void BounceWindow(aura::Window* window) {
   wm::AnimateWindow(window, wm::WINDOW_ANIMATION_TYPE_BOUNCE);
 }
diff --git a/chrome/browser/ui/ash/ash_util.h b/chrome/browser/ui/ash/ash_util.h
index b6e1687..71950db 100644
--- a/chrome/browser/ui/ash/ash_util.h
+++ b/chrome/browser/ui/ash/ash_util.h
@@ -13,10 +13,6 @@
 class Window;
 }
 
-namespace service_manager {
-class Connector;
-}
-
 namespace ash_util {
 
 // Sets up |params| to place the widget in an ash shell window container on
@@ -31,10 +27,6 @@
 // lock screen.
 int GetSystemModalDialogContainerId();
 
-// Returns the connector from ServiceManagerConnection::GetForProcess().
-// May be null in unit tests.
-service_manager::Connector* GetServiceManagerConnector();
-
 // Triggers the window bounce animation.
 void BounceWindow(aura::Window* window);
 
diff --git a/chrome/browser/ui/ash/assistant/assistant_client.cc b/chrome/browser/ui/ash/assistant/assistant_client.cc
index 83f6dbe9..fe8bf1f1 100644
--- a/chrome/browser/ui/ash/assistant/assistant_client.cc
+++ b/chrome/browser/ui/ash/assistant/assistant_client.cc
@@ -9,12 +9,15 @@
 #include "ash/public/interfaces/voice_interaction_controller.mojom.h"
 #include "chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.h"
 #include "chrome/browser/chromeos/assistant/assistant_util.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/ui/ash/assistant/assistant_context_util.h"
 #include "chrome/browser/ui/ash/assistant/assistant_image_downloader.h"
 #include "chrome/browser/ui/ash/assistant/assistant_setup.h"
+#include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/services/assistant/public/mojom/constants.mojom.h"
+#include "components/session_manager/core/session_manager.h"
 #include "content/public/common/content_switches.h"
 #include "services/service_manager/public/cpp/connector.h"
 
@@ -39,12 +42,19 @@
 AssistantClient::AssistantClient() : client_binding_(this) {
   DCHECK_EQ(nullptr, g_instance);
   g_instance = this;
+
+  auto* session_manager = session_manager::SessionManager::Get();
+  // AssistantClient must be created before any user session is created.
+  // Otherwise, it will not get OnUserProfileLoaded notification.
+  DCHECK(session_manager->sessions().empty());
+  session_manager->AddObserver(this);
 }
 
 AssistantClient::~AssistantClient() {
   DCHECK(g_instance);
   g_instance = nullptr;
 
+  session_manager::SessionManager::Get()->RemoveObserver(this);
   if (identity_manager_)
     identity_manager_->RemoveObserver(this);
 }
@@ -112,3 +122,23 @@
 
   MaybeInit(profile_);
 }
+
+void AssistantClient::OnUserProfileLoaded(const AccountId& account_id) {
+  if (!chromeos::switches::IsAssistantEnabled())
+    return;
+
+  // Initialize Assistant when primary user profile is loaded so that it could
+  // be used in post oobe steps. OnPrimaryUserSessionStarted() is too late
+  // because it happens after post oobe steps
+  Profile* user_profile =
+      chromeos::ProfileHelper::Get()->GetProfileByAccountId(account_id);
+  if (!chromeos::ProfileHelper::IsPrimaryProfile(user_profile))
+    return;
+
+  MaybeInit(user_profile);
+}
+
+void AssistantClient::OnPrimaryUserSessionStarted() {
+  if (!chromeos::switches::ShouldSkipOobePostLogin())
+    MaybeStartAssistantOptInFlow();
+}
diff --git a/chrome/browser/ui/ash/assistant/assistant_client.h b/chrome/browser/ui/ash/assistant/assistant_client.h
index 9f7c020..d243039 100644
--- a/chrome/browser/ui/ash/assistant/assistant_client.h
+++ b/chrome/browser/ui/ash/assistant/assistant_client.h
@@ -10,6 +10,7 @@
 #include "base/macros.h"
 #include "chrome/browser/ui/ash/assistant/device_actions.h"
 #include "chromeos/services/assistant/public/mojom/assistant.mojom.h"
+#include "components/session_manager/core/session_manager_observer.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "services/identity/public/cpp/identity_manager.h"
 
@@ -19,7 +20,8 @@
 
 // Class to handle all assistant in-browser-process functionalities.
 class AssistantClient : chromeos::assistant::mojom::Client,
-                        public identity::IdentityManager::Observer {
+                        public identity::IdentityManager::Observer,
+                        public session_manager::SessionManagerObserver {
  public:
   static AssistantClient* Get();
 
@@ -43,6 +45,10 @@
   // will be empty under this case).
   void OnExtendedAccountInfoUpdated(const AccountInfo& info) override;
 
+  // session_manager::SessionManagerObserver:
+  void OnUserProfileLoaded(const AccountId& account_id) override;
+  void OnPrimaryUserSessionStarted() override;
+
   mojo::Binding<chromeos::assistant::mojom::Client> client_binding_;
   chromeos::assistant::mojom::AssistantPlatformPtr assistant_connection_;
 
diff --git a/chrome/browser/ui/ash/chrome_screenshot_grabber.cc b/chrome/browser/ui/ash/chrome_screenshot_grabber.cc
index e6921138..392c48b 100644
--- a/chrome/browser/ui/ash/chrome_screenshot_grabber.cc
+++ b/chrome/browser/ui/ash/chrome_screenshot_grabber.cc
@@ -45,7 +45,7 @@
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/data_decoder/public/cpp/decode_image.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "ui/base/clipboard/clipboard.h"
@@ -97,17 +97,10 @@
     scoped_refptr<base::RefCountedString> png_data) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  service_manager::mojom::ConnectorRequest connector_request;
-  std::unique_ptr<service_manager::Connector> connector =
-      service_manager::Connector::Create(&connector_request);
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindConnectorRequest(std::move(connector_request));
-
   // Decode the image in sandboxed process because |png_data| comes from
   // external storage.
   data_decoder::DecodeImage(
-      connector.get(),
+      content::GetSystemConnector(),
       std::vector<uint8_t>(png_data->data().begin(), png_data->data().end()),
       data_decoder::mojom::ImageCodec::DEFAULT, false,
       data_decoder::kDefaultMaxSizeInBytes, gfx::Size(),
@@ -623,17 +616,10 @@
     return;
   }
 
-  service_manager::mojom::ConnectorRequest connector_request;
-  std::unique_ptr<service_manager::Connector> connector =
-      service_manager::Connector::Create(&connector_request);
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindConnectorRequest(std::move(connector_request));
-
   // Decode the image in sandboxed process becuase decode image_data comes from
   // external storage.
   data_decoder::DecodeImage(
-      connector.get(),
+      content::GetSystemConnector(),
       std::vector<uint8_t>(image_data.begin(), image_data.end()),
       data_decoder::mojom::ImageCodec::DEFAULT, false,
       data_decoder::kDefaultMaxSizeInBytes, gfx::Size(),
diff --git a/chrome/browser/ui/ash/ime_controller_client.cc b/chrome/browser/ui/ash/ime_controller_client.cc
index 3e610ddd..e261390 100644
--- a/chrome/browser/ui/ash/ime_controller_client.cc
+++ b/chrome/browser/ui/ash/ime_controller_client.cc
@@ -10,7 +10,7 @@
 #include "ash/public/interfaces/constants.mojom.h"
 #include "base/logging.h"
 #include "base/strings/utf_string_conversions.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "ui/base/ime/chromeos/extension_ime_util.h"
 #include "ui/base/ime/chromeos/ime_keyboard.h"
@@ -58,9 +58,8 @@
 
 void ImeControllerClient::Init() {
   // Connect to the controller in ash.
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(ash::mojom::kServiceName, &ime_controller_ptr_);
+  content::GetSystemConnector()->BindInterface(ash::mojom::kServiceName,
+                                               &ime_controller_ptr_);
   BindAndSetClient();
 }
 
diff --git a/chrome/browser/ui/ash/session_controller_client_impl.cc b/chrome/browser/ui/ash/session_controller_client_impl.cc
index 6604a15..ae37fc8 100644
--- a/chrome/browser/ui/ash/session_controller_client_impl.cc
+++ b/chrome/browser/ui/ash/session_controller_client_impl.cc
@@ -37,7 +37,6 @@
 #include "chrome/browser/ui/managed_ui.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/assistant/buildflags.h"
-#include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "chromeos/login/session/session_termination_manager.h"
 #include "components/prefs/pref_change_registrar.h"
@@ -53,10 +52,6 @@
 #include "ui/chromeos/resources/grit/ui_chromeos_resources.h"
 #include "ui/gfx/image/image_skia.h"
 
-#if BUILDFLAG(ENABLE_CROS_ASSISTANT)
-#include "chrome/browser/ui/ash/assistant/assistant_client.h"
-#endif
-
 using session_manager::Session;
 using session_manager::SessionManager;
 using session_manager::SessionState;
@@ -497,17 +492,6 @@
     primary_user_session_sent_ = true;
     SendUserSession(*UserManager::Get()->GetPrimaryUser());
     SendUserSessionOrder();
-
-#if BUILDFLAG(ENABLE_CROS_ASSISTANT)
-    // Assistant is initialized only once when primary user logs in.
-    // Initialize Assistant when browser process restarts.
-    if (chromeos::switches::IsAssistantEnabled()) {
-      AssistantClient::Get()->MaybeInit(
-          ProfileManager::GetPrimaryUserProfile());
-      if (!chromeos::switches::ShouldSkipOobePostLogin())
-        AssistantClient::Get()->MaybeStartAssistantOptInFlow();
-    }
-#endif
   }
 
   SendSessionInfoIfChanged();
diff --git a/chrome/browser/ui/ash/tablet_mode_transition_interactive_uitest.cc b/chrome/browser/ui/ash/tablet_mode_transition_interactive_uitest.cc
index bcce0967..168a6668 100644
--- a/chrome/browser/ui/ash/tablet_mode_transition_interactive_uitest.cc
+++ b/chrome/browser/ui/ash/tablet_mode_transition_interactive_uitest.cc
@@ -73,6 +73,8 @@
     auto* cmd = base::CommandLine::ForCurrentProcess();
     if (cmd->HasSwitch(wm::switches::kWindowAnimationsDisabled))
       cmd->RemoveSwitch(wm::switches::kWindowAnimationsDisabled);
+
+    ash::ShellTestApi::SetTabletControllerUseScreenshotForTest(true);
   }
 
   std::vector<std::string> GetUMAHistogramNames() const override {
diff --git a/chrome/browser/ui/ash/vpn_list_forwarder.cc b/chrome/browser/ui/ash/vpn_list_forwarder.cc
index a1a918fe8..6b4d417 100644
--- a/chrome/browser/ui/ash/vpn_list_forwarder.cc
+++ b/chrome/browser/ui/ash/vpn_list_forwarder.cc
@@ -15,7 +15,7 @@
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_source.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_set.h"
@@ -60,9 +60,8 @@
 // Connects to the VpnList mojo interface in ash.
 ash::mojom::VpnListPtr ConnectToVpnList() {
   ash::mojom::VpnListPtr vpn_list;
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(ash::mojom::kServiceName, &vpn_list);
+  content::GetSystemConnector()->BindInterface(ash::mojom::kServiceName,
+                                               &vpn_list);
   return vpn_list;
 }
 
diff --git a/chrome/browser/ui/bookmarks/bookmark_browsertest.cc b/chrome/browser/ui/bookmarks/bookmark_browsertest.cc
index 71ab269..c265dce 100644
--- a/chrome/browser/ui/bookmarks/bookmark_browsertest.cc
+++ b/chrome/browser/ui/bookmarks/bookmark_browsertest.cc
@@ -225,13 +225,15 @@
   const GURL page_url("http://www.google.com");
   const BookmarkNode* root = model->bookmark_bar_node();
   const BookmarkNode* node = model->AddURL(root, 0, page_title, page_url);
+  const gfx::Point expected_point(100, 100);
 
   auto run_loop = std::make_unique<base::RunLoop>();
 
   chrome::DoBookmarkDragCallback cb = base::BindLambdaForTesting(
-      [&run_loop, page_title, page_url](
+      [&run_loop, page_title, page_url, expected_point](
           const ui::OSExchangeData& drag_data, gfx::NativeView native_view,
-          ui::DragDropTypes::DragEventSource source, int operation) {
+          ui::DragDropTypes::DragEventSource source, gfx::Point point,
+          int operation) {
         GURL url;
         base::string16 title;
         EXPECT_TRUE(drag_data.provider().GetURLAndTitle(
@@ -246,6 +248,7 @@
         // See https://crbug.com/893388.
         EXPECT_FALSE(drag_data.provider().GetDragImage().isNull());
 #endif
+        EXPECT_EQ(expected_point, point);
         run_loop->Quit();
       });
 
@@ -255,7 +258,8 @@
       {{node},
        kDragNodeIndex,
        platform_util::GetViewForWindow(browser()->window()->GetNativeWindow()),
-       ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE},
+       ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE,
+       expected_point},
       std::move(cb));
 
   run_loop->Run();
@@ -270,13 +274,15 @@
   const BookmarkNode* root = model->bookmark_bar_node();
   const BookmarkNode* node1 = model->AddURL(root, 0, page_title, page_url);
   const BookmarkNode* node2 = model->AddFolder(root, 0, page_title);
+  const gfx::Point expected_point(100, 100);
 
   auto run_loop = std::make_unique<base::RunLoop>();
 
   chrome::DoBookmarkDragCallback cb = base::BindLambdaForTesting(
-      [&run_loop](const ui::OSExchangeData& drag_data,
-                  gfx::NativeView native_view,
-                  ui::DragDropTypes::DragEventSource source, int operation) {
+      [&run_loop, expected_point](const ui::OSExchangeData& drag_data,
+                                  gfx::NativeView native_view,
+                                  ui::DragDropTypes::DragEventSource source,
+                                  gfx::Point point, int operation) {
 #if !defined(OS_MACOSX)
         GURL url;
         base::string16 title;
@@ -293,6 +299,7 @@
         // See https://crbug.com/893388.
         EXPECT_FALSE(drag_data.provider().GetDragImage().isNull());
 #endif
+        EXPECT_EQ(expected_point, point);
         run_loop->Quit();
       });
 
@@ -304,6 +311,7 @@
                                    platform_util::GetViewForWindow(
                                        browser()->window()->GetNativeWindow()),
                                    ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE,
+                                   expected_point,
                                },
                                std::move(cb));
 
diff --git a/chrome/browser/ui/bookmarks/bookmark_drag_drop.cc b/chrome/browser/ui/bookmarks/bookmark_drag_drop.cc
index 41ff1fe..5b3983e29 100644
--- a/chrome/browser/ui/bookmarks/bookmark_drag_drop.cc
+++ b/chrome/browser/ui/bookmarks/bookmark_drag_drop.cc
@@ -28,11 +28,13 @@
     std::vector<const bookmarks::BookmarkNode*> nodes,
     int drag_node_index,
     gfx::NativeView view,
-    ui::DragDropTypes::DragEventSource source)
+    ui::DragDropTypes::DragEventSource source,
+    gfx::Point start_point)
     : nodes(std::move(nodes)),
       drag_node_index(drag_node_index),
       view(view),
-      source(source) {}
+      source(source),
+      start_point(start_point) {}
 BookmarkDragParams::~BookmarkDragParams() = default;
 
 int DropBookmarks(Profile* profile,
diff --git a/chrome/browser/ui/bookmarks/bookmark_drag_drop.h b/chrome/browser/ui/bookmarks/bookmark_drag_drop.h
index 48b9b6c..71c1f94 100644
--- a/chrome/browser/ui/bookmarks/bookmark_drag_drop.h
+++ b/chrome/browser/ui/bookmarks/bookmark_drag_drop.h
@@ -9,6 +9,7 @@
 
 #include "build/build_config.h"
 #include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/gfx/geometry/point.h"
 #include "ui/gfx/native_widget_types.h"
 
 class Profile;
@@ -30,13 +31,15 @@
     base::OnceCallback<void(const ui::OSExchangeData& drag_data,
                             gfx::NativeView native_view,
                             ui::DragDropTypes::DragEventSource source,
+                            gfx::Point start_point,
                             int operation)>;
 
 struct BookmarkDragParams {
   BookmarkDragParams(std::vector<const bookmarks::BookmarkNode*> nodes,
                      int drag_node_index,
                      gfx::NativeView view,
-                     ui::DragDropTypes::DragEventSource source);
+                     ui::DragDropTypes::DragEventSource source,
+                     gfx::Point start_point);
   ~BookmarkDragParams();
 
   // The bookmark nodes to be dragged.
@@ -50,6 +53,9 @@
 
   // The source of the drag.
   ui::DragDropTypes::DragEventSource source;
+
+  // The point the drag started.
+  gfx::Point start_point;
 };
 
 // Starts the process of dragging a folder of bookmarks.
diff --git a/chrome/browser/ui/libgtkui/app_indicator_icon.cc b/chrome/browser/ui/libgtkui/app_indicator_icon.cc
index 598af116..b3c3ed9 100644
--- a/chrome/browser/ui/libgtkui/app_indicator_icon.cc
+++ b/chrome/browser/ui/libgtkui/app_indicator_icon.cc
@@ -162,7 +162,7 @@
 
   EnsureLibAppIndicatorLoaded();
   tool_tip_ = base::UTF16ToUTF8(tool_tip);
-  SetImage(image);
+  SetIcon(image);
 }
 AppIndicatorIcon::~AppIndicatorIcon() {
   if (icon_) {
@@ -180,7 +180,7 @@
   return g_opened;
 }
 
-void AppIndicatorIcon::SetImage(const gfx::ImageSkia& image) {
+void AppIndicatorIcon::SetIcon(const gfx::ImageSkia& image) {
   if (!g_opened)
     return;
 
diff --git a/chrome/browser/ui/libgtkui/app_indicator_icon.h b/chrome/browser/ui/libgtkui/app_indicator_icon.h
index db66890..a8f207e 100644
--- a/chrome/browser/ui/libgtkui/app_indicator_icon.h
+++ b/chrome/browser/ui/libgtkui/app_indicator_icon.h
@@ -44,7 +44,7 @@
   static bool CouldOpen();
 
   // Overridden from views::StatusIconLinux:
-  void SetImage(const gfx::ImageSkia& image) override;
+  void SetIcon(const gfx::ImageSkia& image) override;
   void SetToolTip(const base::string16& tool_tip) override;
   void UpdatePlatformContextMenu(ui::MenuModel* menu) override;
   void RefreshPlatformContextMenu() override;
diff --git a/chrome/browser/ui/libgtkui/gtk_status_icon.cc b/chrome/browser/ui/libgtkui/gtk_status_icon.cc
index 1280453..d5295c53 100644
--- a/chrome/browser/ui/libgtkui/gtk_status_icon.cc
+++ b/chrome/browser/ui/libgtkui/gtk_status_icon.cc
@@ -42,7 +42,7 @@
   g_object_unref(gtk_status_icon_);
 }
 
-void GtkStatusIcon::SetImage(const gfx::ImageSkia& image) {
+void GtkStatusIcon::SetIcon(const gfx::ImageSkia& image) {
   GdkPixbuf* pixbuf = GdkPixbufFromSkBitmap(*image.bitmap());
   gtk_status_icon_set_from_pixbuf(gtk_status_icon_, pixbuf);
   g_object_unref(pixbuf);
diff --git a/chrome/browser/ui/libgtkui/gtk_status_icon.h b/chrome/browser/ui/libgtkui/gtk_status_icon.h
index 305bad35..ef5faed5 100644
--- a/chrome/browser/ui/libgtkui/gtk_status_icon.h
+++ b/chrome/browser/ui/libgtkui/gtk_status_icon.h
@@ -34,7 +34,7 @@
   ~GtkStatusIcon() override;
 
   // Overridden from views::StatusIconLinux:
-  void SetImage(const gfx::ImageSkia& image) override;
+  void SetIcon(const gfx::ImageSkia& image) override;
   void SetToolTip(const base::string16& tool_tip) override;
   void UpdatePlatformContextMenu(ui::MenuModel* menu) override;
   void RefreshPlatformContextMenu() override;
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_drag_drop_views.cc b/chrome/browser/ui/views/bookmarks/bookmark_drag_drop_views.cc
index b51cff7..a1554c41 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_drag_drop_views.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_drag_drop_views.cc
@@ -174,6 +174,7 @@
         count_(params.nodes.size()),
         native_view_(params.view),
         source_(params.source),
+        start_point_(params.start_point),
         do_drag_callback_(std::move(do_drag_callback)),
         observer_(this),
         weak_factory_(this) {
@@ -229,7 +230,7 @@
                                   BookmarkDragImageSource::kDragImageOffsetY));
 
     std::move(do_drag_callback_)
-        .Run(drag_data_, native_view_, source_, operation_);
+        .Run(drag_data_, native_view_, source_, start_point_, operation_);
 
     delete this;
   }
@@ -260,6 +261,7 @@
   int count_;
   gfx::NativeView native_view_;
   ui::DragDropTypes::DragEventSource source_;
+  const gfx::Point start_point_;
   int operation_;
 
   DoBookmarkDragCallback do_drag_callback_;
@@ -277,13 +279,17 @@
 void DoDragImpl(const ui::OSExchangeData& drag_data,
                 gfx::NativeView native_view,
                 ui::DragDropTypes::DragEventSource source,
+                gfx::Point point,
                 int operation) {
   // Allow nested run loop so we get DnD events as we drag this around.
   base::MessageLoopCurrent::ScopedNestableTaskAllower nestable_task_allower;
 
   views::Widget* widget = views::Widget::GetWidgetForNativeView(native_view);
-  DCHECK(widget);
-  widget->RunShellDrag(nullptr, drag_data, gfx::Point(), operation, source);
+  if (widget) {
+    widget->RunShellDrag(nullptr, drag_data, gfx::Point(), operation, source);
+  } else {
+    views::RunShellDrag(native_view, drag_data, point, operation, source);
+  }
 }
 
 void DragBookmarksImpl(Profile* profile,
diff --git a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc
index 4590795..8b05a88 100644
--- a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc
+++ b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc
@@ -30,7 +30,7 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/content_settings/core/common/content_settings_types.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/test/browser_test_utils.h"
 #include "net/dns/mock_host_resolver.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -793,9 +793,8 @@
   };
 
   ash::mojom::CrosDisplayConfigControllerPtr cros_display_config;
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(ash::mojom::kServiceName, &cros_display_config);
+  content::GetSystemConnector()->BindInterface(ash::mojom::kServiceName,
+                                               &cros_display_config);
   ash::mojom::CrosDisplayConfigControllerAsyncWaiter waiter_for(
       cros_display_config.get());
   std::vector<ash::mojom::DisplayUnitInfoPtr> info_list;
diff --git a/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.cc b/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.cc
index b36f8836..c88b12e 100644
--- a/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.cc
+++ b/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.cc
@@ -160,7 +160,7 @@
       FROM_HERE, base::BindOnce(&dbus::Bus::ShutdownAndBlock, bus_));
 }
 
-void StatusIconLinuxDbus::SetImage(const gfx::ImageSkia& image) {
+void StatusIconLinuxDbus::SetIcon(const gfx::ImageSkia& image) {
   if (!properties_)
     return;
 
@@ -202,14 +202,14 @@
 
 void StatusIconLinuxDbus::OnHostRegisteredResponse(dbus::Response* response) {
   if (!response) {
-    delegate_->OnImplInitialized(false);
+    delegate_->OnImplInitializationFailed();
     return;
   }
 
   dbus::MessageReader reader(response);
   bool registered = false;
   if (!reader.PopVariantOfBool(&registered) || !registered) {
-    delegate_->OnImplInitialized(false);
+    delegate_->OnImplInitializationFailed();
     return;
   }
 
@@ -223,7 +223,7 @@
 void StatusIconLinuxDbus::OnOwnership(const std::string& service_name,
                                       bool success) {
   if (!success) {
-    delegate_->OnImplInitialized(false);
+    delegate_->OnImplInitializationFailed();
     return;
   }
 
@@ -293,7 +293,7 @@
 
 void StatusIconLinuxDbus::OnInitialized(bool success) {
   if (!success) {
-    delegate_->OnImplInitialized(false);
+    delegate_->OnImplInitializationFailed();
     return;
   }
 
@@ -307,7 +307,8 @@
 }
 
 void StatusIconLinuxDbus::OnRegistered(dbus::Response* response) {
-  delegate_->OnImplInitialized(response);
+  if (!response)
+    delegate_->OnImplInitializationFailed();
 }
 
 void StatusIconLinuxDbus::OnActivate(
diff --git a/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h b/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h
index 4c193d0df..12d60f1 100644
--- a/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h
+++ b/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h
@@ -35,7 +35,7 @@
   ~StatusIconLinuxDbus() override;
 
   // StatusIcon:
-  void SetImage(const gfx::ImageSkia& image) override;
+  void SetIcon(const gfx::ImageSkia& image) override;
   void SetToolTip(const base::string16& tool_tip) override;
   void UpdatePlatformContextMenu(ui::MenuModel* model) override;
   void RefreshPlatformContextMenu() override;
diff --git a/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc b/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc
index 6439ec2..09dbb2a 100644
--- a/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc
+++ b/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc
@@ -39,7 +39,7 @@
       image_(image),
       tool_tip_(tool_tip),
       menu_model_(nullptr) {
-  status_icon_->set_delegate(this);
+  status_icon_->SetDelegate(this);
 }
 
 StatusIconLinuxWrapper::~StatusIconLinuxWrapper() {
@@ -48,11 +48,15 @@
 }
 
 void StatusIconLinuxWrapper::SetImage(const gfx::ImageSkia& image) {
-  status_icon_->SetImage(image);
+  image_ = image;
+  if (status_icon_)
+    status_icon_->SetIcon(image);
 }
 
 void StatusIconLinuxWrapper::SetToolTip(const base::string16& tool_tip) {
-  status_icon_->SetToolTip(tool_tip);
+  tool_tip_ = tool_tip;
+  if (status_icon_)
+    status_icon_->SetToolTip(tool_tip);
 }
 
 void StatusIconLinuxWrapper::DisplayBalloon(
@@ -83,16 +87,13 @@
   return menu_model_;
 }
 
-void StatusIconLinuxWrapper::OnImplInitialized(bool success) {
-  if (success)
-    return;
-
+void StatusIconLinuxWrapper::OnImplInitializationFailed() {
   switch (status_icon_type_) {
     case kTypeDbus:
 #if defined(USE_X11)
       status_icon_ = std::make_unique<StatusIconLinuxX11>();
-      status_icon_->set_delegate(this);
       status_icon_type_ = kTypeX11;
+      status_icon_->SetDelegate(this);
       return;
 #else
       // Fallthrough needs to be omitted if USE_X11, otherwise clang will
@@ -102,6 +103,9 @@
     case kTypeX11:
       status_icon_.reset();
       status_icon_type_ = kTypeOther;
+      if (menu_model_)
+        menu_model_->RemoveObserver(this);
+      menu_model_ = nullptr;
       return;
     case kTypeOther:
       NOTREACHED();
@@ -109,7 +113,8 @@
 }
 
 void StatusIconLinuxWrapper::OnMenuStateChanged() {
-  status_icon_->RefreshPlatformContextMenu();
+  if (status_icon_)
+    status_icon_->RefreshPlatformContextMenu();
 }
 
 std::unique_ptr<StatusIconLinuxWrapper>
@@ -141,6 +146,9 @@
 
 void StatusIconLinuxWrapper::UpdatePlatformContextMenu(
     StatusIconMenuModel* model) {
+  if (!status_icon_)
+    return;
+
   // If a menu already exists, remove ourself from its observer list.
   if (menu_model_)
     menu_model_->RemoveObserver(this);
diff --git a/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.h b/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.h
index a5e5a8d3..6542b57 100644
--- a/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.h
+++ b/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.h
@@ -34,7 +34,7 @@
   const gfx::ImageSkia& GetImage() const override;
   const base::string16& GetToolTip() const override;
   ui::MenuModel* GetMenuModel() const override;
-  void OnImplInitialized(bool success) override;
+  void OnImplInitializationFailed() override;
 
   // StatusIconMenuModel::Observer overrides:
   void OnMenuStateChanged() override;
diff --git a/chrome/browser/ui/views/status_icons/status_icon_linux_x11.cc b/chrome/browser/ui/views/status_icons/status_icon_linux_x11.cc
index a6da9c61..6941b80 100644
--- a/chrome/browser/ui/views/status_icons/status_icon_linux_x11.cc
+++ b/chrome/browser/ui/views/status_icons/status_icon_linux_x11.cc
@@ -4,20 +4,153 @@
 
 #include "chrome/browser/ui/views/status_icons/status_icon_linux_x11.h"
 
-#include "base/logging.h"
+#include <X11/X.h>
+#include <X11/Xlib.h>
 
-StatusIconLinuxX11::StatusIconLinuxX11() = default;
+#include <limits>
+#include <memory>
+
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "chrome/browser/shell_integration_linux.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/events/platform/x11/x11_event_source.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/x/x11.h"
+#include "ui/gfx/x/x11_atom_cache.h"
+#include "ui/gfx/x/x11_error_tracker.h"
+#include "ui/gfx/x/x11_types.h"
+#include "ui/views/background.h"
+#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
+
+namespace {
+
+constexpr long kSystemTrayRequestDock = 0;
+
+constexpr int kXembedInfoProtocolVersion = 0;
+constexpr int kXembedInfoFlags = 0;
+
+const int16_t kInitialWindowPos = std::numeric_limits<int16_t>::min();
+
+}  // namespace
+
+StatusIconLinuxX11::StatusIconLinuxX11() : ImageButton(this) {}
 
 StatusIconLinuxX11::~StatusIconLinuxX11() = default;
 
-void StatusIconLinuxX11::SetImage(const gfx::ImageSkia& image) {
-  NOTIMPLEMENTED();
+void StatusIconLinuxX11::SetIcon(const gfx::ImageSkia& image) {
+  SetImage(views::Button::STATE_NORMAL, image);
 }
 
 void StatusIconLinuxX11::SetToolTip(const base::string16& tool_tip) {
-  NOTIMPLEMENTED();
+  SetTooltipText(tool_tip);
 }
 
 void StatusIconLinuxX11::UpdatePlatformContextMenu(ui::MenuModel* model) {
-  NOTIMPLEMENTED();
+  // Nothing to do.
+}
+
+void StatusIconLinuxX11::OnSetDelegate() {
+  XDisplay* const display = gfx::GetXDisplay();
+  std::string atom_name =
+      "_NET_SYSTEM_TRAY_S" + base::NumberToString(DefaultScreen(display));
+  XID manager = XGetSelectionOwner(display, gfx::GetAtom(atom_name.c_str()));
+  if (manager == x11::None) {
+    delegate_->OnImplInitializationFailed();
+    // |this| may be destroyed!
+    return;
+  }
+
+  widget_ = std::make_unique<views::Widget>();
+
+  auto native_widget =
+      std::make_unique<views::DesktopNativeWidgetAura>(widget_.get());
+
+  auto host = std::make_unique<views::DesktopWindowTreeHostX11>(
+      widget_.get(), native_widget.get());
+  aura::WindowTreeHost* window_tree_host = host.get();
+
+  int visual_id;
+  if (ui::GetIntProperty(manager, "_NET_SYSTEM_TRAY_VISUAL", &visual_id))
+    host->SetVisualId(visual_id);
+
+  const int width = std::max(1, delegate_->GetImage().width());
+  const int height = std::max(1, delegate_->GetImage().height());
+
+  views::Widget::InitParams params;
+  params.type = views::Widget::InitParams::TYPE_CONTROL;
+  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
+  params.activatable = views::Widget::InitParams::ACTIVATABLE_NO;
+  params.remove_standard_frame = true;
+  params.bounds =
+      gfx::Rect(kInitialWindowPos, kInitialWindowPos, width, height);
+  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+  params.native_widget = native_widget.release();
+  params.desktop_window_tree_host = host.release();
+  params.wm_class_name = shell_integration_linux::GetProgramClassName();
+  params.wm_class_class = shell_integration_linux::GetProgramClassClass();
+  // The status icon is a tiny window that doesn't update very often, so
+  // creating a compositor would only be wasteful of resources.
+  params.force_software_compositing = true;
+
+  widget_->Init(params);
+
+  Window window = window_tree_host->GetAcceleratedWidget();
+  DCHECK(window);
+
+  widget_->SetContentsView(this);
+  set_owned_by_client();
+
+  SetIcon(delegate_->GetImage());
+  SetImageHorizontalAlignment(ALIGN_CENTER);
+  SetImageVerticalAlignment(ALIGN_MIDDLE);
+  SetTooltipText(delegate_->GetToolTip());
+  set_context_menu_controller(this);
+
+  widget_->Show();
+
+  ui::SetIntArrayProperty(window, "_XEMBED_INFO", "CARDINAL",
+                          {kXembedInfoProtocolVersion, kXembedInfoFlags});
+
+  XEvent ev;
+  memset(&ev, 0, sizeof(ev));
+  ev.xclient.type = ClientMessage;
+  ev.xclient.window = manager;
+  ev.xclient.message_type = gfx::GetAtom("_NET_SYSTEM_TRAY_OPCODE");
+  ev.xclient.format = 32;
+  ev.xclient.data.l[0] = ui::X11EventSource::GetInstance()->GetTimestamp();
+  ev.xclient.data.l[1] = kSystemTrayRequestDock;
+  ev.xclient.data.l[2] = window;
+
+  bool error;
+  {
+    gfx::X11ErrorTracker error_tracker;
+    XSendEvent(display, manager, false, NoEventMask, &ev);
+    error = error_tracker.FoundNewError();
+  }
+  if (error) {
+    delegate_->OnImplInitializationFailed();
+    // |this| may be destroyed!
+  }
+}
+
+void StatusIconLinuxX11::ShowContextMenuForViewImpl(
+    View* source,
+    const gfx::Point& point,
+    ui::MenuSourceType source_type) {
+  ui::MenuModel* menu = delegate_->GetMenuModel();
+  if (!menu)
+    return;
+  menu_runner_ = std::make_unique<views::MenuRunner>(
+      menu, views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU |
+                views::MenuRunner::FIXED_ANCHOR);
+  menu_runner_->RunMenuAt(widget_.get(), nullptr, gfx::Rect(point, gfx::Size()),
+                          views::MenuAnchorPosition::kTopLeft, source_type);
+}
+
+void StatusIconLinuxX11::ButtonPressed(Button* sender, const ui::Event& event) {
+  delegate_->OnClick();
 }
diff --git a/chrome/browser/ui/views/status_icons/status_icon_linux_x11.h b/chrome/browser/ui/views/status_icons/status_icon_linux_x11.h
index 628279d2..94732fd 100644
--- a/chrome/browser/ui/views/status_icons/status_icon_linux_x11.h
+++ b/chrome/browser/ui/views/status_icons/status_icon_linux_x11.h
@@ -5,22 +5,46 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_ICON_LINUX_X11_H_
 #define CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_ICON_LINUX_X11_H_
 
+#include <memory>
+
 #include "base/macros.h"
+#include "ui/gfx/x/x11_types.h"
+#include "ui/views/context_menu_controller.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/controls/button/image_button.h"
+#include "ui/views/controls/menu/menu_runner.h"
 #include "ui/views/linux_ui/status_icon_linux.h"
+#include "ui/views/widget/widget.h"
 
 // A status icon that uses the XEmbed protocol.
 // https://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html
-class StatusIconLinuxX11 : public views::StatusIconLinux {
+class StatusIconLinuxX11 : public views::StatusIconLinux,
+                           public views::ImageButton,
+                           public views::ContextMenuController,
+                           public views::ButtonListener {
  public:
   StatusIconLinuxX11();
   ~StatusIconLinuxX11() override;
 
-  // StatusIcon:
-  void SetImage(const gfx::ImageSkia& image) override;
+  // views::StatusIcon:
+  void SetIcon(const gfx::ImageSkia& image) override;
   void SetToolTip(const base::string16& tool_tip) override;
   void UpdatePlatformContextMenu(ui::MenuModel* model) override;
+  void OnSetDelegate() override;
+
+  // views::ContextMenuController:
+  void ShowContextMenuForViewImpl(View* source,
+                                  const gfx::Point& point,
+                                  ui::MenuSourceType source_type) override;
+
+  // views::ButtonListener:
+  void ButtonPressed(Button* sender, const ui::Event& event) override;
 
  private:
+  std::unique_ptr<views::Widget> widget_;
+
+  std::unique_ptr<views::MenuRunner> menu_runner_;
+
   DISALLOW_COPY_AND_ASSIGN(StatusIconLinuxX11);
 };
 
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc
index 655f4b4..fc09406 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -65,8 +65,8 @@
 #include "components/strings/grit/components_strings.h"
 #include "components/vector_icons/vector_icons.h"
 #include "content/public/browser/render_view_host.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/service_manager_connection.h"
 #include "media/base/media_switches.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -242,8 +242,8 @@
 
   std::unique_ptr<MediaToolbarButtonView> media_button;
   if (base::FeatureList::IsEnabled(media::kGlobalMediaControls)) {
-    media_button = std::make_unique<MediaToolbarButtonView>(
-        content::ServiceManagerConnection::GetForProcess()->GetConnector());
+    media_button =
+        std::make_unique<MediaToolbarButtonView>(content::GetSystemConnector());
   }
 
   std::unique_ptr<ToolbarPageActionIconContainerView>
diff --git a/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc b/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc
index e0f4c10..cce737b 100644
--- a/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc
@@ -53,11 +53,11 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
 #include "content/public/browser/web_ui_message_handler.h"
-#include "content/public/common/service_manager_connection.h"
 #include "google_apis/drive/auth_service.h"
 #include "google_apis/drive/drive_api_error_codes.h"
 #include "google_apis/drive/drive_api_parser.h"
@@ -997,8 +997,7 @@
     (new ZipFileCreator(
          base::BindRepeating(&LogsZipper::OnZipDone, base::Unretained(this)),
          logs_directory_, files, zip_path_))
-        ->Start(
-            content::ServiceManagerConnection::GetForProcess()->GetConnector());
+        ->Start(content::GetSystemConnector());
   }
 
   static std::vector<base::FilePath> EnumerateLogFiles(
diff --git a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
index e4983b92..cd1d375 100644
--- a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
@@ -51,7 +51,7 @@
 #include "components/prefs/pref_service.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/version_info/version_info.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "google_apis/google_api_keys.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "ui/accessibility/accessibility_switches.h"
@@ -103,7 +103,7 @@
   tablet_mode_client->AddObserver(this);
 
   // |connector| may be null in tests.
-  auto* connector = ash_util::GetServiceManagerConnector();
+  auto* connector = content::GetSystemConnector();
   if (connector) {
     connector->BindInterface(ash::mojom::kServiceName,
                              &cros_display_config_ptr_);
diff --git a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc
index 638501b..ed23aaa3 100644
--- a/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc
@@ -39,7 +39,7 @@
 #include "components/login/localized_values_builder.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/device/public/mojom/wake_lock_provider.mojom.h"
@@ -624,17 +624,14 @@
 
   // Service manager connection might be not initialized in some testing
   // contexts.
-  if (!content::ServiceManagerConnection::GetForProcess())
+  if (!content::GetSystemConnector())
     return wake_lock_.get();
 
-  service_manager::Connector* connector =
-      content::ServiceManagerConnection::GetForProcess()->GetConnector();
-  DCHECK(connector);
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   device::mojom::WakeLockProviderPtr wake_lock_provider;
-  connector->BindInterface(device::mojom::kServiceName,
-                           mojo::MakeRequest(&wake_lock_provider));
+  content::GetSystemConnector()->BindInterface(
+      device::mojom::kServiceName, mojo::MakeRequest(&wake_lock_provider));
   wake_lock_provider->GetWakeLockWithoutContext(
       device::mojom::WakeLockType::kPreventAppSuspension,
       device::mojom::WakeLockReason::kOther,
diff --git a/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.cc
index df238a1..c1ba3d2 100644
--- a/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.cc
@@ -14,7 +14,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/login/localized_values_builder.h"
 #include "components/prefs/pref_service.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -54,9 +54,8 @@
     : BaseScreenHandler(kScreenId, js_calls_container) {
   set_user_acted_method_path("login.FingerprintSetupScreen.userActed");
 
-  service_manager::Connector* connector =
-      content::ServiceManagerConnection::GetForProcess()->GetConnector();
-  connector->BindInterface(device::mojom::kServiceName, &fp_service_);
+  content::GetSystemConnector()->BindInterface(device::mojom::kServiceName,
+                                               &fp_service_);
   device::mojom::FingerprintObserverPtr observer;
   binding_.Bind(mojo::MakeRequest(&observer));
   fp_service_->AddFingerprintObserver(std::move(observer));
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
index c48c2b1..cade0803 100644
--- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -542,8 +542,7 @@
                IDS_OFFLINE_LOGIN_FORGOT_PASSWORD_DIALOG_TEXT);
   builder->Add("offlineLoginCloseBtn", IDS_OFFLINE_LOGIN_CLOSE_BUTTON_TEXT);
   builder->Add("enterpriseInfoMessage", IDS_LOGIN_DEVICE_MANAGED_BY_NOTICE);
-  builder->Add("samlInterstitialMessage",
-                IDS_LOGIN_SAML_INTERSTITIAL_MESSAGE);
+  builder->Add("samlInterstitialMessage", IDS_LOGIN_SAML_INTERSTITIAL_MESSAGE);
   builder->Add("samlInterstitialChangeAccountLink",
                IDS_LOGIN_SAML_INTERSTITIAL_CHANGE_ACCOUNT_LINK_TEXT);
   builder->Add("samlInterstitialNextBtn",
@@ -824,8 +823,6 @@
   UserContext user_context(user_type,
                            GetAccountId(email, gaia_id, AccountType::GOOGLE));
   user_context.SetKey(Key(password));
-  // Save the user's plaintext password for possible authentication to a
-  // network. See https://crbug.com/386606 for details.
   user_context.SetPasswordKey(Key(password));
   user_context.SetAuthCode(auth_code);
   user_context.SetAuthFlow(using_saml
@@ -857,8 +854,8 @@
   SetSAMLPrincipalsAPIUsed(false);
   // Use a histogram that has 11 buckets, one for each of the values in [0, 9]
   // and an overflow bucket at the end.
-  UMA_HISTOGRAM_ENUMERATION(
-      "ChromeOS.SAML.Scraping.PasswordCount", std::min(password_count, 10), 11);
+  UMA_HISTOGRAM_ENUMERATION("ChromeOS.SAML.Scraping.PasswordCount",
+                            std::min(password_count, 10), 11);
   if (password_count == 0)
     HandleScrapedPasswordVerificationFailed();
 }
@@ -969,18 +966,6 @@
       user ? UserContext(*user)
            : UserContext(CalculateUserType(account_id), account_id);
   user_context.SetKey(Key(password));
-  // Save the user's plaintext password for possible authentication to a
-  // network. If the user's OpenNetworkConfiguration policy contains a
-  // ${PASSWORD} variable, then the user's password will be used to authenticate
-  // to the specified network.
-  //
-  // The user's password needs to be saved in memory until the policy can be
-  // examined. When the policy comes in, if it does not contain the ${PASSWORD}
-  // variable, the user's password will be discarded. If it contains the
-  // password, it will be sent to the session manager, which will then save it
-  // in a keyring so it can be retrieved for authenticating to the network.
-  //
-  // More details can be found in https://crbug.com/386606
   user_context.SetPasswordKey(Key(password));
   user_context.SetAuthFlow(using_saml
                                ? UserContext::AUTH_FLOW_GAIA_WITH_SAML
@@ -1059,6 +1044,7 @@
   std::string code =
       "document.getElementById('identifier').value = '" + test_user_ + "';"
       "document.getElementById('nextButton').click();";
+
   frame->ExecuteJavaScriptForTests(base::ASCIIToUTF16(code),
                                    base::NullCallback());
 
@@ -1245,10 +1231,8 @@
   CallJS("login.GaiaSigninScreen.showWhitelistCheckFailedError", true, params);
 }
 
-void GaiaScreenHandler::LoadAuthExtension(bool force,
-                                          bool offline) {
-  VLOG(1) << "LoadAuthExtension, force: " << force
-          << ", offline: " << offline;
+void GaiaScreenHandler::LoadAuthExtension(bool force, bool offline) {
+  VLOG(1) << "LoadAuthExtension, force: " << force << ", offline: " << offline;
 
   if (auth_extension_being_loaded_) {
     VLOG(1) << "Skip loading the Auth extension as it's already being loaded";
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc b/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc
index 9746a36..57c06c6f 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc
@@ -14,7 +14,7 @@
 #include "chrome/browser/ui/ash/ash_util.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
@@ -45,7 +45,7 @@
 OobeDisplayChooser::OobeDisplayChooser()
     : scoped_observer_(this), weak_ptr_factory_(this) {
   // |connector| may be null in tests.
-  auto* connector = ash_util::GetServiceManagerConnector();
+  auto* connector = content::GetSystemConnector();
   if (connector) {
     connector->BindInterface(ash::mojom::kServiceName,
                              &cros_display_config_ptr_);
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
index 0e60e35..54b787d4 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -119,10 +119,14 @@
 
 // Timeout to delay first notification about offline state for a
 // current network.
-const int kOfflineTimeoutSec = 5;
+constexpr base::TimeDelta kOfflineTimeout = base::TimeDelta::FromSeconds(1);
+
+// Timeout to delay first notification about offline state when authenticating
+// to a proxy.
+constexpr base::TimeDelta kProxyAuthTimeout = base::TimeDelta::FromSeconds(5);
 
 // Timeout used to prevent infinite connecting to a flaky network.
-const int kConnectingTimeoutSec = 60;
+constexpr base::TimeDelta kConnectingTimeout = base::TimeDelta::FromSeconds(60);
 
 // Max number of Gaia Reload to Show Proxy Auth Dialog.
 const int kMaxGaiaReloadForProxyAuthDialog = 3;
@@ -617,9 +621,8 @@
                    true));
     base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
         FROM_HERE, update_state_closure_.callback(),
-        is_offline_timeout_for_test_set_
-            ? offline_timeout_for_test_
-            : base::TimeDelta::FromSeconds(kOfflineTimeoutSec));
+        is_offline_timeout_for_test_set_ ? offline_timeout_for_test_
+                                         : kOfflineTimeout);
     return;
   }
 
@@ -633,8 +636,7 @@
                      reason,
                      true));
       base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-          FROM_HERE, connecting_closure_.callback(),
-          base::TimeDelta::FromSeconds(kConnectingTimeoutSec));
+          FROM_HERE, connecting_closure_.callback(), kConnectingTimeout);
     }
     return;
   }
@@ -980,7 +982,7 @@
         ReenableNetworkStateUpdatesAfterProxyAuth();
       } else {
         // Gaia is not hidden behind an error yet. Discard last cached network
-        // state notification and wait for |kOfflineTimeoutSec| before
+        // state notification and wait for |kProxyAuthTimeout| before
         // considering network update notifications again (hoping the network
         // will become ONLINE by then).
         update_state_closure_.Cancel();
@@ -989,7 +991,7 @@
             base::BindOnce(
                 &SigninScreenHandler::ReenableNetworkStateUpdatesAfterProxyAuth,
                 weak_factory_.GetWeakPtr()),
-            base::TimeDelta::FromSeconds(kOfflineTimeoutSec));
+            kProxyAuthTimeout);
       }
       break;
     }
@@ -1056,8 +1058,6 @@
     user_context = UserContext(*user);
   }
   user_context.SetKey(Key(password));
-  // Save the user's plaintext password for possible authentication to a
-  // network. See https://crbug.com/386606 for details.
   user_context.SetPasswordKey(Key(password));
   user_context.SetIsUsingPin(authenticated_by_pin);
   if (account_id.GetAccountType() == AccountType::ACTIVE_DIRECTORY) {
diff --git a/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc b/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc
index 3a017464..330df84 100644
--- a/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc
@@ -13,6 +13,7 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_file.h"
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "base/strings/string_split.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
@@ -20,6 +21,7 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -30,24 +32,18 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui_message_handler.h"
 #include "net/base/address_list.h"
 #include "net/base/net_errors.h"
-#include "net/dns/host_cache.h"
-#include "net/dns/host_resolver.h"
+#include "net/dns/host_resolver_source.h"
 #include "net/dns/mock_host_resolver.h"
-#include "net/http/http_network_session.h"
-#include "net/http/http_transaction_factory.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/request_handler_util.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "services/network/public/cpp/features.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
-using content::BrowserThread;
 using content::WebUIMessageHandler;
 
 namespace {
@@ -64,37 +60,44 @@
   return http_response;
 }
 
-// Called on IO thread.  Adds an entry to the cache for the specified hostname.
-// Either |net_error| must be net::OK, or |address| must be NULL.
-void AddCacheEntryOnIOThread(net::URLRequestContextGetter* context_getter,
-                             const std::string& hostname,
-                             const std::string& ip_literal,
-                             int net_error,
-                             int expire_days_from_now) {
-  ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
-  net::URLRequestContext* context = context_getter->GetURLRequestContext();
-  net::HostCache* cache = context->host_resolver()->GetHostCache();
-  ASSERT_TRUE(cache);
+// Notifies the NetInternalsTest.Task JS object of the DNS lookup result once
+// it's complete. Owns itself.
+class DnsLookupClient : public network::mojom::ResolveHostClient {
+ public:
+  using Callback = base::OnceCallback<void(base::Value*)>;
 
-  net::HostCache::Key key(hostname, net::ADDRESS_FAMILY_UNSPECIFIED, 0);
-  base::TimeDelta ttl = base::TimeDelta::FromDays(expire_days_from_now);
+  DnsLookupClient(network::mojom::ResolveHostClientRequest request,
+                  Callback callback)
+      : binding_(this, std::move(request)), callback_(std::move(callback)) {
+    binding_.set_connection_error_handler(
+        base::BindOnce(&DnsLookupClient::OnComplete, base::Unretained(this),
+                       net::ERR_FAILED, base::nullopt));
+  }
+  ~DnsLookupClient() override {}
 
-  net::AddressList address_list;
-  if (net_error == net::OK) {
-    // If |net_error| does not indicate an error, convert |ip_literal| to a
-    // net::AddressList, so it can be used with the cache.
-    int rv = net::ParseAddressList(ip_literal, hostname, &address_list);
-    ASSERT_EQ(net::OK, rv);
-  } else {
-    ASSERT_TRUE(ip_literal.empty());
+  // network::mojom::ResolveHostClient:
+  void OnComplete(
+      int32_t error,
+      const base::Optional<net::AddressList>& resolved_addresses) override {
+    std::string result;
+    if (error == net::OK) {
+      CHECK(resolved_addresses->size() == 1);
+      result = resolved_addresses.value()[0].ToStringWithoutPort();
+    } else {
+      result = net::ErrorToString(error);
+    }
+    base::Value value(result);
+    std::move(callback_).Run(&value);
+    delete this;
+  }
+  void OnTextResults(const std::vector<std::string>& text_results) override {}
+  void OnHostnameResults(const std::vector<net::HostPortPair>& hosts) override {
   }
 
-  // Add entry to the cache.
-  cache->Set(net::HostCache::Key(hostname, net::ADDRESS_FAMILY_UNSPECIFIED, 0),
-             net::HostCache::Entry(net_error, address_list,
-                                   net::HostCache::Entry::SOURCE_UNKNOWN),
-             base::TimeTicks::Now(), ttl);
-}
+ private:
+  mojo::Binding<network::mojom::ResolveHostClient> binding_;
+  Callback callback_;
+};
 
 }  // namespace
 
@@ -123,41 +126,39 @@
   // which must already have been started.
   void GetTestServerURL(const base::ListValue* list_value);
 
-  // Called on UI thread.  Adds an entry to the cache for the specified
-  // hostname by posting a task to the IO thread.  Takes the host name,
-  // ip address, net error code, and expiration time in days from now
-  // as parameters.  If the error code indicates failure, the ip address
-  // must be an empty string.
-  void AddCacheEntry(const base::ListValue* list_value);
-
   // Sets up the test server to receive test Expect-CT reports. Calls the
   // Javascript callback to return the test server URI.
   void SetUpTestReportURI(const base::ListValue* list_value);
 
+  // Performs a DNS lookup. Calls the Javascript callback with the host's IP
+  // address or an error string.
+  void DnsLookup(const base::ListValue* list_value);
+
   Browser* browser() { return net_internals_test_->browser(); }
 
   NetInternalsTest* net_internals_test_;
 
+  base::WeakPtrFactory<MessageHandler> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(MessageHandler);
 };
 
 NetInternalsTest::MessageHandler::MessageHandler(
     NetInternalsTest* net_internals_test)
-    : net_internals_test_(net_internals_test) {}
+    : net_internals_test_(net_internals_test), weak_factory_(this) {}
 
 void NetInternalsTest::MessageHandler::RegisterMessages() {
   RegisterMessage(
       "getTestServerURL",
       base::BindRepeating(&NetInternalsTest::MessageHandler::GetTestServerURL,
-                          base::Unretained(this)));
-  RegisterMessage(
-      "addCacheEntry",
-      base::BindRepeating(&NetInternalsTest::MessageHandler::AddCacheEntry,
-                          base::Unretained(this)));
+                          weak_factory_.GetWeakPtr()));
   RegisterMessage(
       "setUpTestReportURI",
       base::BindRepeating(&NetInternalsTest::MessageHandler::SetUpTestReportURI,
-                          base::Unretained(this)));
+                          weak_factory_.GetWeakPtr()));
+  RegisterMessage("dnsLookup", base::BindRepeating(
+                                   &NetInternalsTest::MessageHandler::DnsLookup,
+                                   weak_factory_.GetWeakPtr()));
 }
 
 void NetInternalsTest::MessageHandler::RegisterMessage(
@@ -166,7 +167,7 @@
   web_ui()->RegisterMessageCallback(
       message,
       base::BindRepeating(&NetInternalsTest::MessageHandler::HandleMessage,
-                          base::Unretained(this), handler));
+                          weak_factory_.GetWeakPtr(), handler));
 }
 
 void NetInternalsTest::MessageHandler::HandleMessage(
@@ -192,33 +193,6 @@
   RunJavascriptCallback(url_value.get());
 }
 
-void NetInternalsTest::MessageHandler::AddCacheEntry(
-    const base::ListValue* list_value) {
-  std::string hostname;
-  std::string ip_literal;
-  double net_error;
-  double expire_days_from_now;
-  ASSERT_TRUE(list_value->GetString(0, &hostname));
-  ASSERT_TRUE(list_value->GetString(1, &ip_literal));
-  ASSERT_TRUE(list_value->GetDouble(2, &net_error));
-  ASSERT_TRUE(list_value->GetDouble(3, &expire_days_from_now));
-  ASSERT_TRUE(browser());
-
-  if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
-    // TODO(mattm): implement this with a ForTesting method on NetworkContext
-    // when it's needed.
-    return;
-  }
-
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::IO},
-      base::BindOnce(
-          &AddCacheEntryOnIOThread,
-          base::RetainedRef(browser()->profile()->GetRequestContext()),
-          hostname, ip_literal, static_cast<int>(net_error),
-          static_cast<int>(expire_days_from_now)));
-}
-
 void NetInternalsTest::MessageHandler::SetUpTestReportURI(
     const base::ListValue* list_value) {
   net_internals_test_->embedded_test_server()->RegisterRequestHandler(
@@ -229,6 +203,28 @@
   RunJavascriptCallback(&report_uri_value);
 }
 
+void NetInternalsTest::MessageHandler::DnsLookup(
+    const base::ListValue* list_value) {
+  std::string hostname;
+  bool local;
+  ASSERT_TRUE(list_value->GetString(0, &hostname));
+  ASSERT_TRUE(list_value->GetBoolean(1, &local));
+  ASSERT_TRUE(browser());
+
+  auto resolve_host_parameters = network::mojom::ResolveHostParameters::New();
+  if (local)
+    resolve_host_parameters->source = net::HostResolverSource::LOCAL_ONLY;
+  network::mojom::ResolveHostClientPtr client_ptr;
+  // DnsLookupClient owns itself.
+  new DnsLookupClient(mojo::MakeRequest(&client_ptr),
+                      base::BindOnce(&MessageHandler::RunJavascriptCallback,
+                                     weak_factory_.GetWeakPtr()));
+  content::BrowserContext::GetDefaultStoragePartition(browser()->profile())
+      ->GetNetworkContext()
+      ->ResolveHost(net::HostPortPair(hostname, 80),
+                    std::move(resolve_host_parameters), std::move(client_ptr));
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // NetInternalsTest
 ////////////////////////////////////////////////////////////////////////////////
@@ -241,6 +237,11 @@
 NetInternalsTest::~NetInternalsTest() {
 }
 
+void NetInternalsTest::SetUpOnMainThread() {
+  WebUIBrowserTest::SetUpOnMainThread();
+  host_resolver()->AddRule("*", "127.0.0.1");
+}
+
 content::WebUIMessageHandler* NetInternalsTest::GetMockMessageHandler() {
   return message_handler_.get();
 }
diff --git a/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.h b/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.h
index 86d996e..a3d2845b 100644
--- a/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.h
+++ b/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.h
@@ -15,6 +15,8 @@
   NetInternalsTest();
   ~NetInternalsTest() override;
 
+  void SetUpOnMainThread() override;
+
  private:
   class MessageHandler;
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc b/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc
index 1e875bc..8af7cb2 100644
--- a/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc
@@ -21,7 +21,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/prefs/pref_service.h"
 #include "components/session_manager/core/session_manager.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -62,9 +62,8 @@
       binding_(this),
       session_observer_(this),
       weak_ptr_factory_(this) {
-  service_manager::Connector* connector =
-      content::ServiceManagerConnection::GetForProcess()->GetConnector();
-  connector->BindInterface(device::mojom::kServiceName, &fp_service_);
+  content::GetSystemConnector()->BindInterface(device::mojom::kServiceName,
+                                               &fp_service_);
   user_id_ = ProfileHelper::Get()->GetUserIdHashFromProfile(profile);
 }
 
diff --git a/chrome/browser/ui/webui/settings/settings_security_key_handler.cc b/chrome/browser/ui/webui/settings/settings_security_key_handler.cc
index 834603a..eb03b1d 100644
--- a/chrome/browser/ui/webui/settings/settings_security_key_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_security_key_handler.cc
@@ -10,8 +10,8 @@
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
 #include "chrome/browser/ui/webui/settings/settings_security_key_handler.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_ui.h"
-#include "content/public/common/service_manager_connection.h"
 #include "device/fido/pin.h"
 #include "device/fido/reset_request_handler.h"
 #include "device/fido/set_pin_request_handler.h"
@@ -92,8 +92,7 @@
   callback_id_ = args->GetList()[0].GetString();
   state_ = State::kStartSetPIN;
   set_pin_ = std::make_unique<device::SetPINRequestHandler>(
-      content::ServiceManagerConnection::GetForProcess()->GetConnector(),
-      supported_transports(),
+      content::GetSystemConnector(), supported_transports(),
       base::BindOnce(&SecurityKeysHandler::OnGatherPIN,
                      weak_factory_->GetWeakPtr()),
       base::BindRepeating(&SecurityKeysHandler::OnSetPINComplete,
@@ -166,8 +165,7 @@
 
   state_ = State::kStartReset;
   reset_ = std::make_unique<device::ResetRequestHandler>(
-      content::ServiceManagerConnection::GetForProcess()->GetConnector(),
-      supported_transports(),
+      content::GetSystemConnector(), supported_transports(),
       base::BindOnce(&SecurityKeysHandler::OnResetSent,
                      weak_factory_->GetWeakPtr()),
       base::BindOnce(&SecurityKeysHandler::OnResetFinished,
diff --git a/chrome/browser/ui/webui/usb_internals/usb_internals_page_handler.cc b/chrome/browser/ui/webui/usb_internals/usb_internals_page_handler.cc
index 3775ba9..c5989ed 100644
--- a/chrome/browser/ui/webui/usb_internals/usb_internals_page_handler.cc
+++ b/chrome/browser/ui/webui/usb_internals/usb_internals_page_handler.cc
@@ -6,7 +6,7 @@
 
 #include <utility>
 
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 
@@ -19,15 +19,13 @@
 void UsbInternalsPageHandler::BindTestInterface(
     device::mojom::UsbDeviceManagerTestRequest request) {
   // Forward the request to the DeviceService.
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(device::mojom::kServiceName, std::move(request));
+  content::GetSystemConnector()->BindInterface(device::mojom::kServiceName,
+                                               std::move(request));
 }
 
 void UsbInternalsPageHandler::BindUsbDeviceManagerInterface(
     device::mojom::UsbDeviceManagerRequest request) {
   // Forward the request to the DeviceService.
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(device::mojom::kServiceName, std::move(request));
+  content::GetSystemConnector()->BindInterface(device::mojom::kServiceName,
+                                               std::move(request));
 }
diff --git a/chrome/browser/ui/webui/welcome/welcome_win10_handler.cc b/chrome/browser/ui/webui/welcome/welcome_win10_handler.cc
index 954431f..0b6d789 100644
--- a/chrome/browser/ui/webui/welcome/welcome_win10_handler.cc
+++ b/chrome/browser/ui/webui/welcome/welcome_win10_handler.cc
@@ -17,8 +17,8 @@
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/common/url_constants.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/service_manager_connection.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "url/gurl.h"
 
@@ -48,13 +48,6 @@
       is_pinned);
 }
 
-// Returns a new Connector that can be used on a different thread.
-std::unique_ptr<service_manager::Connector> GetClonedConnector() {
-  return content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->Clone();
-}
-
 }  // namespace
 
 WelcomeWin10Handler::WelcomeWin10Handler() : weak_ptr_factory_(this) {
@@ -82,7 +75,7 @@
     base::Closure error_callback =
         base::Bind(&RecordPinnedResult, histogram_suffix, false, false);
     shell_integration::win::GetIsPinnedToTaskbarState(
-        GetClonedConnector(), error_callback,
+        content::GetSystemConnector()->Clone(), error_callback,
         base::Bind(&RecordPinnedResult, histogram_suffix));
   }
 }
@@ -158,7 +151,7 @@
                  weak_ptr_factory_.GetWeakPtr(), false, true);
 
   shell_integration::win::GetIsPinnedToTaskbarState(
-      GetClonedConnector(), error_callback,
+      content::GetSystemConnector()->Clone(), error_callback,
       base::Bind(&WelcomeWin10Handler::OnIsPinnedToTaskbarResult,
                  weak_ptr_factory_.GetWeakPtr()));
 }
diff --git a/chrome/browser/usb/usb_chooser_context.cc b/chrome/browser/usb/usb_chooser_context.cc
index c3e534b..5efd847 100644
--- a/chrome/browser/usb/usb_chooser_context.cc
+++ b/chrome/browser/usb/usb_chooser_context.cc
@@ -20,7 +20,7 @@
 #include "chrome/browser/usb/usb_blocklist.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/content_settings/core/common/content_settings.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/device/public/cpp/usb/usb_ids.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/device/public/mojom/usb_device.mojom.h"
@@ -181,10 +181,8 @@
     return;
 
   // Request UsbDeviceManagerPtr from DeviceService.
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(device::mojom::kServiceName,
-                      mojo::MakeRequest(&device_manager_));
+  content::GetSystemConnector()->BindInterface(
+      device::mojom::kServiceName, mojo::MakeRequest(&device_manager_));
 
   SetUpDeviceManagerConnection();
 }
diff --git a/chrome/browser/usb/web_usb_detector.cc b/chrome/browser/usb/web_usb_detector.cc
index b4b2f0e..a58ef13 100644
--- a/chrome/browser/usb/web_usb_detector.cc
+++ b/chrome/browser/usb/web_usb_detector.cc
@@ -25,9 +25,9 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/url_formatter/elide_url.h"
 #include "components/vector_icons/vector_icons.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/origin_util.h"
-#include "content/public/common/service_manager_connection.h"
 #include "device/base/features.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/device/public/mojom/usb_device.mojom.h"
@@ -195,10 +195,8 @@
   // Tests may set a fake manager.
   if (!device_manager_) {
     // Request UsbDeviceManagerPtr from DeviceService.
-    content::ServiceManagerConnection::GetForProcess()
-        ->GetConnector()
-        ->BindInterface(device::mojom::kServiceName,
-                        mojo::MakeRequest(&device_manager_));
+    content::GetSystemConnector()->BindInterface(
+        device::mojom::kServiceName, mojo::MakeRequest(&device_manager_));
   }
   DCHECK(device_manager_);
   device_manager_.set_connection_error_handler(base::BindOnce(
diff --git a/chrome/browser/vr/service/isolated_device_provider.cc b/chrome/browser/vr/service/isolated_device_provider.cc
index 81c14d9e..a5597ef0 100644
--- a/chrome/browser/vr/service/isolated_device_provider.cc
+++ b/chrome/browser/vr/service/isolated_device_provider.cc
@@ -6,7 +6,7 @@
 
 #include "base/bind.h"
 #include "chrome/browser/vr/service/vr_ui_host.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "device/vr/buildflags/buildflags.h"
 #include "device/vr/isolated_gamepad_data_fetcher.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -98,9 +98,7 @@
 }
 
 void IsolatedVRDeviceProvider::SetupDeviceProvider() {
-  content::ServiceManagerConnection* connection =
-      content::ServiceManagerConnection::GetForProcess();
-  connection->GetConnector()->BindInterface(
+  content::GetSystemConnector()->BindInterface(
       device::mojom::kVrIsolatedServiceName,
       mojo::MakeRequest(&device_provider_));
 
diff --git a/chrome/browser/vr/service/xr_runtime_manager.cc b/chrome/browser/vr/service/xr_runtime_manager.cc
index f0703bb..c6dc4e9f 100644
--- a/chrome/browser/vr/service/xr_runtime_manager.cc
+++ b/chrome/browser/vr/service/xr_runtime_manager.cc
@@ -14,8 +14,8 @@
 #include "build/build_config.h"
 #include "chrome/browser/vr/service/browser_xr_runtime.h"
 #include "chrome/common/chrome_features.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/content_features.h"
-#include "content/public/common/service_manager_connection.h"
 #include "device/vr/buildflags/buildflags.h"
 #include "device/vr/orientation/orientation_device_provider.h"
 #include "device/vr/vr_device_provider.h"
@@ -99,12 +99,10 @@
 #endif
 #endif  // ENABLE_ISOLATED_XR_SERVICE
 
-  content::ServiceManagerConnection* connection =
-      content::ServiceManagerConnection::GetForProcess();
-  if (connection) {
+  auto* connector = content::GetSystemConnector();
+  if (connector) {
     providers.emplace_back(
-        std::make_unique<device::VROrientationDeviceProvider>(
-            connection->GetConnector()));
+        std::make_unique<device::VROrientationDeviceProvider>(connector));
   }
 
   return CreateInstance(std::move(providers));
diff --git a/chrome/browser/vr/sounds_manager_audio_delegate.cc b/chrome/browser/vr/sounds_manager_audio_delegate.cc
index 2781c563..8078115 100644
--- a/chrome/browser/vr/sounds_manager_audio_delegate.cc
+++ b/chrome/browser/vr/sounds_manager_audio_delegate.cc
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/vr/sounds_manager_audio_delegate.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/audio/public/cpp/sounds/sounds_manager.h"
 
 namespace vr {
@@ -29,12 +29,8 @@
   DCHECK_NE(id, kSoundNone);
   DCHECK(sounds_.find(id) == sounds_.end());
 
-  if (sounds_.empty()) {
-    audio::SoundsManager::Create(
-        content::ServiceManagerConnection::GetForProcess()
-            ->GetConnector()
-            ->Clone());
-  }
+  if (sounds_.empty())
+    audio::SoundsManager::Create(content::GetSystemConnector()->Clone());
 
   sounds_[id] = std::move(data);
   return audio::SoundsManager::Get()->Initialize(id, *sounds_[id]);
diff --git a/chrome/browser/vr/test/mock_xr_device_hook_base.cc b/chrome/browser/vr/test/mock_xr_device_hook_base.cc
index 65fd3db..4634c5dc 100644
--- a/chrome/browser/vr/test/mock_xr_device_hook_base.cc
+++ b/chrome/browser/vr/test/mock_xr_device_hook_base.cc
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/vr/test/mock_xr_device_hook_base.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "device/vr/public/mojom/isolated_xr_service.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 
@@ -52,9 +52,7 @@
     : tracked_classes_{device_test::mojom::TrackedDeviceClass::
                            kTrackedDeviceInvalid},
       binding_(this) {
-  content::ServiceManagerConnection* connection =
-      content::ServiceManagerConnection::GetForProcess();
-  connection->GetConnector()->BindInterface(
+  content::GetSystemConnector()->BindInterface(
       device::mojom::kVrIsolatedServiceName,
       mojo::MakeRequest(&service_test_hook_));
 
diff --git a/chrome/browser/vr/ui_host/vr_ui_host_impl.cc b/chrome/browser/vr/ui_host/vr_ui_host_impl.cc
index deead21..7a417ae6 100644
--- a/chrome/browser/vr/ui_host/vr_ui_host_impl.cc
+++ b/chrome/browser/vr/ui_host/vr_ui_host_impl.cc
@@ -23,7 +23,7 @@
 #include "chrome/browser/vr/win/vr_browser_renderer_thread_win.h"
 #include "chrome/common/chrome_features.h"
 #include "content/public/browser/navigation_entry.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "device/vr/buildflags/buildflags.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -138,9 +138,8 @@
     runtime->AddObserver(this);
   }
 
-  auto* connector =
-      content::ServiceManagerConnection::GetForProcess()->GetConnector();
-  connector->BindInterface(device::mojom::kServiceName, &geolocation_config_);
+  content::GetSystemConnector()->BindInterface(device::mojom::kServiceName,
+                                               &geolocation_config_);
 }
 
 VRUiHostImpl::~VRUiHostImpl() {
diff --git a/chrome/browser/win/chrome_select_file_dialog_factory.cc b/chrome/browser/win/chrome_select_file_dialog_factory.cc
index 9da1c826..b9c909101 100644
--- a/chrome/browser/win/chrome_select_file_dialog_factory.cc
+++ b/chrome/browser/win/chrome_select_file_dialog_factory.cc
@@ -9,12 +9,10 @@
 #include "base/bind.h"
 #include "base/feature_list.h"
 #include "base/metrics/histogram_functions.h"
-#include "base/task/post_task.h"
 #include "base/win/win_util.h"
 #include "chrome/services/util_win/public/mojom/constants.mojom.h"
 #include "chrome/services/util_win/public/mojom/util_win.mojom.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "mojo/public/cpp/bindings/sync_call_restrictions.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "ui/shell_dialogs/execute_select_file_win.h"
@@ -29,13 +27,6 @@
                                       base::FEATURE_ENABLED_BY_DEFAULT};
 }  // namespace
 
-std::unique_ptr<service_manager::Connector> GetConnectorOnUIThread() {
-  return content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->Clone();
-}
-// static
-
 // Helper class to execute a select file operation on a utility process. It
 // hides the complexity of managing the lifetime of the connection to the
 // UtilWin service.
@@ -64,18 +55,6 @@
       HWND owner,
       ui::OnSelectFileExecutedCallback on_select_file_executed_callback);
 
-  // Invoked back on the sequence this instance was created on when the
-  // connector is received from the UI thread.
-  void OnConnectorReceived(
-      ui::SelectFileDialog::Type type,
-      const base::string16& title,
-      const base::FilePath& default_path,
-      const std::vector<ui::FileFilterSpec>& filter,
-      int file_type_index,
-      const base::string16& default_extension,
-      HWND owner,
-      std::unique_ptr<service_manager::Connector> connector);
-
   // Connection error handler for the interface pipe.
   void OnConnectionError();
 
@@ -123,25 +102,8 @@
     ui::OnSelectFileExecutedCallback on_select_file_executed_callback)
     : on_select_file_executed_callback_(
           std::move(on_select_file_executed_callback)) {
-  // A valid connector is required to create the interface pointer.
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {content::BrowserThread::UI},
-      base::BindOnce(&GetConnectorOnUIThread),
-      base::BindOnce(&UtilWinHelper::OnConnectorReceived,
-                     base::Unretained(this), type, title, default_path, filter,
-                     file_type_index, default_extension, owner));
-}
-
-void UtilWinHelper::OnConnectorReceived(
-    ui::SelectFileDialog::Type type,
-    const base::string16& title,
-    const base::FilePath& default_path,
-    const std::vector<ui::FileFilterSpec>& filter,
-    int file_type_index,
-    const base::string16& default_extension,
-    HWND owner,
-    std::unique_ptr<service_manager::Connector> connector) {
-  connector->BindInterface(chrome::mojom::kUtilWinServiceName, &util_win_ptr_);
+  content::GetSystemConnector()->BindInterface(
+      chrome::mojom::kUtilWinServiceName, &util_win_ptr_);
 
   // |util_win_ptr_| owns the callbacks and is guaranteed to be destroyed before
   // |this|, therefore making base::Unretained() safe to use.
diff --git a/chrome/common/extensions/api/accessibility_private.json b/chrome/common/extensions/api/accessibility_private.json
index 25f85a7..6e26756 100644
--- a/chrome/common/extensions/api/accessibility_private.json
+++ b/chrome/common/extensions/api/accessibility_private.json
@@ -39,6 +39,12 @@
         "description": "Accessibility gestures fired by the touch exploration controller."
       },
       {
+        "id": "SwitchAccessCommand",
+        "type": "string",
+        "enum": [ "select", "next", "previous" ],
+        "description": "Commands that can be triggered by switch activation."
+      },
+      {
         "id": "SyntheticKeyboardEventType",
         "type": "string",
         "description": "The event to send",
@@ -407,6 +413,18 @@
         "platforms": ["chromeos"]
       },
       {
+        "name": "onSwitchAccessCommand",
+        "type": "function",
+        "description": "Called when Chrome OS has received a key event corresponding to a Switch Access command.",
+        "parameters": [
+          {
+            "name": "command",
+            "$ref": "SwitchAccessCommand"
+          }
+        ],
+        "platforms": ["chromeos"]
+      },
+      {
         "name": "onAnnounceForAccessibility",
         "type": "function",
         "description": "Called when an internal component within accessibility wants to force speech output for an accessibility extension. Do not use without approval from accessibility owners.",
diff --git a/chrome/common/extensions/api/bookmark_manager_private.json b/chrome/common/extensions/api/bookmark_manager_private.json
index 922e930c..19bfd70 100644
--- a/chrome/common/extensions/api/bookmark_manager_private.json
+++ b/chrome/common/extensions/api/bookmark_manager_private.json
@@ -123,6 +123,18 @@
             "name": "isFromTouch",
             "type": "boolean",
             "description": "True if the drag was initiated from touch."
+          },
+          {
+            "name": "x",
+            "type": "integer",
+            "minimum": 0,
+            "description": "The clientX of the dragStart event"
+          },
+          {
+            "name": "y",
+            "type": "integer",
+            "minimum": 0,
+            "description": "The clientY of the dragStart event"
           }
         ]
       },
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_base.cc b/chrome/credential_provider/gaiacp/gaia_credential_base.cc
index 5001663a..0c5128d9 100644
--- a/chrome/credential_provider/gaiacp/gaia_credential_base.cc
+++ b/chrome/credential_provider/gaiacp/gaia_credential_base.cc
@@ -1538,7 +1538,9 @@
     return E_INVALIDARG;
   }
 
-  std::string access_token = GetDictStringUTF8(properties, kKeyPassword);
+  // TODO(crbug.com/976744): Use the down scoped kKeyMdmAccessToken instead
+  // of login scoped token.
+  std::string access_token = GetDictStringUTF8(properties, kKeyAccessToken);
   if (!access_token.empty()) {
     // Update the password recovery information if possible.
     HRESULT hr = PasswordRecoveryManager::Get()->StoreWindowsPasswordIfNeeded(
@@ -1807,8 +1809,8 @@
   // password update prompt and continue without authenticating on the provider.
   if (!AreCredentialsValid()) {
     // Change UI into a mode where it expects to have the old password entered.
-    DisplayPasswordField(IDS_PASSWORD_UPDATE_NEEDED_BASE);
     base::string16 old_windows_password;
+    needs_windows_password_ = true;
 
     // Pre-fill the old password if possible so that the sign in will proceed to
     // automatically update the password.
@@ -1816,10 +1818,10 @@
       current_windows_password_ =
           ::SysAllocString(old_windows_password.c_str());
       SecurelyClearString(old_windows_password);
-
+    } else {
       // Fall-through to continue with auto sign in and try the recovered
       // password.
-    } else {
+      DisplayPasswordField(IDS_PASSWORD_UPDATE_NEEDED_BASE);
       return S_FALSE;
     }
   }
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc b/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc
index 6eee29a..dbec687 100644
--- a/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc
+++ b/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc
@@ -21,6 +21,8 @@
 
 namespace testing {
 
+constexpr char kFakeResourceId[] = "fake_resource_id";
+
 class GcpGaiaCredentialBaseTest : public GlsRunnerTestBase {};
 
 TEST_F(GcpGaiaCredentialBaseTest, Advise) {
@@ -968,7 +970,7 @@
   // retrieval.
   std::string generate_success_response =
       fake_password_recovery_manager()->MakeGenerateKeyPairResponseForTesting(
-          "public_key", "resource_id");
+          "public_key", kFakeResourceId);
 
   std::string get_key_success_response =
       fake_password_recovery_manager()->MakeGetPrivateKeyResponseForTesting(
@@ -996,7 +998,8 @@
       generate_key_event ? generate_key_event->handle() : INVALID_HANDLE_VALUE);
 
   fake_http_url_fetcher_factory()->SetFakeResponse(
-      fake_password_recovery_manager()->GetEscrowServiceGetPrivateKeyUrl(),
+      fake_password_recovery_manager()->GetEscrowServiceGetPrivateKeyUrl(
+          kFakeResourceId),
       FakeWinHttpUrlFetcher::Headers(),
       get_private_key_result != 1 ? get_key_success_response : "{}",
       get_key_event ? get_key_event->handle() : INVALID_HANDLE_VALUE);
@@ -1192,7 +1195,7 @@
   // retrieval.
   std::string generate_success_response =
       fake_password_recovery_manager()->MakeGenerateKeyPairResponseForTesting(
-          "public_key", "resource_id");
+          "public_key", kFakeResourceId);
 
   std::string get_key_success_response =
       fake_password_recovery_manager()->MakeGetPrivateKeyResponseForTesting(
@@ -1203,7 +1206,8 @@
       FakeWinHttpUrlFetcher::Headers(), generate_success_response);
 
   fake_http_url_fetcher_factory()->SetFakeResponse(
-      fake_password_recovery_manager()->GetEscrowServiceGetPrivateKeyUrl(),
+      fake_password_recovery_manager()->GetEscrowServiceGetPrivateKeyUrl(
+          kFakeResourceId),
       FakeWinHttpUrlFetcher::Headers(), get_key_success_response);
 
   // Sign on once to store the password in the LSA
diff --git a/chrome/credential_provider/gaiacp/password_recovery_manager.cc b/chrome/credential_provider/gaiacp/password_recovery_manager.cc
index ee7b2de..9fbb976 100644
--- a/chrome/credential_provider/gaiacp/password_recovery_manager.cc
+++ b/chrome/credential_provider/gaiacp/password_recovery_manager.cc
@@ -17,6 +17,7 @@
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
 #include "base/stl_util.h"
+#include "base/strings/strcat.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/credential_provider/common/gcp_strings.h"
@@ -44,16 +45,13 @@
     "encrypted_password";
 
 // Constants used for contacting the password escrow service.
-const char kEscrowServiceGenerateKeyPairPath[] = "/v1/generateKeyPair";
-const char kGenerateKeyPairRequestDeviceIdParameterName[] = "device_id";
-const char kGenerateKeyPairResponsePublicKeyParameterName[] =
-    "base64_public_key";
-const char kGenerateKeyPairResponseResourceIdParameterName[] = "resource_id";
+const char kEscrowServiceGenerateKeyPairPath[] = "/v1/generatekeypair";
+const char kGenerateKeyPairRequestDeviceIdParameterName[] = "deviceId";
+const char kGenerateKeyPairResponsePublicKeyParameterName[] = "base64PublicKey";
+const char kGenerateKeyPairResponseResourceIdParameterName[] = "resourceId";
 
-const char kEscrowServiceGetPrivateKeyPath[] = "/v1/getPrivateKey";
-const char kGetPrivateKeyRequestResourceIdParameterName[] = "resource_id";
-const char kGetPrivateKeyResponsePrivateKeyParameterName[] =
-    "base64_private_key";
+const char kEscrowServiceGetPrivateKeyPath[] = "/v1/getprivatekey";
+const char kGetPrivateKeyResponsePrivateKeyParameterName[] = "base64PrivateKey";
 
 constexpr wchar_t kUserPasswordLsaStoreKeyPrefix[] =
 #if defined(GOOGLE_CHROME_BUILD)
@@ -132,7 +130,6 @@
     result = base::JSONReader::Read(
         base::StringPiece(response_.data(), response_.size()),
         base::JSON_ALLOW_TRAILING_COMMAS);
-
     if (!result || !result->is_dict()) {
       LOGFN(ERROR) << "Failed to read json result from server response";
       result.reset();
@@ -236,21 +233,25 @@
   for (auto& header : headers)
     url_fetcher->SetRequestHeader(header.first.c_str(), header.second.c_str());
 
-  base::Value request_dict(base::Value::Type::DICTIONARY);
+  HRESULT hr = S_OK;
 
-  for (auto& parameter : parameters)
-    request_dict.SetStringKey(parameter.first, parameter.second);
+  if (!parameters.empty()) {
+    base::Value request_dict(base::Value::Type::DICTIONARY);
 
-  std::string json;
-  if (!base::JSONWriter::Write(request_dict, &json)) {
-    LOGFN(ERROR) << "base::JSONWriter::Write failed";
-    return E_FAIL;
-  }
+    for (auto& parameter : parameters)
+      request_dict.SetStringKey(parameter.first, parameter.second);
 
-  HRESULT hr = url_fetcher->SetRequestBody(json.c_str());
-  if (FAILED(hr)) {
-    LOGFN(ERROR) << "fetcher.SetRequestBody hr=" << putHR(hr);
-    return E_FAIL;
+    std::string json;
+    if (!base::JSONWriter::Write(request_dict, &json)) {
+      LOGFN(ERROR) << "base::JSONWriter::Write failed";
+      return E_FAIL;
+    }
+
+    hr = url_fetcher->SetRequestBody(json.c_str());
+    if (FAILED(hr)) {
+      LOGFN(ERROR) << "fetcher.SetRequestBody hr=" << putHR(hr);
+      return E_FAIL;
+    }
   }
 
   base::Optional<base::Value> request_result =
@@ -366,9 +367,9 @@
 
   // Fetch the results and extract the |private_key| to be used for decryption.
   HRESULT hr = BuildRequestAndFetchResultFromEscrowService(
-      PasswordRecoveryManager::Get()->GetEscrowServiceGetPrivateKeyUrl(),
-      {MakeAuthorizationHeader(access_token)},
-      {{kGetPrivateKeyRequestResourceIdParameterName, *resource_id}},
+      PasswordRecoveryManager::Get()->GetEscrowServiceGetPrivateKeyUrl(
+          *resource_id),
+      {MakeAuthorizationHeader(access_token)}, {},
       {
           {kGetPrivateKeyResponsePrivateKeyParameterName, &private_key},
       },
@@ -580,7 +581,8 @@
   return escrow_service_server.Resolve(kEscrowServiceGenerateKeyPairPath);
 }
 
-GURL PasswordRecoveryManager::GetEscrowServiceGetPrivateKeyUrl() {
+GURL PasswordRecoveryManager::GetEscrowServiceGetPrivateKeyUrl(
+    const std::string& resource_id) {
   if (!MdmPasswordRecoveryEnabled())
     return GURL();
 
@@ -591,7 +593,8 @@
     return GURL();
   }
 
-  return escrow_service_server.Resolve(kEscrowServiceGetPrivateKeyPath);
+  return escrow_service_server.Resolve(
+      base::StrCat({kEscrowServiceGetPrivateKeyPath, "/", resource_id}));
 }
 
 std::string PasswordRecoveryManager::MakeGenerateKeyPairResponseForTesting(
diff --git a/chrome/credential_provider/gaiacp/password_recovery_manager.h b/chrome/credential_provider/gaiacp/password_recovery_manager.h
index b8dfceae..0d434700 100644
--- a/chrome/credential_provider/gaiacp/password_recovery_manager.h
+++ b/chrome/credential_provider/gaiacp/password_recovery_manager.h
@@ -41,7 +41,7 @@
   // Calculates the full url of various escrow service requests based on
   // the registry setting for the escrow server url.
   GURL GetEscrowServiceGenerateKeyPairUrl();
-  GURL GetEscrowServiceGetPrivateKeyUrl();
+  GURL GetEscrowServiceGetPrivateKeyUrl(const std::string& resource_id);
 
  protected:
   // Returns the storage used for the instance pointer.
diff --git a/chrome/services/file_util/public/cpp/zip_file_creator_browsertest.cc b/chrome/services/file_util/public/cpp/zip_file_creator_browsertest.cc
index cea017a0..3ac753f 100644
--- a/chrome/services/file_util/public/cpp/zip_file_creator_browsertest.cc
+++ b/chrome/services/file_util/public/cpp/zip_file_creator_browsertest.cc
@@ -15,7 +15,7 @@
 #include "base/run_loop.h"
 #include "base/threading/thread_restrictions.h"
 #include "chrome/test/base/in_process_browser_test.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/test/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/zlib/google/zip_reader.h"
@@ -63,8 +63,7 @@
        base::Bind(&TestCallback, &success,
                   content::GetDeferredQuitTaskForRunLoop(&run_loop)),
        zip_base_dir(), paths, zip_archive_path()))
-      ->Start(
-          content::ServiceManagerConnection::GetForProcess()->GetConnector());
+      ->Start(content::GetSystemConnector());
 
   content::RunThisRunLoop(&run_loop);
   EXPECT_FALSE(success);
@@ -96,8 +95,7 @@
        base::Bind(&TestCallback, &success,
                   content::GetDeferredQuitTaskForRunLoop(&run_loop)),
        zip_base_dir(), paths, zip_archive_path()))
-      ->Start(
-          content::ServiceManagerConnection::GetForProcess()->GetConnector());
+      ->Start(content::GetSystemConnector());
 
   content::RunThisRunLoop(&run_loop);
   EXPECT_TRUE(success);
@@ -192,8 +190,7 @@
        base::Bind(&TestCallback, &success, run_loop.QuitClosure()), root_dir,
        std::vector<base::FilePath>(),  // Empty means zip everything in dir.
        zip_archive_path()))
-      ->Start(
-          content::ServiceManagerConnection::GetForProcess()->GetConnector());
+      ->Start(content::GetSystemConnector());
 
   content::RunThisRunLoop(&run_loop);
   EXPECT_TRUE(success);
diff --git a/chrome/services/media_gallery_util/public/cpp/media_gallery_util_browsertest.cc b/chrome/services/media_gallery_util/public/cpp/media_gallery_util_browsertest.cc
index 71cc64d4..3fdbe5d 100644
--- a/chrome/services/media_gallery_util/public/cpp/media_gallery_util_browsertest.cc
+++ b/chrome/services/media_gallery_util/public/cpp/media_gallery_util_browsertest.cc
@@ -9,7 +9,7 @@
 #include "chrome/services/media_gallery_util/public/cpp/media_parser_provider.h"
 #include "chrome/services/media_gallery_util/public/mojom/constants.mojom.h"
 #include "chrome/test/base/in_process_browser_test.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "media/media_buildflags.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -52,11 +52,9 @@
 // Tests that the MediaParserProvider class used by the client library classes
 // does initialize the CPU info correctly.
 IN_PROC_BROWSER_TEST_F(MediaGalleryUtilBrowserTest, TestThirdPartyCpuInfo) {
-  service_manager::Connector* connector =
-      content::ServiceManagerConnection::GetForProcess()->GetConnector();
   TestMediaParserProvider media_parser_provider;
   chrome::mojom::MediaParser* media_parser =
-      media_parser_provider.GetMediaParser(connector);
+      media_parser_provider.GetMediaParser(content::GetSystemConnector());
 
   base::RunLoop run_loop;
   media_parser->GetCpuInfo(base::BindOnce(
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 4477ee4..28ff84d 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2332,6 +2332,7 @@
     if (is_win) {
       sources += [
         "../browser/printing/pdf_to_emf_converter_browsertest.cc",
+        "../browser/spellchecker/spell_check_host_chrome_impl_win_browsertest.cc",
         "../browser/ui/startup/credential_provider_signin_dialog_win_browsertest.cc",
         "../browser/ui/views/accessibility/invert_bubble_view_browsertest.cc",
         "../browser/ui/views/settings_reset_prompt_dialog_browsertest.cc",
@@ -3956,7 +3957,7 @@
       "../tools/convert_dict/convert_dict_unittest.cc",
     ]
 
-    if (!use_browser_spellchecker) {
+    if (use_renderer_spellchecker) {
       sources +=
           [ "../browser/spellchecker/spell_check_host_chrome_impl_unittest.cc" ]
     }
diff --git a/chrome/test/base/in_process_browser_test.cc b/chrome/test/base/in_process_browser_test.cc
index 5296fd3..41a45ad 100644
--- a/chrome/test/base/in_process_browser_test.cc
+++ b/chrome/test/base/in_process_browser_test.cc
@@ -90,6 +90,7 @@
 #endif
 
 #if defined(OS_CHROMEOS)
+#include "ash/public/cpp/test/shell_test_api.h"
 #include "base/system/sys_info.h"
 #include "chrome/browser/chromeos/input_method/input_method_configuration.h"
 #include "chrome/test/base/default_ash_event_generator_delegate.h"
@@ -278,6 +279,10 @@
   // access to all files here since browser_tests and interactive_ui_tests
   // rely on the ability to open any files via file: scheme.
   ChromeNetworkDelegate::EnableAccessToAllFilesForTesting(true);
+
+  // Using a screenshot for clamshell to tablet mode transitions makes the flow
+  // async which we want to disable for most tests.
+  ash::ShellTestApi::SetTabletControllerUseScreenshotForTest(false);
 #endif  // defined(OS_CHROMEOS)
 
   // Use hardcoded quota settings to have a consistent testing environment.
diff --git a/chrome/test/base/test_service_manager_listener.cc b/chrome/test/base/test_service_manager_listener.cc
index 4ce21ff..a19a7f7 100644
--- a/chrome/test/base/test_service_manager_listener.cc
+++ b/chrome/test/base/test_service_manager_listener.cc
@@ -6,7 +6,7 @@
 
 #include "base/run_loop.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/service_manager/public/cpp/connector.h"
 
 TestServiceManagerListener::TestServiceManagerListener() : binding_(this) {}
@@ -18,10 +18,8 @@
   // Register a listener on the ServiceManager to track when services are
   // started.
   mojo::InterfacePtr<service_manager::mojom::ServiceManager> service_manager;
-  service_manager::Connector* connector =
-      content::ServiceManagerConnection::GetForProcess()->GetConnector();
-  connector->BindInterface(service_manager::mojom::kServiceName,
-                           &service_manager);
+  content::GetSystemConnector()->BindInterface(
+      service_manager::mojom::kServiceName, &service_manager);
   service_manager::mojom::ServiceManagerListenerPtr listener_ptr;
   binding_.Bind(mojo::MakeRequest(&listener_ptr));
   service_manager->AddListener(std::move(listener_ptr));
diff --git a/chrome/test/chromedriver/chrome/navigation_tracker.cc b/chrome/test/chromedriver/chrome/navigation_tracker.cc
index f099fa2..02abf6b 100644
--- a/chrome/test/chromedriver/chrome/navigation_tracker.cc
+++ b/chrome/test/chromedriver/chrome/navigation_tracker.cc
@@ -181,6 +181,17 @@
       loading_state_ = kLoading;
       load_event_fired_ = false;
     }
+  } else if (method == "Page.frameStoppedLoading") {
+    // Sometimes Page.frameStoppedLoading fires without
+    // an associated Page.loadEventFired. If this happens
+    // for the top frame, assume loading has finished.
+    std::string frame_id;
+    if (!params.GetString("frameId", &frame_id))
+      return Status(kUnknownError, "missing or invalid 'frameId'");
+    if (frame_id == top_frame_id_) {
+      loading_state_ = kNotLoading;
+      load_event_fired_ = true;
+    }
   } else if (method == "Inspector.targetCrashed") {
     loading_state_ = kNotLoading;
   }
diff --git a/chrome/test/chromedriver/test/test_expectations b/chrome/test/chromedriver/test/test_expectations
index 42eac924..1eb3776e 100644
--- a/chrome/test/chromedriver/test/test_expectations
+++ b/chrome/test/chromedriver/test/test_expectations
@@ -15,9 +15,6 @@
     'SlowLoadingPageTest.testRefreshShouldBlockUntilPageLoads',
     'PageLoadingTest.testShouldTimeoutIfAPageTakesTooLongToRefresh',
 
-    # https://bugs.chromium.org/p/chromedriver/issues/detail?id=2653
-    'ReferrerTest.navigationWhenProxyInterceptsASpecificUrl',
-
     # https://bugs.chromium.org/p/chromedriver/issues/detail?id=2854
     'ChromeOptionsFunctionalTest.canSetAcceptInsecureCerts',
 
@@ -89,7 +86,6 @@
     'PerformanceLogTypeTest.pageLoadShouldProducePerformanceLogEntries',
     'ProxySettingTest.*',
     'CorrectEventFiringTest.testSendingKeysToAnotherElementShouldCauseTheBlurEventToFireInNonTopmostWindow',
-    'ReferrerTest.navigationWhenProxyInterceptsASpecificUrl',
     'ReferrerTest.crossDomainHistoryNavigationWhenProxyInterceptsHostRequests',
     'ReferrerTest.crossDomainHistoryNavigationWithAProxiedHost',
 
diff --git a/chrome/test/data/extensions/api_test/automation/tests/tabs/word_boundaries.js b/chrome/test/data/extensions/api_test/automation/tests/tabs/word_boundaries.js
index c7eb014..2d43c4c73 100644
--- a/chrome/test/data/extensions/api_test/automation/tests/tabs/word_boundaries.js
+++ b/chrome/test/data/extensions/api_test/automation/tests/tabs/word_boundaries.js
@@ -8,8 +8,8 @@
         { attributes: { name: 'Example text for testing purposes' } });
     var expectedWordStarts = [0, 8, 13, 17, 25];
     var expectedWordEnds = [7, 12, 16, 24, 33];
-    var wordStarts = node.wordStartOffsets();
-    var wordEnds = node.wordEndOffsets();
+    var wordStarts = node.nonInlineTextWordStarts;
+    var wordEnds = node.nonInlineTextWordEnds;
     assertEq(expectedWordStarts.length, wordStarts.length);
     assertEq(expectedWordEnds.length, wordEnds.length);
     assertEq(wordStarts.length, wordEnds.length);
diff --git a/chrome/test/data/previews/resource_loading_hints_iframe.html b/chrome/test/data/previews/resource_loading_hints_iframe.html
new file mode 100644
index 0000000..4db4371
--- /dev/null
+++ b/chrome/test/data/previews/resource_loading_hints_iframe.html
@@ -0,0 +1,15 @@
+<html>
+  <head>
+  </head>
+  <body>
+    <p>Test page for Resource Loading Hints.</p>
+   <iframe src="resource_loading_hints.html"></iframe>
+   <script>
+    window.addEventListener("load", function () {
+      var xhr_foo = new XMLHttpRequest();
+      xhr_foo.open('GET', 'foo.woff2', true /* async */);
+      xhr_foo.send();
+    });
+    </script>
+   </body>
+</html>
diff --git a/chrome/test/data/previews/resource_loading_hints_iframe_preload.html b/chrome/test/data/previews/resource_loading_hints_iframe_preload.html
new file mode 100644
index 0000000..0668e29
--- /dev/null
+++ b/chrome/test/data/previews/resource_loading_hints_iframe_preload.html
@@ -0,0 +1,15 @@
+<html>
+  <head>
+  </head>
+  <body>
+    <p>Test page for Resource Loading Hints.</p>
+   <iframe src="resource_loading_hints_preload.html"></iframe>
+   <script>
+    window.addEventListener("load", function () {
+      var xhr_foo = new XMLHttpRequest();
+      xhr_foo.open('GET', 'foo.woff2', true /* async */);
+      xhr_foo.send();
+    });
+    </script>
+   </body>
+</html>
diff --git a/chrome/test/data/webui/net_internals/dns_view.js b/chrome/test/data/webui/net_internals/dns_view.js
index 429691b81..7743e1a 100644
--- a/chrome/test/data/webui/net_internals/dns_view.js
+++ b/chrome/test/data/webui/net_internals/dns_view.js
@@ -9,38 +9,23 @@
 (function() {
 
 /**
- * A Task that adds a hostname to the cache and waits for it to appear in the
- * data we receive from the cache.
- * @param {string} hostname Name of host address we're waiting for.
- * @param {string} ipAddress IP address we expect it to have.  Null if we expect
- *     a net error other than OK.
- * @param {int} netError The expected network error code.
- * @param {bool} expired True if we expect the entry to be expired.  The added
- *     entry will have an expiration time far enough away from the current time
- *     that there will be no chance of any races.
+ * A Task that performs a DNS lookup.
+ * @param {string} hostname The host address to attempt to look up.
+ * @param {bool} local True if the lookup should be strictly local.
  * @extends {NetInternalsTest.Task}
  */
-function AddCacheEntryTask(hostname, ipAddress, netError, expired) {
+function DnsLookupTask(hostname, local) {
   this.hostname_ = hostname;
-  this.ipAddress_ = ipAddress;
-  this.netError_ = netError;
-  this.expired_ = expired;
+  this.local_ = local;
   NetInternalsTest.Task.call(this);
 }
 
-AddCacheEntryTask.prototype = {
+DnsLookupTask.prototype = {
   __proto__: NetInternalsTest.Task.prototype,
 
-  /**
-   * Adds an entry to the cache and starts waiting to received the results from
-   * the browser process.
-   */
   start: function() {
-    var addCacheEntryParams = [
-      this.hostname_, this.ipAddress_, this.netError_, this.expired_ ? -2 : 2
-    ];
-    chrome.send('addCacheEntry', addCacheEntryParams);
-    this.onTaskDone();
+    NetInternalsTest.setCallback(this.onTaskDone.bind(this));
+    chrome.send('dnsLookup', [this.hostname_, this.local_]);
   },
 };
 
@@ -67,11 +52,26 @@
 TEST_F('NetInternalsTest', 'netInternalsDnsViewClearCache', function() {
   NetInternalsTest.switchToView('dns');
   var taskQueue = new NetInternalsTest.TaskQueue(true);
-  taskQueue.addTask(
-      new AddCacheEntryTask('somewhere.com', '1.2.3.4', 0, false));
-  taskQueue.addTask(new ClearCacheTask());
-  // TODO(mattm): verify that it was actually cleared.
-  taskQueue.run(true);
-});
 
+  // Perform an initial local lookup to make sure somewhere.com isn't cached.
+  taskQueue.addTask(new DnsLookupTask('somewhere.com', true));
+  taskQueue.addFunctionTask(expectEquals.bind(null, 'net::ERR_DNS_CACHE_MISS'));
+
+  // Perform a non-local lookup to get somewhere.com added to the cache.
+  taskQueue.addTask(new DnsLookupTask('somewhere.com', false));
+  taskQueue.addFunctionTask(expectEquals.bind(null, '127.0.0.1'));
+
+  // Perform another local lookup that should be cached this time.
+  taskQueue.addTask(new DnsLookupTask('somewhere.com', true));
+  taskQueue.addFunctionTask(expectEquals.bind(null, '127.0.0.1'));
+
+  // Clear the cache
+  taskQueue.addTask(new ClearCacheTask());
+
+  // One more local lookup to make sure somewhere.com is no longer cached.
+  taskQueue.addTask(new DnsLookupTask('somewhere.com', true));
+  taskQueue.addFunctionTask(expectEquals.bind(null, 'net::ERR_DNS_CACHE_MISS'));
+
+  taskQueue.run();
+});
 })();  // Anonymous namespace
diff --git a/chrome/test/data/webui/settings/languages_page_tests.js b/chrome/test/data/webui/settings/languages_page_tests.js
index 9e6e1dc1..43fef6f2 100644
--- a/chrome/test/data/webui/settings/languages_page_tests.js
+++ b/chrome/test/data/webui/settings/languages_page_tests.js
@@ -269,6 +269,32 @@
         }
       }
 
+      /**
+       * @return {HTMLElement} Traverses the DOM tree to find the lowest level
+       *     active element.
+       */
+      function getActiveElement() {
+        let node = document.activeElement;
+        let lastNode;
+        while (node) {
+          lastNode = node;
+          node = (node.shadowRoot || node).activeElement;
+        }
+        return lastNode;
+      }
+
+      /**
+       * Assert whether the 'restart' button should be active.
+       * @param {boolean} shouldBeActive True to assert that the 'restart'
+       *     button is present and active or false the assert the negation.
+       */
+      function assertRestartButtonActiveState(shouldBeActive) {
+        const activeElement = getActiveElement();
+        isRestartButtonActive =
+            activeElement && (activeElement.id == 'restartButton');
+        assertEquals(isRestartButtonActive, shouldBeActive);
+      }
+
       test('structure', function() {
         const languageOptionsDropdownTrigger =
             languagesCollapse.querySelector('cr-icon-button');
@@ -339,6 +365,47 @@
         });
       });
 
+      test('changing UI language in CrOS', function() {
+        if (!cr.isChromeOS) {
+          return;
+        }
+
+        // Mock changing language.
+        languageHelper.setProspectiveUILanguage = languageCode => {
+          languagesPage.set('languages.prospectiveUILanguage', languageCode);
+        };
+
+        // Restart button is not active.
+        assertRestartButtonActiveState(false);
+
+        const swListItem = languagesCollapse.querySelectorAll('.list-item')[1];
+        // Open options for 'sw'.
+        const languageOptionsDropdownTrigger =
+            swListItem.querySelector('cr-icon-button');
+        assertTrue(!!languageOptionsDropdownTrigger);
+        // No restart button in 'sw' list-item.
+        assertTrue(!swListItem.querySelector('#restartButton'));
+        languageOptionsDropdownTrigger.click();
+        assertTrue(actionMenu.open);
+
+        // OS language is not 'sw'
+        const uiLanguageOption = getMenuItem('isDisplayedInThisLanguage');
+        assertFalse(uiLanguageOption.disabled);
+        assertFalse(uiLanguageOption.checked);
+
+        return new Promise(resolve => {
+          actionMenu.addEventListener('close', () => {
+            // Restart button is attached to 'sw' list item and is active.
+            assertTrue(!!swListItem.querySelector('#restartButton'));
+            assertRestartButtonActiveState(true);
+            resolve();
+          });
+
+          // Change UI language.
+          uiLanguageOption.click();
+        });
+      });
+
       test('toggle translate for a specific language', function(done) {
         // Open options for 'sw'.
         const languageOptionsDropdownTrigger =
diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc
index d12351c..6fedd1a 100644
--- a/chrome/test/ppapi/ppapi_browsertest.cc
+++ b/chrome/test/ppapi/ppapi_browsertest.cc
@@ -30,10 +30,10 @@
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/nacl/common/buildflags.h"
 #include "components/nacl/common/nacl_switches.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/network_service_util.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/test/browser_test_utils.h"
@@ -362,10 +362,8 @@
     return;
 
   network::mojom::NetworkServiceTestPtr network_service_test;
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(content::mojom::kNetworkServiceName,
-                      &network_service_test);
+  content::GetSystemConnector()->BindInterface(
+      content::mojom::kNetworkServiceName, &network_service_test);
   network_service_test->CrashOnResolveHost("crash.com");
 
   RunTestViaHTTP(STRIP_PREFIXES(TCPSocketPrivateCrash_Resolve));
@@ -1262,10 +1260,8 @@
     return;
 
   network::mojom::NetworkServiceTestPtr network_service_test;
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(content::mojom::kNetworkServiceName,
-                      &network_service_test);
+  content::GetSystemConnector()->BindInterface(
+      content::mojom::kNetworkServiceName, &network_service_test);
   network_service_test->CrashOnResolveHost("crash.com");
 
   RunTestViaHTTP(STRIP_PREFIXES(HostResolverCrash_Basic));
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index a1dac14..8f4efd7d 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -65,12 +65,12 @@
 #include "content/public/browser/resource_dispatcher_host.h"
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/storage_partition.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui_url_loader_factory.h"
 #include "content/public/common/content_descriptors.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/common/web_preferences.h"
@@ -343,8 +343,7 @@
       base::BindRepeating(&shell::CastSessionIdMap::GetSessionId),
       base::CreateSingleThreadTaskRunnerWithTraits(
           {content::BrowserThread::UI}),
-      GetMediaTaskRunner(),
-      content::ServiceManagerConnection::GetForProcess()->GetConnector(),
+      GetMediaTaskRunner(), content::GetSystemConnector(),
       BUILDFLAG(ENABLE_CAST_AUDIO_MANAGER_MIXER));
 #else
   return std::make_unique<media::CastAudioManager>(
@@ -354,8 +353,7 @@
       base::BindRepeating(&shell::CastSessionIdMap::GetSessionId),
       base::CreateSingleThreadTaskRunnerWithTraits(
           {content::BrowserThread::UI}),
-      GetMediaTaskRunner(),
-      content::ServiceManagerConnection::GetForProcess()->GetConnector(),
+      GetMediaTaskRunner(), content::GetSystemConnector(),
       BUILDFLAG(ENABLE_CAST_AUDIO_MANAGER_MIXER));
 #endif  // defined(USE_ALSA)
 }
diff --git a/chromecast/browser/general_audience_browsing_service.cc b/chromecast/browser/general_audience_browsing_service.cc
index fcbcb9f..a6f7823 100644
--- a/chromecast/browser/general_audience_browsing_service.cc
+++ b/chromecast/browser/general_audience_browsing_service.cc
@@ -9,7 +9,7 @@
 #include "components/policy/core/browser/url_util.h"
 #include "components/safe_search_api/safe_search/safe_search_url_checker_client.h"
 #include "components/safe_search_api/url_checker.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "net/base/net_errors.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -62,10 +62,9 @@
   mojom::GeneralAudienceBrowsingAPIKeyObserverPtr observer_ptr;
   general_audience_browsing_api_key_observer_binding_.Bind(
       mojo::MakeRequest(&observer_ptr));
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(mojom::kChromecastServiceName,
-                      &general_audience_browsing_api_key_subject_ptr_);
+  content::GetSystemConnector()->BindInterface(
+      mojom::kChromecastServiceName,
+      &general_audience_browsing_api_key_subject_ptr_);
   general_audience_browsing_api_key_subject_ptr_
       ->AddGeneralAudienceBrowsingAPIKeyObserver(std::move(observer_ptr));
 }
diff --git a/chromeos/dbus/session_manager/fake_session_manager_client.cc b/chromeos/dbus/session_manager/fake_session_manager_client.cc
index 2b5653e..4fcef56 100644
--- a/chromeos/dbus/session_manager/fake_session_manager_client.cc
+++ b/chromeos/dbus/session_manager/fake_session_manager_client.cc
@@ -281,7 +281,9 @@
       FROM_HERE, base::BindOnce(std::move(callback), true));
 }
 
-void FakeSessionManagerClient::SaveLoginPassword(const std::string& password) {}
+void FakeSessionManagerClient::SaveLoginPassword(const std::string& password) {
+  login_password_ = password;
+}
 
 void FakeSessionManagerClient::StartSession(
     const cryptohome::AccountIdentifier& cryptohome_id) {
diff --git a/chromeos/dbus/session_manager/fake_session_manager_client.h b/chromeos/dbus/session_manager/fake_session_manager_client.h
index 476c626..b2dd3ba 100644
--- a/chromeos/dbus/session_manager/fake_session_manager_client.h
+++ b/chromeos/dbus/session_manager/fake_session_manager_client.h
@@ -246,6 +246,8 @@
     return user_sessions_;
   }
 
+  const std::string& login_password() const { return login_password_; }
+
  private:
   // Called in response to writing owner key file specified in new device
   // policy - used for in-memory fake only.
@@ -294,6 +296,8 @@
 
   bool container_running_ = false;
 
+  std::string login_password_;
+
   // Contains last request passed to StartArcMiniContainer
   login_manager::StartArcMiniContainerRequest
       last_start_arc_mini_container_request_;
diff --git a/chromeos/login/auth/user_context.h b/chromeos/login/auth/user_context.h
index 1ba35e5..8e3d5302 100644
--- a/chromeos/login/auth/user_context.h
+++ b/chromeos/login/auth/user_context.h
@@ -97,6 +97,20 @@
 
   void SetAccountId(const AccountId& account_id);
   void SetKey(const Key& key);
+  // Saves the user's plaintext password for possible authentication by system
+  // services:
+  // - To networks. If the user's OpenNetworkConfiguration policy contains a
+  //   ${PASSWORD} variable, then the user's password will be used to
+  //   authenticate to the specified network.
+  // - To Kerberos. If the user's KerberosAccounts policy contains a ${PASSWORD}
+  //   variable, then the user's password will be used to authenticate to the
+  //   specified Kerberos account.
+  // The user's password needs to be saved in memory until the policies can be
+  // examined. When policies come in and none of them contain the ${PASSWORD}
+  // variable, the user's password will be discarded. If at least one contains
+  // the password, it will be sent to the session manager, which will then save
+  // it in a keyring so it can be retrieved by the corresponding services.
+  // More details can be found in https://crbug.com/386606.
   void SetPasswordKey(const Key& key);
   void SetAuthCode(const std::string& auth_code);
   void SetRefreshToken(const std::string& refresh_token);
diff --git a/chromeos/services/device_sync/cryptauth_ecies_encryptor.cc b/chromeos/services/device_sync/cryptauth_ecies_encryptor.cc
index 0ee2da0e..30d79a5 100644
--- a/chromeos/services/device_sync/cryptauth_ecies_encryptor.cc
+++ b/chromeos/services/device_sync/cryptauth_ecies_encryptor.cc
@@ -27,6 +27,13 @@
 
 }  // namespace
 
+CryptAuthEciesEncryptor::PayloadAndKey::PayloadAndKey() = default;
+
+CryptAuthEciesEncryptor::PayloadAndKey::PayloadAndKey(
+    const std::string& payload,
+    const std::string& key)
+    : payload(payload), key(key) {}
+
 CryptAuthEciesEncryptor::CryptAuthEciesEncryptor() = default;
 
 CryptAuthEciesEncryptor::~CryptAuthEciesEncryptor() = default;
@@ -35,7 +42,8 @@
     const std::string& unencrypted_payload,
     const std::string& encrypting_public_key,
     SingleInputCallback encryption_finished_callback) {
-  BatchEncrypt({{kSinglePayloadId, unencrypted_payload}}, encrypting_public_key,
+  BatchEncrypt({{kSinglePayloadId,
+                 PayloadAndKey(unencrypted_payload, encrypting_public_key)}},
                base::BindOnce(&ForwardResultToSingleInputCallback,
                               std::move(encryption_finished_callback)));
 }
@@ -44,26 +52,25 @@
     const std::string& encrypted_payload,
     const std::string& decrypting_private_key,
     SingleInputCallback decryption_finished_callback) {
-  BatchDecrypt({{kSinglePayloadId, encrypted_payload}}, decrypting_private_key,
+  BatchDecrypt({{kSinglePayloadId,
+                 PayloadAndKey(encrypted_payload, decrypting_private_key)}},
                base::BindOnce(&ForwardResultToSingleInputCallback,
                               std::move(decryption_finished_callback)));
 }
 
 void CryptAuthEciesEncryptor::BatchEncrypt(
-    const IdToInputMap& id_to_unencrypted_payload_map,
-    const std::string& encrypting_public_key,
+    const IdToInputMap& id_to_payload_and_key_map,
     BatchCallback encryption_finished_callback) {
-  ProcessInput(id_to_unencrypted_payload_map, encrypting_public_key,
+  ProcessInput(id_to_payload_and_key_map,
                std::move(encryption_finished_callback));
 
   OnBatchEncryptionStarted();
 }
 
 void CryptAuthEciesEncryptor::BatchDecrypt(
-    const IdToInputMap& id_to_encrypted_payload_map,
-    const std::string& decrypting_private_key,
+    const IdToInputMap& id_to_payload_and_key_map,
     BatchCallback decryption_finished_callback) {
-  ProcessInput(id_to_encrypted_payload_map, decrypting_private_key,
+  ProcessInput(id_to_payload_and_key_map,
                std::move(decryption_finished_callback));
 
   OnBatchDecryptionStarted();
@@ -75,17 +82,16 @@
 }
 
 void CryptAuthEciesEncryptor::ProcessInput(const IdToInputMap& id_to_input_map,
-                                           const std::string& input_key,
                                            BatchCallback callback) {
   DCHECK(!id_to_input_map.empty());
-  DCHECK(!input_key.empty());
   DCHECK(callback);
+  for (const auto& id_payload_and_key_pair : id_to_input_map)
+    DCHECK(!id_payload_and_key_pair.second.key.empty());
 
   // Fail if a public method has already been called.
   DCHECK(id_to_input_map_.empty());
 
   id_to_input_map_ = id_to_input_map;
-  input_key_ = input_key;
   callback_ = std::move(callback);
 }
 
diff --git a/chromeos/services/device_sync/cryptauth_ecies_encryptor.h b/chromeos/services/device_sync/cryptauth_ecies_encryptor.h
index 4a12eb093..51bfc45 100644
--- a/chromeos/services/device_sync/cryptauth_ecies_encryptor.h
+++ b/chromeos/services/device_sync/cryptauth_ecies_encryptor.h
@@ -24,7 +24,18 @@
 // created.
 class CryptAuthEciesEncryptor {
  public:
-  using IdToInputMap = base::flat_map<std::string, std::string>;
+  struct PayloadAndKey {
+    PayloadAndKey();
+    PayloadAndKey(const std::string& payload, const std::string& key);
+
+    // Unencrypted/Encrypted payload to be encrypted/decrypted.
+    std::string payload;
+
+    // Public/Private key for encryption/decryption.
+    std::string key;
+  };
+
+  using IdToInputMap = base::flat_map<std::string, PayloadAndKey>;
   using IdToOutputMap =
       base::flat_map<std::string, base::Optional<std::string>>;
   using SingleInputCallback =
@@ -33,36 +44,24 @@
 
   virtual ~CryptAuthEciesEncryptor();
 
-  // Encrypts |unencrypted_payload| with |encrypting_public_key|, returning the
-  // encrypted payload in the callback or null if the encryption was
-  // unsuccessful.
+  // Encrypts/Decrypts the input payload with the provided key, returning the
+  // encrypted/decrypted payload in the callback or null if the
+  // encryption/decryption was unsuccessful.
   void Encrypt(const std::string& unencrypted_payload,
                const std::string& encrypting_public_key,
                SingleInputCallback encryption_finished_callback);
-
-  // Decrypts |encrypted_payload| with |decrypting_private_key|, returning the
-  // decrypted payload in the callback or null if the decryption was
-  // unsuccessful.
   void Decrypt(const std::string& encrypted_payload,
                const std::string& decrypting_private_key,
                SingleInputCallback decryption_finished_callback);
 
-  // Encrypts all values of the input ID to payload map,
-  // |id_to_unencrypted_payload_map|, using the same |encrypting_public_key|.
-  // The encrypted payloads are returned in the callback, paired with their
-  // input IDs. Unsuccessful encryptions result in null values. Note: The IDs
-  // are only used to correlate the output with input.
-  void BatchEncrypt(const IdToInputMap& id_to_unencrypted_payload_map,
-                    const std::string& encrypting_public_key,
+  // Encrypts/Decrypts all payloads of the input ID-to-PayloadAndKey map with
+  // the provided keys. The encrypted/decrypted payloads are returned in the
+  // callback, paired with their input IDs. Unsuccessful encryptions/decryptions
+  // result in null values. Note: The IDs are only used to correlate the output
+  // with input.
+  void BatchEncrypt(const IdToInputMap& id_to_payload_and_key_map,
                     BatchCallback encryption_finished_callback);
-
-  // Decrypts all values of the input ID to payload map,
-  // |id_to_encrypted_payload_map|, using the same |decrypting_private_key|.
-  // The decrypted payloads are returned in the callback, paired with their
-  // input IDs. Unsuccessful decryptions result in null values. Note: The IDs
-  // are only used to correlate the output with input.
-  void BatchDecrypt(const IdToInputMap& id_to_encrypted_payload_map,
-                    const std::string& decrypting_private_key,
+  void BatchDecrypt(const IdToInputMap& id_to_payload_and_key_map,
                     BatchCallback decryption_finished_callback);
 
  protected:
@@ -74,11 +73,9 @@
   void OnAttemptFinished(const IdToOutputMap& id_to_output_map);
 
   IdToInputMap id_to_input_map_;
-  std::string input_key_;
 
  private:
   void ProcessInput(const IdToInputMap& id_to_input_map,
-                    const std::string& input_key,
                     BatchCallback callback);
 
   BatchCallback callback_;
diff --git a/chromeos/services/device_sync/cryptauth_ecies_encryptor_impl.cc b/chromeos/services/device_sync/cryptauth_ecies_encryptor_impl.cc
index 6585d29..21df154 100644
--- a/chromeos/services/device_sync/cryptauth_ecies_encryptor_impl.cc
+++ b/chromeos/services/device_sync/cryptauth_ecies_encryptor_impl.cc
@@ -141,7 +141,7 @@
     const std::string& session_private_key) {
   for (const auto& id_input_pair : id_to_input_map_) {
     secure_message_delegate_->DeriveKey(
-        session_private_key, input_key_,
+        session_private_key, id_input_pair.second.key,
         base::Bind(
             &CryptAuthEciesEncryptorImpl::OnDiffieHellmanEncryptionKeyDerived,
             base::Unretained(this), id_input_pair.first, session_public_key));
@@ -158,7 +158,7 @@
   options.decryption_key_id = session_public_key;
 
   secure_message_delegate_->CreateSecureMessage(
-      id_to_input_map_[id], dh_key, options,
+      id_to_input_map_[id].payload, dh_key, options,
       base::Bind(&CryptAuthEciesEncryptorImpl::OnSecureMessageCreated,
                  base::Unretained(this), id));
 }
@@ -182,7 +182,7 @@
 
   for (const auto& id_input_pair : id_to_input_map_) {
     base::Optional<securemessage::Header> header =
-        ParseHeaderFromSerializedSecureMessage(id_input_pair.second);
+        ParseHeaderFromSerializedSecureMessage(id_input_pair.second.payload);
     if (!header) {
       OnSingleOutputFinished(id_input_pair.first, base::nullopt /* output */);
       continue;
@@ -201,10 +201,11 @@
     }
 
     secure_message_delegate_->DeriveKey(
-        input_key_, *session_public_key,
+        id_input_pair.second.key, *session_public_key,
         base::Bind(
             &CryptAuthEciesEncryptorImpl::OnDiffieHellmanDecryptionKeyDerived,
-            base::Unretained(this), id_input_pair.first, id_input_pair.second));
+            base::Unretained(this), id_input_pair.first,
+            id_input_pair.second.payload));
   }
 }
 
diff --git a/chromeos/services/device_sync/cryptauth_ecies_encryptor_impl.h b/chromeos/services/device_sync/cryptauth_ecies_encryptor_impl.h
index e210e91..bcc0a36 100644
--- a/chromeos/services/device_sync/cryptauth_ecies_encryptor_impl.h
+++ b/chromeos/services/device_sync/cryptauth_ecies_encryptor_impl.h
@@ -29,7 +29,7 @@
 // The encryption algorithm is as follows:
 //   1) Generate a session key pair.
 //   2) Use Diffie-Hellman key exchange to derive symmetric key from the session
-//      private key and the input |encrypting_public_key|.
+//      private key and the input encrypting public key.
 //   3) Create a SecureMessage from the input payload, encrypted and signed with
 //      the derived symmetric key, using AES-256-CBC and HMAC-SHA256,
 //      respectively.
@@ -41,15 +41,15 @@
 //   1) Parse the serialized SecureMessage input.
 //   2) Use Diffie-Hellman key exchange to derive symmetric key from the session
 //      public key--provided in the unencrypted SecureMessage Header's
-//      decryption_key_id field--and the input |decrypting_private_key|. This
+//      decryption_key_id field--and the input decrypting private key. This
 //      should match the key derived in the step 2) of the encryption algorithm
-//      if |encrypting_public_key| and |decrypting_private_key| are a key pair.
+//      if the encrypting public key and decrypting private key are a key pair.
 //   3) Decrypt the input SecureMessage and verify the signature using the
 //      derived symmetric key.
 //   4) Extract the decrypted payload string from the body of the decrypted
 //      SecureMessage.
 //
-// Note that the input |encrypting_public_key| must be a serialized
+// Note that the input encrypting public keys must be a serialized
 // securemessage::GenericPublicKey proto, and the encrypting/decrypting key pair
 // must be P-256.
 class CryptAuthEciesEncryptorImpl : public CryptAuthEciesEncryptor {
diff --git a/chromeos/services/device_sync/cryptauth_ecies_encryptor_impl_unittest.cc b/chromeos/services/device_sync/cryptauth_ecies_encryptor_impl_unittest.cc
index 071a6c6..9cbec6f 100644
--- a/chromeos/services/device_sync/cryptauth_ecies_encryptor_impl_unittest.cc
+++ b/chromeos/services/device_sync/cryptauth_ecies_encryptor_impl_unittest.cc
@@ -24,12 +24,13 @@
 
 namespace {
 
-const char kPublicKey[] = "public_key";
 const char kSessionPublicKey[] = "session_public_key";
 const char kPayloadId1[] = "payload_id_1";
-const char kUnencryptedPayload1[] = "unencrypted_payload_1";
 const char kPayloadId2[] = "payload_id_2";
+const char kUnencryptedPayload1[] = "unencrypted_payload_1";
 const char kUnencryptedPayload2[] = "unencrypted_payload_2";
+const char kPublicKey1[] = "public_key_1";
+const char kPublicKey2[] = "public_key_2";
 const char kPayloadNotSet[] = "[Payload not set]";
 
 constexpr securemessage::EncScheme kSecureMessageEncryptionScheme =
@@ -59,27 +60,6 @@
   EXPECT_EQ(expected_session_public_key, header.decryption_key_id());
 }
 
-CryptAuthEciesEncryptor::IdToOutputMap ConvertBatchInputToOutput(
-    const CryptAuthEciesEncryptor::IdToInputMap& id_to_input_map) {
-  CryptAuthEciesEncryptor::IdToOutputMap id_to_output_map;
-  for (const auto& id_input_pair : id_to_input_map) {
-    id_to_output_map.try_emplace(id_input_pair.first, id_input_pair.second);
-  }
-
-  return id_to_output_map;
-}
-
-CryptAuthEciesEncryptor::IdToInputMap ConvertBatchOutputToInput(
-    const CryptAuthEciesEncryptor::IdToOutputMap& id_to_output_map) {
-  CryptAuthEciesEncryptor::IdToInputMap id_to_input_map;
-  for (const auto& id_output_pair : id_to_output_map) {
-    EXPECT_TRUE(id_output_pair.second);
-    id_to_input_map.try_emplace(id_output_pair.first, *id_output_pair.second);
-  }
-
-  return id_to_input_map;
-}
-
 }  // namespace
 
 class DeviceSyncCryptAuthEciesEncryptorImplTest : public testing::Test {
@@ -114,14 +94,13 @@
   }
 
   void BatchEncrypt(const CryptAuthEciesEncryptor::IdToInputMap&
-                        id_to_unencrypted_payload_map,
-                    const std::string& encrypting_public_key) {
+                        id_to_unencrypted_payload_map) {
     encryptor_ = CryptAuthEciesEncryptorImpl::Factory::Get()->BuildInstance();
     fake_secure_message_delegate()->set_next_public_key(kSessionPublicKey);
 
     base::RunLoop run_loop;
     encryptor_->BatchEncrypt(
-        id_to_unencrypted_payload_map, encrypting_public_key,
+        id_to_unencrypted_payload_map,
         base::BindOnce(&DeviceSyncCryptAuthEciesEncryptorImplTest::
                            OnBatchEncryptionFinished,
                        base::Unretained(this), run_loop.QuitClosure()));
@@ -144,14 +123,13 @@
     run_loop.Run();
   }
 
-  void BatchDecrypt(
-      const CryptAuthEciesEncryptor::IdToInputMap& id_to_encrypted_payload_map,
-      const std::string& decrypting_private_key) {
+  void BatchDecrypt(const CryptAuthEciesEncryptor::IdToInputMap&
+                        id_to_encrypted_payload_map) {
     encryptor_ = CryptAuthEciesEncryptorImpl::Factory::Get()->BuildInstance();
 
     base::RunLoop run_loop;
     encryptor_->BatchDecrypt(
-        id_to_encrypted_payload_map, decrypting_private_key,
+        id_to_encrypted_payload_map,
         base::BindOnce(&DeviceSyncCryptAuthEciesEncryptorImplTest::
                            OnBatchDecryptionFinished,
                        base::Unretained(this), run_loop.QuitClosure()));
@@ -168,13 +146,33 @@
     EXPECT_EQ(expected_batch_decrypted_payloads, batch_decrypted_payloads_);
   }
 
-  const base::Optional<std::string>& encrypted_payload() {
-    return encrypted_payload_;
+  // Replaces the unencrypted payloads and encrypting public keys with the
+  // corresponding encrypted payloads and decrypting private keys.
+  CryptAuthEciesEncryptor::IdToInputMap
+  ConvertBatchEncryptInputToBatchDecryptInput(
+      const CryptAuthEciesEncryptor::IdToInputMap&
+          id_to_unencrypted_payload_and_public_key_map) {
+    EXPECT_TRUE(batch_encrypted_payloads_);
+
+    CryptAuthEciesEncryptor::IdToInputMap
+        id_to_encrypted_payload_and_private_key_map =
+            id_to_unencrypted_payload_and_public_key_map;
+    for (auto& id_pk_pair : id_to_encrypted_payload_and_private_key_map) {
+      const base::Optional<std::string>& encrypted_payload =
+          (*batch_encrypted_payloads_)[id_pk_pair.first];
+      EXPECT_TRUE(encrypted_payload);
+
+      id_pk_pair.second = CryptAuthEciesEncryptor::PayloadAndKey(
+          *encrypted_payload,
+          fake_secure_message_delegate()->GetPrivateKeyForPublicKey(
+              id_pk_pair.second.key));
+    }
+
+    return id_to_encrypted_payload_and_private_key_map;
   }
 
-  base::Optional<CryptAuthEciesEncryptor::IdToOutputMap>
-  batch_encrypted_payloads() {
-    return batch_encrypted_payloads_;
+  const base::Optional<std::string>& encrypted_payload() {
+    return encrypted_payload_;
   }
 
   multidevice::FakeSecureMessageDelegate* fake_secure_message_delegate() {
@@ -244,29 +242,30 @@
 };
 
 TEST_F(DeviceSyncCryptAuthEciesEncryptorImplTest, EncryptAndDecrypt) {
-  Encrypt(kUnencryptedPayload1, kPublicKey);
+  Encrypt(kUnencryptedPayload1, kPublicKey1);
 
   Decrypt(
       *encrypted_payload(),
-      fake_secure_message_delegate()->GetPrivateKeyForPublicKey(kPublicKey));
+      fake_secure_message_delegate()->GetPrivateKeyForPublicKey(kPublicKey1));
   VerifyDecryption(kUnencryptedPayload1);
 }
 
 TEST_F(DeviceSyncCryptAuthEciesEncryptorImplTest, BatchEncryptAndDecrypt) {
-  const CryptAuthEciesEncryptor::IdToInputMap id_to_unencrypted_payload_map = {
-      {kPayloadId1, kUnencryptedPayload1}, {kPayloadId2, kUnencryptedPayload2}};
-  BatchEncrypt(id_to_unencrypted_payload_map, kPublicKey);
+  const CryptAuthEciesEncryptor::IdToInputMap unencrypted_input = {
+      {kPayloadId1, CryptAuthEciesEncryptor::PayloadAndKey(kUnencryptedPayload1,
+                                                           kPublicKey1)},
+      {kPayloadId2, CryptAuthEciesEncryptor::PayloadAndKey(kUnencryptedPayload2,
+                                                           kPublicKey2)}};
+  BatchEncrypt(unencrypted_input);
 
-  BatchDecrypt(
-      ConvertBatchOutputToInput(*batch_encrypted_payloads()),
-      fake_secure_message_delegate()->GetPrivateKeyForPublicKey(kPublicKey));
-  VerifyBatchDecryption(
-      ConvertBatchInputToOutput(id_to_unencrypted_payload_map));
+  BatchDecrypt(ConvertBatchEncryptInputToBatchDecryptInput(unencrypted_input));
+  VerifyBatchDecryption({{kPayloadId1, kUnencryptedPayload1},
+                         {kPayloadId2, kUnencryptedPayload2}});
 }
 
 TEST_F(DeviceSyncCryptAuthEciesEncryptorImplTest,
        DecryptionFailure_WrongDecryptionKey) {
-  Encrypt(kUnencryptedPayload1, kPublicKey);
+  Encrypt(kUnencryptedPayload1, kPublicKey1);
 
   Decrypt(*encrypted_payload(), "Invalid private key");
   VerifyDecryption(base::nullopt /* expected_decrypted_payload */);
@@ -274,25 +273,27 @@
 
 TEST_F(DeviceSyncCryptAuthEciesEncryptorImplTest,
        DecryptionFailure_CannotParseSecureMessage) {
-  const CryptAuthEciesEncryptor::IdToInputMap id_to_unencrypted_payload_map = {
-      {kPayloadId1, kUnencryptedPayload1}, {kPayloadId2, kUnencryptedPayload2}};
-  BatchEncrypt(id_to_unencrypted_payload_map, kPublicKey);
-  CryptAuthEciesEncryptor::IdToInputMap id_to_encrypted_payload_map =
-      ConvertBatchOutputToInput(*batch_encrypted_payloads());
+  const CryptAuthEciesEncryptor::IdToInputMap unencrypted_input = {
+      {kPayloadId1, CryptAuthEciesEncryptor::PayloadAndKey(kUnencryptedPayload1,
+                                                           kPublicKey1)},
+      {kPayloadId2, CryptAuthEciesEncryptor::PayloadAndKey(kUnencryptedPayload2,
+                                                           kPublicKey2)}};
+
+  BatchEncrypt(unencrypted_input);
+  CryptAuthEciesEncryptor::IdToInputMap encrypted_input =
+      ConvertBatchEncryptInputToBatchDecryptInput(unencrypted_input);
 
   // Corrupt the second serialized SecureMessage.
-  id_to_encrypted_payload_map[kPayloadId2] = "Invalid SecureMessage";
+  encrypted_input[kPayloadId2].payload = "Invalid SecureMessage";
 
-  BatchDecrypt(
-      id_to_encrypted_payload_map,
-      fake_secure_message_delegate()->GetPrivateKeyForPublicKey(kPublicKey));
+  BatchDecrypt(encrypted_input);
   VerifyBatchDecryption(
       {{kPayloadId1, kUnencryptedPayload1}, {kPayloadId2, base::nullopt}});
 }
 
 TEST_F(DeviceSyncCryptAuthEciesEncryptorImplTest,
        DecryptionFailure_CannotParseSecureMessageHeaderAndBody) {
-  Encrypt(kUnencryptedPayload1, kPublicKey);
+  Encrypt(kUnencryptedPayload1, kPublicKey1);
 
   // Corrupt the HeaderAndBody.
   securemessage::SecureMessage secure_message_with_invalid_header_and_body;
@@ -303,54 +304,53 @@
 
   Decrypt(
       secure_message_with_invalid_header_and_body.SerializeAsString(),
-      fake_secure_message_delegate()->GetPrivateKeyForPublicKey(kPublicKey));
+      fake_secure_message_delegate()->GetPrivateKeyForPublicKey(kPublicKey1));
   VerifyDecryption(base::nullopt /* expected_decrypted_payload */);
 }
 
 TEST_F(DeviceSyncCryptAuthEciesEncryptorImplTest,
        DecryptionFailure_InvalidSchemesInHeader) {
-  const CryptAuthEciesEncryptor::IdToInputMap id_to_unencrypted_payload_map = {
-      {kPayloadId1, kUnencryptedPayload1}, {kPayloadId2, kUnencryptedPayload2}};
-  BatchEncrypt(id_to_unencrypted_payload_map, kPublicKey);
-  CryptAuthEciesEncryptor::IdToInputMap id_to_encrypted_payload_map =
-      ConvertBatchOutputToInput(*batch_encrypted_payloads());
+  const CryptAuthEciesEncryptor::IdToInputMap unencrypted_input = {
+      {kPayloadId1, CryptAuthEciesEncryptor::PayloadAndKey(kUnencryptedPayload1,
+                                                           kPublicKey1)},
+      {kPayloadId2, CryptAuthEciesEncryptor::PayloadAndKey(kUnencryptedPayload2,
+                                                           kPublicKey2)}};
+  BatchEncrypt(unencrypted_input);
+  CryptAuthEciesEncryptor::IdToInputMap encrypted_input =
+      ConvertBatchEncryptInputToBatchDecryptInput(unencrypted_input);
 
   // Corrupt the specified encryption scheme of the first SecureMessage.
   {
     securemessage::SecureMessage secure_message;
-    secure_message.ParseFromString(id_to_encrypted_payload_map[kPayloadId1]);
+    secure_message.ParseFromString(encrypted_input[kPayloadId1].payload);
     securemessage::HeaderAndBody header_and_body;
     header_and_body.ParseFromString(secure_message.header_and_body());
     header_and_body.mutable_header()->set_encryption_scheme(
         securemessage::EncScheme::NONE);
     secure_message.set_header_and_body(header_and_body.SerializeAsString());
-    id_to_encrypted_payload_map[kPayloadId1] =
-        secure_message.SerializeAsString();
+    encrypted_input[kPayloadId1].payload = secure_message.SerializeAsString();
   }
 
   // Corrupt the specified signature scheme of the second SecureMessage.
   {
     securemessage::SecureMessage secure_message;
-    secure_message.ParseFromString(id_to_encrypted_payload_map[kPayloadId2]);
+    secure_message.ParseFromString(encrypted_input[kPayloadId2].payload);
     securemessage::HeaderAndBody header_and_body;
     header_and_body.ParseFromString(secure_message.header_and_body());
     header_and_body.mutable_header()->set_signature_scheme(
         securemessage::SigScheme::RSA2048_SHA256);
     secure_message.set_header_and_body(header_and_body.SerializeAsString());
-    id_to_encrypted_payload_map[kPayloadId2] =
-        secure_message.SerializeAsString();
+    encrypted_input[kPayloadId2].payload = secure_message.SerializeAsString();
   }
 
-  BatchDecrypt(
-      id_to_encrypted_payload_map,
-      fake_secure_message_delegate()->GetPrivateKeyForPublicKey(kPublicKey));
+  BatchDecrypt(encrypted_input);
   VerifyBatchDecryption(
       {{kPayloadId1, base::nullopt}, {kPayloadId2, base::nullopt}});
 }
 
 TEST_F(DeviceSyncCryptAuthEciesEncryptorImplTest,
        DecryptionFailure_EmptyDecryptionKeyId) {
-  Encrypt(kUnencryptedPayload1, kPublicKey);
+  Encrypt(kUnencryptedPayload1, kPublicKey1);
 
   // Remove the session public key.
   securemessage::SecureMessage secure_message;
@@ -362,7 +362,7 @@
 
   Decrypt(
       secure_message.SerializeAsString(),
-      fake_secure_message_delegate()->GetPrivateKeyForPublicKey(kPublicKey));
+      fake_secure_message_delegate()->GetPrivateKeyForPublicKey(kPublicKey1));
   VerifyDecryption(base::nullopt /* expected_decrypted_payload */);
 }
 
diff --git a/chromeos/services/device_sync/fake_cryptauth_ecies_encryptor.h b/chromeos/services/device_sync/fake_cryptauth_ecies_encryptor.h
index 679ef6b..dbf26d3 100644
--- a/chromeos/services/device_sync/fake_cryptauth_ecies_encryptor.h
+++ b/chromeos/services/device_sync/fake_cryptauth_ecies_encryptor.h
@@ -26,7 +26,6 @@
                      const IdToOutputMap& id_to_output_map);
 
   const IdToInputMap& id_to_input_map() const { return id_to_input_map_; }
-  const std::string& input_key() const { return input_key_; }
 
  private:
   // CryptAuthEciesEncryptor:
diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn
index 0d48e3c1..5a7826d 100644
--- a/components/arc/BUILD.gn
+++ b/components/arc/BUILD.gn
@@ -219,6 +219,7 @@
     "//components/prefs",
     "//components/user_manager",
     "//components/version_info",
+    "//content/public/browser",
     "//content/public/common",
     "//mojo/public/cpp/platform",
     "//mojo/public/cpp/system",
diff --git a/components/arc/media_session/BUILD.gn b/components/arc/media_session/BUILD.gn
index 3c28303..cd1ff69 100644
--- a/components/arc/media_session/BUILD.gn
+++ b/components/arc/media_session/BUILD.gn
@@ -11,6 +11,7 @@
   deps = [
     "//components/arc:arc_base",
     "//components/keyed_service/content",
+    "//content/public/browser",
     "//content/public/common",
     "//services/media_session/public/cpp",
     "//services/media_session/public/mojom",
diff --git a/components/arc/media_session/arc_media_session_bridge.cc b/components/arc/media_session/arc_media_session_bridge.cc
index 7f0204e..e5c0dbdf 100644
--- a/components/arc/media_session/arc_media_session_bridge.cc
+++ b/components/arc/media_session/arc_media_session_bridge.cc
@@ -12,7 +12,7 @@
 #include "components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "components/arc/arc_features.h"
 #include "components/arc/session/arc_bridge_service.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/media_session/public/cpp/features.h"
 #include "services/media_session/public/mojom/audio_focus.mojom.h"
 #include "services/media_session/public/mojom/constants.mojom.h"
@@ -88,9 +88,8 @@
   }
 
   media_session::mojom::AudioFocusManagerPtr audio_focus_ptr;
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(media_session::mojom::kServiceName, &audio_focus_ptr);
+  content::GetSystemConnector()->BindInterface(
+      media_session::mojom::kServiceName, &audio_focus_ptr);
 
   audio_focus_ptr->SetSourceName(kAudioFocusSourceName);
 
diff --git a/components/arc/power/arc_power_bridge.cc b/components/arc/power/arc_power_bridge.cc
index 4208144..897e2f0 100644
--- a/components/arc/power/arc_power_bridge.cc
+++ b/components/arc/power/arc_power_bridge.cc
@@ -18,7 +18,7 @@
 #include "components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "components/arc/arc_service_manager.h"
 #include "components/arc/session/arc_bridge_service.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/device/public/mojom/wake_lock.mojom.h"
 #include "services/device/public/mojom/wake_lock_provider.mojom.h"
@@ -280,9 +280,7 @@
     return it->second.get();
 
   service_manager::Connector* connector =
-      connector_for_test_
-          ? connector_for_test_
-          : content::ServiceManagerConnection::GetForProcess()->GetConnector();
+      connector_for_test_ ? connector_for_test_ : content::GetSystemConnector();
   DCHECK(connector);
 
   it = wake_lock_requestors_
diff --git a/components/arc/session/arc_bridge_host_impl.cc b/components/arc/session/arc_bridge_host_impl.cc
index 88359e4c..a672d1c 100644
--- a/components/arc/session/arc_bridge_host_impl.cc
+++ b/components/arc/session/arc_bridge_host_impl.cc
@@ -7,8 +7,7 @@
 #include <algorithm>
 #include <utility>
 
-#include "ash/public/interfaces/ash_message_center_controller.mojom.h"
-#include "ash/public/interfaces/constants.mojom.h"
+#include "ash/public/cpp/arc_notifications_host_initializer.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "components/arc/common/accessibility_helper.mojom.h"
@@ -62,7 +61,7 @@
 #include "components/arc/common/wallpaper.mojom.h"
 #include "components/arc/session/arc_bridge_service.h"
 #include "components/arc/session/mojo_channel.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/service_manager/public/cpp/connector.h"
 
 namespace arc {
@@ -226,11 +225,7 @@
 void ArcBridgeHostImpl::OnNotificationsInstanceReady(
     mojom::NotificationsInstancePtr notifications_ptr) {
   // Forward notification instance to ash.
-  ash::mojom::AshMessageCenterControllerPtr ash_message_center_controller;
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(ash::mojom::kServiceName, &ash_message_center_controller);
-  ash_message_center_controller->SetArcNotificationsInstance(
+  ash::ArcNotificationsHostInitializer::Get()->SetArcNotificationsInstance(
       std::move(notifications_ptr));
 }
 
diff --git a/components/arc/usb/usb_host_bridge.cc b/components/arc/usb/usb_host_bridge.cc
index 2db745a..f94844ee 100644
--- a/components/arc/usb/usb_host_bridge.cc
+++ b/components/arc/usb/usb_host_bridge.cc
@@ -16,7 +16,7 @@
 #include "components/arc/arc_features.h"
 #include "components/arc/session/arc_bridge_service.h"
 #include "components/arc/usb/usb_host_ui_delegate.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -212,10 +212,8 @@
 
 void ArcUsbHostBridge::OnConnectionReady() {
   // Request UsbDeviceManagerPtr from DeviceService.
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(device::mojom::kServiceName,
-                      mojo::MakeRequest(&usb_manager_));
+  content::GetSystemConnector()->BindInterface(
+      device::mojom::kServiceName, mojo::MakeRequest(&usb_manager_));
   usb_manager_.set_connection_error_handler(
       base::BindOnce(&ArcUsbHostBridge::Disconnect, base::Unretained(this)));
 
diff --git a/components/arc/wake_lock/arc_wake_lock_bridge.cc b/components/arc/wake_lock/arc_wake_lock_bridge.cc
index 4f61dc4..f5bfb90 100644
--- a/components/arc/wake_lock/arc_wake_lock_bridge.cc
+++ b/components/arc/wake_lock/arc_wake_lock_bridge.cc
@@ -13,6 +13,7 @@
 #include "components/arc/arc_service_manager.h"
 #include "components/arc/session/arc_bridge_service.h"
 #include "components/arc/wake_lock/arc_wake_lock_bridge.h"
+#include "content/public/browser/system_connector.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/device/public/mojom/wake_lock_provider.mojom.h"
@@ -184,9 +185,7 @@
     return it->second.get();
 
   service_manager::Connector* connector =
-      connector_for_test_
-          ? connector_for_test_
-          : content::ServiceManagerConnection::GetForProcess()->GetConnector();
+      connector_for_test_ ? connector_for_test_ : content::GetSystemConnector();
   DCHECK(connector);
 
   it = wake_lock_requesters_
diff --git a/components/autofill/content/browser/risk/fingerprint_browsertest.cc b/components/autofill/content/browser/risk/fingerprint_browsertest.cc
index 3c461f2b..8cff022 100644
--- a/components/autofill/content/browser/risk/fingerprint_browsertest.cc
+++ b/components/autofill/content/browser/risk/fingerprint_browsertest.cc
@@ -14,8 +14,8 @@
 #include "build/build_config.h"
 #include "components/autofill/content/browser/risk/proto/fingerprint.pb.h"
 #include "content/public/browser/gpu_data_manager.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/screen_info.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/test/content_browser_test.h"
 #include "content/public/test/test_utils.h"
 #include "services/device/public/cpp/test/scoped_geolocation_overrider.h"
@@ -216,7 +216,7 @@
       base::TimeDelta::FromDays(1),  // Ought to be longer than any test run.
       base::Bind(&AutofillRiskFingerprintTest::GetFingerprintTestCallback,
                  base::Unretained(this), run_loop.QuitWhenIdleClosure()),
-      content::ServiceManagerConnection::GetForProcess()->GetConnector());
+      content::GetSystemConnector());
 
   // Wait for the callback to be called.
   run_loop.Run();
diff --git a/components/autofill/core/browser/data_model/credit_card_unittest.cc b/components/autofill/core/browser/data_model/credit_card_unittest.cc
index 0841bf5..3280327 100644
--- a/components/autofill/core/browser/data_model/credit_card_unittest.cc
+++ b/components/autofill/core/browser/data_model/credit_card_unittest.cc
@@ -22,7 +22,6 @@
 #include "components/autofill/core/common/autofill_constants.h"
 #include "components/autofill/core/common/form_field_data.h"
 #include "components/grit/components_scaled_resources.h"
-#include "components/variations/variations_params_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using base::ASCIIToUTF16;
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc b/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
index 6b5703e..6b6fb9f 100644
--- a/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
+++ b/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
@@ -59,8 +59,6 @@
 #include "components/security_state/core/security_state.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/sync/driver/test_sync_service.h"
-#include "components/variations/variations_associated_data.h"
-#include "components/variations/variations_params_manager.h"
 #include "components/version_info/channel.h"
 #include "net/base/url_util.h"
 #include "net/url_request/url_request_context_getter.h"
diff --git a/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc b/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc
index 3bfa546..a53305b5 100644
--- a/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc
+++ b/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc
@@ -55,8 +55,6 @@
 #include "components/security_state/core/security_state.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/sync/driver/test_sync_service.h"
-#include "components/variations/variations_associated_data.h"
-#include "components/variations/variations_params_manager.h"
 #include "components/version_info/channel.h"
 #include "net/base/url_util.h"
 #include "net/url_request/url_request_context_getter.h"
diff --git a/components/favicon/core/large_icon_service_impl.cc b/components/favicon/core/large_icon_service_impl.cc
index ee23e97..f4f37fe 100644
--- a/components/favicon/core/large_icon_service_impl.cc
+++ b/components/favicon/core/large_icon_service_impl.cc
@@ -9,7 +9,6 @@
 
 #include "base/bind.h"
 #include "base/containers/flat_map.h"
-#include "base/feature_list.h"
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
@@ -34,17 +33,18 @@
 #include "url/url_canon.h"
 
 namespace favicon {
-namespace {
-
-using favicon_base::GoogleFaviconServerRequestStatus;
-
-const char kImageFetcherUmaClient[] = "LargeIconService";
 
 // This feature is only used for accessing field trial parameters, not for
 // switching on/off the code.
 const base::Feature kLargeIconServiceFetchingFeature{
     "LargeIconServiceFetching", base::FEATURE_ENABLED_BY_DEFAULT};
 
+namespace {
+
+using favicon_base::GoogleFaviconServerRequestStatus;
+
+const char kImageFetcherUmaClient[] = "LargeIconService";
+
 const char kGoogleServerV2RequestFormat[] =
     "https://t0.gstatic.com/faviconV2?client=chrome&nfrp=2&%s"
     "size=%d&min_size=%d&max_size=%d&fallback_opts=TYPE,SIZE,URL&url=%s";
diff --git a/components/favicon/core/large_icon_service_impl.h b/components/favicon/core/large_icon_service_impl.h
index e09474b..187129f 100644
--- a/components/favicon/core/large_icon_service_impl.h
+++ b/components/favicon/core/large_icon_service_impl.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include <vector>
 
+#include "base/feature_list.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/task/cancelable_task_tracker.h"
@@ -27,6 +28,8 @@
 class FaviconService;
 class FaviconServerFetcherParams;
 
+extern const base::Feature kLargeIconServiceFetchingFeature;
+
 // Implementation class for LargeIconService.
 class LargeIconServiceImpl : public LargeIconService {
  public:
diff --git a/components/favicon/core/large_icon_service_impl_unittest.cc b/components/favicon/core/large_icon_service_impl_unittest.cc
index 02540a8..55243a9 100644
--- a/components/favicon/core/large_icon_service_impl_unittest.cc
+++ b/components/favicon/core/large_icon_service_impl_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/task/cancelable_task_tracker.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/mock_callback.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/favicon/core/favicon_client.h"
@@ -24,7 +25,6 @@
 #include "components/image_fetcher/core/image_fetcher.h"
 #include "components/image_fetcher/core/mock_image_fetcher.h"
 #include "components/image_fetcher/core/request_metadata.h"
-#include "components/variations/variations_params_manager.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -226,14 +226,14 @@
 }
 
 TEST_F(LargeIconServiceTest, ShouldGetFromGoogleServerWithCustomUrl) {
-  variations::testing::VariationParamsManager variation_params(
-      "LargeIconServiceFetching",
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kLargeIconServiceFetchingFeature,
       {{"request_format",
         "https://t0.gstatic.com/"
         "faviconV2?%ssize=%d&min_size=%d&max_size=%d&url=%s"},
        {"enforced_min_size_in_pixel", "43"},
-       {"desired_to_max_size_factor", "6.5"}},
-      {"LargeIconServiceFetching"});
+       {"desired_to_max_size_factor", "6.5"}});
   const GURL kExpectedServerUrl(
       "https://t0.gstatic.com/faviconV2?check_seen=true&"
       "size=61&min_size=43&max_size=396&url=http://www.example.com/");
diff --git a/components/feed/core/feed_networking_host_unittest.cc b/components/feed/core/feed_networking_host_unittest.cc
index a2267b7a..ad8123c 100644
--- a/components/feed/core/feed_networking_host_unittest.cc
+++ b/components/feed/core/feed_networking_host_unittest.cc
@@ -11,10 +11,10 @@
 #include "base/strings/string_split.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "components/feed/feed_feature_list.h"
-#include "components/variations/variations_params_manager.h"
 #include "net/http/http_response_headers.h"
 #include "net/http/http_status_code.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
@@ -374,10 +374,9 @@
 }
 
 TEST_F(FeedNetworkingHostTest, TestParamTimeout) {
-  variations::testing::VariationParamsManager variation_params(
-      kInterestFeedContentSuggestions.name,
-      {{kTimeoutDurationSeconds.name, "2"}},
-      {kInterestFeedContentSuggestions.name});
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kInterestFeedContentSuggestions, {{kTimeoutDurationSeconds.name, "2"}});
   MockResponseDoneCallback done_callback;
   GURL url = GURL("http://foobar.com/feed");
   std::vector<uint8_t> request_body;
diff --git a/components/feed/core/feed_scheduler_host_unittest.cc b/components/feed/core/feed_scheduler_host_unittest.cc
index 72685a97..a0b42eb 100644
--- a/components/feed/core/feed_scheduler_host_unittest.cc
+++ b/components/feed/core/feed_scheduler_host_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/memory/weak_ptr.h"
 #include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/simple_test_clock.h"
 #include "components/feed/core/pref_names.h"
 #include "components/feed/core/refresh_throttler.h"
@@ -19,7 +20,6 @@
 #include "components/feed/feed_feature_list.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
-#include "components/variations/variations_params_manager.h"
 #include "components/web_resource/web_resource_pref_names.h"
 #include "net/base/network_change_notifier.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -315,10 +315,10 @@
                 /*has_outstanding_request*/ false));
 
   // By changing the foregrounded threshold, staleness calculation changes.
-  variations::testing::VariationParamsManager variation_params(
-      kInterestFeedContentSuggestions.name,
-      {{"foregrounded_hours_active_ntp_user", "7.5"}},
-      {kInterestFeedContentSuggestions.name});
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kInterestFeedContentSuggestions,
+      {{"foregrounded_hours_active_ntp_user", "7.5"}});
 
   ResetRefreshState(Time());
   EXPECT_EQ(kRequestWithContent,
@@ -338,10 +338,10 @@
 }
 
 TEST_F(FeedSchedulerHostTest, NtpShownActiveNtpUser) {
-  variations::testing::VariationParamsManager variation_params(
-      kInterestFeedContentSuggestions.name,
-      {{"ntp_shown_hours_active_ntp_user", "2.5"}},
-      {kInterestFeedContentSuggestions.name});
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kInterestFeedContentSuggestions,
+      {{"ntp_shown_hours_active_ntp_user", "2.5"}});
 
   EXPECT_EQ(kNoRequestWithContent,
             ShouldSessionRequestData(
@@ -359,10 +359,10 @@
 }
 
 TEST_F(FeedSchedulerHostTest, NtpShownRareNtpUser) {
-  variations::testing::VariationParamsManager variation_params(
-      kInterestFeedContentSuggestions.name,
-      {{"ntp_shown_hours_rare_ntp_user", "1.5"}},
-      {kInterestFeedContentSuggestions.name});
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kInterestFeedContentSuggestions,
+      {{"ntp_shown_hours_rare_ntp_user", "1.5"}});
 
   ClassifyAsRareNtpUser();
 
@@ -402,10 +402,10 @@
                     TimeDelta::FromMinutes(61),
                 /*has_outstanding_request*/ false));
 
-  variations::testing::VariationParamsManager variation_params(
-      kInterestFeedContentSuggestions.name,
-      {{"ntp_shown_hours_active_suggestions_consumer", "7.5"}},
-      {kInterestFeedContentSuggestions.name});
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kInterestFeedContentSuggestions,
+      {{"ntp_shown_hours_active_suggestions_consumer", "7.5"}});
 
   EXPECT_EQ(kNoRequestWithContent,
             ShouldSessionRequestData(
@@ -453,10 +453,10 @@
   EXPECT_EQ(2, refresh_call_count());
   scheduler()->OnReceiveNewContent(test_clock()->Now());
 
-  variations::testing::VariationParamsManager variation_params(
-      kInterestFeedContentSuggestions.name,
-      {{"foregrounded_hours_active_ntp_user", "7.5"}},
-      {kInterestFeedContentSuggestions.name});
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kInterestFeedContentSuggestions,
+      {{"foregrounded_hours_active_ntp_user", "7.5"}});
 
   test_clock()->Advance(TimeDelta::FromHours(7));
   scheduler()->OnForegrounded();
@@ -484,10 +484,10 @@
   EXPECT_EQ(2, refresh_call_count());
   scheduler()->OnReceiveNewContent(test_clock()->Now());
 
-  variations::testing::VariationParamsManager variation_params(
-      kInterestFeedContentSuggestions.name,
-      {{"foregrounded_hours_rare_ntp_user", "7.5"}},
-      {kInterestFeedContentSuggestions.name});
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kInterestFeedContentSuggestions,
+      {{"foregrounded_hours_rare_ntp_user", "7.5"}});
 
   test_clock()->Advance(TimeDelta::FromHours(7));
   scheduler()->OnForegrounded();
@@ -515,10 +515,10 @@
   EXPECT_EQ(2, refresh_call_count());
   scheduler()->OnReceiveNewContent(test_clock()->Now());
 
-  variations::testing::VariationParamsManager variation_params(
-      kInterestFeedContentSuggestions.name,
-      {{"foregrounded_hours_active_suggestions_consumer", "7.5"}},
-      {kInterestFeedContentSuggestions.name});
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kInterestFeedContentSuggestions,
+      {{"foregrounded_hours_active_suggestions_consumer", "7.5"}});
 
   test_clock()->Advance(TimeDelta::FromHours(7));
   scheduler()->OnForegrounded();
@@ -567,10 +567,10 @@
   EXPECT_EQ(2, refresh_call_count());
   scheduler()->OnReceiveNewContent(test_clock()->Now());
 
-  variations::testing::VariationParamsManager variation_params(
-      kInterestFeedContentSuggestions.name,
-      {{"fixed_timer_hours_active_ntp_user", "7.5"}},
-      {kInterestFeedContentSuggestions.name});
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kInterestFeedContentSuggestions,
+      {{"fixed_timer_hours_active_ntp_user", "7.5"}});
 
   test_clock()->Advance(TimeDelta::FromHours(7));
   scheduler()->OnFixedTimer(base::OnceClosure());
@@ -598,11 +598,10 @@
   EXPECT_EQ(2, refresh_call_count());
   scheduler()->OnReceiveNewContent(test_clock()->Now());
 
-  variations::testing::VariationParamsManager variation_params(
-      kInterestFeedContentSuggestions.name,
-      {{"fixed_timer_hours_rare_ntp_user", "7.5"}},
-      {kInterestFeedContentSuggestions.name});
-
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kInterestFeedContentSuggestions,
+      {{"fixed_timer_hours_rare_ntp_user", "7.5"}});
   test_clock()->Advance(TimeDelta::FromHours(7));
   scheduler()->OnFixedTimer(base::OnceClosure());
   EXPECT_EQ(2, refresh_call_count());
@@ -636,10 +635,10 @@
   EXPECT_EQ(2, refresh_call_count());
   scheduler()->OnReceiveNewContent(test_clock()->Now());
 
-  variations::testing::VariationParamsManager variation_params(
-      kInterestFeedContentSuggestions.name,
-      {{"fixed_timer_hours_active_suggestions_consumer", "7.5"}},
-      {kInterestFeedContentSuggestions.name});
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kInterestFeedContentSuggestions,
+      {{"fixed_timer_hours_active_suggestions_consumer", "7.5"}});
 
   test_clock()->Advance(TimeDelta::FromHours(7));
   scheduler()->OnFixedTimer(base::OnceClosure());
@@ -737,10 +736,10 @@
 }
 
 TEST_F(FeedSchedulerHostTest, DisableOneTrigger) {
-  variations::testing::VariationParamsManager variation_params(
-      kInterestFeedContentSuggestions.name,
-      {{kDisableTriggerTypes.name, "foregrounded"}},
-      {kInterestFeedContentSuggestions.name});
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kInterestFeedContentSuggestions,
+      {{kDisableTriggerTypes.name, "foregrounded"}});
   NewScheduler();
 
   scheduler()->OnForegrounded();
@@ -756,10 +755,10 @@
 }
 
 TEST_F(FeedSchedulerHostTest, DisableAllTriggers) {
-  variations::testing::VariationParamsManager variation_params(
-      kInterestFeedContentSuggestions.name,
-      {{kDisableTriggerTypes.name, "ntp_shown,foregrounded,fixed_timer"}},
-      {kInterestFeedContentSuggestions.name});
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kInterestFeedContentSuggestions,
+      {{kDisableTriggerTypes.name, "ntp_shown,foregrounded,fixed_timer"}});
   NewScheduler();
 
   scheduler()->OnForegrounded();
@@ -775,11 +774,10 @@
 }
 
 TEST_F(FeedSchedulerHostTest, DisableBogusTriggers) {
-  variations::testing::VariationParamsManager variation_params(
-      kInterestFeedContentSuggestions.name,
-      {{kDisableTriggerTypes.name, "foo,123,#$*,,"}},
-      {kInterestFeedContentSuggestions.name});
-
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kInterestFeedContentSuggestions,
+      {{kDisableTriggerTypes.name, "foo,123,#$*,,"}});
   NewScheduler();
 
   scheduler()->OnForegrounded();
@@ -828,10 +826,10 @@
 }
 
 TEST_F(FeedSchedulerHostTest, SuppressRefreshDuration) {
-  variations::testing::VariationParamsManager variation_params(
-      kInterestFeedContentSuggestions.name,
-      {{kSuppressRefreshDurationMinutes.name, "100"}},
-      {kInterestFeedContentSuggestions.name});
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kInterestFeedContentSuggestions,
+      {{kSuppressRefreshDurationMinutes.name, "100"}});
   EXPECT_FALSE(scheduler()->OnArticlesCleared(/*suppress_refreshes*/ true));
 
   test_clock()->Advance(TimeDelta::FromMinutes(99));
@@ -990,10 +988,10 @@
 }
 
 TEST_F(FeedSchedulerHostTest, RefreshThrottler) {
-  variations::testing::VariationParamsManager variation_params(
-      kInterestFeedContentSuggestions.name,
-      {{"quota_SuggestionFetcherActiveNTPUser", "3"}},
-      {kInterestFeedContentSuggestions.name});
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kInterestFeedContentSuggestions,
+      {{"quota_SuggestionFetcherActiveNTPUser", "3"}});
   NewScheduler();
 
   for (int i = 0; i < 5; i++) {
diff --git a/components/feed/core/refresh_throttler_unittest.cc b/components/feed/core/refresh_throttler_unittest.cc
index ac8c9a6..c0c62a4 100644
--- a/components/feed/core/refresh_throttler_unittest.cc
+++ b/components/feed/core/refresh_throttler_unittest.cc
@@ -7,13 +7,13 @@
 #include <limits>
 #include <memory>
 
+#include "base/test/scoped_feature_list.h"
 #include "base/test/simple_test_clock.h"
 #include "components/feed/core/pref_names.h"
 #include "components/feed/core/user_classifier.h"
 #include "components/feed/feed_feature_list.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
-#include "components/variations/variations_params_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace feed {
@@ -34,10 +34,9 @@
     EXPECT_TRUE(base::Time::FromUTCString(kNowString, &now));
     test_clock_.SetNow(now);
 
-    variations::testing::VariationParamsManager variation_params(
-        kInterestFeedContentSuggestions.name,
-        {{"quota_SuggestionFetcherActiveNTPUser", "2"}},
-        {kInterestFeedContentSuggestions.name});
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        kInterestFeedContentSuggestions,
+        {{"quota_SuggestionFetcherActiveNTPUser", "2"}});
 
     throttler_ = std::make_unique<RefreshThrottler>(
         UserClassifier::UserClass::kActiveSuggestionsViewer, &test_prefs_,
@@ -48,6 +47,7 @@
   TestingPrefServiceSimple test_prefs_;
   base::SimpleTestClock test_clock_;
   std::unique_ptr<RefreshThrottler> throttler_;
+  base::test::ScopedFeatureList scoped_feature_list_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(RefreshThrottlerTest);
diff --git a/components/feed/core/user_classifier_unittest.cc b/components/feed/core/user_classifier_unittest.cc
index ddb68952..b83bbaa7 100644
--- a/components/feed/core/user_classifier_unittest.cc
+++ b/components/feed/core/user_classifier_unittest.cc
@@ -9,12 +9,12 @@
 #include <utility>
 
 #include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/simple_test_clock.h"
 #include "base/time/time.h"
 #include "components/feed/feed_feature_list.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
-#include "components/variations/variations_params_manager.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -83,11 +83,11 @@
 TEST_F(FeedUserClassifierTest,
        ShouldBecomeActiveSuggestionsConsumerByClickingOftenWithDecreasedParam) {
   // Increase the param to one half.
-  variations::testing::VariationParamsManager variation_params(
-      kInterestFeedContentSuggestions.name,
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kInterestFeedContentSuggestions,
       {{"user_classifier_active_consumer_clicks_at_least_once_per_hours",
-        "36"}},
-      {kInterestFeedContentSuggestions.name});
+        "36"}});
   UserClassifier* user_classifier = CreateUserClassifier();
 
   // After two clicks still only an active user.
@@ -122,10 +122,10 @@
 TEST_F(FeedUserClassifierTest,
        ShouldBecomeRareSuggestionsViewerByNoActivityWithDecreasedParam) {
   // Decrease the param to one half.
-  variations::testing::VariationParamsManager variation_params(
-      kInterestFeedContentSuggestions.name,
-      {{"user_classifier_rare_user_views_at_most_once_per_hours", "48"}},
-      {kInterestFeedContentSuggestions.name});
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kInterestFeedContentSuggestions,
+      {{"user_classifier_rare_user_views_at_most_once_per_hours", "48"}});
   UserClassifier* user_classifier = CreateUserClassifier();
 
   // After one days of waiting still an active user.
@@ -224,10 +224,9 @@
        ShouldIgnoreSubsequentEventsWithIncreasedLimit) {
   UserClassifier::Event event = GetParam().first;
   // Increase the min_hours to 1.0, i.e. 60 minutes.
-  variations::testing::VariationParamsManager variation_params(
-      kInterestFeedContentSuggestions.name,
-      {{"user_classifier_min_hours", "1.0"}},
-      {kInterestFeedContentSuggestions.name});
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kInterestFeedContentSuggestions, {{"user_classifier_min_hours", "1.0"}});
   UserClassifier* user_classifier = CreateUserClassifier();
 
   // The initial event.
@@ -272,10 +271,9 @@
        ShouldCapDelayBetweenEventsWithDecreasedLimit) {
   UserClassifier::Event event = GetParam().first;
   // Decrease the max_hours to 72, i.e. 3 days.
-  variations::testing::VariationParamsManager variation_params(
-      kInterestFeedContentSuggestions.name,
-      {{"user_classifier_max_hours", "72"}},
-      {kInterestFeedContentSuggestions.name});
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kInterestFeedContentSuggestions, {{"user_classifier_max_hours", "72"}});
   UserClassifier* user_classifier = CreateUserClassifier();
 
   // The initial event.
diff --git a/components/heap_profiling/test_driver.cc b/components/heap_profiling/test_driver.cc
index 94eb977..a8e5ee0f 100644
--- a/components/heap_profiling/test_driver.cc
+++ b/components/heap_profiling/test_driver.cc
@@ -28,7 +28,6 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/system_connector.h"
 #include "content/public/browser/tracing_controller.h"
-#include "content/public/common/service_manager_connection.h"
 
 namespace heap_profiling {
 
@@ -686,7 +685,6 @@
   }
 
   service_manager::Connector* connector = content::GetSystemConnector();
-  content::ServiceManagerConnection::GetForProcess();
   if (!connector) {
     LOG(ERROR) << "A system Connector is not available in this environment.";
     return false;
@@ -739,7 +737,6 @@
   }
 
   service_manager::Connector* connector = content::GetSystemConnector();
-  content::ServiceManagerConnection::GetForProcess();
   if (!connector) {
     LOG(ERROR) << "A system Connector is not available in this environment.";
     return false;
diff --git a/components/ntp_snippets/remote/json_request_unittest.cc b/components/ntp_snippets/remote/json_request_unittest.cc
index 0f084c1..0d12b30 100644
--- a/components/ntp_snippets/remote/json_request_unittest.cc
+++ b/components/ntp_snippets/remote/json_request_unittest.cc
@@ -9,6 +9,7 @@
 
 #include "base/json/json_reader.h"
 #include "base/strings/stringprintf.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/test_mock_time_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/tick_clock.h"
@@ -18,7 +19,6 @@
 #include "components/ntp_snippets/ntp_snippets_constants.h"
 #include "components/ntp_snippets/remote/request_params.h"
 #include "components/prefs/testing_pref_service.h"
-#include "components/variations/variations_params_manager.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
 #include "services/network/test/test_url_loader_factory.h"
@@ -70,17 +70,16 @@
 class JsonRequestTest : public testing::Test {
  public:
   JsonRequestTest()
-      : params_manager_(
-            ntp_snippets::kArticleSuggestionsFeature.name,
-            {{"send_top_languages", "true"}, {"send_user_class", "true"}},
-            {ntp_snippets::kArticleSuggestionsFeature.name}),
-        pref_service_(std::make_unique<TestingPrefServiceSimple>()),
+      : pref_service_(std::make_unique<TestingPrefServiceSimple>()),
         mock_task_runner_(new base::TestMockTimeTaskRunner()),
         mock_runner_handle_(
             std::make_unique<base::ThreadTaskRunnerHandle>(mock_task_runner_)),
         test_shared_loader_factory_(
             base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
                 &test_url_loader_factory_)) {
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        kArticleSuggestionsFeature,
+        {{"send_top_languages", "true"}, {"send_user_class", "true"}});
     language::UrlLanguageHistogram::RegisterProfilePrefs(
         pref_service_->registry());
   }
@@ -107,7 +106,7 @@
   }
 
  private:
-  variations::testing::VariationParamsManager params_manager_;
+  base::test::ScopedFeatureList scoped_feature_list_;
   std::unique_ptr<TestingPrefServiceSimple> pref_service_;
   scoped_refptr<base::TestMockTimeTaskRunner> mock_task_runner_;
   std::unique_ptr<base::ThreadTaskRunnerHandle> mock_runner_handle_;
diff --git a/components/ntp_snippets/remote/remote_suggestions_fetcher_impl_unittest.cc b/components/ntp_snippets/remote/remote_suggestions_fetcher_impl_unittest.cc
index 8de361d4..81fe05b 100644
--- a/components/ntp_snippets/remote/remote_suggestions_fetcher_impl_unittest.cc
+++ b/components/ntp_snippets/remote/remote_suggestions_fetcher_impl_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/default_clock.h"
@@ -30,7 +31,6 @@
 #include "components/ntp_snippets/user_classifier.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/variations/entropy_provider.h"
-#include "components/variations/variations_params_manager.h"
 #include "net/http/http_util.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "services/identity/public/cpp/identity_test_environment.h"
@@ -177,10 +177,9 @@
       : default_variation_params_(
             {{"send_top_languages", "true"},
              {"send_user_class", "true"},
-             {"append_request_priority_as_query_parameter", "true"}}),
-        params_manager_(ntp_snippets::kArticleSuggestionsFeature.name,
-                        default_variation_params_,
-                        {ntp_snippets::kArticleSuggestionsFeature.name}) {
+             {"append_request_priority_as_query_parameter", "true"}}) {
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        ntp_snippets::kArticleSuggestionsFeature, default_variation_params_);
     UserClassifier::RegisterProfilePrefs(utils_.pref_service()->registry());
     user_classifier_ = std::make_unique<UserClassifier>(
         utils_.pref_service(), base::DefaultClock::GetInstance());
@@ -234,10 +233,9 @@
     std::map<std::string, std::string> params = default_variation_params_;
     params[param_name] = value;
 
-    params_manager_.ClearAllVariationParams();
-    params_manager_.SetVariationParamsWithFeatureAssociations(
-        ntp_snippets::kArticleSuggestionsFeature.name, params,
-        {ntp_snippets::kArticleSuggestionsFeature.name});
+    scoped_feature_list_.Reset();
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        ntp_snippets::kArticleSuggestionsFeature, params);
   }
 
   void SetFakeResponse(const GURL& request_url,
@@ -266,7 +264,7 @@
 
  private:
   test::RemoteSuggestionsTestUtils utils_;
-  variations::testing::VariationParamsManager params_manager_;
+  base::test::ScopedFeatureList scoped_feature_list_;
   std::unique_ptr<RemoteSuggestionsFetcherImpl> fetcher_;
   std::unique_ptr<UserClassifier> user_classifier_;
   MockSnippetsAvailableCallback mock_callback_;
diff --git a/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc b/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc
index 66ba221d..6648e669 100644
--- a/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc
+++ b/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc
@@ -22,6 +22,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/test/simple_test_clock.h"
 #include "base/test/test_mock_time_task_runner.h"
@@ -59,7 +60,6 @@
 #include "components/ntp_snippets/user_classifier.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/strings/grit/components_strings.h"
-#include "components/variations/variations_params_manager.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gmock_mutant.h"
@@ -506,34 +506,26 @@
   }
 
   void SetOrderNewRemoteCategoriesBasedOnArticlesCategoryParam(bool value) {
-    // VariationParamsManager supports only one
-    // |SetVariationParamsWithFeatureAssociations| at a time, so we clear
-    // previous settings first to make this explicit.
-    params_manager_.ClearAllVariationParams();
-    params_manager_.SetVariationParamsWithFeatureAssociations(
-        kArticleSuggestionsFeature.name,
+    scoped_feature_list_.Reset();
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        kArticleSuggestionsFeature,
         {{"order_new_remote_categories_based_on_articles_category",
-          value ? "true" : "false"}},
-        {kArticleSuggestionsFeature.name});
+          value ? "true" : "false"}});
   }
 
   void EnableKeepingPrefetchedContentSuggestions(
       int max_additional_prefetched_suggestions,
       const base::TimeDelta& max_age_for_additional_prefetched_suggestion) {
-    // VariationParamsManager supports only one
-    // |SetVariationParamsWithFeatureAssociations| at a time, so we clear
-    // previous settings first to make this explicit.
-    params_manager_.ClearAllVariationParams();
-    params_manager_.SetVariationParamsWithFeatureAssociations(
-        kKeepPrefetchedContentSuggestions.name,
+    scoped_feature_list_.Reset();
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        kKeepPrefetchedContentSuggestions,
         {
             {"max_additional_prefetched_suggestions",
              base::NumberToString(max_additional_prefetched_suggestions)},
             {"max_age_for_additional_prefetched_suggestion_minutes",
              base::NumberToString(
                  max_age_for_additional_prefetched_suggestion.InMinutes())},
-        },
-        {kKeepPrefetchedContentSuggestions.name});
+        });
   }
 
   void SetTriggeringNotificationsAndSubscriptionParams(
@@ -541,12 +533,9 @@
       bool pushed_notifications_enabled,
       bool subscribe_signed_in,
       bool subscribe_signed_out) {
-    // VariationParamsManager supports only one
-    // |SetVariationParamsWithFeatureAssociations| at a time, so we clear
-    // previous settings first to make this explicit.
-    params_manager_.ClearAllVariationParams();
-    params_manager_.SetVariationParamsWithFeatureAssociations(
-        /*trial_name=*/kNotificationsFeature.name,
+    scoped_feature_list_.Reset();
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        kNotificationsFeature,
         {
             {"enable_fetched_suggestions_notifications",
              BoolToString(fetched_notifications_enabled)},
@@ -556,33 +545,24 @@
              BoolToString(subscribe_signed_in)},
             {"enable_signed_out_users_subscription_for_pushed_suggestions",
              BoolToString(subscribe_signed_out)},
-        },
-        {kNotificationsFeature.name});
+        });
   }
 
   void SetFetchedNotificationsParams(bool enable, bool force) {
-    // VariationParamsManager supports only one
-    // |SetVariationParamsWithFeatureAssociations| at a time, so we clear
-    // previous settings first to make this explicit.
-    params_manager_.ClearAllVariationParams();
-    params_manager_.SetVariationParamsWithFeatureAssociations(
-        /*trial_name=*/kNotificationsFeature.name,
+    scoped_feature_list_.Reset();
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        kNotificationsFeature,
         {
             {"enable_fetched_suggestions_notifications", BoolToString(enable)},
             {"force_fetched_suggestions_notifications", BoolToString(force)},
-        },
-        {kNotificationsFeature.name});
+        });
   }
 
   void SetFetchMoreSuggestionsCount(int count) {
-    // VariationParamsManager supports only one
-    // |SetVariationParamsWithFeatureAssociations| at a time, so we clear
-    // previous settings first to make this explicit.
-    params_manager_.ClearAllVariationParams();
-    params_manager_.SetVariationParamsWithFeatureAssociations(
-        /*trial_name=*/kArticleSuggestionsFeature.name,
-        {{"fetch_more_suggestions_count", base::NumberToString(count)}},
-        {kArticleSuggestionsFeature.name});
+    scoped_feature_list_.Reset();
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        kArticleSuggestionsFeature,
+        {{"fetch_more_suggestions_count", base::NumberToString(count)}});
   }
 
   void FastForwardBy(const base::TimeDelta& delta) {
@@ -604,7 +584,7 @@
  private:
   std::unique_ptr<RemoteSuggestionsProviderImpl> provider_;
 
-  variations::testing::VariationParamsManager params_manager_;
+  base::test::ScopedFeatureList scoped_feature_list_;
   test::RemoteSuggestionsTestUtils utils_;
   std::unique_ptr<CategoryRanker> category_ranker_;
   UserClassifier user_classifier_;
diff --git a/components/ntp_snippets/remote/remote_suggestions_scheduler_impl_unittest.cc b/components/ntp_snippets/remote/remote_suggestions_scheduler_impl_unittest.cc
index b3150f1..db646ab 100644
--- a/components/ntp_snippets/remote/remote_suggestions_scheduler_impl_unittest.cc
+++ b/components/ntp_snippets/remote/remote_suggestions_scheduler_impl_unittest.cc
@@ -30,7 +30,6 @@
 #include "components/ntp_snippets/user_classifier.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
-#include "components/variations/variations_params_manager.h"
 #include "components/web_resource/web_resource_pref_names.h"
 #include "net/base/network_change_notifier.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -177,11 +176,11 @@
         default_variation_params_{{"scheduler_trigger_types",
                                    "persistent_scheduler_wake_up,ntp_opened,"
                                    "browser_foregrounded,browser_cold_start"}},
-        params_manager_(ntp_snippets::kArticleSuggestionsFeature.name,
-                        default_variation_params_,
-                        {kArticleSuggestionsFeature.name}),
         user_classifier_(/*pref_service=*/nullptr,
                          base::DefaultClock::GetInstance()) {
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        ntp_snippets::kArticleSuggestionsFeature, default_variation_params_);
+
     RemoteSuggestionsSchedulerImpl::RegisterProfilePrefs(
         utils_.pref_service()->registry());
     RequestThrottler::RegisterProfilePrefs(utils_.pref_service()->registry());
@@ -212,10 +211,9 @@
     std::map<std::string, std::string> params = default_variation_params_;
     params[param_name] = param_value;
 
-    params_manager_.ClearAllVariationParams();
-    params_manager_.SetVariationParamsWithFeatureAssociations(
-        ntp_snippets::kArticleSuggestionsFeature.name, params,
-        {ntp_snippets::kArticleSuggestionsFeature.name});
+    scoped_feature_list_.Reset();
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        ntp_snippets::kArticleSuggestionsFeature, params);
   }
 
   bool IsEulaNotifierAvailable() {
@@ -240,7 +238,7 @@
 
  protected:
   std::map<std::string, std::string> default_variation_params_;
-  variations::testing::VariationParamsManager params_manager_;
+  base::test::ScopedFeatureList scoped_feature_list_;
 
   void ActivateProviderAndEula() {
     SetEulaAcceptedPref();
diff --git a/components/ntp_snippets/remote/remote_suggestions_status_service_impl_unittest.cc b/components/ntp_snippets/remote/remote_suggestions_status_service_impl_unittest.cc
index 86ea8b534..68b570e 100644
--- a/components/ntp_snippets/remote/remote_suggestions_status_service_impl_unittest.cc
+++ b/components/ntp_snippets/remote/remote_suggestions_status_service_impl_unittest.cc
@@ -14,7 +14,6 @@
 #include "components/ntp_snippets/remote/test_utils.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
-#include "components/variations/variations_params_manager.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -60,7 +59,6 @@
 
   RemoteSuggestionsStatus last_status_;
   test::RemoteSuggestionsTestUtils utils_;
-  variations::testing::VariationParamsManager params_manager_;
 };
 
 TEST_F(RemoteSuggestionsStatusServiceImplTest, NoSigninNeeded) {
diff --git a/components/ntp_snippets/user_classifier_unittest.cc b/components/ntp_snippets/user_classifier_unittest.cc
index 69e685e..07513f6 100644
--- a/components/ntp_snippets/user_classifier_unittest.cc
+++ b/components/ntp_snippets/user_classifier_unittest.cc
@@ -9,13 +9,13 @@
 #include <utility>
 
 #include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/simple_test_clock.h"
 #include "base/time/time.h"
 #include "components/ntp_snippets/features.h"
 #include "components/ntp_snippets/ntp_snippets_constants.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
-#include "components/variations/variations_params_manager.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -83,11 +83,11 @@
 TEST_F(UserClassifierTest,
        ShouldBecomeActiveSuggestionsConsumerByClickingOftenWithDecreasedParam) {
   // Increase the param to one half.
-  variations::testing::VariationParamsManager variation_params(
-      kArticleSuggestionsFeature.name,
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kArticleSuggestionsFeature,
       {{"user_classifier_active_consumer_clicks_at_least_once_per_hours",
-        "36"}},
-      {kArticleSuggestionsFeature.name});
+        "36"}});
   UserClassifier* user_classifier = CreateUserClassifier();
 
   // After two clicks still only an active user.
@@ -121,10 +121,10 @@
 TEST_F(UserClassifierTest,
        ShouldBecomeRareNtpUserByNoActivityWithDecreasedParam) {
   // Decrease the param to one half.
-  variations::testing::VariationParamsManager variation_params(
-      kArticleSuggestionsFeature.name,
-      {{"user_classifier_rare_user_opens_ntp_at_most_once_per_hours", "48"}},
-      {kArticleSuggestionsFeature.name});
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kArticleSuggestionsFeature,
+      {{"user_classifier_rare_user_opens_ntp_at_most_once_per_hours", "48"}});
   UserClassifier* user_classifier = CreateUserClassifier();
 
   // After one days of waiting still an active user.
@@ -223,9 +223,9 @@
        ShouldIgnoreSubsequentEventsWithIncreasedLimit) {
   UserClassifier::Metric metric = GetParam().first;
   // Increase the min_hours to 1.0, i.e. 60 minutes.
-  variations::testing::VariationParamsManager variation_params(
-      kArticleSuggestionsFeature.name, {{"user_classifier_min_hours", "1.0"}},
-      {kArticleSuggestionsFeature.name});
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kArticleSuggestionsFeature, {{"user_classifier_min_hours", "1.0"}});
   UserClassifier* user_classifier = CreateUserClassifier();
 
   // The initial event
@@ -270,9 +270,9 @@
        ShouldCapDelayBetweenEventsWithDecreasedLimit) {
   UserClassifier::Metric metric = GetParam().first;
   // Decrease the max_hours to 72, i.e. 3 days.
-  variations::testing::VariationParamsManager variation_params(
-      kArticleSuggestionsFeature.name, {{"user_classifier_max_hours", "72"}},
-      {kArticleSuggestionsFeature.name});
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeatureWithParameters(
+      kArticleSuggestionsFeature, {{"user_classifier_max_hours", "72"}});
   UserClassifier* user_classifier = CreateUserClassifier();
 
   // The initial event
diff --git a/components/offline_pages/core/BUILD.gn b/components/offline_pages/core/BUILD.gn
index a247f833..1d10cff 100644
--- a/components/offline_pages/core/BUILD.gn
+++ b/components/offline_pages/core/BUILD.gn
@@ -58,6 +58,7 @@
     "offline_event_logger.h",
     "offline_page_archiver.cc",
     "offline_page_archiver.h",
+    "offline_page_client_policy.cc",
     "offline_page_client_policy.h",
     "offline_page_item.cc",
     "offline_page_item.h",
diff --git a/components/offline_pages/core/client_policy_controller.cc b/components/offline_pages/core/client_policy_controller.cc
index 7c6f2b8..e05a7f5 100644
--- a/components/offline_pages/core/client_policy_controller.cc
+++ b/components/offline_pages/core/client_policy_controller.cc
@@ -8,102 +8,96 @@
 
 #include "base/time/time.h"
 #include "components/offline_pages/core/client_namespace_constants.h"
-#include "components/offline_pages/core/offline_page_feature.h"
 
 namespace offline_pages {
-namespace {
 
-// Generates a client policy from the input values.
-const OfflinePageClientPolicy MakePolicy(const std::string& name_space,
-                                         LifetimeType lifetime_type,
-                                         const base::TimeDelta& expire_period,
-                                         size_t page_limit,
-                                         size_t pages_allowed_per_url) {
-  return OfflinePageClientPolicyBuilder(name_space, lifetime_type, page_limit,
-                                        pages_allowed_per_url)
-      .SetExpirePeriod(expire_period)
-      .Build();
+OfflinePageClientPolicy* ClientPolicyController::AddTemporaryPolicy(
+    const std::string& name_space,
+    const base::TimeDelta& expiration_period) {
+  auto iter_and_was_inserted_pair = policies_.emplace(
+      name_space, OfflinePageClientPolicy(name_space, LifetimeType::TEMPORARY));
+  DCHECK(iter_and_was_inserted_pair.second) << "Policy was not inserted";
+  OfflinePageClientPolicy& policy = (*iter_and_was_inserted_pair.first).second;
+  policy.expiration_period = expiration_period;
+  return &policy;
 }
 
-}  // namespace
+OfflinePageClientPolicy* ClientPolicyController::AddPersistentPolicy(
+    const std::string& name_space) {
+  auto iter_and_was_inserted_pair = policies_.emplace(
+      name_space,
+      OfflinePageClientPolicy(name_space, LifetimeType::PERSISTENT));
+  DCHECK(iter_and_was_inserted_pair.second) << "Policy was not inserted";
+  OfflinePageClientPolicy& policy = (*iter_and_was_inserted_pair.first).second;
+  return &policy;
+}
 
 ClientPolicyController::ClientPolicyController() {
-  // Manually defining client policies for bookmark and last_n.
-  policies_.emplace(
-      kBookmarkNamespace,
-      MakePolicy(kBookmarkNamespace, LifetimeType::TEMPORARY,
-                 base::TimeDelta::FromDays(7), kUnlimitedPages, 1));
-  policies_.emplace(
-      kLastNNamespace,
-      OfflinePageClientPolicyBuilder(kLastNNamespace, LifetimeType::TEMPORARY,
-                                     kUnlimitedPages, kUnlimitedPages)
-          .SetExpirePeriod(base::TimeDelta::FromDays(30))
-          .SetIsRestrictedToTabFromClientId(true)
-          .Build());
-  policies_.emplace(
-      kAsyncNamespace,
-      OfflinePageClientPolicyBuilder(kAsyncNamespace, LifetimeType::PERSISTENT,
-                                     kUnlimitedPages, kUnlimitedPages)
-          .SetIsSupportedByDownload(true)
-          .Build());
-  policies_.emplace(
-      kCCTNamespace,
-      OfflinePageClientPolicyBuilder(kCCTNamespace, LifetimeType::TEMPORARY,
-                                     kUnlimitedPages, 1)
-          .SetExpirePeriod(base::TimeDelta::FromDays(2))
-          .SetRequiresSpecificUserSettings(true)
-          .Build());
-  policies_.emplace(kDownloadNamespace,
-                    OfflinePageClientPolicyBuilder(
-                        kDownloadNamespace, LifetimeType::PERSISTENT,
-                        kUnlimitedPages, kUnlimitedPages)
-                        .SetIsSupportedByDownload(true)
-                        .Build());
-  policies_.emplace(kNTPSuggestionsNamespace,
-                    OfflinePageClientPolicyBuilder(
-                        kNTPSuggestionsNamespace, LifetimeType::PERSISTENT,
-                        kUnlimitedPages, kUnlimitedPages)
-                        .SetIsSupportedByDownload(true)
-                        .Build());
-  policies_.emplace(
-      kSuggestedArticlesNamespace,
-      OfflinePageClientPolicyBuilder(kSuggestedArticlesNamespace,
-                                     LifetimeType::TEMPORARY, kUnlimitedPages,
-                                     kUnlimitedPages)
-          .SetExpirePeriod(base::TimeDelta::FromDays(30))
-          .SetIsSupportedByDownload(IsPrefetchingOfflinePagesEnabled())
-          .SetIsSuggested(true)
-          .Build());
-  policies_.emplace(kBrowserActionsNamespace,
-                    OfflinePageClientPolicyBuilder(
-                        kBrowserActionsNamespace, LifetimeType::PERSISTENT,
-                        kUnlimitedPages, kUnlimitedPages)
-                        .SetIsSupportedByDownload(true)
-                        .SetAllowConversionToBackgroundFileDownload(true)
-                        .Build());
-  policies_.emplace(kLivePageSharingNamespace,
-                    OfflinePageClientPolicyBuilder(kLivePageSharingNamespace,
-                                                   LifetimeType::TEMPORARY,
-                                                   kUnlimitedPages, 1)
-                        .SetExpirePeriod(base::TimeDelta::FromHours(1))
-                        .SetIsRestrictedToTabFromClientId(true)
-                        .Build());
-  policies_.emplace(
-      kAutoAsyncNamespace,
-      OfflinePageClientPolicyBuilder(
-          kAutoAsyncNamespace, LifetimeType::TEMPORARY, kUnlimitedPages, 1)
-          .SetExpirePeriod(base::TimeDelta::FromDays(30))
-          .SetDeferBackgroundFetchWhilePageIsActive(true)
-          .Build());
+  {
+    OfflinePageClientPolicy* policy =
+        AddTemporaryPolicy(kBookmarkNamespace, base::TimeDelta::FromDays(7));
+    policy->pages_allowed_per_url = 1;
+  }
+  {
+    OfflinePageClientPolicy* policy =
+        AddTemporaryPolicy(kLastNNamespace, base::TimeDelta::FromDays(30));
+    policy->is_restricted_to_tab_from_client_id = true;
+  }
+  {
+    OfflinePageClientPolicy* policy = AddPersistentPolicy(kAsyncNamespace);
+    policy->is_supported_by_download = true;
+  }
+  {
+    OfflinePageClientPolicy* policy =
+        AddTemporaryPolicy(kCCTNamespace, base::TimeDelta::FromDays(2));
+    policy->pages_allowed_per_url = 1;
+    policy->requires_specific_user_settings = true;
+  }
+  {
+    OfflinePageClientPolicy* policy = AddPersistentPolicy(kDownloadNamespace);
+    policy->is_supported_by_download = true;
+  }
+  {
+    OfflinePageClientPolicy* policy =
+        AddPersistentPolicy(kNTPSuggestionsNamespace);
+    policy->is_supported_by_download = true;
+  }
+  {
+    OfflinePageClientPolicy* policy = AddTemporaryPolicy(
+        kSuggestedArticlesNamespace, base::TimeDelta::FromDays(30));
+    policy->is_supported_by_download = 1;
+    policy->is_suggested = true;
+  }
+  {
+    OfflinePageClientPolicy* policy =
+        AddPersistentPolicy(kBrowserActionsNamespace);
+    policy->is_supported_by_download = true;
+    policy->allows_conversion_to_background_file_download = true;
+  }
+  {
+    OfflinePageClientPolicy* policy = AddTemporaryPolicy(
+        kLivePageSharingNamespace, base::TimeDelta::FromHours(1));
+    policy->pages_allowed_per_url = 1;
+    policy->is_restricted_to_tab_from_client_id = true;
+  }
+  {
+    OfflinePageClientPolicy* policy =
+        AddTemporaryPolicy(kAutoAsyncNamespace, base::TimeDelta::FromDays(30));
+    policy->pages_allowed_per_url = 1;
+    policy->defer_background_fetch_while_page_is_active = true;
+  }
 
   // Fallback policy.
-  policies_.emplace(kDefaultNamespace,
-                    MakePolicy(kDefaultNamespace, LifetimeType::TEMPORARY,
-                               base::TimeDelta::FromDays(1), 10, 1));
+  {
+    OfflinePageClientPolicy* policy =
+        AddTemporaryPolicy(kDefaultNamespace, base::TimeDelta::FromDays(1));
+    policy->page_limit = 10;
+    policy->pages_allowed_per_url = 1;
+  }
 
   for (const auto& policy_item : policies_) {
     const std::string& name = policy_item.first;
-    switch (policy_item.second.lifetime_policy.lifetime_type) {
+    switch (policy_item.second.lifetime_type) {
       case LifetimeType::TEMPORARY:
         temporary_namespaces_.push_back(name);
         break;
@@ -134,8 +128,7 @@
 }
 
 bool ClientPolicyController::IsTemporary(const std::string& name_space) const {
-  return GetPolicy(name_space).lifetime_policy.lifetime_type ==
-         LifetimeType::TEMPORARY;
+  return GetPolicy(name_space).lifetime_type == LifetimeType::TEMPORARY;
 }
 
 const std::vector<std::string>& ClientPolicyController::GetTemporaryNamespaces()
@@ -145,12 +138,11 @@
 
 bool ClientPolicyController::IsSupportedByDownload(
     const std::string& name_space) const {
-  return GetPolicy(name_space).feature_policy.is_supported_by_download;
+  return GetPolicy(name_space).is_supported_by_download;
 }
 
 bool ClientPolicyController::IsPersistent(const std::string& name_space) const {
-  return GetPolicy(name_space).lifetime_policy.lifetime_type ==
-         LifetimeType::PERSISTENT;
+  return GetPolicy(name_space).lifetime_type == LifetimeType::PERSISTENT;
 }
 
 const std::vector<std::string>&
@@ -160,23 +152,21 @@
 
 bool ClientPolicyController::IsRestrictedToTabFromClientId(
     const std::string& name_space) const {
-  return GetPolicy(name_space)
-      .feature_policy.is_restricted_to_tab_from_client_id;
+  return GetPolicy(name_space).is_restricted_to_tab_from_client_id;
 }
 
 bool ClientPolicyController::RequiresSpecificUserSettings(
     const std::string& name_space) const {
-  return GetPolicy(name_space).feature_policy.requires_specific_user_settings;
+  return GetPolicy(name_space).requires_specific_user_settings;
 }
 
 bool ClientPolicyController::IsSuggested(const std::string& name_space) const {
-  return GetPolicy(name_space).feature_policy.is_suggested;
+  return GetPolicy(name_space).is_suggested;
 }
 
 bool ClientPolicyController::AllowsConversionToBackgroundFileDownload(
     const std::string& name_space) const {
-  return GetPolicy(name_space)
-      .feature_policy.allows_conversion_to_background_file_download;
+  return GetPolicy(name_space).allows_conversion_to_background_file_download;
 }
 
 }  // namespace offline_pages
diff --git a/components/offline_pages/core/client_policy_controller.h b/components/offline_pages/core/client_policy_controller.h
index df95a7b..6d973e8e 100644
--- a/components/offline_pages/core/client_policy_controller.h
+++ b/components/offline_pages/core/client_policy_controller.h
@@ -52,7 +52,7 @@
 
   // Returns whether pages for |name_space| can be saved only if specific user
   // settings are properly set. See
-  // FeaturePolicy::requires_specific_user_settings for details).
+  // OfflinePageClientPolicy::requires_specific_user_settings for details).
   bool RequiresSpecificUserSettings(const std::string& name_space) const;
 
   // Returns whether pages for |name_space| originate from suggested URLs and
@@ -65,6 +65,11 @@
       const std::string& name_space) const;
 
  private:
+  OfflinePageClientPolicy* AddTemporaryPolicy(
+      const std::string& name_space,
+      const base::TimeDelta& expiration_period);
+  OfflinePageClientPolicy* AddPersistentPolicy(const std::string& name_space);
+
   // The map from name_space to a client policy. Will be generated
   // as pre-defined values for now.
   std::map<std::string, OfflinePageClientPolicy> policies_;
diff --git a/components/offline_pages/core/client_policy_controller_unittest.cc b/components/offline_pages/core/client_policy_controller_unittest.cc
index 932596c..9d354a2 100644
--- a/components/offline_pages/core/client_policy_controller_unittest.cc
+++ b/components/offline_pages/core/client_policy_controller_unittest.cc
@@ -19,7 +19,7 @@
 const char kUndefinedNamespace[] = "undefined";
 
 bool isTemporary(const OfflinePageClientPolicy& policy) {
-  return policy.lifetime_policy.lifetime_type == LifetimeType::TEMPORARY;
+  return policy.lifetime_type == LifetimeType::TEMPORARY;
 }
 }  // namespace
 
diff --git a/components/offline_pages/core/model/clear_storage_task.cc b/components/offline_pages/core/model/clear_storage_task.cc
index 570394c..a9b7465 100644
--- a/components/offline_pages/core/model/clear_storage_task.cc
+++ b/components/offline_pages/core/model/clear_storage_task.cc
@@ -54,9 +54,8 @@
     const std::string& name_space = page.client_id.name_space;
     const OfflinePageClientPolicy& policy =
         policy_controller_->GetPolicy(name_space);
-    const size_t page_limit = policy.lifetime_policy.page_limit;
-    const base::TimeDelta expiration_period =
-        policy.lifetime_policy.expiration_period;
+    const size_t page_limit = policy.page_limit;
+    const base::TimeDelta expiration_period = policy.expiration_period;
 
     // If the cached pages exceed the storage limit, we need to clear more than
     // just expired pages to make the storage usage below the threshold.
diff --git a/components/offline_pages/core/model/clear_storage_task_unittest.cc b/components/offline_pages/core/model/clear_storage_task_unittest.cc
index b3139f1..3392c91 100644
--- a/components/offline_pages/core/model/clear_storage_task_unittest.cc
+++ b/components/offline_pages/core/model/clear_storage_task_unittest.cc
@@ -164,10 +164,9 @@
     AddPage();
   }
 
-  generator()->SetLastAccessTime(clock_.Now() -
-                                 policy_controller()
-                                     ->GetPolicy(setting.name_space)
-                                     .lifetime_policy.expiration_period);
+  generator()->SetLastAccessTime(
+      clock_.Now() -
+      policy_controller()->GetPolicy(setting.name_space).expiration_period);
   for (int i = 0; i < setting.expired_page_count; ++i) {
     AddPage();
   }
@@ -264,12 +263,12 @@
 
   // Check preconditions, especially that last_n expiration is longer than
   // bookmark's.
-  LifetimePolicy bookmark_policy =
-      policy_controller()->GetPolicy(kBookmarkNamespace).lifetime_policy;
-  LifetimePolicy last_n_policy =
-      policy_controller()->GetPolicy(kLastNNamespace).lifetime_policy;
-  LifetimePolicy download_policy =
-      policy_controller()->GetPolicy(kDownloadNamespace).lifetime_policy;
+  OfflinePageClientPolicy bookmark_policy =
+      policy_controller()->GetPolicy(kBookmarkNamespace);
+  OfflinePageClientPolicy last_n_policy =
+      policy_controller()->GetPolicy(kLastNNamespace);
+  OfflinePageClientPolicy download_policy =
+      policy_controller()->GetPolicy(kDownloadNamespace);
   ASSERT_EQ(LifetimeType::TEMPORARY, bookmark_policy.lifetime_type);
   ASSERT_EQ(LifetimeType::TEMPORARY, last_n_policy.lifetime_type);
   ASSERT_EQ(LifetimeType::PERSISTENT, download_policy.lifetime_type);
diff --git a/components/offline_pages/core/offline_page_client_policy.cc b/components/offline_pages/core/offline_page_client_policy.cc
new file mode 100644
index 0000000..7038fbb
--- /dev/null
+++ b/components/offline_pages/core/offline_page_client_policy.cc
@@ -0,0 +1,18 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/offline_pages/core/offline_page_client_policy.h"
+
+namespace offline_pages {
+
+OfflinePageClientPolicy::OfflinePageClientPolicy(std::string namespace_val,
+                                                 LifetimeType lifetime_type_val)
+    : name_space(namespace_val), lifetime_type(lifetime_type_val) {}
+
+OfflinePageClientPolicy::OfflinePageClientPolicy(
+    const OfflinePageClientPolicy& other) = default;
+
+OfflinePageClientPolicy::~OfflinePageClientPolicy() = default;
+
+}  // namespace offline_pages
diff --git a/components/offline_pages/core/offline_page_client_policy.h b/components/offline_pages/core/offline_page_client_policy.h
index c974d52..3a06d7d 100644
--- a/components/offline_pages/core/offline_page_client_policy.h
+++ b/components/offline_pages/core/offline_page_client_policy.h
@@ -28,152 +28,57 @@
   PERSISTENT,
 };
 
-// The struct describing the lifetime policy of offline pages.
-// The following behaviors are controlled by policy:
-//    a. Persistency of the offline page.
-//    b. Expiration time of an offline page
-//    c. Limit of number of pages offline.
-struct LifetimePolicy {
-  // Type of the page generated by the client.
-  LifetimeType lifetime_type;
+// The struct describing policies for offline pages' clients (Bookmark, Last-N
+// etc.) describing how their pages are handled by the offline page model.
+struct OfflinePageClientPolicy {
+  OfflinePageClientPolicy(std::string namespace_val,
+                          LifetimeType lifetime_type_val);
+  OfflinePageClientPolicy(const OfflinePageClientPolicy& other);
+  ~OfflinePageClientPolicy();
 
-  // The time after which the page expires.
-  // A TimeDelta of 0 means no expiration.
+  // Namespace that uniquely identifies this client.
+  std::string name_space;
+
+  // Lifetime type for the pages saved by this client.
+  LifetimeType lifetime_type = LifetimeType::TEMPORARY;
+
+  // The time after which pages expire. A zero value (default) means pages from
+  // this client never expire.
   base::TimeDelta expiration_period;
 
-  // The maximum number of pages allowed to be saved by the namespace.
-  // kUnlimitedPages (defined above) means no limit set.
-  size_t page_limit;
+  // The maximum number of pages allowed to be saved for this client.
+  // |kUnlimitedPages| (default) means no limit is set.
+  size_t page_limit = kUnlimitedPages;
 
-  LifetimePolicy(LifetimeType init_lifetime_type, size_t init_page_limit)
-      : lifetime_type(init_lifetime_type),
-        expiration_period(base::TimeDelta::FromDays(0)),
-        page_limit(init_page_limit) {}
-};
+  // The maximum number of pages for the same URL that can be stored for this
+  // client. |kUnlimitedPages| (default) means no limit is set.
+  size_t pages_allowed_per_url = kUnlimitedPages;
 
-// The struct describing feature set of the offline pages.
-struct FeaturePolicy {
-  // Whether pages are shown in download ui.
+  // Whether pages are shown in the Downloads UI.
   bool is_supported_by_download = false;
+
   // Whether pages can only be viewed in a specific tab. Pages controlled by
   // this policy must have their ClientId::id field set to their assigned tab's
   // id.
   bool is_restricted_to_tab_from_client_id = false;
-  // Whether the namespace should be disabled if any of these user settings are
+
+  // Whether this client should be "disabled" if any of these user settings are
   // set to:
   // * 3rd party cookies are blocked (prefs::kBlockThirdPartyCookies).
   // * Network predictions (prefs::kNetworkPredictionOptions) are fully
   //   disabled.
   bool requires_specific_user_settings = false;
-  // Whether the pages originated from suggestions by zine or elsewhere.
+
+  // Whether the pages originate from suggestion engines like Zine or the Feed.
   bool is_suggested = false;
+
   // Whether a background page download is allowed to be converted to a regular
   // download if the URL turns out to point to a file (i.e. a PDF).
   bool allows_conversion_to_background_file_download = false;
-};
-
-// The struct describing policies for various namespaces (Bookmark, Last-N etc.)
-// used by offline page model. The name_space is supposed to be key, so that
-// it's sufficient to compare name_space only when doing comparisons.
-struct OfflinePageClientPolicy {
-  // Namespace to which the policy applied.
-  std::string name_space;
-
-  // Policy to control the lifetime of a page generated by this namespace.
-  LifetimePolicy lifetime_policy;
-
-  // How many pages for the same online URL can be stored at any time.
-  // kUnlimitedPages means there's no limit.
-  size_t pages_allowed_per_url;
-
-  FeaturePolicy feature_policy;
 
   // Whether background fetches are deferred while the active tab matches the
   // SavePageRequestURL.
   bool defer_background_fetch_while_page_is_active = false;
-
-  OfflinePageClientPolicy(std::string namespace_val,
-                          LifetimePolicy lifetime_policy_val,
-                          size_t pages_allowed_per_url_val,
-                          FeaturePolicy feature_policy_val)
-      : name_space(namespace_val),
-        lifetime_policy(lifetime_policy_val),
-        pages_allowed_per_url(pages_allowed_per_url_val),
-        feature_policy(feature_policy_val) {}
-
-  OfflinePageClientPolicy(std::string namespace_val,
-                          LifetimePolicy lifetime_policy_val,
-                          size_t pages_allowed_per_url_val)
-      : OfflinePageClientPolicy(namespace_val,
-                                lifetime_policy_val,
-                                pages_allowed_per_url_val,
-                                FeaturePolicy()) {}
-};
-
-class OfflinePageClientPolicyBuilder {
- public:
-  OfflinePageClientPolicyBuilder(const std::string& name_space,
-                                 LifetimeType lifetime_type,
-                                 size_t page_limit,
-                                 size_t pages_allowed_per_url)
-      : policy_(
-            OfflinePageClientPolicy(name_space,
-                                    LifetimePolicy(lifetime_type, page_limit),
-                                    pages_allowed_per_url)) {}
-
-  ~OfflinePageClientPolicyBuilder() {}
-
-  // Calling build does not reset the object inside.
-  const OfflinePageClientPolicy Build() const { return policy_; }
-
-  OfflinePageClientPolicyBuilder& SetExpirePeriod(
-      const base::TimeDelta& expire_period) {
-    policy_.lifetime_policy.expiration_period = expire_period;
-    return *this;
-  }
-
-  OfflinePageClientPolicyBuilder& SetIsSupportedByDownload(
-      const bool is_downloaded) {
-    policy_.feature_policy.is_supported_by_download = is_downloaded;
-    return *this;
-  }
-
-  OfflinePageClientPolicyBuilder& SetIsRestrictedToTabFromClientId(
-      const bool is_restricted_to_tab_from_client_id) {
-    policy_.feature_policy.is_restricted_to_tab_from_client_id =
-        is_restricted_to_tab_from_client_id;
-    return *this;
-  }
-
-  OfflinePageClientPolicyBuilder& SetRequiresSpecificUserSettings(
-      const bool requires_specific_user_settings) {
-    policy_.feature_policy.requires_specific_user_settings =
-        requires_specific_user_settings;
-    return *this;
-  }
-
-  OfflinePageClientPolicyBuilder& SetIsSuggested(const bool is_suggested) {
-    policy_.feature_policy.is_suggested = is_suggested;
-    return *this;
-  }
-
-  OfflinePageClientPolicyBuilder& SetAllowConversionToBackgroundFileDownload(
-      const bool allows_conversion_to_background_file_download) {
-    policy_.feature_policy.allows_conversion_to_background_file_download =
-        allows_conversion_to_background_file_download;
-    return *this;
-  }
-
-  OfflinePageClientPolicyBuilder& SetDeferBackgroundFetchWhilePageIsActive(
-      bool defer) {
-    policy_.defer_background_fetch_while_page_is_active = defer;
-    return *this;
-  }
-
- private:
-  OfflinePageClientPolicy policy_;
-
-  DISALLOW_COPY_AND_ASSIGN(OfflinePageClientPolicyBuilder);
 };
 
 }  // namespace offline_pages
diff --git a/components/offline_pages/core/page_criteria.cc b/components/offline_pages/core/page_criteria.cc
index 1ca7471..11f64128 100644
--- a/components/offline_pages/core/page_criteria.cc
+++ b/components/offline_pages/core/page_criteria.cc
@@ -39,22 +39,21 @@
     const OfflinePageClientPolicy& policy =
         policy_controller.GetPolicy(client_id.name_space);
     if (criteria.exclude_tab_bound_pages &&
-        policy.feature_policy.is_restricted_to_tab_from_client_id) {
+        policy.is_restricted_to_tab_from_client_id) {
       return false;
     }
     if (criteria.pages_for_tab_id &&
-        policy.feature_policy.is_restricted_to_tab_from_client_id) {
+        policy.is_restricted_to_tab_from_client_id) {
       std::string tab_id_str =
           base::NumberToString(criteria.pages_for_tab_id.value());
       if (client_id.id != tab_id_str)
         return false;
     }
-    if (criteria.supported_by_downloads &&
-        !policy.feature_policy.is_supported_by_download) {
+    if (criteria.supported_by_downloads && !policy.is_supported_by_download) {
       return false;
     }
-    if (criteria.lifetime_type && criteria.lifetime_type.value() !=
-                                      policy.lifetime_policy.lifetime_type) {
+    if (criteria.lifetime_type &&
+        criteria.lifetime_type.value() != policy.lifetime_type) {
       return false;
     }
   }
@@ -109,9 +108,9 @@
           !policy_controller.IsSupportedByDownload(name_space)) {
         continue;
       }
-      if (criteria.lifetime_type && criteria.lifetime_type.value() !=
-                                        policy_controller.GetPolicy(name_space)
-                                            .lifetime_policy.lifetime_type) {
+      if (criteria.lifetime_type &&
+          criteria.lifetime_type.value() !=
+              policy_controller.GetPolicy(name_space).lifetime_type) {
         continue;
       }
       matching_namespaces.push_back(name_space);
diff --git a/components/offline_pages/core/prefetch/prefetch_server_urls_unittest.cc b/components/offline_pages/core/prefetch/prefetch_server_urls_unittest.cc
index 4ebbb85..63242fb 100644
--- a/components/offline_pages/core/prefetch/prefetch_server_urls_unittest.cc
+++ b/components/offline_pages/core/prefetch/prefetch_server_urls_unittest.cc
@@ -4,8 +4,8 @@
 
 #include "components/offline_pages/core/prefetch/prefetch_server_urls.h"
 
+#include "base/test/scoped_feature_list.h"
 #include "components/offline_pages/core/offline_page_feature.h"
-#include "components/variations/variations_params_manager.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace offline_pages {
@@ -23,16 +23,15 @@
   void SetTestingServerEndpoint(const std::string& server_config);
 
  private:
-  variations::testing::VariationParamsManager params_manager_;
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 void PrefetchServerURLsTest::SetTestingServerEndpoint(
     const std::string& server_config) {
-  params_manager_.ClearAllVariationParams();
-  params_manager_.SetVariationParamsWithFeatureAssociations(
-      kPrefetchingOfflinePagesFeature.name,
-      {{"offline_pages_backend", server_config}},
-      {kPrefetchingOfflinePagesFeature.name});
+  scoped_feature_list_.Reset();
+  scoped_feature_list_.InitAndEnableFeatureWithParameters(
+      kPrefetchingOfflinePagesFeature,
+      {{"offline_pages_backend", server_config}});
 }
 
 TEST_F(PrefetchServerURLsTest, TestVariationsConfig) {
diff --git a/components/offline_pages/core/prefetch/store/prefetch_downloader_quota_unittest.cc b/components/offline_pages/core/prefetch/store/prefetch_downloader_quota_unittest.cc
index d87ab9f..f3922335 100644
--- a/components/offline_pages/core/prefetch/store/prefetch_downloader_quota_unittest.cc
+++ b/components/offline_pages/core/prefetch/store/prefetch_downloader_quota_unittest.cc
@@ -4,11 +4,11 @@
 
 #include "components/offline_pages/core/prefetch/store/prefetch_downloader_quota.h"
 
+#include "base/test/scoped_feature_list.h"
 #include "base/test/test_mock_time_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/offline_pages/core/offline_page_feature.h"
 #include "components/offline_pages/core/prefetch/store/prefetch_store_test_util.h"
-#include "components/variations/variations_params_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace offline_pages {
@@ -40,7 +40,7 @@
   scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
   base::ThreadTaskRunnerHandle task_runner_handle_;
   PrefetchStoreTestUtil store_test_util_;
-  variations::testing::VariationParamsManager params_manager_;
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 PrefetchDownloaderQuotaTest::PrefetchDownloaderQuotaTest()
@@ -50,11 +50,10 @@
 
 void PrefetchDownloaderQuotaTest::SetTestingMaxDailyQuotaBytes(
     const std::string& max_config) {
-  params_manager_.ClearAllVariationParams();
-  params_manager_.SetVariationParamsWithFeatureAssociations(
-      kPrefetchingOfflinePagesFeature.name,
-      {{"offline_pages_max_daily_quota_bytes", max_config}},
-      {kPrefetchingOfflinePagesFeature.name});
+  scoped_feature_list_.Reset();
+  scoped_feature_list_.InitAndEnableFeatureWithParameters(
+      kPrefetchingOfflinePagesFeature,
+      {{"offline_pages_max_daily_quota_bytes", max_config}});
 }
 
 TEST_F(PrefetchDownloaderQuotaTest, GetMaxDailyQuotaBytes) {
diff --git a/components/omnibox/browser/zero_suggest_provider.cc b/components/omnibox/browser/zero_suggest_provider.cc
index 9b483e78..6d8d4d3 100644
--- a/components/omnibox/browser/zero_suggest_provider.cc
+++ b/components/omnibox/browser/zero_suggest_provider.cc
@@ -97,9 +97,9 @@
     "Omnibox.ZeroSuggest.Eligible.OnFocusV2";
 
 // If the user is not signed-in or the user does not have Google set up as their
-// default search engine, the personalized service is replaced with the most
-// visited service.
-bool PersonalizedServiceShouldFallBackToMostVisited(
+// default search engine, the remote suggestions service is replaced with the
+// most visited service.
+bool RemoteSuggestionsShouldFallBackToMostVisited(
     AutocompleteProviderClient* client,
     const TemplateURLService* template_url_service) {
   if (!client->SearchSuggestEnabled())
@@ -359,7 +359,7 @@
   if (!data)
     return false;
 
-  // When running the personalized service, we want to store suggestion
+  // When running the REMOTE_NO_URL variant, we want to store suggestion
   // responses if non-empty.
   if (result_type_running_ == REMOTE_NO_URL && !json_data.empty()) {
     client()->GetPrefs()->SetString(omnibox::kZeroSuggestCachedResults,
@@ -632,8 +632,11 @@
     return REMOTE_NO_URL;
 
   if (field_trial_variant == kRemoteNoUrlVariant) {
-    return PersonalizedServiceShouldFallBackToMostVisited(client(),
-                                                          template_url_service)
+    // TODO(tommycli): It's odd that this doesn't apply to kRemoteSendUrlVariant
+    // as well. Most likely this fallback concept should be replaced by
+    // a more general configuration setup.
+    return RemoteSuggestionsShouldFallBackToMostVisited(client(),
+                                                        template_url_service)
                ? MOST_VISITED
                : REMOTE_NO_URL;
   }
diff --git a/components/policy/core/browser/configuration_policy_handler.cc b/components/policy/core/browser/configuration_policy_handler.cc
index f722895f8..3af00fd 100644
--- a/components/policy/core/browser/configuration_policy_handler.cc
+++ b/components/policy/core/browser/configuration_policy_handler.cc
@@ -579,10 +579,11 @@
   std::string error_path;
   const Schema json_string_schema =
       IsListSchema() ? schema_.GetItems() : schema_;
-  // TODO(https://crbug.com/953615): Consider switching from SCHEMA_STRICT to
-  // SCHEMA_ALLOW_UNKNOWN for all schema validating policy handlers.
-  bool validated = json_string_schema.Validate(*parsed_value, SCHEMA_STRICT,
-                                               &error_path, &schema_error);
+  // Even though we are validating this schema here, we don't actually change
+  // the policy if it fails to validate. This validation is just so we can show
+  // the user errors.
+  bool validated = json_string_schema.Validate(
+      *parsed_value, SCHEMA_ALLOW_UNKNOWN, &error_path, &schema_error);
   if (errors && !schema_error.empty())
     errors->AddError(policy_name_, ErrorPath(index, error_path), schema_error);
   if (!validated)
diff --git a/components/policy/core/common/schema.h b/components/policy/core/common/schema.h
index a57e0a2..0a1a18b 100644
--- a/components/policy/core/common/schema.h
+++ b/components/policy/core/common/schema.h
@@ -33,7 +33,11 @@
 // list items might be ignored (or dropped in Normalize()) or trigger whole
 // dictionary/list validation failure.
 enum SchemaOnErrorStrategy {
-  // No errors will be allowed.
+  // No errors will be allowed. This should not be used for policies, since it
+  // basically prevents future changes to the policy (Server sends newField, but
+  // clients running older versions of Chrome reject the policy because they
+  // don't know newField). Prefer to use |SCHEMA_ALLOW_UNKNOWN| for policies
+  // instead.
   SCHEMA_STRICT = 0,
   // Unknown properties in the top-level dictionary will be ignored.
   SCHEMA_ALLOW_UNKNOWN_TOPLEVEL,
diff --git a/components/policy/core/common/schema_map.cc b/components/policy/core/common/schema_map.cc
index 0779cd3..d701c48 100644
--- a/components/policy/core/common/schema_map.cc
+++ b/components/policy/core/common/schema_map.cc
@@ -61,16 +61,14 @@
 
     for (auto it_map = policy_map->begin(); it_map != policy_map->end();) {
       const std::string& policy_name = it_map->first;
-      const base::Value* policy_value = it_map->second.value.get();
+      base::Value* policy_value = it_map->second.value.get();
       Schema policy_schema = schema->GetProperty(policy_name);
       ++it_map;
       std::string error_path;
       std::string error;
       if (!policy_value ||
-          !policy_schema.Validate(*policy_value,
-                                  SCHEMA_STRICT,
-                                  &error_path,
-                                  &error)) {
+          !policy_schema.Normalize(policy_value, SCHEMA_ALLOW_UNKNOWN,
+                                   &error_path, &error, nullptr)) {
         LOG(ERROR) << "Dropping policy " << policy_name << " of component "
                    << ns.component_id << " due to error at "
                    << (error_path.empty() ? "root" : error_path) << ": "
diff --git a/components/policy/core/common/schema_map.h b/components/policy/core/common/schema_map.h
index 835941e..923a808c2 100644
--- a/components/policy/core/common/schema_map.h
+++ b/components/policy/core/common/schema_map.h
@@ -39,7 +39,8 @@
   const Schema* GetSchema(const PolicyNamespace& ns) const;
 
   // Removes all the policies in |bundle| that don't match the known schemas.
-  // Unknown components are also dropped.
+  // Unknown components are also dropped. Unknown fields in component policies
+  // are removed.
   void FilterBundle(PolicyBundle* bundle) const;
 
   // Returns true if this map contains at least one component of a domain other
diff --git a/components/previews/content/previews_user_data.cc b/components/previews/content/previews_user_data.cc
index 3f6d66c1..08294dc 100644
--- a/components/previews/content/previews_user_data.cc
+++ b/components/previews/content/previews_user_data.cc
@@ -26,9 +26,12 @@
           other.cache_control_no_transform_directive_),
       offline_preview_used_(other.offline_preview_used_),
       black_listed_for_lite_page_(other.black_listed_for_lite_page_),
-      committed_previews_type_(other.committed_previews_type_),
-      allowed_previews_state_(other.allowed_previews_state_),
-      committed_previews_state_(other.committed_previews_state_),
+      committed_previews_type_without_holdback_(
+          other.committed_previews_type_without_holdback_),
+      allowed_previews_state_without_holdback_(
+          other.allowed_previews_state_without_holdback_),
+      committed_previews_state_without_holdback_(
+          other.committed_previews_state_without_holdback_),
       coin_flip_holdback_result_(other.coin_flip_holdback_result_),
       preview_eligibility_reasons_(other.preview_eligibility_reasons_) {
   if (other.server_lite_page_info_) {
@@ -39,13 +42,13 @@
 
 void PreviewsUserData::SetCommittedPreviewsType(
     previews::PreviewsType previews_type) {
-  DCHECK(committed_previews_type_ == PreviewsType::NONE);
-  committed_previews_type_ = previews_type;
+  DCHECK(committed_previews_type_without_holdback_ == PreviewsType::NONE);
+  committed_previews_type_without_holdback_ = previews_type;
 }
 
 void PreviewsUserData::SetCommittedPreviewsTypeForTesting(
     previews::PreviewsType previews_type) {
-  committed_previews_type_ = previews_type;
+  committed_previews_type_without_holdback_ = previews_type;
 }
 
 bool PreviewsUserData::CoinFlipForNavigation() const {
@@ -72,4 +75,41 @@
   return iter->second;
 }
 
+bool PreviewsUserData::HasCommittedPreviewsType() const {
+  return CommittedPreviewsType() != PreviewsType::NONE;
+}
+
+previews::PreviewsType PreviewsUserData::PreHoldbackCommittedPreviewsType()
+    const {
+  return committed_previews_type_without_holdback_;
+}
+
+previews::PreviewsType PreviewsUserData::CommittedPreviewsType() const {
+  if (coin_flip_holdback_result_ == CoinFlipHoldbackResult::kHoldback)
+    return PreviewsType::NONE;
+  return committed_previews_type_without_holdback_;
+}
+
+content::PreviewsState PreviewsUserData::PreHoldbackAllowedPreviewsState()
+    const {
+  return allowed_previews_state_without_holdback_;
+}
+
+content::PreviewsState PreviewsUserData::AllowedPreviewsState() const {
+  if (coin_flip_holdback_result_ == CoinFlipHoldbackResult::kHoldback)
+    return content::PREVIEWS_OFF;
+  return allowed_previews_state_without_holdback_;
+}
+
+content::PreviewsState PreviewsUserData::PreHoldbackCommittedPreviewsState()
+    const {
+  return committed_previews_state_without_holdback_;
+}
+
+content::PreviewsState PreviewsUserData::CommittedPreviewsState() const {
+  if (coin_flip_holdback_result_ == CoinFlipHoldbackResult::kHoldback)
+    return content::PREVIEWS_OFF;
+  return committed_previews_state_without_holdback_;
+}
+
 }  // namespace previews
diff --git a/components/previews/content/previews_user_data.h b/components/previews/content/previews_user_data.h
index 5553858..476145c 100644
--- a/components/previews/content/previews_user_data.h
+++ b/components/previews/content/previews_user_data.h
@@ -116,13 +116,17 @@
   }
 
   // Whether there is a committed previews type.
-  bool HasCommittedPreviewsType() const {
-    return committed_previews_type_ != previews::PreviewsType::NONE;
-  }
-  // The committed previews type, if any. Otherwise PreviewsType::NONE.
-  previews::PreviewsType committed_previews_type() const {
-    return committed_previews_type_;
-  }
+  bool HasCommittedPreviewsType() const;
+
+  // The committed previews type, if any. Otherwise, PreviewsType::NONE. This
+  // should be used for metrics only since it does not respect the coin flip
+  // holdback.
+  previews::PreviewsType PreHoldbackCommittedPreviewsType() const;
+
+  // The committed previews type, if any. Otherwise, PreviewsType::NONE. Returns
+  // NONE if the coin flip holdback is kHoldback.
+  previews::PreviewsType CommittedPreviewsType() const;
+
   // Sets the committed previews type. Should only be called once.
   void SetCommittedPreviewsType(previews::PreviewsType previews_type);
   // Sets the committed previews type for testing. Can be called multiple times.
@@ -135,22 +139,29 @@
   }
 
   // The PreviewsState that was allowed for the navigation. This should be used
-  // for metrics only.
-  content::PreviewsState allowed_previews_state() const {
-    return allowed_previews_state_;
-  }
+  // for metrics only since it does not respect the coin flip holdback.
+  content::PreviewsState PreHoldbackAllowedPreviewsState() const;
+
+  // The PreviewsState that was allowed for the navigation. Returns PREVIEWS_OFF
+  // if the coin flip holdback is kHoldback.
+  content::PreviewsState AllowedPreviewsState() const;
+
   void set_allowed_previews_state(
       content::PreviewsState allowed_previews_state) {
-    allowed_previews_state_ = allowed_previews_state;
+    allowed_previews_state_without_holdback_ = allowed_previews_state;
   }
 
-  // The PreviewsState that was committed for the navigation.
-  content::PreviewsState committed_previews_state() const {
-    return committed_previews_state_;
-  }
+  // The PreviewsState that was committed for the navigation. This should be
+  // used for metrics only since it does not respect the coin flip holdback.
+  content::PreviewsState PreHoldbackCommittedPreviewsState() const;
+
+  // The PreviewsState that was committed for the navigation. Returns
+  // PREVIEWS_OFF if the coin flip holdback is kHoldback.
+  content::PreviewsState CommittedPreviewsState() const;
+
   void set_committed_previews_state(
       content::PreviewsState committed_previews_state) {
-    committed_previews_state_ = committed_previews_state;
+    committed_previews_state_without_holdback_ = committed_previews_state;
   }
 
   // The result of a coin flip (if present) for this page load.
@@ -208,15 +219,20 @@
   // blacklist.
   bool black_listed_for_lite_page_ = false;
 
-  // The committed previews type, if any.
-  previews::PreviewsType committed_previews_type_ = PreviewsType::NONE;
+  // The committed previews type, if any. Is not influenced by the coin flip
+  // holdback.
+  previews::PreviewsType committed_previews_type_without_holdback_ =
+      PreviewsType::NONE;
 
-  // The PreviewsState that was allowed for the navigation.
-  content::PreviewsState allowed_previews_state_ =
+  // The PreviewsState that was allowed for the navigation. Is not influenced by
+  // the coin flip holdback.
+  content::PreviewsState allowed_previews_state_without_holdback_ =
       content::PREVIEWS_UNSPECIFIED;
 
-  // The PreviewsState that was committed for the navigation.
-  content::PreviewsState committed_previews_state_ = content::PREVIEWS_OFF;
+  // The PreviewsState that was committed for the navigation. Is not influenced
+  // by the coin flip holdback.
+  content::PreviewsState committed_previews_state_without_holdback_ =
+      content::PREVIEWS_OFF;
 
   // The state of a random coin flip holdback, if any.
   CoinFlipHoldbackResult coin_flip_holdback_result_ =
diff --git a/components/previews/content/previews_user_data_unittest.cc b/components/previews/content/previews_user_data_unittest.cc
index 2ac8829..67bfc8b 100644
--- a/components/previews/content/previews_user_data_unittest.cc
+++ b/components/previews/content/previews_user_data_unittest.cc
@@ -42,7 +42,7 @@
 
   EXPECT_EQ(0, data->data_savings_inflation_percent());
   EXPECT_FALSE(data->cache_control_no_transform_directive());
-  EXPECT_EQ(previews::PreviewsType::NONE, data->committed_previews_type());
+  EXPECT_EQ(previews::PreviewsType::NONE, data->CommittedPreviewsType());
   EXPECT_FALSE(data->black_listed_for_lite_page());
   EXPECT_FALSE(data->offline_preview_used());
   EXPECT_EQ(data->server_lite_page_info(), nullptr);
@@ -66,7 +66,7 @@
   EXPECT_EQ(123, data_copy.data_savings_inflation_percent());
   EXPECT_TRUE(data_copy.cache_control_no_transform_directive());
   EXPECT_EQ(previews::PreviewsType::NOSCRIPT,
-            data_copy.committed_previews_type());
+            data_copy.CommittedPreviewsType());
   EXPECT_TRUE(data_copy.black_listed_for_lite_page());
   EXPECT_TRUE(data_copy.offline_preview_used());
   EXPECT_NE(data->server_lite_page_info(), nullptr);
@@ -74,4 +74,62 @@
   EXPECT_EQ("someversion", data->serialized_hint_version_string());
 }
 
+TEST(PreviewsUserDataTest, TestCoinFlip_HasCommittedPreviewsType) {
+  uint64_t id = 1u;
+  std::unique_ptr<PreviewsUserData> data =
+      std::make_unique<PreviewsUserData>(id);
+
+  data->SetCommittedPreviewsTypeForTesting(PreviewsType::NOSCRIPT);
+  data->set_coin_flip_holdback_result(CoinFlipHoldbackResult::kHoldback);
+  EXPECT_FALSE(data->HasCommittedPreviewsType());
+
+  data->set_coin_flip_holdback_result(CoinFlipHoldbackResult::kAllowed);
+  EXPECT_TRUE(data->HasCommittedPreviewsType());
+}
+
+TEST(PreviewsUserDataTest, TestCoinFlip_CommittedPreviewsType) {
+  uint64_t id = 1u;
+  std::unique_ptr<PreviewsUserData> data =
+      std::make_unique<PreviewsUserData>(id);
+
+  data->SetCommittedPreviewsTypeForTesting(PreviewsType::NOSCRIPT);
+  data->set_coin_flip_holdback_result(CoinFlipHoldbackResult::kHoldback);
+  EXPECT_EQ(data->CommittedPreviewsType(), PreviewsType::NONE);
+  EXPECT_EQ(data->PreHoldbackCommittedPreviewsType(), PreviewsType::NOSCRIPT);
+
+  data->set_coin_flip_holdback_result(CoinFlipHoldbackResult::kAllowed);
+  EXPECT_EQ(data->CommittedPreviewsType(), PreviewsType::NOSCRIPT);
+  EXPECT_EQ(data->PreHoldbackCommittedPreviewsType(), PreviewsType::NOSCRIPT);
+}
+
+TEST(PreviewsUserDataTest, TestCoinFlip_AllowedPreviewsState) {
+  uint64_t id = 1u;
+  std::unique_ptr<PreviewsUserData> data =
+      std::make_unique<PreviewsUserData>(id);
+
+  data->set_allowed_previews_state(content::NOSCRIPT_ON);
+  data->set_coin_flip_holdback_result(CoinFlipHoldbackResult::kHoldback);
+  EXPECT_EQ(data->AllowedPreviewsState(), content::PREVIEWS_OFF);
+  EXPECT_EQ(data->PreHoldbackAllowedPreviewsState(), content::NOSCRIPT_ON);
+
+  data->set_coin_flip_holdback_result(CoinFlipHoldbackResult::kAllowed);
+  EXPECT_EQ(data->AllowedPreviewsState(), content::NOSCRIPT_ON);
+  EXPECT_EQ(data->PreHoldbackAllowedPreviewsState(), content::NOSCRIPT_ON);
+}
+
+TEST(PreviewsUserDataTest, TestCoinFlip_CommittedPreviewsState) {
+  uint64_t id = 1u;
+  std::unique_ptr<PreviewsUserData> data =
+      std::make_unique<PreviewsUserData>(id);
+
+  data->set_committed_previews_state(content::NOSCRIPT_ON);
+  data->set_coin_flip_holdback_result(CoinFlipHoldbackResult::kHoldback);
+  EXPECT_EQ(data->CommittedPreviewsState(), content::PREVIEWS_OFF);
+  EXPECT_EQ(data->PreHoldbackCommittedPreviewsState(), content::NOSCRIPT_ON);
+
+  data->set_coin_flip_holdback_result(CoinFlipHoldbackResult::kAllowed);
+  EXPECT_EQ(data->CommittedPreviewsState(), content::NOSCRIPT_ON);
+  EXPECT_EQ(data->PreHoldbackCommittedPreviewsState(), content::NOSCRIPT_ON);
+}
+
 }  // namespace previews
diff --git a/components/printing/browser/print_composite_client.cc b/components/printing/browser/print_composite_client.cc
index 61d1bc854..29fb8d3 100644
--- a/components/printing/browser/print_composite_client.cc
+++ b/components/printing/browser/print_composite_client.cc
@@ -15,7 +15,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "printing/printing_utils.h"
 #include "services/service_manager/public/cpp/connector.h"
 
@@ -240,13 +240,8 @@
 }
 
 mojom::PdfCompositorPtr PrintCompositeClient::CreateCompositeRequest() {
-  if (!connector_) {
-    service_manager::mojom::ConnectorRequest connector_request;
-    connector_ = service_manager::Connector::Create(&connector_request);
-    content::ServiceManagerConnection::GetForProcess()
-        ->GetConnector()
-        ->BindConnectorRequest(std::move(connector_request));
-  }
+  if (!connector_)
+    connector_ = content::GetSystemConnector()->Clone();
   mojom::PdfCompositorPtr compositor;
   connector_->BindInterface(mojom::kServiceName, &compositor);
   compositor->SetWebContentsURL(web_contents()->GetLastCommittedURL());
diff --git a/components/session_manager/core/session_manager.cc b/components/session_manager/core/session_manager.cc
index be163bd..bb94497 100644
--- a/components/session_manager/core/session_manager.cc
+++ b/components/session_manager/core/session_manager.cc
@@ -67,7 +67,14 @@
 }
 
 void SessionManager::SessionStarted() {
+  if (session_started_)
+    return;
+
   session_started_ = true;
+
+  // SessionStarted() could be called in tests without any session created.
+  if (sessions_.size() == 1)
+    NotifyPrimaryUserSessionStarted();
 }
 
 bool SessionManager::HasSessionForAccountId(
@@ -98,6 +105,16 @@
   observers_.RemoveObserver(observer);
 }
 
+void SessionManager::NotifyUserProfileLoaded(const AccountId& account_id) {
+  for (auto& observer : observers_)
+    observer.OnUserProfileLoaded(account_id);
+}
+
+void SessionManager::NotifyPrimaryUserSessionStarted() {
+  for (auto& observer : observers_)
+    observer.OnPrimaryUserSessionStarted();
+}
+
 void SessionManager::NotifyUserLoggedIn(const AccountId& user_account_id,
                                         const std::string& user_id_hash,
                                         bool browser_restart,
diff --git a/components/session_manager/core/session_manager.h b/components/session_manager/core/session_manager.h
index 7913c821..2414f04 100644
--- a/components/session_manager/core/session_manager.h
+++ b/components/session_manager/core/session_manager.h
@@ -62,6 +62,10 @@
   void AddObserver(SessionManagerObserver* observer);
   void RemoveObserver(SessionManagerObserver* observer);
 
+  // Various helpers to notify observers.
+  void NotifyUserProfileLoaded(const AccountId& account_id);
+  void NotifyPrimaryUserSessionStarted();
+
   SessionState session_state() const { return session_state_; }
   const std::vector<Session>& sessions() const { return sessions_; }
 
@@ -102,7 +106,7 @@
   // Keeps track of user sessions.
   std::vector<Session> sessions_;
 
-  base::ObserverList<SessionManagerObserver>::Unchecked observers_;
+  base::ObserverList<SessionManagerObserver> observers_;
 
   DISALLOW_COPY_AND_ASSIGN(SessionManager);
 };
diff --git a/components/session_manager/core/session_manager_observer.h b/components/session_manager/core/session_manager_observer.h
index b702a2d..e3748ca 100644
--- a/components/session_manager/core/session_manager_observer.h
+++ b/components/session_manager/core/session_manager_observer.h
@@ -6,6 +6,7 @@
 #define COMPONENTS_SESSION_MANAGER_CORE_SESSION_MANAGER_OBSERVER_H_
 
 #include "base/macros.h"
+#include "base/observer_list_types.h"
 #include "components/session_manager/session_manager_types.h"
 
 namespace session_manager {
@@ -13,18 +14,16 @@
 // An observer interface for SessionManager.
 // TODO(xiyuan): Use this to replace UserManager::UserSessionStateObserver,
 //     http://crbug.com/657149.
-class SessionManagerObserver {
+class SessionManagerObserver : public base::CheckedObserver {
  public:
-  SessionManagerObserver() = default;
-
   // Invoked when session state is changed.
-  virtual void OnSessionStateChanged() = 0;
+  virtual void OnSessionStateChanged() {}
 
- protected:
-  virtual ~SessionManagerObserver() = default;
+  // Invoked when a user profile is loaded.
+  virtual void OnUserProfileLoaded(const AccountId& account_id) {}
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(SessionManagerObserver);
+  // Invoked when the primary user session is started.
+  virtual void OnPrimaryUserSessionStarted() {}
 };
 
 }  // namespace session_manager
diff --git a/components/spellcheck/BUILD.gn b/components/spellcheck/BUILD.gn
index 06df29d..0baee9c 100644
--- a/components/spellcheck/BUILD.gn
+++ b/components/spellcheck/BUILD.gn
@@ -13,6 +13,7 @@
   flags = [
     "ENABLE_SPELLCHECK=$enable_spellcheck",
     "USE_BROWSER_SPELLCHECKER=$use_browser_spellchecker",
+    "USE_RENDERER_SPELLCHECKER=$use_renderer_spellchecker",
     "HAS_SPELLCHECK_PANEL=$has_spellcheck_panel",
   ]
 }
diff --git a/components/spellcheck/browser/BUILD.gn b/components/spellcheck/browser/BUILD.gn
index 92d24df1..5df0c36 100644
--- a/components/spellcheck/browser/BUILD.gn
+++ b/components/spellcheck/browser/BUILD.gn
@@ -24,6 +24,10 @@
     "spelling_service_client.h",
   ]
 
+  if (is_win) {
+    sources += [ "spellcheck_platform_win.cc" ]
+  }
+
   public_deps = [
     "//base",
     "//components/spellcheck:buildflags",
@@ -49,6 +53,7 @@
   sources = [
     "spellcheck_host_metrics_unittest.cc",
     "spellcheck_platform_mac_unittest.cc",
+    "spellcheck_platform_win_unittest.cc",
   ]
 
   deps = [
diff --git a/components/spellcheck/browser/spell_check_host_impl.cc b/components/spellcheck/browser/spell_check_host_impl.cc
index d5482a5..8eb4ec5 100644
--- a/components/spellcheck/browser/spell_check_host_impl.cc
+++ b/components/spellcheck/browser/spell_check_host_impl.cc
@@ -32,7 +32,7 @@
   return;
 }
 
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#if BUILDFLAG(USE_RENDERER_SPELLCHECKER)
 void SpellCheckHostImpl::CallSpellingService(
     const base::string16& text,
     CallSpellingServiceCallback callback) {
@@ -44,7 +44,7 @@
   // This API requires Chrome-only features.
   std::move(callback).Run(false, std::vector<SpellCheckResult>());
 }
-#endif  // !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#endif  // BUILDFLAG(USE_RENDERER_SPELLCHECKER)
 
 #if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
 void SpellCheckHostImpl::RequestTextCheck(const base::string16& text,
diff --git a/components/spellcheck/browser/spell_check_host_impl.h b/components/spellcheck/browser/spell_check_host_impl.h
index f2a1d66e1..a935033 100644
--- a/components/spellcheck/browser/spell_check_host_impl.h
+++ b/components/spellcheck/browser/spell_check_host_impl.h
@@ -36,10 +36,10 @@
   void RequestDictionary() override;
   void NotifyChecked(const base::string16& word, bool misspelled) override;
 
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#if BUILDFLAG(USE_RENDERER_SPELLCHECKER)
   void CallSpellingService(const base::string16& text,
                            CallSpellingServiceCallback callback) override;
-#endif  // !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#endif  // BUILDFLAG(USE_RENDERER_SPELLCHECKER)
 
 #if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
   void RequestTextCheck(const base::string16& text,
diff --git a/components/spellcheck/browser/spellcheck_platform.h b/components/spellcheck/browser/spellcheck_platform.h
index 0153eb9..b33b0275 100644
--- a/components/spellcheck/browser/spellcheck_platform.h
+++ b/components/spellcheck/browser/spellcheck_platform.h
@@ -52,8 +52,14 @@
 // then returns true, otherwise false.
 bool PlatformSupportsLanguage(const std::string& current_language);
 
-// Sets the language for the platform-specific spellchecker.
-void SetLanguage(const std::string& lang_to_set);
+// Sets the language for the platform-specific spellchecker asynchronously. The
+// callback will be invoked with boolean parameter indicating the status of the
+// spellchecker for the language |lang_to_set|.
+void SetLanguage(const std::string& lang_to_set,
+                 base::OnceCallback<void(bool)> callback);
+
+// Removes the language for the platform-specific spellchecker.
+void DisableLanguage(const std::string& lang_to_disable);
 
 // Checks the spelling of the given string, using the platform-specific
 // spellchecker. Returns true if the word is spelled correctly.
diff --git a/components/spellcheck/browser/spellcheck_platform_android.cc b/components/spellcheck/browser/spellcheck_platform_android.cc
index 3cca6be1..50263d1 100644
--- a/components/spellcheck/browser/spellcheck_platform_android.cc
+++ b/components/spellcheck/browser/spellcheck_platform_android.cc
@@ -39,9 +39,13 @@
   return true;
 }
 
-void SetLanguage(const std::string& lang_to_set) {
+void SetLanguage(const std::string& lang_to_set,
+                 base::OnceCallback<void(bool)> callback) {
+  std::move(callback).Run(true);
 }
 
+void DisableLanguage(const std::string& lang_to_disable) {}
+
 bool CheckSpelling(const base::string16& word_to_check, int tag) {
   return true;
 }
diff --git a/components/spellcheck/browser/spellcheck_platform_mac.mm b/components/spellcheck/browser/spellcheck_platform_mac.mm
index 80c7a509..b24b172 100644
--- a/components/spellcheck/browser/spellcheck_platform_mac.mm
+++ b/components/spellcheck/browser/spellcheck_platform_mac.mm
@@ -162,15 +162,19 @@
   return [availableLanguages containsObject:mac_lang_code];
 }
 
-void SetLanguage(const std::string& lang_to_set) {
+void SetLanguage(const std::string& lang_to_set,
+                 base::OnceCallback<void(bool)> callback) {
   // Do not set any language right now, since Chrome should honor the
   // system spellcheck settings. (http://crbug.com/166046)
   // Fix this once Chrome actually allows setting a spellcheck language
   // in chrome://settings.
   //  NSString* NS_lang_to_set = ConvertLanguageCodeToMac(lang_to_set);
   //  [SharedSpellChecker() setLanguage:NS_lang_to_set];
+  std::move(callback).Run(true);
 }
 
+void DisableLanguage(const std::string& lang_to_disable) {}
+
 static int last_seen_tag_;
 
 bool CheckSpelling(const base::string16& word_to_check, int tag) {
diff --git a/components/spellcheck/browser/spellcheck_platform_win.cc b/components/spellcheck/browser/spellcheck_platform_win.cc
new file mode 100644
index 0000000..9fe5131c
--- /dev/null
+++ b/components/spellcheck/browser/spellcheck_platform_win.cc
@@ -0,0 +1,488 @@
+// Copyright 2019 The Chromium 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/spellcheck/browser/spellcheck_platform.h"
+
+#include <objidl.h>
+#include <spellcheck.h>
+#include <wrl/client.h>
+
+#include <codecvt>
+#include <locale>
+#include <string>
+
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/command_line.h"
+#include "base/no_destructor.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/win/windows_types.h"
+#include "base/win/windows_version.h"
+#include "components/spellcheck/common/spellcheck_common.h"
+#include "components/spellcheck/common/spellcheck_features.h"
+#include "components/spellcheck/common/spellcheck_result.h"
+
+namespace spellcheck_platform {
+
+namespace {
+// WindowsSpellChecker class is used to store all the COM objects and
+// control their lifetime. The class also provides wrappers for
+// ISpellCheckerFactory and ISpellChecker APIs. All COM calls are on the
+// background thread.
+class WindowsSpellChecker {
+ public:
+  WindowsSpellChecker(
+      const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+      const scoped_refptr<base::SingleThreadTaskRunner> background_task_runner);
+
+  void CreateSpellChecker(const std::string& lang_tag,
+                          base::OnceCallback<void(bool)> callback);
+
+  void DisableSpellChecker(const std::string& lang_tag);
+
+  void RequestTextCheckForAllLanguages(int document_tag,
+                                       const base::string16& text,
+                                       TextCheckCompleteCallback callback);
+
+  void AddWordForAllLanguages(const base::string16& word);
+
+  void RemoveWordForAllLanguages(const base::string16& word);
+
+  void IgnoreWordForAllLanguages(const base::string16& word);
+
+ private:
+  void CreateSpellCheckerFactoryInBackgroundThread();
+
+  // Creates ISpellchecker for given language |lang_tag| and run callback with
+  // the creation result. This function must run on the background thread.
+  void CreateSpellCheckerWithCallbackInBackgroundThread(
+      const std::string& lang_tag,
+      base::OnceCallback<void(bool)> callback);
+
+  // Removes the Windows Spellchecker for the given language |lang_tag|. This
+  // function must run on the background thread.
+  void DisableSpellCheckerInBackgroundThread(const std::string& lang_tag);
+
+  // Request spell checking of string |text| for all available spellchecking
+  // languages and run callback with spellchecking results. This function must
+  // run on the background thread.
+  void RequestTextCheckForAllLanguagesInBackgroundThread(
+      int document_tag,
+      const base::string16& text,
+      TextCheckCompleteCallback callback);
+
+  // Fills the given vector |optional_suggestions| with a number (up to
+  // kMaxSuggestions) of suggestions for the string |wrong_word| of language
+  // |lang_tag|. This function must run on the background thread.
+  void FillSuggestionListInBackgroundThread(
+      const std::string& lang_tag,
+      const base::string16& wrong_word,
+      std::vector<base::string16>* optional_suggestions);
+
+  void AddWordForAllLanguagesInBackgroundThread(const base::string16& word);
+
+  void RemoveWordForAllLanguagesInBackgroundThread(const base::string16& word);
+
+  void IgnoreWordForAllLanguagesInBackgroundThread(const base::string16& word);
+
+  // Returns true if spellchecker is available for the given language
+  // |current_language|. This function must run on the background thread.
+  bool IsLanguageSupportedInBackgroundThread(
+      const std::string& current_language);
+
+  // Returns true if ISpellCheckerFactory has been initialized.
+  bool IsSpellCheckerFactoryInitialized();
+
+  // Returns true if the ISpellChecker has been initialized for given laugnage
+  // |lang_tag|.
+  bool SpellCheckerReady(const std::string& lang_tag);
+
+  // Returns the ISpellChecker pointer for given language |lang_tag|.
+  Microsoft::WRL::ComPtr<ISpellChecker> GetSpellChecker(
+      const std::string& lang_tag);
+
+  // Spellchecker objects are owned by WindowsSpellChecker class.
+  Microsoft::WRL::ComPtr<ISpellCheckerFactory> spell_checker_factory_;
+  std::map<std::string, Microsoft::WRL::ComPtr<ISpellChecker>>
+      spell_checker_map_;
+
+  // |main_task_runner_| is running on the main thread, which is used to post
+  // task to the main thread from the background thread.
+  // |background_task_runner_| is running on the background thread, which is
+  // used to post task to the background thread from main thread.
+  scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+  scoped_refptr<base::SingleThreadTaskRunner> background_task_runner_;
+  base::WeakPtrFactory<WindowsSpellChecker> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(WindowsSpellChecker);
+};
+
+WindowsSpellChecker::WindowsSpellChecker(
+    const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+    const scoped_refptr<base::SingleThreadTaskRunner> background_task_runner)
+    : main_task_runner_(main_task_runner),
+      background_task_runner_(background_task_runner),
+      weak_ptr_factory_(this) {
+  background_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          &WindowsSpellChecker::CreateSpellCheckerFactoryInBackgroundThread,
+          weak_ptr_factory_.GetWeakPtr()));
+}
+
+void WindowsSpellChecker::CreateSpellChecker(
+    const std::string& lang_tag,
+    base::OnceCallback<void(bool)> callback) {
+  background_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&WindowsSpellChecker::
+                         CreateSpellCheckerWithCallbackInBackgroundThread,
+                     weak_ptr_factory_.GetWeakPtr(), lang_tag,
+                     std::move(callback)));
+}
+
+void WindowsSpellChecker::DisableSpellChecker(const std::string& lang_tag) {
+  background_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          &WindowsSpellChecker::DisableSpellCheckerInBackgroundThread,
+          weak_ptr_factory_.GetWeakPtr(), lang_tag));
+}
+
+void WindowsSpellChecker::RequestTextCheckForAllLanguages(
+    int document_tag,
+    const base::string16& text,
+    TextCheckCompleteCallback callback) {
+  background_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&WindowsSpellChecker::
+                         RequestTextCheckForAllLanguagesInBackgroundThread,
+                     weak_ptr_factory_.GetWeakPtr(), document_tag, text,
+                     std::move(callback)));
+}
+
+void WindowsSpellChecker::AddWordForAllLanguages(const base::string16& word) {
+  background_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          &WindowsSpellChecker::AddWordForAllLanguagesInBackgroundThread,
+          weak_ptr_factory_.GetWeakPtr(), word));
+}
+
+void WindowsSpellChecker::RemoveWordForAllLanguages(
+    const base::string16& word) {
+  background_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          &WindowsSpellChecker::RemoveWordForAllLanguagesInBackgroundThread,
+          weak_ptr_factory_.GetWeakPtr(), word));
+}
+
+void WindowsSpellChecker::IgnoreWordForAllLanguages(
+    const base::string16& word) {
+  background_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          &WindowsSpellChecker::IgnoreWordForAllLanguagesInBackgroundThread,
+          weak_ptr_factory_.GetWeakPtr(), word));
+}
+
+void WindowsSpellChecker::CreateSpellCheckerFactoryInBackgroundThread() {
+  DCHECK(!main_task_runner_->BelongsToCurrentThread());
+  DCHECK(SUCCEEDED(::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED)));
+
+  if (!spellcheck::UseBrowserSpellChecker() ||
+      FAILED(::CoCreateInstance(__uuidof(::SpellCheckerFactory), nullptr,
+                                (CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER),
+                                IID_PPV_ARGS(&spell_checker_factory_)))) {
+    spell_checker_factory_ = nullptr;
+  }
+}
+
+void WindowsSpellChecker::CreateSpellCheckerWithCallbackInBackgroundThread(
+    const std::string& lang_tag,
+    base::OnceCallback<void(bool)> callback) {
+  DCHECK(!main_task_runner_->BelongsToCurrentThread());
+
+  bool result = false;
+  if (IsSpellCheckerFactoryInitialized()) {
+    if (SpellCheckerReady(lang_tag)) {
+      result = true;
+    } else if (IsLanguageSupportedInBackgroundThread(lang_tag)) {
+      Microsoft::WRL::ComPtr<ISpellChecker> spell_checker;
+      std::wstring bcp47_language_tag = base::UTF8ToWide(lang_tag);
+      HRESULT hr = spell_checker_factory_->CreateSpellChecker(
+          bcp47_language_tag.c_str(), &spell_checker);
+      if (SUCCEEDED(hr)) {
+        spell_checker_map_.insert({lang_tag, spell_checker});
+        result = true;
+      }
+    }
+  }
+
+  // Run the callback with result on the main thread.
+  main_task_runner_->PostTask(FROM_HERE,
+                              base::BindOnce(std::move(callback), result));
+}
+
+void WindowsSpellChecker::DisableSpellCheckerInBackgroundThread(
+    const std::string& lang_tag) {
+  DCHECK(!main_task_runner_->BelongsToCurrentThread());
+
+  if (!IsSpellCheckerFactoryInitialized())
+    return;
+
+  auto it = spell_checker_map_.find(lang_tag);
+  if (it != spell_checker_map_.end()) {
+    spell_checker_map_.erase(it);
+  }
+}
+
+void WindowsSpellChecker::RequestTextCheckForAllLanguagesInBackgroundThread(
+    int document_tag,
+    const base::string16& text,
+    TextCheckCompleteCallback callback) {
+  DCHECK(!main_task_runner_->BelongsToCurrentThread());
+
+  // Construct a map to store spellchecking results. The key of the map is a
+  // tuple which contains the start index and the word length of the misspelled
+  // word. The value of the map is a vector which contains suggestion lists for
+  // each available language.
+  std::map<std::tuple<ULONG, ULONG>, std::vector<std::vector<base::string16>>>
+      result_map;
+
+  std::vector<SpellCheckResult> results;
+  for (auto it = spell_checker_map_.begin(); it != spell_checker_map_.end();
+       ++it) {
+    std::wstring word_to_check_wide(base::UTF16ToWide(text));
+    Microsoft::WRL::ComPtr<IEnumSpellingError> spelling_errors;
+
+    HRESULT hr = it->second->ComprehensiveCheck(word_to_check_wide.c_str(),
+                                                &spelling_errors);
+    if (SUCCEEDED(hr) && spelling_errors) {
+      do {
+        Microsoft::WRL::ComPtr<ISpellingError> spelling_error;
+        ULONG start_index = 0;
+        ULONG error_length = 0;
+        CORRECTIVE_ACTION action = CORRECTIVE_ACTION_NONE;
+        hr = spelling_errors->Next(&spelling_error);
+        if (SUCCEEDED(hr) && spelling_error &&
+            SUCCEEDED(spelling_error->get_StartIndex(&start_index)) &&
+            SUCCEEDED(spelling_error->get_Length(&error_length)) &&
+            SUCCEEDED(spelling_error->get_CorrectiveAction(&action)) &&
+            (action == CORRECTIVE_ACTION_GET_SUGGESTIONS ||
+             action == CORRECTIVE_ACTION_REPLACE)) {
+          std::vector<base::string16> suggestions;
+          FillSuggestionListInBackgroundThread(
+              it->first, text.substr(start_index, error_length), &suggestions);
+          result_map[std::tuple<ULONG, ULONG>(start_index, error_length)]
+              .push_back(suggestions);
+        }
+      } while (hr == S_OK);
+    }
+  }
+
+  // Generates results vector from map. Remove entries if the word is not
+  // misspelled for all available laugages.
+  for (auto it = result_map.begin(); it != result_map.end();) {
+    if (it->second.size() < spell_checker_map_.size()) {
+      it = result_map.erase(it);
+    } else {
+      // Prepare results vector.
+      std::vector<base::string16> suggestions_result;
+      for (auto suggestions_list : it->second) {
+        for (auto suggestions : suggestions_list) {
+          suggestions_result.push_back(suggestions);
+        }
+      }
+
+      results.push_back(SpellCheckResult(
+          SpellCheckResult::Decoration::SPELLING, std::get<0>(it->first),
+          std::get<1>(it->first), suggestions_result));
+
+      ++it;
+    }
+  }
+
+  // Runs the callback on the main thread after spellcheck completed.
+  main_task_runner_->PostTask(FROM_HERE,
+                              base::BindOnce(std::move(callback), results));
+}
+
+void WindowsSpellChecker::FillSuggestionListInBackgroundThread(
+    const std::string& lang_tag,
+    const base::string16& wrong_word,
+    std::vector<base::string16>* optional_suggestions) {
+  DCHECK(!main_task_runner_->BelongsToCurrentThread());
+
+  std::wstring word_wide(base::UTF16ToWide(wrong_word));
+
+  Microsoft::WRL::ComPtr<IEnumString> suggestions;
+  HRESULT hr =
+      GetSpellChecker(lang_tag)->Suggest(word_wide.c_str(), &suggestions);
+
+  // Populate the vector of WideStrings.
+  while (hr == S_OK) {
+    wchar_t* suggestion = nullptr;
+    hr = suggestions->Next(1, &suggestion, nullptr);
+    if (hr == S_OK) {
+      base::string16 utf16_suggestion;
+      if (base::WideToUTF16(suggestion, wcslen(suggestion),
+                            &utf16_suggestion)) {
+        optional_suggestions->push_back(utf16_suggestion);
+      }
+      CoTaskMemFree(suggestion);
+    }
+  }
+}
+
+void WindowsSpellChecker::AddWordForAllLanguagesInBackgroundThread(
+    const base::string16& word) {
+  DCHECK(!main_task_runner_->BelongsToCurrentThread());
+  for (auto it = spell_checker_map_.begin(); it != spell_checker_map_.end();
+       ++it) {
+    std::wstring word_to_add_wide(base::UTF16ToWide(word));
+    it->second->Add(word_to_add_wide.c_str());
+  }
+}
+
+void WindowsSpellChecker::RemoveWordForAllLanguagesInBackgroundThread(
+    const base::string16& word) {
+  DCHECK(!main_task_runner_->BelongsToCurrentThread());
+  for (auto it = spell_checker_map_.begin(); it != spell_checker_map_.end();
+       ++it) {
+    std::wstring word_to_remove_wide(base::UTF16ToWide(word));
+    Microsoft::WRL::ComPtr<ISpellChecker2> spell_checker_2;
+    it->second->QueryInterface(IID_PPV_ARGS(&spell_checker_2));
+    if (spell_checker_2 != nullptr) {
+      spell_checker_2->Remove(word_to_remove_wide.c_str());
+    }
+  }
+}
+
+void WindowsSpellChecker::IgnoreWordForAllLanguagesInBackgroundThread(
+    const base::string16& word) {
+  DCHECK(!main_task_runner_->BelongsToCurrentThread());
+  for (auto it = spell_checker_map_.begin(); it != spell_checker_map_.end();
+       ++it) {
+    std::wstring word_to_ignore_wide(base::UTF16ToWide(word));
+    it->second->Ignore(word_to_ignore_wide.c_str());
+  }
+}
+
+bool WindowsSpellChecker::IsLanguageSupportedInBackgroundThread(
+    const std::string& current_language) {
+  DCHECK(!main_task_runner_->BelongsToCurrentThread());
+  DCHECK(IsSpellCheckerFactoryInitialized());
+
+  BOOL is_language_supported = (BOOL) false;
+  std::wstring bcp47_language_tag = base::UTF8ToWide(current_language);
+
+  HRESULT hr = spell_checker_factory_->IsSupported(bcp47_language_tag.c_str(),
+                                                   &is_language_supported);
+  return SUCCEEDED(hr) && is_language_supported;
+}
+
+bool WindowsSpellChecker::IsSpellCheckerFactoryInitialized() {
+  return spell_checker_factory_ != nullptr;
+}
+
+bool WindowsSpellChecker::SpellCheckerReady(const std::string& lang_tag) {
+  return spell_checker_map_.find(lang_tag) != spell_checker_map_.end();
+}
+
+Microsoft::WRL::ComPtr<ISpellChecker> WindowsSpellChecker::GetSpellChecker(
+    const std::string& lang_tag) {
+  DCHECK(SpellCheckerReady(lang_tag));
+  return spell_checker_map_.find(lang_tag)->second;
+}
+
+// Create WindowsSpellChecker class with static storage duration that is only
+// constructed on first access and never invokes the destructor.
+std::unique_ptr<WindowsSpellChecker>& GetWindowsSpellChecker() {
+  static base::NoDestructor<std::unique_ptr<WindowsSpellChecker>>
+      win_spell_checker(std::make_unique<WindowsSpellChecker>(
+          base::ThreadTaskRunnerHandle::Get(),
+          base::CreateCOMSTATaskRunnerWithTraits({base::MayBlock()})));
+  return *win_spell_checker;
+}
+}  // anonymous namespace
+
+bool SpellCheckerAvailable() {
+  return true;
+}
+
+bool PlatformSupportsLanguage(const std::string& current_language) {
+  return true;
+}
+
+void SetLanguage(const std::string& lang_to_set,
+                 base::OnceCallback<void(bool)> callback) {
+  GetWindowsSpellChecker()->CreateSpellChecker(lang_to_set,
+                                               std::move(callback));
+}
+
+void DisableLanguage(const std::string& lang_to_disable) {
+  GetWindowsSpellChecker()->DisableSpellChecker(lang_to_disable);
+}
+
+bool CheckSpelling(const base::string16& word_to_check, int tag) {
+  return true;  // Not used in Windows
+}
+
+void FillSuggestionList(const base::string16& wrong_word,
+                        std::vector<base::string16>* optional_suggestions) {
+  // Not used in Windows.
+}
+
+void RequestTextCheck(int document_tag,
+                      const base::string16& text,
+                      TextCheckCompleteCallback callback) {
+  GetWindowsSpellChecker()->RequestTextCheckForAllLanguages(
+      document_tag, text, std::move(callback));
+}
+
+void AddWord(const base::string16& word) {
+  GetWindowsSpellChecker()->AddWordForAllLanguages(word);
+}
+
+void RemoveWord(const base::string16& word) {
+  GetWindowsSpellChecker()->RemoveWordForAllLanguages(word);
+}
+
+void IgnoreWord(const base::string16& word) {
+  GetWindowsSpellChecker()->IgnoreWordForAllLanguages(word);
+}
+
+void GetAvailableLanguages(std::vector<std::string>* spellcheck_languages) {
+  // Not used in Windows
+}
+
+int GetDocumentTag() {
+  return 1;  // Not used in Windows
+}
+
+void CloseDocumentWithTag(int tag) {
+  // Not implemented since Windows spellchecker doesn't have this concept
+}
+
+bool SpellCheckerProvidesPanel() {
+  return false;  // Windows doesn't have a spelling panel
+}
+
+bool SpellingPanelVisible() {
+  return false;  // Windows doesn't have a spelling panel
+}
+
+void ShowSpellingPanel(bool show) {
+  // Not implemented since Windows doesn't have spelling panel like Mac
+}
+
+void UpdateSpellingPanelWithMisspelledWord(const base::string16& word) {
+  // Not implemented since Windows doesn't have spelling panel like Mac
+}
+
+}  // namespace spellcheck_platform
diff --git a/components/spellcheck/browser/spellcheck_platform_win_unittest.cc b/components/spellcheck/browser/spellcheck_platform_win_unittest.cc
new file mode 100644
index 0000000..cd71ff6c5
--- /dev/null
+++ b/components/spellcheck/browser/spellcheck_platform_win_unittest.cc
@@ -0,0 +1,118 @@
+// Copyright 2019 The Chromium 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/spellcheck/browser/spellcheck_platform.h"
+
+#include <stddef.h>
+
+#include "base/bind.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/win/windows_version.h"
+#include "components/spellcheck/common/spellcheck_features.h"
+#include "components/spellcheck/common/spellcheck_result.h"
+#include "content/public/test/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class SpellcheckPlatformWinTest : public testing::Test {
+ public:
+  void RunUntilResultReceived() {
+    if (callback_finished_)
+      return;
+    base::RunLoop run_loop;
+    quit_ = run_loop.QuitClosure();
+    run_loop.Run();
+
+    // reset status
+    callback_finished_ = false;
+  }
+
+  void SetLanguageCompletionCallback(bool result) {
+    set_language_result_ = result;
+    callback_finished_ = true;
+    if (quit_)
+      std::move(quit_).Run();
+  }
+
+  void TextCheckCompletionCallback(
+      const std::vector<SpellCheckResult>& results) {
+    callback_finished_ = true;
+    spell_check_results_ = results;
+    if (quit_)
+      std::move(quit_).Run();
+  }
+
+ protected:
+  bool callback_finished_ = false;
+
+  bool set_language_result_;
+  std::vector<SpellCheckResult> spell_check_results_;
+  base::OnceClosure quit_;
+
+  base::test::ScopedTaskEnvironment task_environment_{
+      base::test::ScopedTaskEnvironment::MainThreadType::UI};
+};
+
+TEST_F(SpellcheckPlatformWinTest, SpellCheckSuggestions_EN_US) {
+  static const struct {
+    const char* input;           // A string to be tested.
+    const char* suggested_word;  // A suggested word that should occur.
+  } kTestCases[] = {
+      {"absense", "absence"},    {"becomeing", "becoming"},
+      {"cieling", "ceiling"},    {"definate", "definite"},
+      {"eigth", "eight"},        {"exellent", "excellent"},
+      {"finaly", "finally"},     {"garantee", "guarantee"},
+      {"humerous", "humorous"},  {"imediately", "immediately"},
+      {"jellous", "jealous"},    {"knowlege", "knowledge"},
+      {"lenght", "length"},      {"manuever", "maneuver"},
+      {"naturaly", "naturally"}, {"ommision", "omission"},
+  };
+
+  if (base::win::GetVersion() < base::win::Version::WIN8)
+    return;
+
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(spellcheck::kWinUseBrowserSpellChecker);
+
+  spellcheck_platform::SetLanguage(
+      "en-US",
+      base::BindOnce(&SpellcheckPlatformWinTest::SetLanguageCompletionCallback,
+                     base::Unretained(this)));
+
+  RunUntilResultReceived();
+
+  for (const auto& test_case : kTestCases) {
+    const base::string16 word(base::ASCIIToUTF16(test_case.input));
+
+    // Check if the suggested words occur.
+    spellcheck_platform::RequestTextCheck(
+        1, word,
+        base::BindOnce(&SpellcheckPlatformWinTest::TextCheckCompletionCallback,
+                       base::Unretained(this)));
+    RunUntilResultReceived();
+
+    ASSERT_EQ(1u, spell_check_results_.size());
+
+    const std::vector<base::string16>& suggestions =
+        spell_check_results_.front().replacements;
+    const base::string16 suggested_word(
+        base::ASCIIToUTF16(test_case.suggested_word));
+    auto position =
+        std::find_if(suggestions.begin(), suggestions.end(),
+                     [&](const base::string16& suggestion) {
+                       return suggestion.compare(suggested_word) == 0;
+                     });
+
+    ASSERT_NE(suggestions.end(), position);
+  }
+}
+
+}  // namespace
diff --git a/components/spellcheck/common/BUILD.gn b/components/spellcheck/common/BUILD.gn
index 86ec100..5fbfa95 100644
--- a/components/spellcheck/common/BUILD.gn
+++ b/components/spellcheck/common/BUILD.gn
@@ -55,7 +55,9 @@
   enabled_features = []
   if (use_browser_spellchecker) {
     enabled_features += [ "USE_BROWSER_SPELLCHECKER" ]
-  } else {
+  }
+
+  if (use_renderer_spellchecker) {
     enabled_features += [ "USE_RENDERER_SPELLCHECKER" ]
   }
 }
diff --git a/components/spellcheck/common/spellcheck_features.cc b/components/spellcheck/common/spellcheck_features.cc
index 0cdac8d..b0c342d 100644
--- a/components/spellcheck/common/spellcheck_features.cc
+++ b/components/spellcheck/common/spellcheck_features.cc
@@ -5,6 +5,8 @@
 #include "components/spellcheck/common/spellcheck_features.h"
 
 #include "base/system/sys_info.h"
+#include "base/win/windows_version.h"
+#include "build/build_config.h"
 #include "components/spellcheck/spellcheck_buildflags.h"
 
 namespace spellcheck {
@@ -14,6 +16,22 @@
 const base::Feature kSpellingServiceRestApi{"SpellingServiceRestApi",
                                             base::FEATURE_DISABLED_BY_DEFAULT};
 
+#if defined(OS_WIN)
+const base::Feature kWinUseBrowserSpellChecker{
+    "WinUseBrowserSpellChecker", base::FEATURE_DISABLED_BY_DEFAULT};
+#endif
+
+bool UseBrowserSpellChecker() {
+#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+  return false;
+#elif defined(OS_WIN)
+  return base::FeatureList::IsEnabled(spellcheck::kWinUseBrowserSpellChecker) &&
+         base::win::GetVersion() > base::win::Version::WIN7 &&
+         base::win::GetVersion() < base::win::Version::WIN_LAST;
+#else
+  return true;
+#endif
+}
 #endif  // BUILDFLAG(ENABLE_SPELLCHECK)
 
 #if BUILDFLAG(ENABLE_SPELLCHECK) && defined(OS_ANDROID)
diff --git a/components/spellcheck/common/spellcheck_features.h b/components/spellcheck/common/spellcheck_features.h
index 0a724a5..60f1158 100644
--- a/components/spellcheck/common/spellcheck_features.h
+++ b/components/spellcheck/common/spellcheck_features.h
@@ -6,12 +6,19 @@
 #define COMPONENTS_SPELLCHECK_COMMON_SPELLCHECK_FEATURES_H_
 
 #include "base/feature_list.h"
+#include "build/build_config.h"
 #include "components/spellcheck/spellcheck_buildflags.h"
 
 namespace spellcheck {
 
 #if BUILDFLAG(ENABLE_SPELLCHECK)
 extern const base::Feature kSpellingServiceRestApi;
+
+#if defined(OS_WIN)
+extern const base::Feature kWinUseBrowserSpellChecker;
+#endif
+
+bool UseBrowserSpellChecker();
 #endif  // BUILDFLAG(ENABLE_SPELLCHECK)
 
 #if BUILDFLAG(ENABLE_SPELLCHECK) && defined(OS_ANDROID)
diff --git a/components/spellcheck/renderer/BUILD.gn b/components/spellcheck/renderer/BUILD.gn
index d993ecf..2b28c57 100644
--- a/components/spellcheck/renderer/BUILD.gn
+++ b/components/spellcheck/renderer/BUILD.gn
@@ -16,6 +16,7 @@
     "spellcheck_provider.h",
     "spellcheck_worditerator.cc",
     "spellcheck_worditerator.h",
+    "spelling_engine.cc",
     "spelling_engine.h",
   ]
 
diff --git a/components/spellcheck/renderer/hunspell_engine.cc b/components/spellcheck/renderer/hunspell_engine.cc
index 78d62802..325e3a3 100644
--- a/components/spellcheck/renderer/hunspell_engine.cc
+++ b/components/spellcheck/renderer/hunspell_engine.cc
@@ -36,14 +36,6 @@
                 "MaxSuggestLen too long");
 }  // namespace
 
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
-SpellingEngine* CreateNativeSpellingEngine(
-    service_manager::LocalInterfaceProvider* embedder_provider) {
-  DCHECK(embedder_provider);
-  return new HunspellEngine(embedder_provider);
-}
-#endif
-
 HunspellEngine::HunspellEngine(
     service_manager::LocalInterfaceProvider* embedder_provider)
     : hunspell_enabled_(false),
diff --git a/components/spellcheck/renderer/platform_spelling_engine.cc b/components/spellcheck/renderer/platform_spelling_engine.cc
index 2828538..176462e 100644
--- a/components/spellcheck/renderer/platform_spelling_engine.cc
+++ b/components/spellcheck/renderer/platform_spelling_engine.cc
@@ -9,12 +9,6 @@
 
 using content::RenderThread;
 
-SpellingEngine* CreateNativeSpellingEngine(
-    service_manager::LocalInterfaceProvider* embedder_provider) {
-  DCHECK(embedder_provider);
-  return new PlatformSpellingEngine(embedder_provider);
-}
-
 PlatformSpellingEngine::PlatformSpellingEngine(
     service_manager::LocalInterfaceProvider* embedder_provider)
     : embedder_provider_(embedder_provider) {}
@@ -31,7 +25,6 @@
 }
 
 void PlatformSpellingEngine::Init(base::File bdict_file) {
-  DCHECK(!bdict_file.IsValid());
 }
 
 bool PlatformSpellingEngine::InitializeIfNeeded() {
diff --git a/components/spellcheck/renderer/spellcheck.cc b/components/spellcheck/renderer/spellcheck.cc
index 821f1c9..a674683 100644
--- a/components/spellcheck/renderer/spellcheck.cc
+++ b/components/spellcheck/renderer/spellcheck.cc
@@ -215,8 +215,10 @@
 
   custom_dictionary_.Init(
       std::set<std::string>(custom_words.begin(), custom_words.end()));
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
-  PostDelayedSpellCheckTask(pending_request_param_.release());
+#if BUILDFLAG(USE_RENDERER_SPELLCHECKER)
+  if (!spellcheck::UseBrowserSpellChecker()) {
+    PostDelayedSpellCheckTask(pending_request_param_.release());
+  }
 #endif
 
   spellcheck_enabled_ = enable;
@@ -344,48 +346,48 @@
 bool SpellCheck::SpellCheckParagraph(
     const base::string16& text,
     WebVector<WebTextCheckingResult>* results) {
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
-  // Mac and Android have their own spell checkers,so this method won't be used
-  DCHECK(results);
-  std::vector<WebTextCheckingResult> textcheck_results;
-  size_t length = text.length();
-  size_t position_in_text = 0;
+#if BUILDFLAG(USE_RENDERER_SPELLCHECKER)
+  if (!spellcheck::UseBrowserSpellChecker()) {
+    DCHECK(results);
+    std::vector<WebTextCheckingResult> textcheck_results;
+    size_t length = text.length();
+    size_t position_in_text = 0;
 
-  // Spellcheck::SpellCheckWord() automatically breaks text into words and
-  // checks the spellings of the extracted words. This function sets the
-  // position and length of the first misspelled word and returns false when
-  // the text includes misspelled words. Therefore, we just repeat calling the
-  // function until it returns true to check the whole text.
-  size_t misspelling_start = 0;
-  size_t misspelling_length = 0;
-  while (position_in_text <= length) {
-    if (SpellCheckWord(text.c_str(), position_in_text, length, kNoTag,
-                       &misspelling_start, &misspelling_length, nullptr)) {
-      results->Assign(textcheck_results);
-      return true;
-    }
+    // Spellcheck::SpellCheckWord() automatically breaks text into words and
+    // checks the spellings of the extracted words. This function sets the
+    // position and length of the first misspelled word and returns false when
+    // the text includes misspelled words. Therefore, we just repeat calling the
+    // function until it returns true to check the whole text.
+    size_t misspelling_start = 0;
+    size_t misspelling_length = 0;
+    while (position_in_text <= length) {
+      if (SpellCheckWord(text.c_str(), position_in_text, length, kNoTag,
+                         &misspelling_start, &misspelling_length, nullptr)) {
+        results->Assign(textcheck_results);
+        return true;
+      }
 
-    if (!custom_dictionary_.SpellCheckWord(
-            text, misspelling_start, misspelling_length)) {
-      textcheck_results.push_back(
-          WebTextCheckingResult(blink::kWebTextDecorationTypeSpelling,
-                                base::checked_cast<int>(misspelling_start),
-                                base::checked_cast<int>(misspelling_length)));
+      if (!custom_dictionary_.SpellCheckWord(text, misspelling_start,
+                                             misspelling_length)) {
+        textcheck_results.push_back(
+            WebTextCheckingResult(blink::kWebTextDecorationTypeSpelling,
+                                  base::checked_cast<int>(misspelling_start),
+                                  base::checked_cast<int>(misspelling_length)));
+      }
+      position_in_text = misspelling_start + misspelling_length;
     }
-    position_in_text = misspelling_start + misspelling_length;
+    results->Assign(textcheck_results);
+    return false;
   }
-  results->Assign(textcheck_results);
-  return false;
-#else
-  // This function is only invoked for spell checker functionality that runs
-  // on the render thread. OSX and Android builds don't have that.
+#endif
+
+  // This function is only invoked if renderer(hunspell) spellchecker is used.
+  DCHECK(spellcheck::UseBrowserSpellChecker());
   NOTREACHED();
   return true;
-#endif
 }
 
-// OSX and Android use their own spell checkers
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#if BUILDFLAG(USE_RENDERER_SPELLCHECKER)
 void SpellCheck::RequestTextChecking(
     const base::string16& text,
     std::unique_ptr<blink::WebTextCheckingCompletion> completion) {
@@ -414,8 +416,7 @@
   return initialize_if_needed;
 }
 
-// OSX and Android don't have |pending_request_param_|
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#if BUILDFLAG(USE_RENDERER_SPELLCHECKER)
 void SpellCheck::PostDelayedSpellCheckTask(SpellcheckRequest* request) {
   if (!request)
     return;
@@ -426,8 +427,7 @@
 }
 #endif
 
-// Mac and Android use their platform engines instead.
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#if BUILDFLAG(USE_RENDERER_SPELLCHECKER)
 void SpellCheck::PerformSpellCheck(SpellcheckRequest* param) {
   DCHECK(param);
 
diff --git a/components/spellcheck/renderer/spellcheck.h b/components/spellcheck/renderer/spellcheck.h
index 25d1f07..d62fe6a8 100644
--- a/components/spellcheck/renderer/spellcheck.h
+++ b/components/spellcheck/renderer/spellcheck.h
@@ -100,9 +100,9 @@
       const base::string16& text,
       blink::WebVector<blink::WebTextCheckingResult>* results);
 
+#if BUILDFLAG(USE_RENDERER_SPELLCHECKER)
   // Requests to spellcheck the specified text in the background. This function
   // posts a background task and calls SpellCheckParagraph() in the task.
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
   void RequestTextChecking(
       const base::string16& text,
       std::unique_ptr<blink::WebTextCheckingCompletion> completion);
@@ -156,20 +156,20 @@
    void NotifyDictionaryObservers(
        const blink::WebVector<blink::WebString>& words_added);
 
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
-  // Posts delayed spellcheck task and clear it if any.
-  // Takes ownership of |request|.
-  void PostDelayedSpellCheckTask(SpellcheckRequest* request);
+#if BUILDFLAG(USE_RENDERER_SPELLCHECKER)
+   // Posts delayed spellcheck task and clear it if any.
+   // Takes ownership of |request|.
+   void PostDelayedSpellCheckTask(SpellcheckRequest* request);
 
-  // Performs spell checking from the request queue.
-  void PerformSpellCheck(SpellcheckRequest* request);
+   // Performs spell checking from the request queue.
+   void PerformSpellCheck(SpellcheckRequest* request);
 
-  // The parameters of a pending background-spellchecking request. When WebKit
-  // sends a background-spellchecking request before initializing hunspell,
-  // we save its parameters and start spellchecking after we finish initializing
-  // hunspell. (When WebKit sends two or more requests, we cancel the previous
-  // requests so we do not have to use vectors.)
-  std::unique_ptr<SpellcheckRequest> pending_request_param_;
+   // The parameters of a pending background-spellchecking request. When WebKit
+   // sends a background-spellchecking request before initializing hunspell,
+   // we save its parameters and start spellchecking after we finish
+   // initializing hunspell. (When WebKit sends two or more requests, we cancel
+   // the previous requests so we do not have to use vectors.)
+   std::unique_ptr<SpellcheckRequest> pending_request_param_;
 #endif
 
   // Bindings for SpellChecker clients.
diff --git a/components/spellcheck/renderer/spellcheck_provider.cc b/components/spellcheck/renderer/spellcheck_provider.cc
index e4f2a344..ead78b8c 100644
--- a/components/spellcheck/renderer/spellcheck_provider.cc
+++ b/components/spellcheck/renderer/spellcheck_provider.cc
@@ -8,6 +8,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "build/build_config.h"
 #include "components/spellcheck/common/spellcheck.mojom.h"
+#include "components/spellcheck/common/spellcheck_features.h"
 #include "components/spellcheck/common/spellcheck_result.h"
 #include "components/spellcheck/renderer/spellcheck.h"
 #include "components/spellcheck/renderer/spellcheck_language.h"
@@ -130,18 +131,24 @@
   last_identifier_ = text_check_completions_.Add(std::move(completion));
 
 #if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
-  // Text check (unified request for grammar and spell check) is only
-  // available for browser process, so we ask the system spellchecker
-  // over mojo or return an empty result if the checker is not available.
-  GetSpellCheckHost().RequestTextCheck(
-      text, routing_id(),
-      base::BindOnce(&SpellCheckProvider::OnRespondTextCheck,
-                     weak_factory_.GetWeakPtr(), last_identifier_, text));
-#else
-  GetSpellCheckHost().CallSpellingService(
-      text, base::BindOnce(&SpellCheckProvider::OnRespondSpellingService,
-                           weak_factory_.GetWeakPtr(), last_identifier_, text));
-#endif  // !USE_BROWSER_SPELLCHECKER
+  if (spellcheck::UseBrowserSpellChecker()) {
+    // Text check (unified request for grammar and spell check) is only
+    // available for browser process, so we ask the system spellchecker
+    // over mojo or return an empty result if the checker is not available.
+    GetSpellCheckHost().RequestTextCheck(
+        text, routing_id(),
+        base::BindOnce(&SpellCheckProvider::OnRespondTextCheck,
+                       weak_factory_.GetWeakPtr(), last_identifier_, text));
+  }
+#endif
+#if BUILDFLAG(USE_RENDERER_SPELLCHECKER)
+  if (!spellcheck::UseBrowserSpellChecker()) {
+    GetSpellCheckHost().CallSpellingService(
+        text,
+        base::BindOnce(&SpellCheckProvider::OnRespondSpellingService,
+                       weak_factory_.GetWeakPtr(), last_identifier_, text));
+  }
+#endif
 }
 
 void SpellCheckProvider::FocusedElementChanged(
@@ -200,7 +207,7 @@
                           base::saturated_cast<int>(text.length()));
 }
 
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#if BUILDFLAG(USE_RENDERER_SPELLCHECKER)
 void SpellCheckProvider::OnRespondSpellingService(
     int identifier,
     const base::string16& line,
diff --git a/components/spellcheck/renderer/spellcheck_provider.h b/components/spellcheck/renderer/spellcheck_provider.h
index 66bbda3..d17ae4d 100644
--- a/components/spellcheck/renderer/spellcheck_provider.h
+++ b/components/spellcheck/renderer/spellcheck_provider.h
@@ -98,7 +98,7 @@
       const blink::WebString& text,
       std::unique_ptr<blink::WebTextCheckingCompletion> completion) override;
 
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#if BUILDFLAG(USE_RENDERER_SPELLCHECKER)
   void OnRespondSpellingService(int identifier,
                                 const base::string16& text,
                                 bool success,
diff --git a/components/spellcheck/renderer/spellcheck_provider_test.cc b/components/spellcheck/renderer/spellcheck_provider_test.cc
index 22df2d0..1c51f66 100644
--- a/components/spellcheck/renderer/spellcheck_provider_test.cc
+++ b/components/spellcheck/renderer/spellcheck_provider_test.cc
@@ -69,7 +69,7 @@
 void TestingSpellCheckProvider::NotifyChecked(const base::string16& word,
                                               bool misspelled) {}
 
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#if BUILDFLAG(USE_RENDERER_SPELLCHECKER)
 void TestingSpellCheckProvider::CallSpellingService(
     const base::string16& text,
     CallSpellingServiceCallback callback) {
@@ -100,7 +100,7 @@
 void TestingSpellCheckProvider::ResetResult() {
   text_.clear();
 }
-#endif  // !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#endif  // BUILDFLAG(USE_RENDERER_SPELLCHECKER)
 
 #if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
 void TestingSpellCheckProvider::RequestTextCheck(
diff --git a/components/spellcheck/renderer/spellcheck_provider_test.h b/components/spellcheck/renderer/spellcheck_provider_test.h
index 74bb59bc..b888ced 100644
--- a/components/spellcheck/renderer/spellcheck_provider_test.h
+++ b/components/spellcheck/renderer/spellcheck_provider_test.h
@@ -61,7 +61,7 @@
   bool SatisfyRequestFromCache(const base::string16& text,
                                blink::WebTextCheckingCompletion* completion);
 
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#if BUILDFLAG(USE_RENDERER_SPELLCHECKER)
   void ResetResult();
 
   // Variables logging CallSpellingService() mojo calls.
@@ -84,7 +84,7 @@
   void RequestDictionary() override;
   void NotifyChecked(const base::string16& word, bool misspelled) override;
 
-#if !BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#if BUILDFLAG(USE_RENDERER_SPELLCHECKER)
   void CallSpellingService(const base::string16& text,
                            CallSpellingServiceCallback callback) override;
   void OnCallSpellingService(const base::string16& text);
diff --git a/components/spellcheck/renderer/spelling_engine.cc b/components/spellcheck/renderer/spelling_engine.cc
new file mode 100644
index 0000000..b4485f18
--- /dev/null
+++ b/components/spellcheck/renderer/spelling_engine.cc
@@ -0,0 +1,34 @@
+// Copyright 2019 The Chromium 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/spellcheck/renderer/spelling_engine.h"
+
+#include "build/build_config.h"
+#include "components/spellcheck/common/spellcheck_features.h"
+#include "services/service_manager/public/cpp/local_interface_provider.h"
+
+#if BUILDFLAG(USE_RENDERER_SPELLCHECKER)
+#include "components/spellcheck/renderer/hunspell_engine.h"
+#endif
+
+#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#include "components/spellcheck/renderer/platform_spelling_engine.h"
+#endif
+
+SpellingEngine* CreateNativeSpellingEngine(
+    service_manager::LocalInterfaceProvider* embedder_provider) {
+  DCHECK(embedder_provider);
+#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#if defined(OS_WIN)
+  if (spellcheck::UseBrowserSpellChecker())
+    return new PlatformSpellingEngine(embedder_provider);
+#else
+  return new PlatformSpellingEngine(embedder_provider);
+#endif  // defined(OS_WIN)
+#endif  // BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+
+#if BUILDFLAG(USE_RENDERER_SPELLCHECKER)
+  return new HunspellEngine(embedder_provider);
+#endif  // BUILDFLAG(USE_RENDERER_SPELLCHECKER)
+}
diff --git a/components/spellcheck/spellcheck.md b/components/spellcheck/spellcheck.md
new file mode 100644
index 0000000..2a43b86
--- /dev/null
+++ b/components/spellcheck/spellcheck.md
@@ -0,0 +1,25 @@
+# About the 'use_browser_spellchecker' and 'use_renderer_spellchecker' build time flag.
+
+## use_browser_spellchecker
+
+Use the operating system's spellchecker rather than hunspell. This does
+not affect the "red underline" spellchecker which can consult Google's
+server-based spellcheck service.
+
+## use_renderer_spellchecker
+Use hunspell spellchecker rather than the operating system's spellchecker.
+
+## Note:
+
+For most operating system except Windows, the decision to use the platform
+spellchecker or hunspell spellchecker is made at build time. Therefore,
+use_browser_spellchecker and use_renderer_spellchecker are mutually
+exclusive for most operating systems except Windows.
+
+For Windows OS, the decision to use the platform spellchecker or hunspell
+spellchecker is made during runtime. Therefore, we include both build
+flags if the platform is Windows.
+
+We also need to create the runtime feature flag kWinUseBrowserSpellChecker
+for Windows OS. The feature flag is used to choose between the platform or
+hunspell spellchecker at runtime.
diff --git a/components/spellcheck/spellcheck_build_features.gni b/components/spellcheck/spellcheck_build_features.gni
index 34a27d7..2f79dfe 100644
--- a/components/spellcheck/spellcheck_build_features.gni
+++ b/components/spellcheck/spellcheck_build_features.gni
@@ -8,7 +8,11 @@
 # Use the operating system's spellchecker rather than hunspell. This does
 # not affect the "red underline" spellchecker which can consult Google's
 # server-based spellcheck service.
-use_browser_spellchecker = is_android || is_mac
+use_browser_spellchecker = is_android || is_mac || is_win
+
+# Use hunspell. Windows is switching between OS's spellchecker and hunspell.
+# Therefore, include Windows in both build flags.
+use_renderer_spellchecker = !use_browser_spellchecker || is_win
 
 # Only Mac has a spellcheck panel.
 has_spellcheck_panel = is_mac
diff --git a/components/viz/service/display_embedder/buffer_queue.cc b/components/viz/service/display_embedder/buffer_queue.cc
index a813220..83545a7 100644
--- a/components/viz/service/display_embedder/buffer_queue.cc
+++ b/components/viz/service/display_embedder/buffer_queue.cc
@@ -17,7 +17,6 @@
 #include "ui/display/types/display_snapshot.h"
 #include "ui/gfx/gpu_memory_buffer.h"
 #include "ui/gfx/skia_util.h"
-#include "ui/gl/gl_enums.h"
 
 namespace viz {
 
@@ -27,73 +26,45 @@
                          gpu::SurfaceHandle surface_handle,
                          const gpu::Capabilities& capabilities)
     : gl_(gl),
-      fbo_(0),
       allocated_count_(0),
       texture_target_(gpu::GetBufferTextureTarget(gfx::BufferUsage::SCANOUT,
                                                   format,
                                                   capabilities)),
-      internal_format_(gpu::InternalFormatForGpuMemoryBufferFormat(format)),
+      internal_format_(base::strict_cast<uint32_t>(
+          gpu::InternalFormatForGpuMemoryBufferFormat(format))),
       format_(format),
       gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
       surface_handle_(surface_handle) {}
 
 BufferQueue::~BufferQueue() {
   FreeAllSurfaces();
-
-  if (fbo_)
-    gl_->DeleteFramebuffers(1, &fbo_);
 }
 
-void BufferQueue::Initialize() {
-  gl_->GenFramebuffers(1, &fbo_);
-}
-
-void BufferQueue::BindFramebuffer() {
-  gl_->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
-
+unsigned BufferQueue::GetCurrentBuffer(unsigned* stencil) {
+  DCHECK(stencil);
   if (!current_surface_)
     current_surface_ = GetNextSurface();
-
-  if (!current_surface_)
-    return;
-  gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-                            texture_target_, current_surface_->texture, 0);
-
-#if DCHECK_IS_ON() && defined(OS_CHROMEOS)
-  const GLenum result = gl_->CheckFramebufferStatus(GL_FRAMEBUFFER);
-  if (result != GL_FRAMEBUFFER_COMPLETE)
-    DLOG(ERROR) << " Incomplete fb: " << gl::GLEnums::GetStringError(result);
-#endif
-
-  if (current_surface_->stencil) {
-    gl_->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
-                                 GL_RENDERBUFFER, current_surface_->stencil);
+  if (current_surface_) {
+    *stencil = current_surface_->stencil;
+    return current_surface_->texture;
   }
+  *stencil = 0u;
+  return 0u;
 }
 
-void BufferQueue::CopyBufferDamage(int texture,
-                                   int source_texture,
+void BufferQueue::CopyBufferDamage(unsigned texture,
+                                   unsigned source_texture,
                                    const gfx::Rect& new_damage,
                                    const gfx::Rect& old_damage) {
   SkRegion region(gfx::RectToSkIRect(old_damage));
   if (!region.op(gfx::RectToSkIRect(new_damage), SkRegion::kDifference_Op))
     return;
-
-  GLuint dst_framebuffer = 0;
-  gl_->GenFramebuffers(1, &dst_framebuffer);
-  DCHECK(dst_framebuffer);
-  gl_->BindFramebuffer(GL_FRAMEBUFFER, dst_framebuffer);
-  gl_->BindTexture(texture_target_, texture);
-  gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-                            texture_target_, source_texture, 0);
   for (SkRegion::Iterator it(region); !it.done(); it.next()) {
     const SkIRect& rect = it.rect();
-    gl_->CopyTexSubImage2D(texture_target_, 0, rect.x(), rect.y(), rect.x(),
-                           rect.y(), rect.width(), rect.height());
+    gl_->CopySubTextureCHROMIUM(
+        source_texture, 0, texture_target_, texture, 0, rect.x(), rect.y(),
+        rect.x(), rect.y(), rect.width(), rect.height(), false, false, false);
   }
-  gl_->BindTexture(texture_target_, 0);
-  gl_->Flush();
-  gl_->DeleteFramebuffers(1, &dst_framebuffer);
 }
 
 void BufferQueue::UpdateBufferDamage(const gfx::Rect& damage) {
@@ -115,7 +86,7 @@
     // Copy damage from the most recently swapped buffer. In the event that
     // the buffer was destroyed and failed to recreate, pick from the most
     // recently available buffer.
-    uint32_t texture_id = 0;
+    unsigned texture_id = 0;
     for (auto& surface : base::Reversed(in_flight_surfaces_)) {
       if (surface) {
         texture_id = surface->texture;
@@ -128,7 +99,6 @@
     if (texture_id) {
       CopyBufferDamage(current_surface_->texture, texture_id, damage,
                        current_surface_->damage);
-      gl_->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
     }
   }
   current_surface_->damage = gfx::Rect();
@@ -143,19 +113,15 @@
   DCHECK(!current_surface_ || current_surface_->damage.IsEmpty());
   UpdateBufferDamage(damage);
   in_flight_surfaces_.push_back(std::move(current_surface_));
-  // Some things reset the framebuffer (CopyBufferDamage, some GLRenderer
-  // paths), so ensure we restore it here.
-  // TODO(khushalsagar): Not needed anymore. Remove this.
-  gl_->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
 }
 
-void BufferQueue::Reshape(const gfx::Size& size,
+bool BufferQueue::Reshape(const gfx::Size& size,
                           float scale_factor,
                           const gfx::ColorSpace& color_space,
                           bool use_stencil) {
   if (size == size_ && color_space == color_space_ &&
       use_stencil == use_stencil_) {
-    return;
+    return false;
   }
 #if !defined(OS_MACOSX)
   // TODO(ccameron): This assert is being hit on Mac try jobs. Determine if that
@@ -167,16 +133,11 @@
   color_space_ = color_space;
   use_stencil_ = use_stencil;
 
-  gl_->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
-  gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-                            texture_target_, 0, 0);
-  gl_->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
-                               GL_RENDERBUFFER, 0);
-
   FreeAllSurfaces();
+  return true;
 }
 
-void BufferQueue::RecreateBuffers() {
+unsigned BufferQueue::RecreateBuffers() {
   // We need to recreate the buffers, for whatever reason the old ones are not
   // presentable on the device anymore.
   // Unused buffers can be freed directly, they will be re-allocated as needed.
@@ -190,12 +151,7 @@
   current_surface_ = RecreateBuffer(std::move(current_surface_));
   displayed_surface_ = RecreateBuffer(std::move(displayed_surface_));
 
-  if (current_surface_) {
-    // If we have a texture bound, we will need to re-bind it.
-    gl_->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
-    gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-                              texture_target_, current_surface_->texture, 0);
-  }
+  return current_surface_ ? current_surface_->texture : 0u;
 }
 
 std::unique_ptr<BufferQueue::AllocatedSurface> BufferQueue::RecreateBuffer(
@@ -226,25 +182,6 @@
   in_flight_surfaces_.pop_front();
 }
 
-uint32_t BufferQueue::GetCurrentTextureId() const {
-  if (current_surface_)
-    return current_surface_->texture;
-
-  // Return in-flight or displayed surface texture if no surface is
-  // currently bound. This can happen when using overlays and surface
-  // damage is empty. Note: |in_flight_surfaces_| entries can be null
-  // as a result of calling FreeAllSurfaces().
-  for (auto& surface : base::Reversed(in_flight_surfaces_)) {
-    if (surface)
-      return surface->texture;
-  }
-
-  if (displayed_surface_)
-    return displayed_surface_->texture;
-
-  return 0;
-}
-
 void BufferQueue::FreeAllSurfaces() {
   displayed_surface_.reset();
   current_surface_.reset();
@@ -277,10 +214,10 @@
     return surface;
   }
 
-  GLuint texture;
+  unsigned texture;
   gl_->GenTextures(1, &texture);
 
-  GLuint stencil = 0;
+  unsigned stencil = 0;
   if (use_stencil_) {
     gl_->GenRenderbuffers(1, &stencil);
     gl_->BindRenderbuffer(GL_RENDERBUFFER, stencil);
@@ -301,7 +238,7 @@
   }
   buffer->SetColorSpace(color_space_);
 
-  uint32_t id =
+  unsigned id =
       gl_->CreateImageCHROMIUM(buffer->AsClientBuffer(), size_.width(),
                                size_.height(), internal_format_);
   if (!id) {
@@ -325,9 +262,9 @@
 BufferQueue::AllocatedSurface::AllocatedSurface(
     BufferQueue* buffer_queue,
     std::unique_ptr<gfx::GpuMemoryBuffer> buffer,
-    uint32_t texture,
-    uint32_t image,
-    uint32_t stencil,
+    unsigned texture,
+    unsigned image,
+    unsigned stencil,
     const gfx::Rect& rect)
     : buffer_queue(buffer_queue),
       buffer(buffer.release()),
diff --git a/components/viz/service/display_embedder/buffer_queue.h b/components/viz/service/display_embedder/buffer_queue.h
index 990cb2a..2abf9dca 100644
--- a/components/viz/service/display_embedder/buffer_queue.h
+++ b/components/viz/service/display_embedder/buffer_queue.h
@@ -48,20 +48,41 @@
               const gpu::Capabilities& capabilities);
   virtual ~BufferQueue();
 
-  void Initialize();
+  // Returns the texture name of the current buffer and the name of the
+  // corresponding stencil buffer. The returned values are 0u if there is no
+  // current buffer and one could not be created.
+  unsigned GetCurrentBuffer(unsigned* stencil);
 
-  void BindFramebuffer();
+  // Called by the user of this object to indicate that the buffer currently
+  // marked for drawing should be moved to the list of in-flight buffers. If
+  // |damage| is not empty, the damage rectangle for all buffers except the
+  // one currently marked for drawing is unioned with |damage|.
   void SwapBuffers(const gfx::Rect& damage);
+
+  // Called by the user of this object to indicate that a previous request to
+  // swap buffers has completed. This allows us to correctly keep track of the
+  // state of the buffers: the buffer currently marked as being displayed will
+  // now marked as available, and the next buffer marked as in-flight will now
+  // be marked as displayed.
   void PageFlipComplete();
-  void Reshape(const gfx::Size& size,
+
+  // Frees all buffers if |size|, |color_space|, or |use_stencil| correspond to
+  // a change of state. Otherwise, it's a no-op. Returns true if there was a
+  // change of state, false otherwise.
+  bool Reshape(const gfx::Size& size,
                float scale_factor,
                const gfx::ColorSpace& color_space,
                bool use_stencil);
-  void RecreateBuffers();
-  uint32_t GetCurrentTextureId() const;
+
+  // Recreates all the buffers (useful if for some reason, the old buffers are
+  // no longer presentable). Returns the name of the texture corresponding to
+  // the current buffer or 0u if there is no current buffer.
+  unsigned RecreateBuffers();
+
+  // Copies the damage from the most recently swapped available buffer into the
+  // current buffer.
   void CopyDamageForCurrentSurface(const gfx::Rect& damage);
 
-  uint32_t fbo() const { return fbo_; }
   uint32_t internal_format() const { return internal_format_; }
   gfx::BufferFormat buffer_format() const { return format_; }
   uint32_t texture_target() const { return texture_target_; }
@@ -73,16 +94,16 @@
   struct VIZ_SERVICE_EXPORT AllocatedSurface {
     AllocatedSurface(BufferQueue* buffer_queue,
                      std::unique_ptr<gfx::GpuMemoryBuffer> buffer,
-                     uint32_t texture,
-                     uint32_t image,
-                     uint32_t stencil,
+                     unsigned texture,
+                     unsigned image,
+                     unsigned stencil,
                      const gfx::Rect& rect);
     ~AllocatedSurface();
     BufferQueue* const buffer_queue;
     std::unique_ptr<gfx::GpuMemoryBuffer> buffer;
-    const uint32_t texture;
-    const uint32_t image;
-    const uint32_t stencil;
+    const unsigned texture;
+    const unsigned image;
+    const unsigned stencil;
     gfx::Rect damage;  // This is the damage for this frame from the previous.
   };
 
@@ -92,8 +113,8 @@
 
   // Copy everything that is in |copy_rect|, except for what is in
   // |exclude_rect| from |source_texture| to |texture|.
-  virtual void CopyBufferDamage(int texture,
-                                int source_texture,
+  virtual void CopyBufferDamage(unsigned texture,
+                                unsigned source_texture,
                                 const gfx::Rect& new_damage,
                                 const gfx::Rect& old_damage);
 
@@ -109,7 +130,6 @@
   gfx::Size size_;
   gfx::ColorSpace color_space_;
   bool use_stencil_ = false;
-  uint32_t fbo_;
   size_t allocated_count_;
   uint32_t texture_target_;
   uint32_t internal_format_;
diff --git a/components/viz/service/display_embedder/buffer_queue_unittest.cc b/components/viz/service/display_embedder/buffer_queue_unittest.cc
index 14278c2..c4602db 100644
--- a/components/viz/service/display_embedder/buffer_queue_unittest.cc
+++ b/components/viz/service/display_embedder/buffer_queue_unittest.cc
@@ -115,7 +115,7 @@
                     kFakeSurfaceHandle,
                     capabilities) {}
   MOCK_METHOD4(CopyBufferDamage,
-               void(int, int, const gfx::Rect&, const gfx::Rect&));
+               void(unsigned, unsigned, const gfx::Rect&, const gfx::Rect&));
 };
 
 class BufferQueueTest : public ::testing::Test {
@@ -134,7 +134,6 @@
         context_provider_->ContextGL(), gpu_memory_buffer_manager_.get(),
         context_provider_->ContextCapabilities());
     output_surface_.reset(mock_output_surface_);
-    output_surface_->Initialize();
   }
 
   unsigned current_surface() {
@@ -194,7 +193,8 @@
   void SendDamagedFrame(const gfx::Rect& damage) {
     // We don't care about the GL-level implementation here, just how it uses
     // damage rects.
-    output_surface_->BindFramebuffer();
+    unsigned stencil;
+    EXPECT_GT(output_surface_->GetCurrentBuffer(&stencil), 0u);
     SwapBuffers(damage);
     if (doublebuffering_ || !first_frame_)
       output_surface_->PageFlipComplete();
@@ -239,14 +239,11 @@
     ON_CALL(*this, CreateImageCHROMIUM(_, _, _, _))
         .WillByDefault(testing::InvokeWithoutArgs(&CreateImageDefault));
   }
-  MOCK_METHOD2(BindFramebuffer, void(GLenum, GLuint));
   MOCK_METHOD2(BindTexture, void(GLenum, GLuint));
   MOCK_METHOD2(BindTexImage2DCHROMIUM, void(GLenum, GLint));
   MOCK_METHOD4(CreateImageCHROMIUM,
                GLuint(ClientBuffer, GLsizei, GLsizei, GLenum));
   MOCK_METHOD1(DestroyImageCHROMIUM, void(GLuint));
-  MOCK_METHOD5(FramebufferTexture2D,
-               void(GLenum, GLenum, GLenum, GLuint, GLint));
 };
 
 class BufferQueueMockedContextTest : public BufferQueueTest {
@@ -277,28 +274,10 @@
   std::unique_ptr<BufferQueue> buffer_queue(
       new BufferQueue(gl, kBufferQueueFormat, gpu_memory_buffer_manager,
                       kFakeSurfaceHandle, capabilities));
-  buffer_queue->Initialize();
   return buffer_queue;
 }
 
-TEST(BufferQueueStandaloneTest, FboInitialization) {
-  MockedContext* context;
-  scoped_refptr<TestContextProvider> context_provider =
-      CreateMockedContextProvider(&context);
-  std::unique_ptr<StubGpuMemoryBufferManager> gpu_memory_buffer_manager(
-      new StubGpuMemoryBufferManager);
-  std::unique_ptr<BufferQueue> output_surface = CreateBufferQueue(
-      context_provider->ContextGL(), gpu_memory_buffer_manager.get(),
-      context_provider->ContextCapabilities());
-
-  EXPECT_CALL(*context, BindFramebuffer(GL_FRAMEBUFFER, Ne(0U)));
-  ON_CALL(*context, FramebufferTexture2D(_, _, _, _, _))
-      .WillByDefault(Return());
-
-  output_surface->Reshape(gfx::Size(10, 20), 1.0f, gfx::ColorSpace(), false);
-}
-
-TEST(BufferQueueStandaloneTest, FboBinding) {
+TEST(BufferQueueStandaloneTest, BufferCreation) {
   MockedContext* context;
   scoped_refptr<TestContextProvider> context_provider =
       CreateMockedContextProvider(&context);
@@ -316,21 +295,16 @@
       EXPECT_CALL(*context,
                   CreateImageCHROMIUM(_, 0, 0, kBufferQueueInternalformat))
           .WillOnce(Return(1));
-  Expectation fb =
-      EXPECT_CALL(*context, BindFramebuffer(GL_FRAMEBUFFER, Ne(0U)));
   Expectation tex = EXPECT_CALL(*context, BindTexture(target, Ne(0U)));
   Expectation bind_tex =
       EXPECT_CALL(*context, BindTexImage2DCHROMIUM(target, 1))
           .After(tex, image);
-  EXPECT_CALL(*context,
-              FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target,
-                                   Ne(0U), _))
-      .After(fb, bind_tex);
 
-  output_surface->BindFramebuffer();
+  unsigned stencil;
+  EXPECT_GT(output_surface->GetCurrentBuffer(&stencil), 0u);
 }
 
-TEST(BufferQueueStandaloneTest, CheckBoundFramebuffer) {
+TEST(BufferQueueStandaloneTest, CopyBufferDamage) {
   scoped_refptr<TestContextProvider> context_provider =
       TestContextProvider::Create();
   context_provider->BindToCurrentThread();
@@ -342,25 +316,22 @@
       new BufferQueue(context_provider->ContextGL(), kBufferQueueFormat,
                       gpu_memory_buffer_manager.get(), kFakeSurfaceHandle,
                       context_provider->ContextCapabilities()));
-  output_surface->Initialize();
-  output_surface->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false);
+  EXPECT_TRUE(
+      output_surface->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false));
   // Trigger a sub-buffer copy to exercise all paths.
-  output_surface->BindFramebuffer();
+  unsigned stencil;
+  EXPECT_GT(output_surface->GetCurrentBuffer(&stencil), 0u);
   output_surface->CopyDamageForCurrentSurface(screen_rect);
   output_surface->SwapBuffers(screen_rect);
   output_surface->PageFlipComplete();
-  output_surface->BindFramebuffer();
+  EXPECT_GT(output_surface->GetCurrentBuffer(&stencil), 0u);
   output_surface->CopyDamageForCurrentSurface(small_damage);
   output_surface->SwapBuffers(small_damage);
-
-  int current_fbo = 0;
-  context_provider->ContextGL()->GetIntegerv(GL_FRAMEBUFFER_BINDING,
-                                             &current_fbo);
-  EXPECT_EQ(static_cast<int>(output_surface->fbo()), current_fbo);
 }
 
 TEST_F(BufferQueueTest, PartialSwapReuse) {
-  output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false);
+  EXPECT_TRUE(
+      output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false));
   ASSERT_TRUE(doublebuffering_);
   EXPECT_CALL(*mock_output_surface_,
               CopyBufferDamage(_, _, small_damage, screen_rect))
@@ -380,7 +351,8 @@
 }
 
 TEST_F(BufferQueueTest, PartialSwapFullFrame) {
-  output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false);
+  EXPECT_TRUE(
+      output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false));
   ASSERT_TRUE(doublebuffering_);
   EXPECT_CALL(*mock_output_surface_,
               CopyBufferDamage(_, _, small_damage, screen_rect))
@@ -393,7 +365,8 @@
 }
 
 TEST_F(BufferQueueTest, PartialSwapOverlapping) {
-  output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false);
+  EXPECT_TRUE(
+      output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false));
   ASSERT_TRUE(doublebuffering_);
   EXPECT_CALL(*mock_output_surface_,
               CopyBufferDamage(_, _, small_damage, screen_rect))
@@ -408,21 +381,24 @@
   EXPECT_EQ(next_frame()->damage, overlapping_damage);
 }
 
-TEST_F(BufferQueueTest, MultipleBindCalls) {
+TEST_F(BufferQueueTest, MultipleGetCurrentBufferCalls) {
   // Check that multiple bind calls do not create or change surfaces.
-  output_surface_->BindFramebuffer();
+  unsigned stencil;
+  EXPECT_GT(output_surface_->GetCurrentBuffer(&stencil), 0u);
   EXPECT_EQ(1, CountBuffers());
   unsigned int fb = current_surface();
-  output_surface_->BindFramebuffer();
+  EXPECT_GT(output_surface_->GetCurrentBuffer(&stencil), 0u);
   EXPECT_EQ(1, CountBuffers());
   EXPECT_EQ(fb, current_surface());
 }
 
 TEST_F(BufferQueueTest, CheckDoubleBuffering) {
   // Check buffer flow through double buffering path.
-  output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false);
+  EXPECT_TRUE(
+      output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false));
   EXPECT_EQ(0, CountBuffers());
-  output_surface_->BindFramebuffer();
+  unsigned stencil;
+  EXPECT_GT(output_surface_->GetCurrentBuffer(&stencil), 0u);
   EXPECT_EQ(1, CountBuffers());
   EXPECT_NE(0U, current_surface());
   EXPECT_FALSE(displayed_frame());
@@ -431,7 +407,7 @@
   output_surface_->PageFlipComplete();
   EXPECT_EQ(0U, in_flight_surfaces().size());
   EXPECT_TRUE(displayed_frame()->texture);
-  output_surface_->BindFramebuffer();
+  EXPECT_GT(output_surface_->GetCurrentBuffer(&stencil), 0u);
   EXPECT_EQ(2, CountBuffers());
   CheckUnique();
   EXPECT_NE(0U, current_surface());
@@ -446,7 +422,7 @@
   EXPECT_EQ(0U, in_flight_surfaces().size());
   EXPECT_EQ(1U, available_surfaces().size());
   EXPECT_TRUE(displayed_frame()->texture);
-  output_surface_->BindFramebuffer();
+  EXPECT_GT(output_surface_->GetCurrentBuffer(&stencil), 0u);
   EXPECT_EQ(2, CountBuffers());
   CheckUnique();
   EXPECT_TRUE(available_surfaces().empty());
@@ -454,21 +430,23 @@
 
 TEST_F(BufferQueueTest, CheckTripleBuffering) {
   // Check buffer flow through triple buffering path.
-  output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false);
+  EXPECT_TRUE(
+      output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false));
 
   // This bit is the same sequence tested in the doublebuffering case.
-  output_surface_->BindFramebuffer();
+  unsigned stencil;
+  EXPECT_GT(output_surface_->GetCurrentBuffer(&stencil), 0u);
   EXPECT_FALSE(displayed_frame());
   SwapBuffers();
   output_surface_->PageFlipComplete();
-  output_surface_->BindFramebuffer();
+  EXPECT_GT(output_surface_->GetCurrentBuffer(&stencil), 0u);
   SwapBuffers();
 
   EXPECT_EQ(2, CountBuffers());
   CheckUnique();
   EXPECT_EQ(1U, in_flight_surfaces().size());
   EXPECT_TRUE(displayed_frame()->texture);
-  output_surface_->BindFramebuffer();
+  EXPECT_GT(output_surface_->GetCurrentBuffer(&stencil), 0u);
   EXPECT_EQ(3, CountBuffers());
   CheckUnique();
   EXPECT_NE(0U, current_surface());
@@ -487,17 +465,18 @@
   // Check empty swap flow, in which the damage is empty and BindFramebuffer
   // might not be called.
   EXPECT_EQ(0, CountBuffers());
-  output_surface_->BindFramebuffer();
+  unsigned stencil;
+  unsigned texture = output_surface_->GetCurrentBuffer(&stencil);
+  EXPECT_GT(texture, 0u);
   EXPECT_EQ(1, CountBuffers());
   EXPECT_NE(0U, current_surface());
   EXPECT_FALSE(displayed_frame());
 
-  // This is the texture to scanout.
-  uint32_t texture_id = output_surface_->GetCurrentTextureId();
   SwapBuffers();
   // Make sure we won't be drawing to the texture we just sent for scanout.
-  output_surface_->BindFramebuffer();
-  EXPECT_NE(texture_id, output_surface_->GetCurrentTextureId());
+  unsigned new_texture = output_surface_->GetCurrentBuffer(&stencil);
+  EXPECT_GT(new_texture, 0u);
+  EXPECT_NE(texture, new_texture);
 
   EXPECT_EQ(1U, in_flight_surfaces().size());
   output_surface_->PageFlipComplete();
@@ -516,10 +495,12 @@
 }
 
 TEST_F(BufferQueueTest, CheckCorrectBufferOrdering) {
-  output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false);
+  EXPECT_TRUE(
+      output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false));
   const size_t kSwapCount = 3;
   for (size_t i = 0; i < kSwapCount; ++i) {
-    output_surface_->BindFramebuffer();
+    unsigned stencil;
+    EXPECT_GT(output_surface_->GetCurrentBuffer(&stencil), 0u);
     SwapBuffers();
   }
 
@@ -532,14 +513,17 @@
 }
 
 TEST_F(BufferQueueTest, ReshapeWithInFlightSurfaces) {
-  output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false);
+  EXPECT_TRUE(
+      output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false));
   const size_t kSwapCount = 3;
   for (size_t i = 0; i < kSwapCount; ++i) {
-    output_surface_->BindFramebuffer();
+    unsigned stencil;
+    EXPECT_GT(output_surface_->GetCurrentBuffer(&stencil), 0u);
     SwapBuffers();
   }
 
-  output_surface_->Reshape(gfx::Size(10, 20), 1.0f, gfx::ColorSpace(), false);
+  EXPECT_TRUE(output_surface_->Reshape(gfx::Size(10, 20), 1.0f,
+                                       gfx::ColorSpace(), false));
   EXPECT_EQ(3u, in_flight_surfaces().size());
 
   for (size_t i = 0; i < kSwapCount; ++i) {
@@ -553,19 +537,23 @@
 
 TEST_F(BufferQueueTest, SwapAfterReshape) {
   DCHECK_EQ(0u, gpu_memory_buffer_manager_->set_color_space_count());
-  output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false);
+  EXPECT_TRUE(
+      output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false));
   const size_t kSwapCount = 3;
   for (size_t i = 0; i < kSwapCount; ++i) {
-    output_surface_->BindFramebuffer();
+    unsigned stencil;
+    EXPECT_GT(output_surface_->GetCurrentBuffer(&stencil), 0u);
     SwapBuffers();
   }
   DCHECK_EQ(kSwapCount, gpu_memory_buffer_manager_->set_color_space_count());
 
-  output_surface_->Reshape(gfx::Size(10, 20), 1.0f, gfx::ColorSpace(), false);
+  EXPECT_TRUE(output_surface_->Reshape(gfx::Size(10, 20), 1.0f,
+                                       gfx::ColorSpace(), false));
   DCHECK_EQ(kSwapCount, gpu_memory_buffer_manager_->set_color_space_count());
 
   for (size_t i = 0; i < kSwapCount; ++i) {
-    output_surface_->BindFramebuffer();
+    unsigned stencil;
+    EXPECT_GT(output_surface_->GetCurrentBuffer(&stencil), 0u);
     SwapBuffers();
   }
   DCHECK_EQ(2 * kSwapCount,
@@ -589,7 +577,8 @@
   DCHECK_EQ(2 * kSwapCount,
             gpu_memory_buffer_manager_->set_color_space_count());
   for (size_t i = 0; i < kSwapCount; ++i) {
-    output_surface_->BindFramebuffer();
+    unsigned stencil;
+    EXPECT_GT(output_surface_->GetCurrentBuffer(&stencil), 0u);
     SwapBuffers();
     output_surface_->PageFlipComplete();
   }
@@ -606,14 +595,17 @@
   // This tests buffers in all states.
   // Bind/swap pushes frames into the in flight list, then the PageFlipComplete
   // calls pull one frame into displayed and another into the free list.
-  output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false);
-  output_surface_->BindFramebuffer();
+  EXPECT_TRUE(
+      output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false));
+  // TODO(andrescj): fix a bunch of uninteresting mock function calls.
+  unsigned stencil;
+  EXPECT_GT(output_surface_->GetCurrentBuffer(&stencil), 0u);
   SwapBuffers();
-  output_surface_->BindFramebuffer();
+  EXPECT_GT(output_surface_->GetCurrentBuffer(&stencil), 0u);
   SwapBuffers();
-  output_surface_->BindFramebuffer();
+  EXPECT_GT(output_surface_->GetCurrentBuffer(&stencil), 0u);
   SwapBuffers();
-  output_surface_->BindFramebuffer();
+  EXPECT_GT(output_surface_->GetCurrentBuffer(&stencil), 0u);
   output_surface_->PageFlipComplete();
   output_surface_->PageFlipComplete();
   // We should have one buffer in each possible state right now, including one
@@ -654,15 +646,6 @@
       .Times(1)
       .After(copy3);
   EXPECT_CALL(*context_, DestroyImageCHROMIUM(available->image)).Times(1);
-  // After copying, we expect the framebuffer binding to be updated.
-  EXPECT_CALL(*context_, BindFramebuffer(_, _))
-      .After(copy1)
-      .After(copy2)
-      .After(copy3);
-  EXPECT_CALL(*context_, FramebufferTexture2D(_, _, _, _, _))
-      .After(copy1)
-      .After(copy2)
-      .After(copy3);
 
   output_surface_->RecreateBuffers();
   testing::Mock::VerifyAndClearExpectations(context_);
@@ -677,16 +660,18 @@
 }
 
 TEST_F(BufferQueueTest, AllocateFails) {
-  output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false);
+  EXPECT_TRUE(
+      output_surface_->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false));
 
   // Succeed in the two swaps.
-  output_surface_->BindFramebuffer();
+  unsigned stencil;
+  EXPECT_GT(output_surface_->GetCurrentBuffer(&stencil), 0u);
   EXPECT_TRUE(current_frame());
   SwapBuffers(screen_rect);
 
   // Fail the next surface allocation.
   gpu_memory_buffer_manager_->set_allocate_succeeds(false);
-  output_surface_->BindFramebuffer();
+  EXPECT_EQ(0u, output_surface_->GetCurrentBuffer(&stencil));
   EXPECT_FALSE(current_frame());
   SwapBuffers(screen_rect);
   EXPECT_FALSE(current_frame());
@@ -694,7 +679,7 @@
   // Try another swap. It should copy the buffer damage from the back
   // surface.
   gpu_memory_buffer_manager_->set_allocate_succeeds(true);
-  output_surface_->BindFramebuffer();
+  EXPECT_GT(output_surface_->GetCurrentBuffer(&stencil), 0u);
   unsigned int source_texture = in_flight_surfaces().front()->texture;
   unsigned int target_texture = current_frame()->texture;
   testing::Mock::VerifyAndClearExpectations(mock_output_surface_);
@@ -712,7 +697,7 @@
   EXPECT_EQ(2u, in_flight_surfaces().size());
   for (auto& surface : in_flight_surfaces())
     EXPECT_FALSE(surface);
-  output_surface_->BindFramebuffer();
+  EXPECT_GT(output_surface_->GetCurrentBuffer(&stencil), 0u);
   source_texture = displayed_frame()->texture;
   EXPECT_TRUE(current_frame());
   EXPECT_TRUE(displayed_frame());
diff --git a/components/viz/service/display_embedder/gl_output_surface_buffer_queue.cc b/components/viz/service/display_embedder/gl_output_surface_buffer_queue.cc
index d343b9f9..8ab97f3e 100644
--- a/components/viz/service/display_embedder/gl_output_surface_buffer_queue.cc
+++ b/components/viz/service/display_embedder/gl_output_surface_buffer_queue.cc
@@ -14,6 +14,7 @@
 #include "components/viz/service/display_embedder/buffer_queue.h"
 #include "gpu/command_buffer/client/context_support.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
+#include "ui/gl/gl_enums.h"
 
 namespace viz {
 
@@ -22,7 +23,9 @@
     gpu::SurfaceHandle surface_handle,
     gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
     gfx::BufferFormat buffer_format)
-    : GLOutputSurface(context_provider, surface_handle) {
+    : GLOutputSurface(context_provider, surface_handle),
+      current_texture_(0u),
+      fbo_(0u) {
   capabilities_.uses_default_gl_framebuffer = false;
   capabilities_.flipped_output_surface = true;
   // Set |max_frames_pending| to 2 for buffer_queue, which aligns scheduling
@@ -37,14 +40,39 @@
   buffer_queue_ = std::make_unique<BufferQueue>(
       context_provider->ContextGL(), buffer_format, gpu_memory_buffer_manager,
       surface_handle, context_provider->ContextCapabilities());
-  buffer_queue_->Initialize();
+  context_provider_->ContextGL()->GenFramebuffers(1, &fbo_);
 }
 
-GLOutputSurfaceBufferQueue::~GLOutputSurfaceBufferQueue() = default;
+GLOutputSurfaceBufferQueue::~GLOutputSurfaceBufferQueue() {
+  DCHECK_NE(0u, fbo_);
+  context_provider_->ContextGL()->DeleteFramebuffers(1, &fbo_);
+}
 
 void GLOutputSurfaceBufferQueue::BindFramebuffer() {
+  auto* gl = context_provider_->ContextGL();
+  gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
   DCHECK(buffer_queue_);
-  buffer_queue_->BindFramebuffer();
+  unsigned stencil;
+  current_texture_ = buffer_queue_->GetCurrentBuffer(&stencil);
+  if (!current_texture_)
+    return;
+  // TODO(andrescj): if the texture hasn't changed since the last call to
+  // BindFrameBuffer(), we may be able to avoid mutating the FBO which may lead
+  // to performance improvements.
+  gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                           buffer_queue_->texture_target(), current_texture_,
+                           0);
+
+#if DCHECK_IS_ON() && defined(OS_CHROMEOS)
+  const GLenum result = gl->CheckFramebufferStatus(GL_FRAMEBUFFER);
+  if (result != GL_FRAMEBUFFER_COMPLETE)
+    DLOG(ERROR) << " Incomplete fb: " << gl::GLEnums::GetStringError(result);
+#endif
+
+  if (stencil) {
+    gl->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+                                GL_RENDERBUFFER, stencil);
+  }
 }
 
 // We call this on every frame that a value changes, but changing the size once
@@ -61,7 +89,15 @@
   reshape_size_ = size;
   GLOutputSurface::Reshape(size, device_scale_factor, color_space, has_alpha,
                            use_stencil);
-  buffer_queue_->Reshape(size, device_scale_factor, color_space, use_stencil);
+  if (buffer_queue_->Reshape(size, device_scale_factor, color_space,
+                             use_stencil)) {
+    auto* gl = context_provider_->ContextGL();
+    gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
+    gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                             buffer_queue_->texture_target(), 0, 0);
+    gl->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+                                GL_RENDERBUFFER, 0);
+  }
 }
 
 void GLOutputSurfaceBufferQueue::SetDrawRectangle(const gfx::Rect& damage) {
@@ -93,7 +129,8 @@
 }
 
 unsigned GLOutputSurfaceBufferQueue::GetOverlayTextureId() const {
-  return buffer_queue_->GetCurrentTextureId();
+  DCHECK(current_texture_);
+  return current_texture_;
 }
 
 gfx::BufferFormat GLOutputSurfaceBufferQueue::GetOverlayBufferFormat() const {
@@ -107,7 +144,9 @@
   if (response.result == gfx::SwapResult::SWAP_NAK_RECREATE_BUFFERS) {
     // Even through the swap failed, this is a fixable error so we can pretend
     // it succeeded to the rest of the system.
-    buffer_queue_->RecreateBuffers();
+    unsigned current_surface_texture = buffer_queue_->RecreateBuffers();
+    if (current_surface_texture)
+      BindFramebuffer();
     force_swap = true;
   }
 
diff --git a/components/viz/service/display_embedder/gl_output_surface_buffer_queue.h b/components/viz/service/display_embedder/gl_output_surface_buffer_queue.h
index 476cb0b..594b38b 100644
--- a/components/viz/service/display_embedder/gl_output_surface_buffer_queue.h
+++ b/components/viz/service/display_embedder/gl_output_surface_buffer_queue.h
@@ -5,6 +5,8 @@
 #ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_GL_OUTPUT_SURFACE_BUFFER_QUEUE_H_
 #define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_GL_OUTPUT_SURFACE_BUFFER_QUEUE_H_
 
+#include <stdint.h>
+
 #include <memory>
 
 #include "base/memory/weak_ptr.h"
@@ -65,6 +67,8 @@
   void DidReceiveSwapBuffersAck(const gfx::SwapResponse& response) override;
 
   std::unique_ptr<BufferQueue> buffer_queue_;
+  unsigned current_texture_;
+  uint32_t fbo_;
 
   gfx::OverlayTransform display_transform_ = gfx::OVERLAY_TRANSFORM_NONE;
   gfx::Size reshape_size_;
diff --git a/content/app/service_manager_environment.cc b/content/app/service_manager_environment.cc
index 4ca8c85..2658257 100644
--- a/content/app/service_manager_environment.cc
+++ b/content/app/service_manager_environment.cc
@@ -11,7 +11,6 @@
 #include "content/browser/service_manager/common_browser_interfaces.h"
 #include "content/browser/service_manager/service_manager_context.h"
 #include "content/browser/startup_data_impl.h"
-#include "content/browser/system_connector_impl.h"
 #include "content/public/common/service_manager_connection.h"
 #include "mojo/core/embedder/embedder.h"
 #include "mojo/core/embedder/scoped_ipc_support.h"
@@ -37,8 +36,6 @@
   auto* system_connection = ServiceManagerConnection::GetForProcess();
   RegisterCommonBrowserInterfaces(system_connection);
   system_connection->Start();
-
-  SetSystemConnector(system_connection->GetConnector()->Clone());
 }
 
 ServiceManagerEnvironment::~ServiceManagerEnvironment() = default;
diff --git a/content/browser/accessibility/accessibility_ipc_error_browsertest.cc b/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
index 918af5b..719abd7e 100644
--- a/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
+++ b/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
@@ -39,9 +39,8 @@
   DISALLOW_COPY_AND_ASSIGN(AccessibilityIpcErrorBrowserTest);
 };
 
-// Flaky on all platforms. http://crbug.com/973946
 IN_PROC_BROWSER_TEST_F(AccessibilityIpcErrorBrowserTest,
-                       DISABLED_ResetBrowserAccessibilityManager) {
+                       ResetBrowserAccessibilityManager) {
   // Create a data url and load it.
   const char url_str[] =
       "data:text/html,"
diff --git a/content/browser/android/nfc_host.cc b/content/browser/android/nfc_host.cc
index ee3ec1d0..6ae07c5 100644
--- a/content/browser/android/nfc_host.cc
+++ b/content/browser/android/nfc_host.cc
@@ -7,7 +7,7 @@
 #include <utility>
 
 #include "base/atomic_sequence_num.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "jni/NfcHost_jni.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/device/public/mojom/nfc.mojom.h"
@@ -30,9 +30,8 @@
   java_nfc_host_.Reset(
       Java_NfcHost_create(env, web_contents_->GetJavaWebContents(), id_));
 
-  if (ServiceManagerConnection::GetForProcess()) {
-    service_manager::Connector* connector =
-        ServiceManagerConnection::GetForProcess()->GetConnector();
+  service_manager::Connector* connector = content::GetSystemConnector();
+  if (connector) {
     connector->BindInterface(device::mojom::kServiceName,
                              mojo::MakeRequest(&nfc_provider_));
   }
diff --git a/content/browser/background_fetch/storage/cache_entry_handler_impl.cc b/content/browser/background_fetch/storage/cache_entry_handler_impl.cc
index b9f2178..8b1fe1b 100644
--- a/content/browser/background_fetch/storage/cache_entry_handler_impl.cc
+++ b/content/browser/background_fetch/storage/cache_entry_handler_impl.cc
@@ -43,40 +43,42 @@
 }
 
 void CacheEntryHandlerImpl::PopulateBody(
-    scoped_refptr<BlobDataHandle> data_handle,
+    scoped_refptr<DiskCacheBlobEntry> blob_entry,
     const blink::mojom::SerializedBlobPtr& blob,
     CacheStorageCache::EntryIndex index) {
-  disk_cache::Entry* entry = data_handle->entry().get();
+  disk_cache::Entry* entry = blob_entry->disk_cache_entry().get();
   DCHECK(entry);
 
   blob->size = entry->GetDataSize(index);
   blob->uuid = base::GenerateGUID();
 
   auto blob_data = std::make_unique<storage::BlobDataBuilder>(blob->uuid);
-  blob_data->AppendDiskCacheEntry(std::move(data_handle), entry, index);
+  auto handle = MakeDataHandle(std::move(blob_entry), index);
+  blob_data->AppendReadableDataHandle(std::move(handle));
 
   auto blob_handle = blob_context_->AddFinishedBlob(std::move(blob_data));
   storage::BlobImpl::Create(std::move(blob_handle), MakeRequest(&blob->blob));
 }
 
 void CacheEntryHandlerImpl::PopulateResponseBody(
-    scoped_refptr<BlobDataHandle> data_handle,
+    scoped_refptr<DiskCacheBlobEntry> blob_entry,
     blink::mojom::FetchAPIResponse* response) {
   response->blob = blink::mojom::SerializedBlob::New();
-  PopulateBody(std::move(data_handle), response->blob,
+  PopulateBody(std::move(blob_entry), response->blob,
                CacheStorageCache::INDEX_RESPONSE_BODY);
 }
 
 void CacheEntryHandlerImpl::PopulateRequestBody(
-    scoped_refptr<BlobDataHandle> data_handle,
+    scoped_refptr<DiskCacheBlobEntry> blob_entry,
     blink::mojom::FetchAPIRequest* request) {
-  if (!data_handle->entry() ||
-      !data_handle->entry()->GetDataSize(CacheStorageCache::INDEX_SIDE_DATA)) {
+  if (!blob_entry->disk_cache_entry() ||
+      !blob_entry->disk_cache_entry()->GetDataSize(
+          CacheStorageCache::INDEX_SIDE_DATA)) {
     return;
   }
 
   request->blob = blink::mojom::SerializedBlob::New();
-  PopulateBody(std::move(data_handle), request->blob,
+  PopulateBody(std::move(blob_entry), request->blob,
                CacheStorageCache::INDEX_SIDE_DATA);
 }
 
diff --git a/content/browser/background_fetch/storage/cache_entry_handler_impl.h b/content/browser/background_fetch/storage/cache_entry_handler_impl.h
index 7f98dbf..0646ca89 100644
--- a/content/browser/background_fetch/storage/cache_entry_handler_impl.h
+++ b/content/browser/background_fetch/storage/cache_entry_handler_impl.h
@@ -24,13 +24,13 @@
       blink::mojom::FetchAPIRequestPtr request,
       blink::mojom::FetchAPIResponsePtr response,
       int64_t trace_id) override;
-  void PopulateResponseBody(scoped_refptr<BlobDataHandle> data_handle,
+  void PopulateResponseBody(scoped_refptr<DiskCacheBlobEntry> blob_entry,
                             blink::mojom::FetchAPIResponse* response) override;
-  void PopulateRequestBody(scoped_refptr<BlobDataHandle> data_handle,
+  void PopulateRequestBody(scoped_refptr<DiskCacheBlobEntry> blob_entry,
                            blink::mojom::FetchAPIRequest* request) override;
 
  private:
-  void PopulateBody(scoped_refptr<BlobDataHandle> data_handle,
+  void PopulateBody(scoped_refptr<DiskCacheBlobEntry> blob_entry,
                     const blink::mojom::SerializedBlobPtr& blob,
                     CacheStorageCache::EntryIndex index);
 
diff --git a/content/browser/blob_storage/blob_url_unittest.cc b/content/browser/blob_storage/blob_url_unittest.cc
index 9e53c46e3..31b19402 100644
--- a/content/browser/blob_storage/blob_url_unittest.cc
+++ b/content/browser/blob_storage/blob_url_unittest.cc
@@ -23,7 +23,6 @@
 #include "net/base/net_errors.h"
 #include "net/base/request_priority.h"
 #include "net/base/test_completion_callback.h"
-#include "net/disk_cache/disk_cache.h"
 #include "net/http/http_byte_range.h"
 #include "net/http/http_request_headers.h"
 #include "net/http/http_response_headers.h"
@@ -44,6 +43,7 @@
 #include "storage/browser/fileapi/file_system_operation_context.h"
 #include "storage/browser/fileapi/file_system_url.h"
 #include "storage/browser/test/async_file_test_helper.h"
+#include "storage/browser/test/fake_blob_data_handle.h"
 #include "storage/browser/test/mock_blob_registry_delegate.h"
 #include "storage/browser/test/test_file_system_context.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -63,10 +63,8 @@
 const char kTestFileData2[] = "This is sample file.";
 const char kTestFileSystemFileData1[] = "abcdefghijklmnop";
 const char kTestFileSystemFileData2[] = "File system file test data.";
-const char kTestDiskCacheKey1[] = "key1";
-const char kTestDiskCacheKey2[] = "key2";
-const char kTestDiskCacheData1[] = "disk cache test data1.";
-const char kTestDiskCacheData2[] = "disk cache test data2.";
+const char kTestDataHandleData1[] = "data handle test data1.";
+const char kTestDataHandleData2[] = "data handle test data2.";
 const char kTestDiskCacheSideData[] = "test side data";
 const char kTestContentType[] = "foo/bar";
 const char kTestContentDisposition[] = "attachment; filename=foo.txt";
@@ -75,61 +73,6 @@
 const storage::FileSystemType kFileSystemType =
     storage::kFileSystemTypeTemporary;
 
-const int kTestDiskCacheStreamIndex = 0;
-const int kTestDiskCacheSideStreamIndex = 1;
-
-// Our disk cache tests don't need a real data handle since the tests themselves
-// scope the disk cache and entries.
-class EmptyDataHandle : public storage::BlobDataBuilder::DataHandle {
- private:
-  ~EmptyDataHandle() override {}
-};
-
-std::unique_ptr<disk_cache::Backend> CreateInMemoryDiskCache() {
-  std::unique_ptr<disk_cache::Backend> cache;
-  net::TestCompletionCallback callback;
-  int rv = disk_cache::CreateCacheBackend(
-      net::MEMORY_CACHE, net::CACHE_BACKEND_DEFAULT, base::FilePath(), 0, false,
-      nullptr, &cache, callback.callback());
-  EXPECT_EQ(net::OK, callback.GetResult(rv));
-
-  return cache;
-}
-
-disk_cache::ScopedEntryPtr CreateDiskCacheEntry(disk_cache::Backend* cache,
-                                                const char* key,
-                                                const std::string& data) {
-  disk_cache::Entry* temp_entry = nullptr;
-  net::TestCompletionCallback callback;
-  int rv =
-      cache->CreateEntry(key, net::HIGHEST, &temp_entry, callback.callback());
-  if (callback.GetResult(rv) != net::OK)
-    return nullptr;
-  disk_cache::ScopedEntryPtr entry(temp_entry);
-
-  scoped_refptr<net::StringIOBuffer> iobuffer =
-      base::MakeRefCounted<net::StringIOBuffer>(data);
-  rv = entry->WriteData(kTestDiskCacheStreamIndex, 0, iobuffer.get(),
-                        iobuffer->size(), callback.callback(), false);
-  EXPECT_EQ(static_cast<int>(data.size()), callback.GetResult(rv));
-  return entry;
-}
-
-disk_cache::ScopedEntryPtr CreateDiskCacheEntryWithSideData(
-    disk_cache::Backend* cache,
-    const char* key,
-    const std::string& data,
-    const std::string& side_data) {
-  disk_cache::ScopedEntryPtr entry = CreateDiskCacheEntry(cache, key, data);
-  scoped_refptr<net::StringIOBuffer> iobuffer =
-      base::MakeRefCounted<net::StringIOBuffer>(side_data);
-  net::TestCompletionCallback callback;
-  int rv = entry->WriteData(kTestDiskCacheSideStreamIndex, 0, iobuffer.get(),
-                            iobuffer->size(), callback.callback(), false);
-  EXPECT_EQ(static_cast<int>(side_data.size()), callback.GetResult(rv));
-  return entry;
-}
-
 enum class RequestTestType {
   kNetRequest,
   kRequestFromBlobImpl
@@ -184,10 +127,6 @@
     base::GetFileInfo(temp_file2_, &file_info2);
     temp_file_modification_time2_ = file_info2.last_modified;
 
-    disk_cache_backend_ = CreateInMemoryDiskCache();
-    disk_cache_entry_ = CreateDiskCacheEntry(
-        disk_cache_backend_.get(), kTestDiskCacheKey1, kTestDiskCacheData1);
-
     url_request_job_factory_.SetProtocolHandler(
         "blob", std::make_unique<MockProtocolHandler>(this));
     url_request_context_.set_job_factory(&url_request_job_factory_);
@@ -357,10 +296,10 @@
     blob_data_->AppendFile(temp_file1_, 2, 3, temp_file_modification_time1_);
     *expected_result += std::string(kTestFileData1 + 2, 3);
 
-    blob_data_->AppendDiskCacheEntry(new EmptyDataHandle(),
-                                     disk_cache_entry_.get(),
-                                     kTestDiskCacheStreamIndex);
-    *expected_result += std::string(kTestDiskCacheData1);
+    blob_data_->AppendReadableDataHandle(
+        base::MakeRefCounted<storage::FakeBlobDataHandle>(kTestDataHandleData1,
+                                                          ""));
+    *expected_result += std::string(kTestDataHandleData1);
 
     blob_data_->AppendFileSystemFile(temp_file_system_file1_, 3, 4,
                                      temp_file_system_file_modification_time1_,
@@ -417,9 +356,6 @@
   base::Time temp_file_system_file_modification_time1_;
   base::Time temp_file_system_file_modification_time2_;
 
-  std::unique_ptr<disk_cache::Backend> disk_cache_backend_;
-  disk_cache::ScopedEntryPtr disk_cache_entry_;
-
   TestBrowserThreadBundle thread_bundle_;
   scoped_refptr<storage::FileSystemContext> file_system_context_;
 
@@ -549,12 +485,12 @@
   TestSuccessNonrangeRequest(result, 4);
 }
 
-TEST_P(BlobURLRequestJobTest, TestGetSimpleDiskCacheRequest) {
-  blob_data_->AppendDiskCacheEntry(new EmptyDataHandle(),
-                                   disk_cache_entry_.get(),
-                                   kTestDiskCacheStreamIndex);
-  TestSuccessNonrangeRequest(kTestDiskCacheData1,
-                             base::size(kTestDiskCacheData1) - 1);
+TEST_P(BlobURLRequestJobTest, TestGetSimpleDataHandleRequest) {
+  blob_data_->AppendReadableDataHandle(
+      base::MakeRefCounted<storage::FakeBlobDataHandle>(kTestDataHandleData1,
+                                                        ""));
+  TestSuccessNonrangeRequest(kTestDataHandleData1,
+                             base::size(kTestDataHandleData1) - 1);
 }
 
 TEST_P(BlobURLRequestJobTest, TestGetComplicatedDataFileAndDiskCacheRequest) {
@@ -648,34 +584,26 @@
 }
 
 TEST_P(BlobURLRequestJobTest, TestSideData) {
-  disk_cache::ScopedEntryPtr disk_cache_entry_with_side_data =
-      CreateDiskCacheEntryWithSideData(disk_cache_backend_.get(),
-                                       kTestDiskCacheKey2, kTestDiskCacheData2,
-                                       kTestDiskCacheSideData);
-  blob_data_->AppendDiskCacheEntryWithSideData(
-      new EmptyDataHandle(), disk_cache_entry_with_side_data.get(),
-      kTestDiskCacheStreamIndex, kTestDiskCacheSideStreamIndex);
+  blob_data_->AppendReadableDataHandle(
+      base::MakeRefCounted<storage::FakeBlobDataHandle>(
+          kTestDataHandleData2, kTestDiskCacheSideData));
   expected_status_code_ = 200;
-  expected_response_ = kTestDiskCacheData2;
+  expected_response_ = kTestDataHandleData2;
   TestRequest("GET", net::HttpRequestHeaders());
-  EXPECT_EQ(static_cast<int>(base::size(kTestDiskCacheData2) - 1),
+  EXPECT_EQ(static_cast<int>(base::size(kTestDataHandleData2) - 1),
             response_headers_->GetContentLength());
 
   EXPECT_EQ(std::string(kTestDiskCacheSideData), response_metadata_);
 }
 
 TEST_P(BlobURLRequestJobTest, TestZeroSizeSideData) {
-  disk_cache::ScopedEntryPtr disk_cache_entry_with_side_data =
-      CreateDiskCacheEntryWithSideData(disk_cache_backend_.get(),
-                                       kTestDiskCacheKey2, kTestDiskCacheData2,
-                                       "");
-  blob_data_->AppendDiskCacheEntryWithSideData(
-      new EmptyDataHandle(), disk_cache_entry_with_side_data.get(),
-      kTestDiskCacheStreamIndex, kTestDiskCacheSideStreamIndex);
+  blob_data_->AppendReadableDataHandle(
+      base::MakeRefCounted<storage::FakeBlobDataHandle>(kTestDataHandleData2,
+                                                        ""));
   expected_status_code_ = 200;
-  expected_response_ = kTestDiskCacheData2;
+  expected_response_ = kTestDataHandleData2;
   TestRequest("GET", net::HttpRequestHeaders());
-  EXPECT_EQ(static_cast<int>(base::size(kTestDiskCacheData2) - 1),
+  EXPECT_EQ(static_cast<int>(base::size(kTestDataHandleData2) - 1),
             response_headers_->GetContentLength());
 
   EXPECT_TRUE(response_metadata_.empty());
diff --git a/content/browser/browser_context.cc b/content/browser/browser_context.cc
index bd5d10b9..5c941456 100644
--- a/content/browser/browser_context.cc
+++ b/content/browser/browser_context.cc
@@ -54,6 +54,7 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/shared_cors_origin_access_list.h"
 #include "content/public/browser/site_instance.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
@@ -648,9 +649,8 @@
       kServiceInstanceGroup,
       std::make_unique<ServiceInstanceGroupHolder>(new_group));
 
-  ServiceManagerConnection* service_manager_connection =
-      ServiceManagerConnection::GetForProcess();
-  if (service_manager_connection && base::ThreadTaskRunnerHandle::IsSet()) {
+  auto* system_connector = GetSystemConnector();
+  if (system_connector && base::ThreadTaskRunnerHandle::IsSet()) {
     // NOTE: Many unit tests create a TestBrowserContext without initializing
     // Mojo or the global service manager connection.
 
@@ -661,7 +661,7 @@
     service_manager::Identity identity(mojom::kBrowserServiceName, new_group,
                                        base::Token{},
                                        base::Token::CreateRandom());
-    service_manager_connection->GetConnector()->RegisterServiceInstance(
+    system_connector->RegisterServiceInstance(
         identity, std::move(service), metadata.BindNewPipeAndPassReceiver());
     metadata->SetPID(base::GetCurrentProcId());
 
diff --git a/content/browser/browsing_data/clear_site_data_handler_browsertest.cc b/content/browser/browsing_data/clear_site_data_handler_browsertest.cc
index dfaec124..9d062066 100644
--- a/content/browser/browsing_data/clear_site_data_handler_browsertest.cc
+++ b/content/browser/browsing_data/clear_site_data_handler_browsertest.cc
@@ -29,10 +29,10 @@
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/storage_usage_info.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/network_service_util.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/cache_test_util.h"
@@ -454,8 +454,8 @@
   void SetUpMockCertVerifier(int32_t default_result) {
     DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
     network::mojom::NetworkServiceTestPtr network_service_test;
-    ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
-        mojom::kNetworkServiceName, &network_service_test);
+    GetSystemConnector()->BindInterface(mojom::kNetworkServiceName,
+                                        &network_service_test);
 
     base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
     network_service_test->MockCertVerifierSetDefaultResult(
diff --git a/content/browser/cache_storage/cache_storage_cache_entry_handler.cc b/content/browser/cache_storage/cache_storage_cache_entry_handler.cc
index febe5a2b..cf4cc4e 100644
--- a/content/browser/cache_storage/cache_storage_cache_entry_handler.cc
+++ b/content/browser/cache_storage/cache_storage_cache_entry_handler.cc
@@ -16,27 +16,122 @@
 
 namespace content {
 
-CacheStorageCacheEntryHandler::BlobDataHandle::BlobDataHandle(
+namespace {
+
+constexpr int kInvalidSideDataIndex = -1;
+
+// A |BlobDataItem::DataHandle| implementation that wraps a
+// |DiskCacheBlobEntry|.  In addition, each |DataHandleImpl| maps the main
+// and side data to particular disk_cache indices.
+//
+// The |DataHandleImpl| is a "readable" handle.  It overrides the virtual
+// size and reading methods to access the underlying disk_cache entry.
+class DataHandleImpl : public storage::BlobDataItem::DataHandle {
+ public:
+  DataHandleImpl(
+      scoped_refptr<CacheStorageCacheEntryHandler::DiskCacheBlobEntry>
+          blob_entry,
+      int disk_cache_index,
+      int side_data_disk_cache_index)
+      : blob_entry_(std::move(blob_entry)),
+        disk_cache_index_(disk_cache_index),
+        side_data_disk_cache_index_(side_data_disk_cache_index) {}
+
+  uint64_t GetSize() const override {
+    return blob_entry_->GetSize(disk_cache_index_);
+  }
+
+  int Read(scoped_refptr<net::IOBuffer> dst_buffer,
+           uint64_t src_offset,
+           int bytes_to_read,
+           base::OnceCallback<void(int)> callback) override {
+    return blob_entry_->Read(std::move(dst_buffer), disk_cache_index_,
+                             src_offset, bytes_to_read, std::move(callback));
+  }
+
+  uint64_t GetSideDataSize() const override {
+    if (side_data_disk_cache_index_ == kInvalidSideDataIndex)
+      return 0;
+    return blob_entry_->GetSize(side_data_disk_cache_index_);
+  }
+
+  int ReadSideData(scoped_refptr<net::IOBuffer> dst_buffer,
+                   base::OnceCallback<void(int)> callback) override {
+    if (side_data_disk_cache_index_ == kInvalidSideDataIndex)
+      return net::ERR_FAILED;
+    return blob_entry_->Read(std::move(dst_buffer), side_data_disk_cache_index_,
+                             /* offset= */ 0, GetSideDataSize(),
+                             std::move(callback));
+  }
+
+  void PrintTo(::std::ostream* os) const override {
+    blob_entry_->PrintTo(os);
+    *os << ",disk_cache_index:" << disk_cache_index_;
+  }
+
+  const char* BytesReadHistogramLabel() const override {
+    return "DiskCache.CacheStorage";
+  }
+
+ private:
+  ~DataHandleImpl() override = default;
+
+  const scoped_refptr<CacheStorageCacheEntryHandler::DiskCacheBlobEntry>
+      blob_entry_;
+  const int disk_cache_index_;
+  const int side_data_disk_cache_index_;
+
+  DISALLOW_COPY_AND_ASSIGN(DataHandleImpl);
+};
+
+}  // namespace
+
+CacheStorageCacheEntryHandler::DiskCacheBlobEntry::DiskCacheBlobEntry(
+    util::PassKey<CacheStorageCacheEntryHandler> key,
     base::WeakPtr<CacheStorageCacheEntryHandler> entry_handler,
     CacheStorageCacheHandle cache_handle,
-    disk_cache::ScopedEntryPtr entry)
+    disk_cache::ScopedEntryPtr disk_cache_entry)
     : entry_handler_(std::move(entry_handler)),
       cache_handle_(std::move(cache_handle)),
-      entry_(std::move(entry)) {}
+      disk_cache_entry_(std::move(disk_cache_entry)) {}
 
-bool CacheStorageCacheEntryHandler::BlobDataHandle::IsValid() {
-  return entry_ != nullptr;
+int CacheStorageCacheEntryHandler::DiskCacheBlobEntry::Read(
+    scoped_refptr<net::IOBuffer> dst_buffer,
+    int disk_cache_index,
+    uint64_t offset,
+    int bytes_to_read,
+    base::OnceCallback<void(int)> callback) {
+  if (!disk_cache_entry_)
+    return net::ERR_CACHE_READ_FAILURE;
+
+  return disk_cache_entry_->ReadData(disk_cache_index, offset, dst_buffer.get(),
+                                     bytes_to_read, std::move(callback));
 }
 
-void CacheStorageCacheEntryHandler::BlobDataHandle::Invalidate() {
+int CacheStorageCacheEntryHandler::DiskCacheBlobEntry::GetSize(
+    int disk_cache_index) const {
+  if (!disk_cache_entry_)
+    return 0;
+  return disk_cache_entry_->GetDataSize(disk_cache_index);
+}
+
+void CacheStorageCacheEntryHandler::DiskCacheBlobEntry::PrintTo(
+    ::std::ostream* os) const {
+  if (disk_cache_entry_)
+    *os << "disk_cache_key:" << disk_cache_entry_->GetKey();
+  else
+    *os << "<invalidated>";
+}
+
+void CacheStorageCacheEntryHandler::DiskCacheBlobEntry::Invalidate() {
   cache_handle_ = base::nullopt;
   entry_handler_ = nullptr;
-  entry_ = nullptr;
+  disk_cache_entry_ = nullptr;
 }
 
-CacheStorageCacheEntryHandler::BlobDataHandle::~BlobDataHandle() {
+CacheStorageCacheEntryHandler::DiskCacheBlobEntry::~DiskCacheBlobEntry() {
   if (entry_handler_)
-    entry_handler_->EraseBlobDataHandle(this);
+    entry_handler_->EraseDiskCacheBlobEntry(this);
 }
 
 PutContext::PutContext(blink::mojom::FetchAPIRequestPtr request,
@@ -88,9 +183,9 @@
         std::move(side_data_blob), side_data_blob_size, trace_id);
   }
 
-  void PopulateResponseBody(scoped_refptr<BlobDataHandle> data_handle,
+  void PopulateResponseBody(scoped_refptr<DiskCacheBlobEntry> blob_entry,
                             blink::mojom::FetchAPIResponse* response) override {
-    disk_cache::Entry* entry = data_handle->entry().get();
+    disk_cache::Entry* entry = blob_entry->disk_cache_entry().get();
     DCHECK(entry);
 
     // Create a blob with the response body data.
@@ -101,16 +196,17 @@
     auto blob_data =
         std::make_unique<storage::BlobDataBuilder>(response->blob->uuid);
 
-    blob_data->AppendDiskCacheEntryWithSideData(
-        std::move(data_handle), entry, CacheStorageCache::INDEX_RESPONSE_BODY,
+    auto inner_handle = MakeDataHandleWithSideData(
+        std::move(blob_entry), CacheStorageCache::INDEX_RESPONSE_BODY,
         CacheStorageCache::INDEX_SIDE_DATA);
+    blob_data->AppendReadableDataHandle(std::move(inner_handle));
     auto blob_handle = blob_context_->AddFinishedBlob(std::move(blob_data));
 
     storage::BlobImpl::Create(std::move(blob_handle),
                               MakeRequest(&response->blob->blob));
   }
 
-  void PopulateRequestBody(scoped_refptr<BlobDataHandle> data_handle,
+  void PopulateRequestBody(scoped_refptr<DiskCacheBlobEntry> blob_entry,
                            blink::mojom::FetchAPIRequest* request) override {}
 
  private:
@@ -125,32 +221,33 @@
     base::WeakPtr<storage::BlobStorageContext> blob_context)
     : blob_context_(blob_context) {}
 
-scoped_refptr<CacheStorageCacheEntryHandler::BlobDataHandle>
-CacheStorageCacheEntryHandler::CreateBlobDataHandle(
+scoped_refptr<CacheStorageCacheEntryHandler::DiskCacheBlobEntry>
+CacheStorageCacheEntryHandler::CreateDiskCacheBlobEntry(
     CacheStorageCacheHandle cache_handle,
-    disk_cache::ScopedEntryPtr entry) {
-  auto handle =
-      base::MakeRefCounted<CacheStorageCacheEntryHandler::BlobDataHandle>(
-          GetWeakPtr(), std::move(cache_handle), std::move(entry));
-  DCHECK_EQ(blob_data_handles_.count(handle.get()), 0u);
-  blob_data_handles_.insert(handle.get());
-  return handle;
+    disk_cache::ScopedEntryPtr disk_cache_entry) {
+  auto blob_entry =
+      base::MakeRefCounted<CacheStorageCacheEntryHandler::DiskCacheBlobEntry>(
+          util::PassKey<CacheStorageCacheEntryHandler>(), GetWeakPtr(),
+          std::move(cache_handle), std::move(disk_cache_entry));
+  DCHECK_EQ(blob_entries_.count(blob_entry.get()), 0u);
+  blob_entries_.insert(blob_entry.get());
+  return blob_entry;
 }
 
 CacheStorageCacheEntryHandler::~CacheStorageCacheEntryHandler() = default;
 
-void CacheStorageCacheEntryHandler::InvalidateBlobDataHandles() {
+void CacheStorageCacheEntryHandler::InvalidateDiskCacheBlobEntrys() {
   // Calling Invalidate() can cause the CacheStorageCacheEntryHandler to be
   // destroyed. Be careful not to touch |this| after calling Invalidate().
-  std::set<BlobDataHandle*> handles = std::move(blob_data_handles_);
-  for (auto* handle : handles)
-    handle->Invalidate();
+  std::set<DiskCacheBlobEntry*> entries = std::move(blob_entries_);
+  for (auto* entry : entries)
+    entry->Invalidate();
 }
 
-void CacheStorageCacheEntryHandler::EraseBlobDataHandle(
-    BlobDataHandle* handle) {
-  DCHECK_NE(blob_data_handles_.count(handle), 0u);
-  blob_data_handles_.erase(handle);
+void CacheStorageCacheEntryHandler::EraseDiskCacheBlobEntry(
+    DiskCacheBlobEntry* blob_entry) {
+  DCHECK_NE(blob_entries_.count(blob_entry), 0u);
+  blob_entries_.erase(blob_entry);
 }
 
 // static
@@ -169,4 +266,23 @@
   NOTREACHED();
 }
 
+// static
+scoped_refptr<storage::BlobDataItem::DataHandle>
+CacheStorageCacheEntryHandler::MakeDataHandle(
+    scoped_refptr<DiskCacheBlobEntry> blob_entry,
+    int disk_cache_index) {
+  return MakeDataHandleWithSideData(std::move(blob_entry), disk_cache_index,
+                                    kInvalidSideDataIndex);
+}
+
+// static
+scoped_refptr<storage::BlobDataItem::DataHandle>
+CacheStorageCacheEntryHandler::MakeDataHandleWithSideData(
+    scoped_refptr<DiskCacheBlobEntry> blob_entry,
+    int disk_cache_index,
+    int side_data_disk_cache_index) {
+  return base::MakeRefCounted<DataHandleImpl>(
+      std::move(blob_entry), disk_cache_index, side_data_disk_cache_index);
+}
+
 }  // namespace content
diff --git a/content/browser/cache_storage/cache_storage_cache_entry_handler.h b/content/browser/cache_storage/cache_storage_cache_entry_handler.h
index 688ec2e..4a3ff54 100644
--- a/content/browser/cache_storage/cache_storage_cache_entry_handler.h
+++ b/content/browser/cache_storage/cache_storage_cache_entry_handler.h
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
+#include "base/util/type_safety/pass_key.h"
 #include "content/browser/cache_storage/cache_storage_cache_handle.h"
 #include "content/browser/cache_storage/scoped_writable_entry.h"
 #include "content/common/content_export.h"
@@ -60,33 +61,51 @@
 
 class CONTENT_EXPORT CacheStorageCacheEntryHandler {
  public:
-  // This class ensures that the cache and the entry have a lifetime as long as
-  // the blob that is created to contain them.
-  class BlobDataHandle : public storage::BlobDataBuilder::DataHandle {
+  // The |DiskCacheBlobEntry| is a ref-counted object containing both
+  // a disk_cache Entry and a Handle to the cache in which it lives.  This
+  // blob entry can then be used to create a specialized
+  // |BlobDataItem::DataHandle| by calling CacheStorageCacheEntryHandle's
+  // MakeDataHandle().  This ensure both the cache and the disk_cache entry live
+  // as long as the blob.
+  // TODO(crbug/960012): Support |DiskCacheBlobEntry| on a separate sequence
+  // from the |BlobDataItem::DataHandle|.
+  class DiskCacheBlobEntry : public base::RefCounted<DiskCacheBlobEntry> {
    public:
-    BlobDataHandle(base::WeakPtr<CacheStorageCacheEntryHandler> entry_handler,
-                   CacheStorageCacheHandle cache_handle,
-                   disk_cache::ScopedEntryPtr entry);
+    // Use |CacheStorageCacheEntryHandler::CreateDiskCacheBlobEntry|.
+    DiskCacheBlobEntry(
+        util::PassKey<CacheStorageCacheEntryHandler> key,
+        base::WeakPtr<CacheStorageCacheEntryHandler> entry_handler,
+        CacheStorageCacheHandle cache_handle,
+        disk_cache::ScopedEntryPtr disk_cache_entry);
 
-    bool IsValid() override;
+    int Read(scoped_refptr<net::IOBuffer> dst_buffer,
+             int disk_cache_index,
+             uint64_t offset,
+             int bytes_to_read,
+             base::OnceCallback<void(int)> callback);
+
+    int GetSize(int disk_cache_index) const;
+
+    void PrintTo(::std::ostream* os) const;
 
     void Invalidate();
 
-    disk_cache::ScopedEntryPtr& entry() { return entry_; }
+    disk_cache::ScopedEntryPtr& disk_cache_entry() { return disk_cache_entry_; }
 
    private:
-    ~BlobDataHandle() override;
+    friend class base::RefCounted<DiskCacheBlobEntry>;
+    ~DiskCacheBlobEntry();
 
     base::WeakPtr<CacheStorageCacheEntryHandler> entry_handler_;
     base::Optional<CacheStorageCacheHandle> cache_handle_;
-    disk_cache::ScopedEntryPtr entry_;
+    disk_cache::ScopedEntryPtr disk_cache_entry_;
 
-    DISALLOW_COPY_AND_ASSIGN(BlobDataHandle);
+    DISALLOW_COPY_AND_ASSIGN(DiskCacheBlobEntry);
   };
 
-  scoped_refptr<BlobDataHandle> CreateBlobDataHandle(
+  scoped_refptr<DiskCacheBlobEntry> CreateDiskCacheBlobEntry(
       CacheStorageCacheHandle cache_handle,
-      disk_cache::ScopedEntryPtr entry);
+      disk_cache::ScopedEntryPtr disk_cache_entry);
 
   virtual ~CacheStorageCacheEntryHandler();
 
@@ -95,32 +114,46 @@
       blink::mojom::FetchAPIResponsePtr response,
       int64_t trace_id) = 0;
   virtual void PopulateResponseBody(
-      scoped_refptr<BlobDataHandle> data_handle,
+      scoped_refptr<DiskCacheBlobEntry> blob_entry,
       blink::mojom::FetchAPIResponse* response) = 0;
-  virtual void PopulateRequestBody(scoped_refptr<BlobDataHandle> data_handle,
+  virtual void PopulateRequestBody(scoped_refptr<DiskCacheBlobEntry> blob_entry,
                                    blink::mojom::FetchAPIRequest* request) = 0;
 
   static std::unique_ptr<CacheStorageCacheEntryHandler> CreateCacheEntryHandler(
       CacheStorageOwner owner,
       base::WeakPtr<storage::BlobStorageContext> blob_context);
 
-  void InvalidateBlobDataHandles();
-  void EraseBlobDataHandle(BlobDataHandle* handle);
+  void InvalidateDiskCacheBlobEntrys();
+  void EraseDiskCacheBlobEntry(DiskCacheBlobEntry* blob_entry);
 
  protected:
   CacheStorageCacheEntryHandler(
       base::WeakPtr<storage::BlobStorageContext> blob_context);
 
+  // Create a |BlobDataItem::DataHandle| for a |DiskCacheBlobEntry|
+  // where the data is stored in the given disk_cache index.
+  static scoped_refptr<storage::BlobDataItem::DataHandle> MakeDataHandle(
+      scoped_refptr<DiskCacheBlobEntry> blob_entry,
+      int disk_cache_index);
+
+  // Create a |BlobDataItem::DataHandle| for a |DiskCacheBlobEntry|
+  // where the main data and side data are stored in the given disk_cache
+  // indices.
+  static scoped_refptr<storage::BlobDataItem::DataHandle>
+  MakeDataHandleWithSideData(scoped_refptr<DiskCacheBlobEntry> blob_entry,
+                             int disk_cache_index,
+                             int side_data_disk_cache_index);
+
   base::WeakPtr<storage::BlobStorageContext> blob_context_;
 
   // Every subclass should provide its own implementation to avoid partial
   // destruction.
   virtual base::WeakPtr<CacheStorageCacheEntryHandler> GetWeakPtr() = 0;
 
-  // We keep track of the BlobDataHandle instances to allow us to invalidate
+  // We keep track of the DiskCacheBlobEntry instances to allow us to invalidate
   // them if the cache has to be deleted while there are still references to
   // data in it.
-  std::set<BlobDataHandle*> blob_data_handles_;
+  std::set<DiskCacheBlobEntry*> blob_entries_;
 
   DISALLOW_COPY_AND_ASSIGN(CacheStorageCacheEntryHandler);
 };
diff --git a/content/browser/cache_storage/cache_storage_cache_unittest.cc b/content/browser/cache_storage/cache_storage_cache_unittest.cc
index 23b82b2..a4e3515 100644
--- a/content/browser/cache_storage/cache_storage_cache_unittest.cc
+++ b/content/browser/cache_storage/cache_storage_cache_unittest.cc
@@ -239,8 +239,8 @@
   base::RunLoop loop;
   actual_blob->ReadSideData(base::BindLambdaForTesting(
       [&](const base::Optional<mojo_base::BigBuffer> data) {
-        ASSERT_TRUE(data);
-        output.append(data->data(), data->data() + data->size());
+        if (data)
+          output.append(data->data(), data->data() + data->size());
         loop.Quit();
       }));
   loop.Run();
diff --git a/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc b/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
index 43eeb5e9..0e51b9e 100644
--- a/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
+++ b/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
@@ -1159,11 +1159,11 @@
     return;
   }
 
-  auto data_handle = cache_entry_handler_->CreateBlobDataHandle(
+  auto blob_entry = cache_entry_handler_->CreateDiskCacheBlobEntry(
       CreateHandle(), std::move(entry));
 
   if (query_cache_context->query_types & QUERY_CACHE_ENTRIES)
-    match->entry = std::move(data_handle->entry());
+    match->entry = std::move(blob_entry->disk_cache_entry());
 
   if (query_cache_context->query_types & QUERY_CACHE_REQUESTS) {
     query_cache_context->estimated_out_bytes +=
@@ -1174,8 +1174,7 @@
       return;
     }
 
-    cache_entry_handler_->PopulateRequestBody(data_handle,
-                                              match->request.get());
+    cache_entry_handler_->PopulateRequestBody(blob_entry, match->request.get());
   } else {
     match->request.reset();
   }
@@ -1188,7 +1187,7 @@
           .Run(CacheStorageError::kErrorQueryTooLarge, nullptr);
       return;
     }
-    if (data_handle->entry()->GetDataSize(INDEX_RESPONSE_BODY) == 0) {
+    if (blob_entry->disk_cache_entry()->GetDataSize(INDEX_RESPONSE_BODY) == 0) {
       QueryCacheOpenNextEntry(std::move(query_cache_context));
       return;
     }
@@ -1201,7 +1200,7 @@
       return;
     }
 
-    cache_entry_handler_->PopulateResponseBody(data_handle,
+    cache_entry_handler_->PopulateResponseBody(blob_entry,
                                                match->response.get());
   } else if (!(query_cache_context->query_types &
                QUERY_CACHE_RESPONSES_NO_BODIES)) {
@@ -2199,7 +2198,7 @@
 
 void LegacyCacheStorageCache::GetSizeThenCloseDidGetSize(SizeCallback callback,
                                                          int64_t cache_size) {
-  cache_entry_handler_->InvalidateBlobDataHandles();
+  cache_entry_handler_->InvalidateDiskCacheBlobEntrys();
   CloseImpl(base::BindOnce(std::move(callback), cache_size));
 }
 
diff --git a/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc b/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc
index f38ece2..b48fe688 100644
--- a/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc
+++ b/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc
@@ -15,6 +15,7 @@
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/command_buffer/common/swap_buffers_complete_params.h"
 #include "services/viz/public/cpp/gpu/context_provider_command_buffer.h"
+#include "ui/gl/gl_enums.h"
 
 namespace content {
 
@@ -30,6 +31,8 @@
           context_provider_->ContextCapabilities()
               .use_gpu_fences_for_overlay_planes),
       gpu_fence_id_(0),
+      current_texture_(0u),
+      fbo_(0u),
       gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
       surface_handle_(surface_handle) {
   capabilities_.uses_default_gl_framebuffer = false;
@@ -43,16 +46,20 @@
   // implementation.
   capabilities_.max_frames_pending = 2;
 
+  auto* gl = context_provider_->ContextGL();
   buffer_queue_.reset(new viz::BufferQueue(
-      context_provider_->ContextGL(), format, gpu_memory_buffer_manager_,
-      surface_handle, context_provider_->ContextCapabilities()));
-  buffer_queue_->Initialize();
+      gl, format, gpu_memory_buffer_manager_, surface_handle,
+      context_provider_->ContextCapabilities()));
+  gl->GenFramebuffers(1, &fbo_);
 }
 
 GpuSurfacelessBrowserCompositorOutputSurface::
     ~GpuSurfacelessBrowserCompositorOutputSurface() {
+  auto* gl = context_provider_->ContextGL();
   if (gpu_fence_id_ > 0)
-    context_provider_->ContextGL()->DestroyGpuFenceCHROMIUM(gpu_fence_id_);
+    gl->DestroyGpuFenceCHROMIUM(gpu_fence_id_);
+  DCHECK_NE(0u, fbo_);
+  gl->DeleteFramebuffers(1, &fbo_);
 }
 
 bool GpuSurfacelessBrowserCompositorOutputSurface::IsDisplayedAsOverlayPlane()
@@ -62,7 +69,8 @@
 
 unsigned GpuSurfacelessBrowserCompositorOutputSurface::GetOverlayTextureId()
     const {
-  return buffer_queue_->GetCurrentTextureId();
+  DCHECK(current_texture_);
+  return current_texture_;
 }
 
 gfx::BufferFormat
@@ -87,8 +95,30 @@
 }
 
 void GpuSurfacelessBrowserCompositorOutputSurface::BindFramebuffer() {
+  auto* gl = context_provider_->ContextGL();
+  gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
   DCHECK(buffer_queue_);
-  buffer_queue_->BindFramebuffer();
+  unsigned stencil;
+  current_texture_ = buffer_queue_->GetCurrentBuffer(&stencil);
+  if (!current_texture_)
+    return;
+  // TODO(andrescj): if the texture hasn't changed since the last call to
+  // BindFrameBuffer(), we may be able to avoid mutating the FBO which may lead
+  // to performance improvements.
+  gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                           buffer_queue_->texture_target(), current_texture_,
+                           0);
+
+#if DCHECK_IS_ON() && defined(OS_CHROMEOS)
+  const GLenum result = gl->CheckFramebufferStatus(GL_FRAMEBUFFER);
+  if (result != GL_FRAMEBUFFER_COMPLETE)
+    DLOG(ERROR) << " Incomplete fb: " << gl::GLEnums::GetStringError(result);
+#endif
+
+  if (stencil) {
+    gl->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+                                GL_RENDERBUFFER, stencil);
+  }
 }
 
 GLenum GpuSurfacelessBrowserCompositorOutputSurface::
@@ -106,7 +136,15 @@
   GpuBrowserCompositorOutputSurface::Reshape(
       size, device_scale_factor, color_space, has_alpha, use_stencil);
   DCHECK(buffer_queue_);
-  buffer_queue_->Reshape(size, device_scale_factor, color_space, use_stencil);
+  if (buffer_queue_->Reshape(size, device_scale_factor, color_space,
+                             use_stencil)) {
+    auto* gl = context_provider_->ContextGL();
+    gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
+    gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                             buffer_queue_->texture_target(), 0, 0);
+    gl->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+                                GL_RENDERBUFFER, 0);
+  }
 }
 
 void GpuSurfacelessBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted(
@@ -119,7 +157,9 @@
     // Even through the swap failed, this is a fixable error so we can pretend
     // it succeeded to the rest of the system.
     modified_params.swap_response.result = gfx::SwapResult::SWAP_ACK;
-    buffer_queue_->RecreateBuffers();
+    unsigned current_surface_texture = buffer_queue_->RecreateBuffers();
+    if (current_surface_texture)
+      BindFramebuffer();
     force_swap = true;
   }
   buffer_queue_->PageFlipComplete();
@@ -133,10 +173,11 @@
   if (!use_gpu_fence_)
     return 0;
 
+  auto* gl = context_provider_->ContextGL();
   if (gpu_fence_id_ > 0)
-    context_provider_->ContextGL()->DestroyGpuFenceCHROMIUM(gpu_fence_id_);
+    gl->DestroyGpuFenceCHROMIUM(gpu_fence_id_);
 
-  gpu_fence_id_ = context_provider_->ContextGL()->CreateGpuFenceCHROMIUM();
+  gpu_fence_id_ = gl->CreateGpuFenceCHROMIUM();
 
   return gpu_fence_id_;
 }
diff --git a/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h b/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h
index d7bc2e04..49c1e62 100644
--- a/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h
+++ b/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h
@@ -5,6 +5,8 @@
 #ifndef CONTENT_BROWSER_COMPOSITOR_GPU_SURFACELESS_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_
 #define CONTENT_BROWSER_COMPOSITOR_GPU_SURFACELESS_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_
 
+#include <stdint.h>
+
 #include <memory>
 #include <vector>
 
@@ -59,6 +61,9 @@
   unsigned gpu_fence_id_;
 
   std::unique_ptr<viz::BufferQueue> buffer_queue_;
+  unsigned current_texture_;
+  uint32_t fbo_;
+
   gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_;
   gpu::SurfaceHandle surface_handle_;
 };
diff --git a/content/browser/devtools/protocol/tracing_handler.cc b/content/browser/devtools/protocol/tracing_handler.cc
index 5748f64..8349a1fc 100644
--- a/content/browser/devtools/protocol/tracing_handler.cc
+++ b/content/browser/devtools/protocol/tracing_handler.cc
@@ -42,6 +42,7 @@
 #include "content/browser/tracing/tracing_controller_impl.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/system_connector.h"
 #include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
 #include "services/tracing/public/cpp/perfetto/perfetto_config.h"
 #include "services/tracing/public/cpp/tracing_features.h"
@@ -305,8 +306,8 @@
     DCHECK(!tracing_active_);
     tracing_active_ = true;
 
-    ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
-        tracing::mojom::kServiceName, &consumer_host_);
+    GetSystemConnector()->BindInterface(tracing::mojom::kServiceName,
+                                        &consumer_host_);
 
     perfetto::TraceConfig perfetto_config =
         CreatePerfettoConfiguration(chrome_config);
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index ef9e5d6..89024db0 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -67,6 +67,7 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/resource_context.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents_delegate.h"
 #include "content/public/common/origin_util.h"
 #include "content/public/common/previews_state.h"
@@ -681,9 +682,7 @@
 
 service_manager::Connector* DownloadManagerImpl::GetServiceManagerConnector() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (auto* connection = ServiceManagerConnection::GetForProcess())
-    return connection->GetConnector();
-  return nullptr;
+  return GetSystemConnector();
 }
 
 void DownloadManagerImpl::StartDownload(
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 644e87e9..c205895 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -430,11 +430,43 @@
 }
 
 base::Optional<url::Origin> GetOriginForURLLoaderFactory(
-    GURL target_url,
-    SiteInstanceImpl* site_instance) {
+    NavigationRequest* navigation_request) {
+  // Return a safe unique origin when there is no |navigation_request| (e.g.
+  // when RFHI::CommitNavigation is called via RFHI::NavigateToInterstitialURL).
+  if (!navigation_request)
+    return url::Origin();
+
+  // GetOriginForURLLoaderFactory should only be called at the ready-to-commit
+  // time, when the RFHI and process to commit the navigation are already known.
+  DCHECK_LE(NavigationRequest::RESPONSE_STARTED, navigation_request->state());
+  RenderFrameHostImpl* target_frame = navigation_request->render_frame_host();
+
+  // Check if this is loadDataWithBaseUrl (which needs special treatment).
+  const CommonNavigationParams& common_params =
+      navigation_request->common_params();
+  if (common_params.url.SchemeIs(url::kDataScheme) &&
+      !common_params.base_url_for_data_url.is_empty()) {
+    // A (potentially attacker-controlled) renderer process should not be able
+    // to use loadDataWithBaseUrl code path to initiate fetches on behalf of a
+    // victim origin (fetches controlled by attacker-provided
+    // |common_params.url| data: URL in a victim's origin from the
+    // attacker-provided |common_params.base_url_for_data_url|).  Browser
+    // process should verify that |common_params.base_url_for_data_url| is empty
+    // for all renderer-initiated navigations (e.g. see
+    // VerifyBeginNavigationCommonParams), but as a defense-in-depth this is
+    // also asserted below.
+    CHECK(navigation_request->browser_initiated());
+
+    // loadDataWithBaseUrl submits a data: |common_params.url| (which has a
+    // unique origin), but commits that URL as if it came from
+    // |common_params.base_url_for_data_url|.  See also
+    // https://crbug.com/976253.
+    return url::Origin::Create(common_params.base_url_for_data_url);
+  }
+
   // TODO(lukasza, nasko): https://crbug.com/888079: Use exact origin, instead
   // of falling back to site URL for about:blank and about:srcdoc.
-  if (target_url.SchemeIs(url::kAboutScheme)) {
+  if (common_params.url.SchemeIs(url::kAboutScheme)) {
     // |site_instance|'s site URL cannot be used as
     // |request_initiator_site_lock| unless the site requires a dedicated
     // process.  Otherwise b.com may share a process associated with a.com, in
@@ -442,19 +474,19 @@
     // "http://nonisolated.invalid" in the future) and in that scenario
     // |request_initiator| for requests from b.com should NOT be locked to
     // a.com.
+    SiteInstanceImpl* site_instance = target_frame->GetSiteInstance();
     if (!SiteInstanceImpl::ShouldLockToOrigin(
             site_instance->GetIsolationContext(), site_instance->GetSiteURL()))
       return base::nullopt;
-
     return SiteInstanceImpl::GetRequestInitiatorSiteLock(
         site_instance->GetSiteURL());
   }
 
   // In cases not covered above, URLLoaderFactory should be associated with the
-  // origin of |target_url|.  This works fine for all URLs, including data: URLs
-  // (which should use an opaque origin for their subresource requests) and
-  // blob: URLs (which embed their origin inside the |target_url|).
-  return url::Origin::Create(target_url);
+  // origin of |common_params.url|.  This works fine for all URLs, including
+  // data: URLs (which should use an opaque origin for their subresource
+  // requests) and blob: URLs (which embed their origin inside the URL).
+  return url::Origin::Create(common_params.url);
 }
 
 std::unique_ptr<blink::URLLoaderFactoryBundleInfo> CloneFactoryBundle(
@@ -4842,8 +4874,7 @@
       recreate_default_url_loader_factory_after_network_service_crash_ = true;
       bool bypass_redirect_checks =
           CreateNetworkServiceDefaultFactoryAndObserve(
-              GetOriginForURLLoaderFactory(common_params.url,
-                                           GetSiteInstance()),
+              GetOriginForURLLoaderFactory(navigation_request),
               mojo::MakeRequest(&default_factory_info));
       subresource_loader_factories->set_bypass_redirect_checks(
           bypass_redirect_checks);
@@ -4907,7 +4938,7 @@
       GetContentClient()->browser()->WillCreateURLLoaderFactory(
           browser_context, this, GetProcess()->GetID(),
           false /* is_navigation */, false /* is_download */,
-          GetOriginForURLLoaderFactory(common_params.url, GetSiteInstance())
+          GetOriginForURLLoaderFactory(navigation_request)
               .value_or(url::Origin()),
           &factory_request, nullptr /* header_client */,
           nullptr /* bypass_redirect_checks */);
diff --git a/content/browser/generic_sensor/sensor_provider_proxy_impl.cc b/content/browser/generic_sensor/sensor_provider_proxy_impl.cc
index b67dfc7..5901ce6 100644
--- a/content/browser/generic_sensor/sensor_provider_proxy_impl.cc
+++ b/content/browser/generic_sensor/sensor_provider_proxy_impl.cc
@@ -13,8 +13,8 @@
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/permission_type.h"
 #include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/service_manager_connection.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -51,16 +51,15 @@
   }
 
   if (!sensor_provider_) {
-    auto* connection = ServiceManagerConnection::GetForProcess();
-
-    if (!connection) {
+    auto* connector = GetSystemConnector();
+    if (!connector) {
       std::move(callback).Run(SensorCreationResult::ERROR_NOT_AVAILABLE,
                               nullptr);
       return;
     }
 
-    connection->GetConnector()->BindInterface(
-        device::mojom::kServiceName, mojo::MakeRequest(&sensor_provider_));
+    connector->BindInterface(device::mojom::kServiceName,
+                             mojo::MakeRequest(&sensor_provider_));
     sensor_provider_.set_connection_error_handler(base::BindOnce(
         &SensorProviderProxyImpl::OnConnectionError, base::Unretained(this)));
   }
diff --git a/content/browser/geolocation/geolocation_service_impl_unittest.cc b/content/browser/geolocation/geolocation_service_impl_unittest.cc
index d4ee6f50..9f29a84c 100644
--- a/content/browser/geolocation/geolocation_service_impl_unittest.cc
+++ b/content/browser/geolocation/geolocation_service_impl_unittest.cc
@@ -10,7 +10,7 @@
 #include "content/browser/permissions/permission_controller_impl.h"
 #include "content/public/browser/permission_controller.h"
 #include "content/public/browser/permission_type.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/test/mock_permission_manager.h"
 #include "content/public/test/navigation_simulator.h"
 #include "content/public/test/test_browser_context.h"
@@ -91,10 +91,8 @@
     geolocation_overrider_ =
         std::make_unique<device::ScopedGeolocationOverrider>(kMockLatitude,
                                                              kMockLongitude);
-    service_manager::Connector* connector =
-        ServiceManagerConnection::GetForProcess()->GetConnector();
-    connector->BindInterface(device::mojom::kServiceName,
-                             mojo::MakeRequest(&context_ptr_));
+    GetSystemConnector()->BindInterface(device::mojom::kServiceName,
+                                        mojo::MakeRequest(&context_ptr_));
   }
 
   void TearDown() override {
diff --git a/content/browser/loader/cross_site_document_blocking_browsertest.cc b/content/browser/loader/cross_site_document_blocking_browsertest.cc
index 76f7816b..4721675c 100644
--- a/content/browser/loader/cross_site_document_blocking_browsertest.cc
+++ b/content/browser/loader/cross_site_document_blocking_browsertest.cc
@@ -643,7 +643,7 @@
   EXPECT_EQ("", interceptor.response_body());
 }
 
-IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest, BlockFetches) {
+IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest, AllowCorsFetches) {
   embedded_test_server()->StartAcceptingConnections();
   GURL foo_url("http://foo.com/cross_site_document_blocking/request.html");
   EXPECT_TRUE(NavigateToURL(shell(), foo_url));
@@ -672,6 +672,48 @@
   }
 }
 
+IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest,
+                       AllowSameOriginFetchFromLoadDataWithBaseUrl) {
+  embedded_test_server()->StartAcceptingConnections();
+
+  // LoadDataWithBaseURL is never subject to --site-per-process policy today
+  // (this API is only used by Android WebView [where OOPIFs have not shipped
+  // yet] and GuestView cases [which always hosts guests inside a renderer
+  // without an origin lock]).  Therefore, skip the test in --site-per-process
+  // mode to avoid renderer kills which won't happen in practice as described
+  // above.
+  //
+  // TODO(https://crbug.com/962643): Consider enabling this test once Android
+  // Webview or WebView guests support OOPIFs and/or origin locks.
+  if (AreAllSitesIsolatedForTesting())
+    return;
+
+  // Navigate via LoadDataWithBaseURL.
+  const GURL base_url("http://foo.com");
+  const std::string data = "<html><body>foo</body></html>";
+  const GURL data_url = GURL("data:text/html;charset=utf-8," + data);
+  TestNavigationObserver nav_observer(shell()->web_contents(), 1);
+  shell()->LoadDataWithBaseURL(base_url /* history_url */, data, base_url);
+  nav_observer.Wait();
+
+  // Fetch a same-origin resource.
+  GURL resource_url("http://foo.com/site_isolation/nosniff.html");
+  EXPECT_EQ(url::Origin::Create(resource_url),
+            shell()->web_contents()->GetMainFrame()->GetLastCommittedOrigin());
+  FetchHistogramsFromChildProcesses();
+  base::HistogramTester histograms;
+  std::string fetch_result =
+      EvalJs(shell(), JsReplace("fetch($1).then(response => response.text())",
+                                resource_url))
+          .ExtractString();
+  fetch_result = TrimWhitespaceASCII(fetch_result, base::TRIM_ALL).as_string();
+
+  // Verify that the response was not blocked.
+  EXPECT_EQ("runMe({ \"name\" : \"chromium\" });", fetch_result);
+  InspectHistograms(histograms, kShouldBeAllowedWithoutSniffing, "nosniff.html",
+                    ResourceType::kXhr);
+}
+
 // Regression test for https://crbug.com/958421.
 IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest, BackToAboutBlank) {
   embedded_test_server()->StartAcceptingConnections();
diff --git a/content/browser/loader/navigation_url_loader_impl_unittest.cc b/content/browser/loader/navigation_url_loader_impl_unittest.cc
index 23b754f4..3899f07 100644
--- a/content/browser/loader/navigation_url_loader_impl_unittest.cc
+++ b/content/browser/loader/navigation_url_loader_impl_unittest.cc
@@ -20,16 +20,15 @@
 #include "content/browser/web_package/prefetched_signed_exchange_cache.h"
 #include "content/common/navigation_params.h"
 #include "content/common/navigation_params.mojom.h"
-#include "content/common/service_manager/service_manager_connection_impl.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_ui_data.h"
 #include "content/public/browser/plugin_service.h"
 #include "content/public/browser/storage_partition.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/test/test_browser_context.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/test/test_navigation_url_loader_delegate.h"
@@ -131,15 +130,13 @@
       : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {
     feature_list_.InitAndEnableFeature(network::features::kNetworkService);
 
-    // Because the network service is enabled we need a ServiceManagerConnection
-    // or BrowserContext::GetDefaultStoragePartition will segfault when
+    // Because the network service is enabled we need a system Connector or
+    // BrowserContext::GetDefaultStoragePartition will segfault when
     // ContentBrowserClient::CreateNetworkContext tries to call
     // GetNetworkService.
-    service_manager::mojom::ServicePtr service;
-    ServiceManagerConnection::SetForProcess(
-        std::make_unique<ServiceManagerConnectionImpl>(
-            mojo::MakeRequest(&service),
-            base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})));
+    service_manager::mojom::ConnectorRequest connector_request;
+    SetSystemConnectorForTesting(
+        service_manager::Connector::Create(&connector_request));
 
     browser_context_.reset(new TestBrowserContext);
     http_test_server_.AddDefaultHandlers(
@@ -151,11 +148,8 @@
   }
 
   ~NavigationURLLoaderImplTest() override {
-    // The context needs to be deleted before ServiceManagerConnection is
-    // destroyed, so the storage partition in the context does not try to
-    // reconnect to the network service after ServiceManagerConnection is dead.
     browser_context_.reset();
-    ServiceManagerConnection::DestroyForProcess();
+    SetSystemConnectorForTesting(nullptr);
   }
 
   std::unique_ptr<NavigationURLLoader> CreateTestLoader(
diff --git a/content/browser/media/audible_metrics_unittest.cc b/content/browser/media/audible_metrics_unittest.cc
index 014f3dd..e9e9b0a 100644
--- a/content/browser/media/audible_metrics_unittest.cc
+++ b/content/browser/media/audible_metrics_unittest.cc
@@ -82,9 +82,8 @@
   base::HistogramTester histogram_tester_;
   base::UserActionTester user_action_tester_;
 
-  // WebContentsImpl accesses
-  // content::ServiceManagerConnection::GetForProcess(), so
-  // we must make sure it is instantiated.
+  // WebContentsImpl accesses the system Connector, so the Service Manager must
+  // be initialized.
   std::unique_ptr<content::TestServiceManagerContext>
       test_service_manager_context_;
 
diff --git a/content/browser/media/capture/desktop_capture_device.cc b/content/browser/media/capture/desktop_capture_device.cc
index 9a25c23..78988c0 100644
--- a/content/browser/media/capture/desktop_capture_device.cc
+++ b/content/browser/media/capture/desktop_capture_device.cc
@@ -30,8 +30,8 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/desktop_capture.h"
 #include "content/public/browser/desktop_media_id.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/content_switches.h"
-#include "content/public/common/service_manager_connection.h"
 #include "media/base/video_util.h"
 #include "media/capture/content/capture_resolution_chooser.h"
 #include "services/device/public/mojom/constants.mojom.h"
@@ -77,11 +77,8 @@
 std::unique_ptr<service_manager::Connector> GetServiceConnector() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  service_manager::Connector* connector =
-      ServiceManagerConnection::GetForProcess()->GetConnector();
-
-  DCHECK(connector);
-  return connector->Clone();
+  DCHECK(GetSystemConnector());
+  return GetSystemConnector()->Clone();
 }
 
 int GetMaximumCpuConsumptionPercentage() {
diff --git a/content/browser/media/capture/frame_sink_video_capture_device.cc b/content/browser/media/capture/frame_sink_video_capture_device.cc
index c6a10d3f..edb2b9e 100644
--- a/content/browser/media/capture/frame_sink_video_capture_device.cc
+++ b/content/browser/media/capture/frame_sink_video_capture_device.cc
@@ -21,7 +21,7 @@
 #include "content/browser/compositor/surface_utils.h"
 #include "content/browser/media/capture/mouse_cursor_overlay_controller.h"
 #include "content/public/browser/browser_task_traits.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "media/base/bind_to_current_loop.h"
 #include "media/capture/mojom/video_capture_types.mojom.h"
 #include "services/device/public/mojom/constants.mojom.h"
@@ -57,12 +57,9 @@
 std::unique_ptr<service_manager::Connector> MaybeGetServiceConnector() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  // In some testing contexts, the service manager connection isn't initialized.
-  if (auto* connection = ServiceManagerConnection::GetForProcess()) {
-    service_manager::Connector* connector = connection->GetConnector();
-    DCHECK(connector);
+  // In some testing environments, the system Connector isn't initialized.
+  if (auto* connector = GetSystemConnector())
     return connector->Clone();  // Clone for use on a different thread.
-  }
   return nullptr;
 }
 
diff --git a/content/browser/media/in_process_audio_loopback_stream_creator.cc b/content/browser/media/in_process_audio_loopback_stream_creator.cc
index 12b51f3..981c0edc 100644
--- a/content/browser/media/in_process_audio_loopback_stream_creator.cc
+++ b/content/browser/media/in_process_audio_loopback_stream_creator.cc
@@ -17,7 +17,7 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_frame_host.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "media/audio/audio_device_description.h"
 #include "media/base/user_input_monitor.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
@@ -100,9 +100,7 @@
                    ? static_cast<media::UserInputMonitorBase*>(
                          BrowserMainLoop::GetInstance()->user_input_monitor())
                    : nullptr,
-               content::ServiceManagerConnection::GetForProcess()
-                   ->GetConnector()
-                   ->Clone(),
+               content::GetSystemConnector()->Clone(),
                AudioStreamBrokerFactory::CreateImpl()) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 }
diff --git a/content/browser/media/media_interface_proxy.cc b/content/browser/media/media_interface_proxy.cc
index 53ac65c8d..2e8b743 100644
--- a/content/browser/media/media_interface_proxy.cc
+++ b/content/browser/media/media_interface_proxy.cc
@@ -15,8 +15,8 @@
 #include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/content_client.h"
-#include "content/public/common/service_manager_connection.h"
 #include "media/mojo/buildflags.h"
 #include "media/mojo/interfaces/cdm_proxy.mojom.h"
 #include "media/mojo/interfaces/constants.mojom.h"
@@ -297,9 +297,8 @@
   media::mojom::MediaServicePtr media_service;
 
   // TODO(slan): Use the BrowserContext Connector instead. See crbug.com/638950.
-  service_manager::Connector* connector =
-      ServiceManagerConnection::GetForProcess()->GetConnector();
-  connector->BindInterface(media::mojom::kMediaServiceName, &media_service);
+  GetSystemConnector()->BindInterface(media::mojom::kMediaServiceName,
+                                      &media_service);
 
   media_service->CreateInterfaceFactory(
       MakeRequest(&interface_factory_ptr_),
@@ -361,13 +360,11 @@
   DCHECK(!cdm_factory_map_.count(cdm_guid));
 
   // TODO(slan): Use the BrowserContext Connector instead. See crbug.com/638950.
-  service_manager::Connector* connector =
-      ServiceManagerConnection::GetForProcess()->GetConnector();
-
   media::mojom::CdmServicePtr cdm_service;
-  connector->BindInterface(service_manager::ServiceFilter::ByNameWithId(
-                               media::mojom::kCdmServiceName, cdm_guid),
-                           &cdm_service);
+  GetSystemConnector()->BindInterface(
+      service_manager::ServiceFilter::ByNameWithId(
+          media::mojom::kCdmServiceName, cdm_guid),
+      &cdm_service);
 
 #if defined(OS_MACOSX)
   // LoadCdm() should always be called before CreateInterfaceFactory().
diff --git a/content/browser/media/media_internals_audio_focus_helper.cc b/content/browser/media/media_internals_audio_focus_helper.cc
index 5399809..31dc7ed 100644
--- a/content/browser/media/media_internals_audio_focus_helper.cc
+++ b/content/browser/media/media_internals_audio_focus_helper.cc
@@ -14,8 +14,8 @@
 #include "content/browser/media/media_internals.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_ui.h"
-#include "content/public/common/service_manager_connection.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "services/media_session/public/mojom/constants.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -104,13 +104,8 @@
   if (!enabled_)
     return false;
 
-  // |connection| and |connector| may be nullptr in some tests.
-  ServiceManagerConnection* connection =
-      ServiceManagerConnection::GetForProcess();
-  if (!connection)
-    return false;
-
-  service_manager::Connector* connector = connection->GetConnector();
+  // |connector| may be nullptr in some tests.
+  service_manager::Connector* connector = GetSystemConnector();
   if (!connector)
     return false;
 
diff --git a/content/browser/media/media_internals_unittest.cc b/content/browser/media/media_internals_unittest.cc
index cb9ce20..d1a59c6a 100644
--- a/content/browser/media/media_internals_unittest.cc
+++ b/content/browser/media/media_internals_unittest.cc
@@ -16,7 +16,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "content/browser/media/session/media_session_impl.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_renderer_host.h"
 #include "content/public/test/test_service_manager_context.h"
@@ -341,9 +341,8 @@
                             base::Unretained(this));
     run_loop_ = std::make_unique<base::RunLoop>();
 
-    content::ServiceManagerConnection::GetForProcess()
-        ->GetConnector()
-        ->BindInterface(media_session::mojom::kServiceName, &audio_focus_ptr_);
+    content::GetSystemConnector()->BindInterface(
+        media_session::mojom::kServiceName, &audio_focus_ptr_);
 
     content::MediaInternals::GetInstance()->AddUpdateCallback(update_cb_);
   }
diff --git a/content/browser/media/session/audio_focus_delegate_default.cc b/content/browser/media/session/audio_focus_delegate_default.cc
index ff75f216..311a83c 100644
--- a/content/browser/media/session/audio_focus_delegate_default.cc
+++ b/content/browser/media/session/audio_focus_delegate_default.cc
@@ -10,7 +10,7 @@
 #include "build/build_config.h"
 #include "content/browser/media/session/media_session_impl.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "media/base/media_switches.h"
 #include "services/media_session/public/cpp/features.h"
 #include "services/media_session/public/mojom/audio_focus.mojom.h"
@@ -182,10 +182,8 @@
   audio_focus_ptr_.reset();
 
   // Connect to the Media Session service and bind |audio_focus_ptr_| to it.
-  service_manager::Connector* connector =
-      ServiceManagerConnection::GetForProcess()->GetConnector();
-  connector->BindInterface(media_session::mojom::kServiceName,
-                           mojo::MakeRequest(&audio_focus_ptr_));
+  GetSystemConnector()->BindInterface(media_session::mojom::kServiceName,
+                                      mojo::MakeRequest(&audio_focus_ptr_));
 
   audio_focus_ptr_->SetSourceName(kAudioFocusSourceName);
 }
diff --git a/content/browser/media/session/audio_focus_delegate_default_browsertest.cc b/content/browser/media/session/audio_focus_delegate_default_browsertest.cc
index 81b7121..e65673f 100644
--- a/content/browser/media/session/audio_focus_delegate_default_browsertest.cc
+++ b/content/browser/media/session/audio_focus_delegate_default_browsertest.cc
@@ -9,7 +9,7 @@
 #include "build/build_config.h"
 #include "content/browser/media/session/media_session_impl.h"
 #include "content/browser/media/session/mock_media_session_player_observer.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/test/content_browser_test.h"
 #include "content/shell/browser/shell.h"
 #include "media/base/media_content_type.h"
@@ -36,10 +36,8 @@
   void SetUpOnMainThread() override {
     ContentBrowserTest::SetUpOnMainThread();
 
-    service_manager::Connector* connector =
-        ServiceManagerConnection::GetForProcess()->GetConnector();
-    connector->BindInterface(media_session::mojom::kServiceName,
-                             mojo::MakeRequest(&audio_focus_ptr_));
+    GetSystemConnector()->BindInterface(media_session::mojom::kServiceName,
+                                        mojo::MakeRequest(&audio_focus_ptr_));
   }
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
diff --git a/content/browser/media/session/media_session_impl_unittest.cc b/content/browser/media/session/media_session_impl_unittest.cc
index 4b122ec..4880f1e 100644
--- a/content/browser/media/session/media_session_impl_unittest.cc
+++ b/content/browser/media/session/media_session_impl_unittest.cc
@@ -12,7 +12,7 @@
 #include "content/browser/media/session/media_session_player_observer.h"
 #include "content/browser/media/session/mock_media_session_player_observer.h"
 #include "content/browser/media/session/mock_media_session_service_impl.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/test/test_renderer_host.h"
 #include "content/public/test/test_service_manager_context.h"
 #include "media/base/media_content_type.h"
@@ -96,10 +96,8 @@
 
     // Connect to the Media Session service and bind |audio_focus_ptr_| to it.
     service_manager_context_ = std::make_unique<TestServiceManagerContext>();
-    service_manager::Connector* connector =
-        ServiceManagerConnection::GetForProcess()->GetConnector();
-    connector->BindInterface(media_session::mojom::kServiceName,
-                             mojo::MakeRequest(&audio_focus_ptr_));
+    GetSystemConnector()->BindInterface(media_session::mojom::kServiceName,
+                                        mojo::MakeRequest(&audio_focus_ptr_));
   }
 
   void TearDown() override {
diff --git a/content/browser/media/video_decoder_proxy.cc b/content/browser/media/video_decoder_proxy.cc
index ef825a53..6c25154 100644
--- a/content/browser/media/video_decoder_proxy.cc
+++ b/content/browser/media/video_decoder_proxy.cc
@@ -6,7 +6,7 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "media/mojo/interfaces/constants.mojom.h"
 #include "media/mojo/interfaces/media_service.mojom.h"
 #include "media/mojo/interfaces/renderer_extensions.mojom.h"
@@ -93,9 +93,8 @@
   media::mojom::MediaServicePtr media_service;
   // TODO(slan): Use the BrowserContext Connector instead.
   // See https://crbug.com/638950.
-  service_manager::Connector* connector =
-      ServiceManagerConnection::GetForProcess()->GetConnector();
-  connector->BindInterface(media::mojom::kMediaServiceName, &media_service);
+  GetSystemConnector()->BindInterface(media::mojom::kMediaServiceName,
+                                      &media_service);
 
   // TODO(sandersd): Do we need to bind an empty |interfaces| implementation?
   service_manager::mojom::InterfaceProviderPtr interfaces;
diff --git a/content/browser/network_service_browsertest.cc b/content/browser/network_service_browsertest.cc
index 92a3ad30..6508151 100644
--- a/content/browser/network_service_browsertest.cc
+++ b/content/browser/network_service_browsertest.cc
@@ -11,6 +11,7 @@
 #include "content/browser/storage_partition_impl.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/network_service_instance.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/url_data_source.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -19,7 +20,6 @@
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/network_service_util.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/common/url_utils.h"
 #include "content/public/test/browser_test_utils.h"
@@ -347,8 +347,8 @@
     return;
 
   network::mojom::NetworkServiceTestPtr network_service_test;
-  ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
-      mojom::kNetworkServiceName, &network_service_test);
+  GetSystemConnector()->BindInterface(mojom::kNetworkServiceName,
+                                      &network_service_test);
   // TODO(crbug.com/901026): Make sure the network process is started to avoid a
   // deadlock on Android.
   network_service_test.FlushForTesting();
@@ -376,8 +376,8 @@
     return;
 
   network::mojom::NetworkServiceTestPtr network_service_test;
-  ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
-      mojom::kNetworkServiceName, &network_service_test);
+  GetSystemConnector()->BindInterface(mojom::kNetworkServiceName,
+                                      &network_service_test);
   network::mojom::NetworkServiceTestPtrInfo network_service_test_info =
       network_service_test.PassInterface();
 
@@ -405,8 +405,8 @@
     return;
 
   network::mojom::NetworkServiceTestPtr network_service_test;
-  ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
-      mojom::kNetworkServiceName, &network_service_test);
+  GetSystemConnector()->BindInterface(mojom::kNetworkServiceName,
+                                      &network_service_test);
   network_service_test->CrashOnGetCookieList();
 
   NavigateToURL(shell(), embedded_test_server()->GetURL("/empty.html"));
diff --git a/content/browser/network_service_instance_impl.cc b/content/browser/network_service_instance_impl.cc
index 7c7cfc6..9304b41d 100644
--- a/content/browser/network_service_instance_impl.cc
+++ b/content/browser/network_service_instance_impl.cc
@@ -25,8 +25,8 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/network_service_instance.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/network_service_util.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
 #include "net/log/net_log_util.h"
 #include "services/network/network_service.h"
@@ -123,9 +123,9 @@
 network::mojom::NetworkService* GetNetworkService() {
   service_manager::Connector* connector = nullptr;
   if (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
-      ServiceManagerConnection::GetForProcess() &&  // null in unit tests.
+      GetSystemConnector() &&  // null in unit tests.
       !g_force_create_network_service_directly) {
-    connector = ServiceManagerConnection::GetForProcess()->GetConnector();
+    connector = GetSystemConnector();
   }
   return GetNetworkServiceFromConnector(connector);
 }
diff --git a/content/browser/network_service_restart_browsertest.cc b/content/browser/network_service_restart_browsertest.cc
index 59ba0a17..6396a449 100644
--- a/content/browser/network_service_restart_browsertest.cc
+++ b/content/browser/network_service_restart_browsertest.cc
@@ -24,6 +24,7 @@
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/network_service_instance.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/network_service_util.h"
@@ -1136,16 +1137,16 @@
     return;
   network::mojom::NetworkServiceTestPtr network_service_test;
   base::RunLoop run_loop;
-  ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
-      mojom::kNetworkServiceName, &network_service_test);
+  GetSystemConnector()->BindInterface(mojom::kNetworkServiceName,
+                                      &network_service_test);
 
   // Crash the network service, but do not wait for full startup.
   network_service_test.set_connection_error_handler(run_loop.QuitClosure());
   network_service_test->SimulateCrash();
   run_loop.Run();
 
-  ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
-      mojom::kNetworkServiceName, &network_service_test);
+  GetSystemConnector()->BindInterface(mojom::kNetworkServiceName,
+                                      &network_service_test);
 
   // Sync call should be fine, even though network process is still starting up.
   mojo::ScopedAllowSyncCallForTesting allow_sync_call;
diff --git a/content/browser/picture_in_picture/picture_in_picture_session.cc b/content/browser/picture_in_picture/picture_in_picture_session.cc
index 74a817c..06e7062 100644
--- a/content/browser/picture_in_picture/picture_in_picture_session.cc
+++ b/content/browser/picture_in_picture/picture_in_picture_session.cc
@@ -28,11 +28,7 @@
   binding_.set_connection_error_handler(base::BindOnce(
       &PictureInPictureSession::OnConnectionError, base::Unretained(this)));
 
-  // TODO(mlamouri): figure out why this can be null and have the method return
-  // a const ref.
-  auto* controller = GetController();
-  if (controller)
-    controller->SetActiveSession(this);
+  GetController().SetActiveSession(this);
 
   // TODO(beccahughes): Pass PictureInPictureResult::kNotSupported back to
   // Blink.
@@ -40,11 +36,9 @@
                                                             natural_size);
   DCHECK_EQ(PictureInPictureResult::kSuccess, result);
 
-  if (controller) {
-    controller->SetAlwaysHidePlayPauseButton(show_play_pause_button);
-    controller->SetAlwaysHideMuteButton(show_mute_button);
-    *window_size = controller->GetSize();
-  }
+  GetController().SetAlwaysHidePlayPauseButton(show_play_pause_button);
+  GetController().SetAlwaysHideMuteButton(show_mute_button);
+  *window_size = GetController().GetSize();
 }
 
 PictureInPictureSession::~PictureInPictureSession() {
@@ -63,14 +57,10 @@
     bool show_mute_button) {
   player_id_ = MediaPlayerId(service_->render_frame_host_, player_id);
 
-  // The PictureInPictureWindowController instance may not have been created by
-  // the embedder.
-  if (auto* pip_controller = GetController()) {
-    pip_controller->EmbedSurface(surface_id.value(), natural_size);
-    pip_controller->SetAlwaysHidePlayPauseButton(show_play_pause_button);
-    pip_controller->SetAlwaysHideMuteButton(show_mute_button);
-    pip_controller->SetActiveSession(this);
-  }
+  GetController().EmbedSurface(surface_id.value(), natural_size);
+  GetController().SetAlwaysHidePlayPauseButton(show_play_pause_button);
+  GetController().SetAlwaysHideMuteButton(show_mute_button);
+  GetController().SetActiveSession(this);
 }
 
 void PictureInPictureSession::NotifyWindowResized(const gfx::Size& size) {
@@ -98,8 +88,7 @@
   else
     observer_->OnStopped();
 
-  if (auto* controller = GetController())
-    controller->SetActiveSession(nullptr);
+  GetController().SetActiveSession(nullptr);
 
   // Reset must happen after everything is done as it will destroy |this|.
   service_->active_session_.reset();
@@ -114,8 +103,8 @@
   return static_cast<WebContentsImpl*>(service_->web_contents());
 }
 
-PictureInPictureWindowControllerImpl* PictureInPictureSession::GetController() {
-  return PictureInPictureWindowControllerImpl::GetOrCreateForWebContents(
+PictureInPictureWindowControllerImpl& PictureInPictureSession::GetController() {
+  return *PictureInPictureWindowControllerImpl::GetOrCreateForWebContents(
       GetWebContentsImpl());
 }
 
diff --git a/content/browser/picture_in_picture/picture_in_picture_session.h b/content/browser/picture_in_picture/picture_in_picture_session.h
index 7d34db7..6cdeb36 100644
--- a/content/browser/picture_in_picture/picture_in_picture_session.h
+++ b/content/browser/picture_in_picture/picture_in_picture_session.h
@@ -68,9 +68,9 @@
   // session. It relies on the WebContents associated with the |service_|.
   WebContentsImpl* GetWebContentsImpl();
 
-  // Returns the PictureInPictureWindowControllerImpl associated with the
-  // WebContents. Can be null.
-  PictureInPictureWindowControllerImpl* GetController();
+  // Returns the Picture-in-Picture window controller associated with the
+  // session.
+  PictureInPictureWindowControllerImpl& GetController();
 
   // Owns |this|.
   PictureInPictureServiceImpl* service_;
diff --git a/content/browser/portal/portal.cc b/content/browser/portal/portal.cc
index 9bd9cf7..63f5099 100644
--- a/content/browser/portal/portal.cc
+++ b/content/browser/portal/portal.cc
@@ -11,11 +11,11 @@
 #include "base/memory/ptr_util.h"
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/devtools/devtools_instrumentation.h"
+#include "content/browser/frame_host/navigator.h"
 #include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/browser/frame_host/render_frame_host_manager.h"
 #include "content/browser/frame_host/render_frame_proxy_host.h"
 #include "content/browser/web_contents/web_contents_impl.h"
-#include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/web_contents_delegate.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/referrer_type_converters.h"
@@ -178,12 +178,22 @@
     return;
   }
 
-  // TODO(lfg): Investigate which other restrictions we might need when
-  // navigating portals. See http://crbug.com/964395.
+  GURL out_validated_url = url;
+  owner_render_frame_host_->GetSiteInstance()->GetProcess()->FilterURL(
+      false, &out_validated_url);
 
-  NavigationController::LoadURLParams load_url_params(url);
-  load_url_params.referrer = mojo::ConvertTo<Referrer>(referrer);
-  portal_contents_impl_->GetController().LoadURLWithParams(load_url_params);
+  FrameTreeNode* portal_root = portal_contents_impl_->GetFrameTree()->root();
+  RenderFrameHostImpl* portal_frame = portal_root->current_frame_host();
+
+  // TODO(lfg): Figure out download policies for portals.
+  // https://github.com/WICG/portals/issues/150
+  NavigationDownloadPolicy download_policy;
+
+  portal_root->navigator()->NavigateFromFrameProxy(
+      portal_frame, url, owner_render_frame_host_->GetLastCommittedOrigin(),
+      owner_render_frame_host_->GetSiteInstance(),
+      mojo::ConvertTo<Referrer>(referrer), ui::PAGE_TRANSITION_LINK, false,
+      download_policy, "GET", nullptr, "", nullptr, false);
 }
 
 void Portal::Activate(blink::TransferableMessage data,
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc
index 76d2278..67ed6291 100644
--- a/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -52,6 +52,7 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents_media_capture_id.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_features.h"
@@ -551,16 +552,9 @@
 #endif
 
     if (base::FeatureList::IsEnabled(features::kMojoVideoCapture)) {
-      auto* service_manager_connection =
-          content::ServiceManagerConnection::GetForProcess();
       video_capture_provider = std::make_unique<VideoCaptureProviderSwitcher>(
           std::make_unique<ServiceVideoCaptureProvider>(
-              // There are test cases (e.g.
-              // AudioOutputAuthorizationHandlerTest.DoNothing), where no
-              // service_manager_connection is available.
-              service_manager_connection
-                  ? service_manager_connection->GetConnector()
-                  : nullptr,
+              GetSystemConnector(),
               base::BindRepeating(&SendVideoCaptureLogMessage)),
           InProcessVideoCaptureProvider::CreateInstanceForNonDeviceCapture(
               std::move(device_task_runner),
@@ -580,9 +574,9 @@
   InitializeMaybeAsync(std::move(video_capture_provider));
 
   // May be null in tests.
-  if (ServiceManagerConnection::GetForProcess()) {
-    audio_service_listener_ = std::make_unique<AudioServiceListener>(
-        ServiceManagerConnection::GetForProcess()->GetConnector()->Clone());
+  if (GetSystemConnector()) {
+    audio_service_listener_ =
+        std::make_unique<AudioServiceListener>(GetSystemConnector()->Clone());
   }
 
   base::PowerMonitor::AddObserver(this);
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 11f802d..fcbe860 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -162,6 +162,7 @@
 #include "content/public/browser/render_widget_host_iterator.h"
 #include "content/public/browser/resource_context.h"
 #include "content/public/browser/site_isolation_policy.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/webrtc_log.h"
 #include "content/public/common/bind_interface_helpers.h"
 #include "content/public/common/child_process_host.h"
@@ -721,9 +722,7 @@
 void ForwardRequest(const char* service_name,
                     mojo::InterfaceRequest<Interface> request) {
   // TODO(beng): This should really be using the per-profile connector.
-  service_manager::Connector* connector =
-      ServiceManagerConnection::GetForProcess()->GetConnector();
-  connector->BindInterface(service_name, std::move(request));
+  GetSystemConnector()->BindInterface(service_name, std::move(request));
 }
 
 class RenderProcessHostIsReadyObserver : public RenderProcessHostObserver {
@@ -1770,15 +1769,17 @@
     // Note that some embedders (e.g. Android WebView) may not initialize a
     // Connector per BrowserContext. In those cases we fall back to the
     // browser-wide Connector.
-    if (!ServiceManagerConnection::GetForProcess()) {
-      // Additionally, some test code may not initialize the process-wide
-      // ServiceManagerConnection prior to this point. This class of test code
-      // doesn't care about render processes, so we can initialize a dummy
-      // connection.
+    connector = GetSystemConnector();
+    if (!connector && !ServiceManagerConnection::GetForProcess()) {
+      // Additionally, some test code may not initialize the system Connector.
+      // We initialize one that the ChildConnection below can use.
+      // TODO(crbug.com/904240): Figure out why some unit tests fail when this
+      // doesn't create a full ServiceManagerConnection.
+      service_manager::mojom::ServicePtr unused_service;
       ServiceManagerConnection::SetForProcess(ServiceManagerConnection::Create(
-          mojo::MakeRequest(&test_service_), io_task_runner));
+          mojo::MakeRequest(&unused_service), io_task_runner));
+      connector = ServiceManagerConnection::GetForProcess()->GetConnector();
     }
-    connector = ServiceManagerConnection::GetForProcess()->GetConnector();
   }
 
   // Establish a ServiceManager connection for the new render service instance.
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h
index da7d3ca..88b217b 100644
--- a/content/browser/renderer_host/render_process_host_impl.h
+++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -692,7 +692,6 @@
   int connection_filter_id_ =
       ServiceManagerConnection::kInvalidConnectionFilterId;
   scoped_refptr<ConnectionFilterController> connection_filter_controller_;
-  service_manager::mojom::ServicePtr test_service_;
 
   size_t keep_alive_ref_count_;
 
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 482d38b..5227bc8 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -124,7 +124,7 @@
 
 #if defined(OS_MACOSX)
 #include "content/browser/renderer_host/input/fling_scheduler_mac.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/device/public/mojom/wake_lock_provider.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -3000,15 +3000,11 @@
   // Here is a lazy binding, and will not reconnect after connection error.
   if (!wake_lock_) {
     device::mojom::WakeLockRequest request = mojo::MakeRequest(&wake_lock_);
-    // In some testing contexts, the service manager connection isn't
-    // initialized.
-    if (ServiceManagerConnection::GetForProcess()) {
-      service_manager::Connector* connector =
-          ServiceManagerConnection::GetForProcess()->GetConnector();
-      DCHECK(connector);
+    // In some testing contexts, the system Connector isn't3 initialized.
+    if (GetSystemConnector()) {
       device::mojom::WakeLockProviderPtr wake_lock_provider;
-      connector->BindInterface(device::mojom::kServiceName,
-                               mojo::MakeRequest(&wake_lock_provider));
+      GetSystemConnector()->BindInterface(
+          device::mojom::kServiceName, mojo::MakeRequest(&wake_lock_provider));
       wake_lock_provider->GetWakeLockWithoutContext(
           device::mojom::WakeLockType::kPreventDisplaySleep,
           device::mojom::WakeLockReason::kOther, "GetSnapshot",
diff --git a/content/browser/service_manager/service_manager_context.cc b/content/browser/service_manager/service_manager_context.cc
index 377a9584..559c3bd 100644
--- a/content/browser/service_manager/service_manager_context.cc
+++ b/content/browser/service_manager/service_manager_context.cc
@@ -19,6 +19,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "base/no_destructor.h"
+#include "base/optional.h"
 #include "base/process/process_handle.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
@@ -31,6 +32,7 @@
 #include "content/browser/child_process_launcher.h"
 #include "content/browser/gpu/gpu_process_host.h"
 #include "content/browser/service_manager/common_browser_interfaces.h"
+#include "content/browser/system_connector_impl.h"
 #include "content/browser/utility_process_host.h"
 #include "content/browser/wake_lock/wake_lock_context_host.h"
 #include "content/common/service_manager/service_manager_connection_impl.h"
@@ -69,6 +71,7 @@
 #include "services/network/public/cpp/cross_thread_shared_url_loader_factory_info.h"
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/mojom/network_service_test.mojom.h"
+#include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h"
 #include "services/resource_coordinator/public/mojom/service_constants.mojom.h"
 #include "services/resource_coordinator/resource_coordinator_service.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -160,8 +163,9 @@
 class ContentChildServiceProcessHost
     : public service_manager::ServiceProcessHost {
  public:
-  explicit ContentChildServiceProcessHost(bool run_in_gpu_process)
-      : run_in_gpu_process_(run_in_gpu_process) {}
+  ContentChildServiceProcessHost(bool run_in_gpu_process,
+                                 base::Optional<int> child_flags)
+      : run_in_gpu_process_(run_in_gpu_process), child_flags_(child_flags) {}
   ~ContentChildServiceProcessHost() override = default;
 
   // service_manager::ServiceProcessHost:
@@ -200,6 +204,8 @@
     process_host->SetMetricsName(identity.name());
     process_host->SetServiceIdentity(identity);
     process_host->SetSandboxType(sandbox_type);
+    if (child_flags_.has_value())
+      process_host->set_child_flags(child_flags_.value());
     process_host->Start();
     process_host->RunService(
         identity.name(), std::move(receiver),
@@ -214,6 +220,7 @@
 
  private:
   const bool run_in_gpu_process_;
+  const base::Optional<int> child_flags_;
   DISALLOW_COPY_AND_ASSIGN(ContentChildServiceProcessHost);
 };
 
@@ -450,13 +457,23 @@
     // TODO(crbug.com/895615): Package these services in content_gpu instead
     // of using this hack.
     bool run_in_gpu_process = false;
+    base::Optional<int> child_flags;
 #if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
     if (identity.name() == media::mojom::kMediaServiceName)
       run_in_gpu_process = true;
 #endif
     if (identity.name() == shape_detection::mojom::kServiceName)
       run_in_gpu_process = true;
-    return std::make_unique<ContentChildServiceProcessHost>(run_in_gpu_process);
+#if defined(OS_MACOSX)
+    // The proxy_resolver service runs V8, so it needs to run in the helper
+    // application that has the com.apple.security.cs.allow-jit code signing
+    // entitlement, which is CHILD_RENDERER. The service still runs under the
+    // utility process sandbox.
+    if (identity.name() == proxy_resolver::mojom::kProxyResolverServiceName)
+      child_flags = ChildProcessHost::CHILD_RENDERER;
+#endif
+    return std::make_unique<ContentChildServiceProcessHost>(run_in_gpu_process,
+                                                            child_flags);
   }
 
   std::unique_ptr<service_manager::ServiceProcessHost>
@@ -618,6 +635,7 @@
       system_remote.InitWithNewPipeAndPassReceiver(),
       service_manager_thread_task_runner_));
   auto* system_connection = ServiceManagerConnection::GetForProcess();
+  SetSystemConnector(system_connection->GetConnector()->Clone());
 
   RegisterInProcessService(
       resource_coordinator::mojom::kServiceName,
diff --git a/content/browser/service_manager/service_manager_context_browsertest.cc b/content/browser/service_manager/service_manager_context_browsertest.cc
index 8f753d45..b853867 100644
--- a/content/browser/service_manager/service_manager_context_browsertest.cc
+++ b/content/browser/service_manager/service_manager_context_browsertest.cc
@@ -12,7 +12,7 @@
 #include "base/test/launcher/test_launcher.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/test/content_browser_test.h"
 #include "content/public/test/test_launcher.h"
 #include "content/shell/browser/shell_content_browser_client.h"
@@ -103,9 +103,7 @@
 
   // Launch a test service.
   echo::mojom::EchoPtr echo_ptr;
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(echo::mojom::kServiceName, &echo_ptr);
+  GetSystemConnector()->BindInterface(echo::mojom::kServiceName, &echo_ptr);
 
   base::RunLoop loop;
   // Terminate the service. Browser should exit in response with an error.
@@ -150,8 +148,7 @@
   service_manager::mojom::ServiceManagerListenerPtr listener_proxy;
   ServiceInstanceListener listener(mojo::MakeRequest(&listener_proxy));
 
-  auto* connector = ServiceManagerConnection::GetForProcess()->GetConnector();
-
+  auto* connector = GetSystemConnector();
   service_manager::mojom::ServiceManagerPtr service_manager;
   connector->BindInterface(service_manager::mojom::kServiceName,
                            &service_manager);
diff --git a/content/browser/speech/tts_controller_impl.cc b/content/browser/speech/tts_controller_impl.cc
index bf5d302..99bd75f1 100644
--- a/content/browser/speech/tts_controller_impl.cc
+++ b/content/browser/speech/tts_controller_impl.cc
@@ -17,7 +17,7 @@
 #include "base/values.h"
 #include "build/build_config.h"
 #include "content/public/browser/content_browser_client.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "services/data_decoder/public/cpp/safe_xml_parser.h"
 #include "services/data_decoder/public/mojom/constants.mojom.h"
 #include "services/data_decoder/public/mojom/xml_parser.mojom.h"
@@ -493,15 +493,9 @@
     return;
   }
 
-  // Get ServiceManagerConnection and Connector.
-  ServiceManagerConnection* service_manager_connection =
-      ServiceManagerConnection::GetForProcess();
-  CHECK(service_manager_connection);
-  service_manager::Connector* connector =
-      service_manager_connection->GetConnector();
-  CHECK(connector);
-
   // Parse using safe, out-of-process Xml Parser.
+  service_manager::Connector* connector = GetSystemConnector();
+  DCHECK(connector);
   data_decoder::ParseXml(connector, utterance,
                          base::BindOnce(&TtsControllerImpl::StripSSMLHelper,
                                         utterance, std::move(on_ssml_parsed)));
diff --git a/content/browser/system_connector_impl.cc b/content/browser/system_connector_impl.cc
index 7cbacd2..5ecc0868 100644
--- a/content/browser/system_connector_impl.cc
+++ b/content/browser/system_connector_impl.cc
@@ -41,8 +41,10 @@
 
 service_manager::Connector* GetSystemConnector() {
   auto& storage = GetConnectorStorage();
-  if (BrowserThread::CurrentlyOn(BrowserThread::UI))
+  if (!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
+      BrowserThread::CurrentlyOn(BrowserThread::UI)) {
     return storage.GetValuePointer();
+  }
 
   if (!storage) {
     mojo::PendingRemote<service_manager::mojom::Connector> remote;
@@ -57,6 +59,10 @@
 }
 
 void SetSystemConnector(std::unique_ptr<service_manager::Connector> connector) {
+  if (!connector) {
+    GetConnectorStorage().reset();
+    return;
+  }
   mojo::PendingRemote<service_manager::mojom::Connector> remote;
   connector->BindConnectorRequest(remote.InitWithNewPipeAndPassReceiver());
   GetConnectorStorage().emplace(std::move(remote));
diff --git a/content/browser/tracing/background_tracing_active_scenario.cc b/content/browser/tracing/background_tracing_active_scenario.cc
index 30f66f89..f51917ee 100644
--- a/content/browser/tracing/background_tracing_active_scenario.cc
+++ b/content/browser/tracing/background_tracing_active_scenario.cc
@@ -16,7 +16,7 @@
 #include "content/browser/tracing/background_tracing_manager_impl.h"
 #include "content/browser/tracing/background_tracing_rule.h"
 #include "content/browser/tracing/tracing_controller_impl.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/system/data_pipe_drainer.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -84,8 +84,8 @@
     }
 #endif
 
-    ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
-        tracing::mojom::kServiceName, &consumer_host_);
+    GetSystemConnector()->BindInterface(tracing::mojom::kServiceName,
+                                        &consumer_host_);
 
     perfetto::TraceConfig perfetto_config = tracing::GetDefaultPerfettoConfig(
         chrome_config, /*privacy_filtering_enabled=*/true);
diff --git a/content/browser/tracing/perfetto_file_tracer.cc b/content/browser/tracing/perfetto_file_tracer.cc
index 2f2f3f7..3aa3e8b 100644
--- a/content/browser/tracing/perfetto_file_tracer.cc
+++ b/content/browser/tracing/perfetto_file_tracer.cc
@@ -14,7 +14,7 @@
 #include "base/threading/scoped_blocking_call.h"
 #include "components/tracing/common/trace_startup_config.h"
 #include "components/tracing/common/tracing_switches.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "mojo/public/cpp/system/data_pipe_drainer.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/tracing/public/cpp/perfetto/perfetto_config.h"
@@ -86,8 +86,8 @@
           {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
            base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
       background_drainer_(background_task_runner_) {
-  ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
-      tracing::mojom::kServiceName, &consumer_host_);
+  GetSystemConnector()->BindInterface(tracing::mojom::kServiceName,
+                                      &consumer_host_);
 
   const auto& chrome_config =
       tracing::TraceStartupConfig::GetInstance()->GetTraceConfig();
diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc
index b5c09bbc..50e34fea 100644
--- a/content/browser/tracing/tracing_controller_impl.cc
+++ b/content/browser/tracing/tracing_controller_impl.cc
@@ -1,6 +1,7 @@
 // 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/browser/tracing/tracing_controller_impl.h"
 
 #include <memory>
@@ -29,10 +30,10 @@
 #include "content/browser/tracing/tracing_ui.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/tracing_controller.h"
 #include "content/public/browser/tracing_delegate.h"
 #include "content/public/common/content_client.h"
-#include "content/public/common/service_manager_connection.h"
 #include "gpu/config/gpu_info.h"
 #include "mojo/public/cpp/system/data_pipe.h"
 #include "net/base/network_change_notifier.h"
@@ -228,8 +229,8 @@
 
 void TracingControllerImpl::ConnectToServiceIfNeeded() {
   if (!coordinator_) {
-    ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
-        tracing::mojom::kServiceName, &coordinator_);
+    GetSystemConnector()->BindInterface(tracing::mojom::kServiceName,
+                                        &coordinator_);
     coordinator_.set_connection_error_handler(base::BindOnce(
         [](TracingControllerImpl* controller) {
           controller->coordinator_.reset();
diff --git a/content/browser/wake_lock/wake_lock_context_host.cc b/content/browser/wake_lock/wake_lock_context_host.cc
index 8ebbaa6..e5088822e 100644
--- a/content/browser/wake_lock/wake_lock_context_host.cc
+++ b/content/browser/wake_lock/wake_lock_context_host.cc
@@ -6,7 +6,7 @@
 
 #include "base/atomic_sequence_num.h"
 #include "base/lazy_instance.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/device/public/mojom/wake_lock_provider.mojom.h"
@@ -33,11 +33,9 @@
   g_id_to_context_host.Get()[id_] = this;
 
   // Connect to a WakeLockContext, associating it with |id_| (note that in some
-  // testing contexts, the service manager connection isn't initialized).
-  if (ServiceManagerConnection::GetForProcess()) {
-    service_manager::Connector* connector =
-        ServiceManagerConnection::GetForProcess()->GetConnector();
-    DCHECK(connector);
+  // testing environments, the system Connector isn't initialized.
+  service_manager::Connector* connector = GetSystemConnector();
+  if (connector) {
     device::mojom::WakeLockProviderPtr wake_lock_provider;
     connector->BindInterface(device::mojom::kServiceName,
                              mojo::MakeRequest(&wake_lock_provider));
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 970def0..becc966 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -122,6 +122,7 @@
 #include "content/public/browser/security_style_explanations.h"
 #include "content/public/browser/ssl_status.h"
 #include "content/public/browser/storage_partition.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents_binding_set.h"
 #include "content/public/browser/web_contents_delegate.h"
 #include "content/public/browser/web_ui_controller.h"
@@ -134,7 +135,6 @@
 #include "content/public/common/page_zoom.h"
 #include "content/public/common/referrer_type_converters.h"
 #include "content/public/common/result_codes.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/common/url_utils.h"
 #include "content/public/common/web_preferences.h"
 #include "media/base/user_input_monitor.h"
@@ -3210,12 +3210,9 @@
     return geolocation_context_.get();
 
   auto request = mojo::MakeRequest(&geolocation_context_);
-  if (!ServiceManagerConnection::GetForProcess())
-    return geolocation_context_.get();
-
-  service_manager::Connector* connector =
-      ServiceManagerConnection::GetForProcess()->GetConnector();
-  connector->BindInterface(device::mojom::kServiceName, std::move(request));
+  service_manager::Connector* connector = GetSystemConnector();
+  if (connector)
+    connector->BindInterface(device::mojom::kServiceName, std::move(request));
   return geolocation_context_.get();
 }
 
@@ -6067,11 +6064,28 @@
 }
 
 void WebContentsImpl::ForSecurityDropFullscreen() {
-  WebContentsImpl* web_contents = this;
+  // There are two chains of WebContents to kick out of fullscreen.
+  //
+  // Chain 1, the inner/outer WebContents chain. If an inner WebContents has
+  // done something that requires the browser to drop fullscreen, drop
+  // fullscreen from it and any outer WebContents that may be in fullscreen.
+  //
+  // Chain 2, the opener WebContents chain. If a WebContents has done something
+  // that requires the browser to drop fullscreen, drop fullscreen from any
+  // WebContents that was involved in the chain of opening it.
+  //
+  // Note that these two chains don't interact, as only a top-level WebContents
+  // can have an opener. This simplifies things.
+
+  WebContents* web_contents = this;
   while (web_contents) {
     if (web_contents->IsFullscreenForCurrentTab())
       web_contents->ExitFullscreen(true);
-    web_contents = web_contents->GetOuterWebContents();
+
+    if (web_contents->HasOriginalOpener())
+      web_contents = FromRenderFrameHost(web_contents->GetOriginalOpener());
+    else
+      web_contents = web_contents->GetOuterWebContents();
   }
 }
 
@@ -6885,10 +6899,7 @@
             ? static_cast<media::UserInputMonitorBase*>(
                   BrowserMainLoop::GetInstance()->user_input_monitor())
             : nullptr,
-        content::ServiceManagerConnection::GetForProcess()
-            ->GetConnector()
-            ->Clone(),
-        AudioStreamBrokerFactory::CreateImpl());
+        GetSystemConnector()->Clone(), AudioStreamBrokerFactory::CreateImpl());
   }
 
   return &*audio_stream_factory_;
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index 100bfcc..67e8c17 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -1941,6 +1941,8 @@
 
   std::string last_message() { return last_message_; }
 
+  WebContents* last_popup() { return popup_.get(); }
+
   // WebContentsDelegate
 
   JavaScriptDialogManager* GetJavaScriptDialogManager(
@@ -2633,6 +2635,38 @@
   EXPECT_FALSE(wc->IsFullscreenForCurrentTab());
 }
 
+// Tests that if a popup is opened, all WebContentses down the opener chain are
+// kicked out of fullscreen.
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+                       PopupsOfPopupsFromJavaScriptEndFullscreen) {
+  WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
+  TestWCDelegateForDialogsAndFullscreen test_delegate(wc);
+
+  GURL url("about:blank");
+  EXPECT_TRUE(NavigateToURL(shell(), url));
+
+  // Make a popup.
+  std::string popup_script = "window.open('', '', 'width=200,height=100')";
+  test_delegate.WillWaitForNewContents();
+  EXPECT_TRUE(content::ExecuteScript(wc, popup_script));
+  test_delegate.Wait();
+  WebContentsImpl* popup =
+      static_cast<WebContentsImpl*>(test_delegate.last_popup());
+
+  // Put the original page into fullscreen.
+  wc->EnterFullscreenMode(url, blink::WebFullscreenOptions());
+  EXPECT_TRUE(wc->IsFullscreenForCurrentTab());
+
+  // Have the popup open a popup.
+  TestWCDelegateForDialogsAndFullscreen popup_test_delegate(popup);
+  popup_test_delegate.WillWaitForNewContents();
+  EXPECT_TRUE(content::ExecuteScript(popup, popup_script));
+  popup_test_delegate.Wait();
+
+  // Ensure the original page, being in the opener chain, loses fullscreen.
+  EXPECT_FALSE(wc->IsFullscreenForCurrentTab());
+}
+
 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
                        FocusFromJavaScriptEndsFullscreen) {
   WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
diff --git a/content/browser/webauth/authenticator_common.cc b/content/browser/webauth/authenticator_common.cc
index e46ee6c0..626b7fc 100644
--- a/content/browser/webauth/authenticator_common.cc
+++ b/content/browser/webauth/authenticator_common.cc
@@ -29,12 +29,12 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/origin_util.h"
-#include "content/public/common/service_manager_connection.h"
 #include "crypto/sha2.h"
 #include "device/base/features.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
@@ -760,7 +760,7 @@
       FROM_HERE, options->adjusted_timeout,
       base::BindOnce(&AuthenticatorCommon::OnTimeout, base::Unretained(this)));
   if (!connector_)
-    connector_ = ServiceManagerConnection::GetForProcess()->GetConnector();
+    connector_ = GetSystemConnector();
 
   // Save client data to return with the authenticator response.
   // TODO(kpaulhamus): Fetch and add the Channel ID/Token Binding ID public key
@@ -922,7 +922,7 @@
       base::BindOnce(&AuthenticatorCommon::OnTimeout, base::Unretained(this)));
 
   if (!connector_)
-    connector_ = ServiceManagerConnection::GetForProcess()->GetConnector();
+    connector_ = GetSystemConnector();
 
   ctap_get_assertion_request_ = CreateCtapGetAssertionRequest(
       client_data_json_, std::move(options), app_id_,
diff --git a/content/browser/webrtc/webrtc_content_browsertest_base.cc b/content/browser/webrtc/webrtc_content_browsertest_base.cc
index d13dc9b..61672cc 100644
--- a/content/browser/webrtc/webrtc_content_browsertest_base.cc
+++ b/content/browser/webrtc/webrtc_content_browsertest_base.cc
@@ -11,8 +11,8 @@
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/content_switches.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
@@ -121,10 +121,7 @@
 bool WebRtcContentBrowserTestBase::HasAudioOutputDevices() {
   bool has_devices = false;
   base::RunLoop run_loop;
-  auto audio_system = audio::CreateAudioSystem(
-      content::ServiceManagerConnection::GetForProcess()
-          ->GetConnector()
-          ->Clone());
+  auto audio_system = audio::CreateAudioSystem(GetSystemConnector()->Clone());
   audio_system->HasOutputDevices(base::BindOnce(
       [](base::Closure finished_callback, bool* result, bool received) {
         *result = received;
diff --git a/content/browser/webrtc/webrtc_getusermedia_browsertest.cc b/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
index 71d0b37d..10ab3d4 100644
--- a/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
+++ b/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
@@ -17,9 +17,9 @@
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/browser/webrtc/webrtc_content_browsertest_base.h"
 #include "content/browser/webrtc/webrtc_internals.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
@@ -866,12 +866,10 @@
 
   ExecuteJavascriptAndWaitForOk("setUpForAudioServiceCrash()");
 
-  // Crash the utility process for the audio service
-  service_manager::Connector* connector =
-      ServiceManagerConnection::GetForProcess()->GetConnector();
+  // Crash the audio service process.
   audio::mojom::TestingApiPtr service_testing_api;
-  connector->BindInterface(audio::mojom::kServiceName,
-                           mojo::MakeRequest(&service_testing_api));
+  GetSystemConnector()->BindInterface(audio::mojom::kServiceName,
+                                      mojo::MakeRequest(&service_testing_api));
   service_testing_api->Crash();
 
   ExecuteJavascriptAndWaitForOk("verifyAfterAudioServiceCrash()");
diff --git a/content/browser/webrtc/webrtc_internals.cc b/content/browser/webrtc/webrtc_internals.cc
index eca0ad3..eae73aa7 100644
--- a/content/browser/webrtc/webrtc_internals.cc
+++ b/content/browser/webrtc/webrtc_internals.cc
@@ -21,10 +21,10 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/webrtc_event_logger.h"
 #include "content/public/common/content_switches.h"
-#include "content/public/common/service_manager_connection.h"
 #include "ipc/ipc_platform_file.h"
 #include "media/audio/audio_debug_recording_session.h"
 #include "media/audio/audio_manager.h"
@@ -567,10 +567,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(!audio_debug_recording_session_);
   audio_debug_recording_session_ = audio::CreateAudioDebugRecordingSession(
-      audio_debug_recordings_file_path_,
-      content::ServiceManagerConnection::GetForProcess()
-          ->GetConnector()
-          ->Clone());
+      audio_debug_recordings_file_path_, GetSystemConnector()->Clone());
 
   for (RenderProcessHost::iterator i(
            content::RenderProcessHost::AllHostsIterator());
@@ -640,12 +637,9 @@
   // Here is a lazy binding, and will not reconnect after connection error.
   if (!wake_lock_) {
     device::mojom::WakeLockRequest request = mojo::MakeRequest(&wake_lock_);
-    // In some testing contexts, the service manager connection isn't
-    // initialized.
-    if (ServiceManagerConnection::GetForProcess()) {
-      service_manager::Connector* connector =
-          ServiceManagerConnection::GetForProcess()->GetConnector();
-      DCHECK(connector);
+    // In some testing environments, the system Connector isn't initialized.
+    service_manager::Connector* connector = GetSystemConnector();
+    if (connector) {
       device::mojom::WakeLockProviderPtr wake_lock_provider;
       connector->BindInterface(device::mojom::kServiceName,
                                mojo::MakeRequest(&wake_lock_provider));
diff --git a/content/browser/webrtc/webrtc_video_capture_browsertest.cc b/content/browser/webrtc/webrtc_video_capture_browsertest.cc
index a9eb78c..03ad9fb 100644
--- a/content/browser/webrtc/webrtc_video_capture_browsertest.cc
+++ b/content/browser/webrtc/webrtc_video_capture_browsertest.cc
@@ -7,10 +7,10 @@
 #include "build/build_config.h"
 #include "content/browser/webrtc/webrtc_webcam_browsertest.h"
 #include "content/public/browser/browser_child_process_host.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/child_process_host.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
@@ -80,11 +80,9 @@
   ASSERT_EQ("OK", result);
 
   // Simulate crash in video capture process
-  service_manager::Connector* connector =
-      ServiceManagerConnection::GetForProcess()->GetConnector();
   video_capture::mojom::TestingControlsPtr service_controls;
-  connector->BindInterface(video_capture::mojom::kServiceName,
-                           mojo::MakeRequest(&service_controls));
+  GetSystemConnector()->BindInterface(video_capture::mojom::kServiceName,
+                                      mojo::MakeRequest(&service_controls));
   service_controls->Crash();
 
   // Wait for video element to turn black
diff --git a/content/browser/webrtc/webrtc_video_capture_service_browsertest.cc b/content/browser/webrtc/webrtc_video_capture_service_browsertest.cc
index e7228848..9619ff9 100644
--- a/content/browser/webrtc/webrtc_video_capture_service_browsertest.cc
+++ b/content/browser/webrtc/webrtc_video_capture_service_browsertest.cc
@@ -10,9 +10,9 @@
 #include "cc/base/math_util.h"
 #include "components/viz/common/gpu/context_provider.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test.h"
 #include "content/public/test/content_browser_test_utils.h"
@@ -502,9 +502,7 @@
     DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
     main_task_runner_ = base::ThreadTaskRunnerHandle::Get();
 
-    auto* connection = content::ServiceManagerConnection::GetForProcess();
-    ASSERT_TRUE(connection);
-    auto* connector = connection->GetConnector();
+    auto* connector = GetSystemConnector();
     ASSERT_TRUE(connector);
     // We need to clone it so that we can use the clone on a different thread.
     connector_ = connector->Clone();
diff --git a/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc b/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc
index c4d58eb..7a991574 100644
--- a/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc
+++ b/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc
@@ -6,9 +6,9 @@
 #include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test.h"
 #include "content/public/test/content_browser_test_utils.h"
@@ -219,9 +219,7 @@
     NavigateToURL(shell(),
                   GURL(embedded_test_server()->GetURL(kVideoCaptureHtmlFile)));
 
-    auto* connection = content::ServiceManagerConnection::GetForProcess();
-    ASSERT_TRUE(connection);
-    auto* connector = connection->GetConnector();
+    auto* connector = GetSystemConnector();
     ASSERT_TRUE(connector);
     connector_ = connector->Clone();
   }
diff --git a/content/browser/webrtc/webrtc_video_capture_shared_device_browsertest.cc b/content/browser/webrtc/webrtc_video_capture_shared_device_browsertest.cc
index bb47bd4..f056db9 100644
--- a/content/browser/webrtc/webrtc_video_capture_shared_device_browsertest.cc
+++ b/content/browser/webrtc/webrtc_video_capture_shared_device_browsertest.cc
@@ -6,9 +6,9 @@
 #include "base/run_loop.h"
 #include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test.h"
 #include "content/public/test/content_browser_test_utils.h"
@@ -127,9 +127,7 @@
     DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
     main_task_runner_ = base::ThreadTaskRunnerHandle::Get();
 
-    auto* connection = content::ServiceManagerConnection::GetForProcess();
-    ASSERT_TRUE(connection);
-    auto* connector = connection->GetConnector();
+    auto* connector = GetSystemConnector();
     ASSERT_TRUE(connector);
     // We need to clone it so that we can use the clone on a different thread.
     connector_ = connector->Clone();
diff --git a/content/public/test/browser_test_base.cc b/content/public/test/browser_test_base.cc
index cea58d9..201fce5 100644
--- a/content/public/test/browser_test_base.cc
+++ b/content/public/test/browser_test_base.cc
@@ -40,11 +40,11 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/network_service_instance.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/main_function_params.h"
 #include "content/public/common/network_service_util.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/no_renderer_crashes_assertion.h"
@@ -469,8 +469,8 @@
   CHECK(!IsInProcessNetworkService())
       << "Can't crash the network service if it's running in-process!";
   network::mojom::NetworkServiceTestPtr network_service_test;
-  ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
-      mojom::kNetworkServiceName, &network_service_test);
+  GetSystemConnector()->BindInterface(mojom::kNetworkServiceName,
+                                      &network_service_test);
 
   base::RunLoop run_loop{base::RunLoop::Type::kNestableTasksAllowed};
   network_service_test.set_connection_error_handler(run_loop.QuitClosure());
@@ -671,8 +671,8 @@
     return;
 
   network::mojom::NetworkServiceTestPtr network_service_test;
-  ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
-      mojom::kNetworkServiceName, &network_service_test);
+  GetSystemConnector()->BindInterface(mojom::kNetworkServiceName,
+                                      &network_service_test);
 
   // Send the DNS rules to network service process. Android needs the RunLoop
   // to dispatch a Java callback that makes network process to enter native
diff --git a/content/public/test/content_mock_cert_verifier.cc b/content/public/test/content_mock_cert_verifier.cc
index 232b5523..59242e2 100644
--- a/content/public/test/content_mock_cert_verifier.cc
+++ b/content/public/test/content_mock_cert_verifier.cc
@@ -5,9 +5,9 @@
 #include "content/public/test/content_mock_cert_verifier.h"
 
 #include "base/command_line.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/network_service_util.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/network_service_test_helper.h"
@@ -73,8 +73,8 @@
 void ContentMockCertVerifier::CertVerifier::
     EnsureNetworkServiceTestInitialized() {
   if (!network_service_test_) {
-    ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
-        mojom::kNetworkServiceName, &network_service_test_);
+    GetSystemConnector()->BindInterface(mojom::kNetworkServiceName,
+                                        &network_service_test_);
   }
   // TODO(crbug.com/901026): Make sure the network process is started to avoid a
   // deadlock on Android.
diff --git a/content/public/test/network_connection_change_simulator.cc b/content/public/test/network_connection_change_simulator.cc
index d55d5852..b52de8d2 100644
--- a/content/public/test/network_connection_change_simulator.cc
+++ b/content/public/test/network_connection_change_simulator.cc
@@ -9,8 +9,8 @@
 #include "base/bind.h"
 #include "base/run_loop.h"
 #include "content/public/browser/network_service_instance.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/network_service_util.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
 #include "net/base/network_change_notifier.h"
 #include "services/network/public/mojom/network_service_test.mojom.h"
@@ -94,8 +94,8 @@
     network::mojom::ConnectionType type) {
   if (IsOutOfProcessNetworkService()) {
     network::mojom::NetworkServiceTestPtr network_service_test;
-    ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface(
-        mojom::kNetworkServiceName, &network_service_test);
+    GetSystemConnector()->BindInterface(mojom::kNetworkServiceName,
+                                        &network_service_test);
     base::RunLoop run_loop(kRunLoopType);
     network_service_test->SimulateNetworkChange(type, run_loop.QuitClosure());
     run_loop.Run();
diff --git a/content/public/test/test_utils.cc b/content/public/test/test_utils.cc
index 73a636f..200324b 100644
--- a/content/public/test/test_utils.cc
+++ b/content/public/test/test_utils.cc
@@ -22,7 +22,6 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "build/build_config.h"
-#include "components/variations/variations_params_manager.h"
 #include "content/browser/frame_host/render_frame_host_delegate.h"
 #include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/common/url_schemes.h"
@@ -214,23 +213,6 @@
          host;
 }
 
-void DeprecatedEnableFeatureWithParam(const base::Feature& feature,
-                                      const std::string& param_name,
-                                      const std::string& param_value,
-                                      base::CommandLine* command_line) {
-  static const char kFakeTrialName[] = "TrialNameForTesting";
-  static const char kFakeTrialGroupName[] = "TrialGroupForTesting";
-
-  // Enable all the |feature|, associating them with |trial_name|.
-  command_line->AppendSwitchASCII(
-      switches::kEnableFeatures,
-      std::string(feature.name) + "<" + kFakeTrialName);
-
-  std::map<std::string, std::string> param_values = {{param_name, param_value}};
-  variations::testing::VariationParamsManager::AppendVariationParams(
-      kFakeTrialName, kFakeTrialGroupName, param_values, command_line);
-}
-
 WebContents* CreateAndAttachInnerContents(RenderFrameHost* rfh) {
   WebContents* outer_contents =
       static_cast<RenderFrameHostImpl*>(rfh)->delegate()->GetAsWebContents();
diff --git a/content/public/test/test_utils.h b/content/public/test/test_utils.h
index 90a6784..f86541a 100644
--- a/content/public/test/test_utils.h
+++ b/content/public/test/test_utils.h
@@ -32,7 +32,6 @@
 namespace base {
 class CommandLine;
 class Value;
-struct Feature;
 }  // namespace base
 
 // A collection of functions designed for use with unit and browser tests.
@@ -112,19 +111,6 @@
 // Returns a string constructed from the WebUI scheme and the given host.
 std::string GetWebUIURLString(const std::string& host);
 
-// Appends command line switches to |command_line| to enable the |feature| and
-// to set field trial params associated with the feature as specified by
-// |param_name| and |param_value|.
-//
-// Note that a dummy trial and trial group will be registered behind the scenes.
-// See also variations::testing::VariationsParamsManager class.
-// This method is deprecated because we want to unify the FeatureList change to
-// ScopedFeatureList. See crbug.com/713390
-void DeprecatedEnableFeatureWithParam(const base::Feature& feature,
-                                      const std::string& param_name,
-                                      const std::string& param_value,
-                                      base::CommandLine* command_line);
-
 // Creates a WebContents and attaches it as an inner WebContents, replacing
 // |rfh| in the frame tree. |rfh| should not be a main frame (in a browser test,
 // it should be an <iframe>). Delegate interfaces are mocked out.
diff --git a/content/renderer/render_thread_impl_browsertest.cc b/content/renderer/render_thread_impl_browsertest.cc
index 05b242e..3e38e1b 100644
--- a/content/renderer/render_thread_impl_browsertest.cc
+++ b/content/renderer/render_thread_impl_browsertest.cc
@@ -31,10 +31,10 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/renderer/content_renderer_client.h"
 #include "content/public/test/content_browser_test.h"
@@ -173,8 +173,7 @@
         service_manager::Identity(mojom::kRendererServiceName,
                                   service_manager::kSystemInstanceGroup,
                                   base::Token{}, base::Token::CreateRandom()),
-        &invitation, ServiceManagerConnection::GetForProcess()->GetConnector(),
-        io_task_runner);
+        &invitation, GetSystemConnector(), io_task_runner);
 
     mojo::MessagePipe pipe;
     child_connection_->BindInterface(IPC::mojom::ChannelBootstrap::Name_,
diff --git a/docs/mojo_and_services.md b/docs/mojo_and_services.md
index 492d62314..1de450b 100644
--- a/docs/mojo_and_services.md
+++ b/docs/mojo_and_services.md
@@ -617,9 +617,9 @@
 the browser process. Somewhere in `src/chrome/browser`, we can write:
 
 ``` cpp
-// This gives us the global content_browser's Connector
-service_manager::Connector* connector =
-    content::ServiceManagerConnection::GetForProcess()->GetConnector();
+// This gives us the system Connector for the browser process, which has access
+// to most service interfaces.
+service_manager::Connector* connector = content::GetSystemConnector();
 
 // Recall from the earlier Mojo section that mojo::MakeRequest creates a new
 // message pipe for our interface. Connector passes the request endpoint to
diff --git a/extensions/browser/api/declarative_net_request/file_sequence_helper.cc b/extensions/browser/api/declarative_net_request/file_sequence_helper.cc
index 5475c9e..b5b11be 100644
--- a/extensions/browser/api/declarative_net_request/file_sequence_helper.cc
+++ b/extensions/browser/api/declarative_net_request/file_sequence_helper.cc
@@ -15,7 +15,7 @@
 #include "base/task/post_task.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/browser/api/declarative_net_request/constants.h"
 #include "extensions/browser/api/declarative_net_request/parse_info.h"
 #include "extensions/browser/api/declarative_net_request/utils.h"
@@ -350,10 +350,7 @@
 LoadRequestData& LoadRequestData::operator=(LoadRequestData&&) = default;
 
 FileSequenceHelper::FileSequenceHelper()
-    : connector_(content::ServiceManagerConnection::GetForProcess()
-                     ->GetConnector()
-                     ->Clone()),
-      weak_factory_(this) {}
+    : connector_(content::GetSystemConnector()->Clone()), weak_factory_(this) {}
 
 FileSequenceHelper::~FileSequenceHelper() {
   DCHECK(GetExtensionFileTaskRunner()->RunsTasksInCurrentSequence());
diff --git a/extensions/browser/api/device_permissions_prompt.cc b/extensions/browser/api/device_permissions_prompt.cc
index c49c413..f28fa32 100644
--- a/extensions/browser/api/device_permissions_prompt.cc
+++ b/extensions/browser/api/device_permissions_prompt.cc
@@ -15,7 +15,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/browser/api/device_permissions_manager.h"
 #include "extensions/browser/api/usb/usb_device_manager.h"
 #include "extensions/common/extension.h"
@@ -214,10 +214,8 @@
     }
 
     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-    DCHECK(content::ServiceManagerConnection::GetForProcess());
-
-    service_manager::Connector* connector =
-        content::ServiceManagerConnection::GetForProcess()->GetConnector();
+    service_manager::Connector* connector = content::GetSystemConnector();
+    DCHECK(connector);
     connector->BindInterface(device::mojom::kServiceName,
                              mojo::MakeRequest(&hid_manager_));
 
diff --git a/extensions/browser/api/hid/hid_device_manager.cc b/extensions/browser/api/hid/hid_device_manager.cc
index 672d07c..e3cc1d3 100644
--- a/extensions/browser/api/hid/hid_device_manager.cc
+++ b/extensions/browser/api/hid/hid_device_manager.cc
@@ -18,7 +18,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/browser/api/device_permissions_manager.h"
 #include "extensions/common/permissions/permissions_data.h"
 #include "extensions/common/permissions/usb_device_permission.h"
@@ -286,9 +286,8 @@
     device::mojom::HidManagerRequest request = mojo::MakeRequest(&hid_manager_);
 
     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-    DCHECK(content::ServiceManagerConnection::GetForProcess());
-    auto* connector =
-        content::ServiceManagerConnection::GetForProcess()->GetConnector();
+    auto* connector = content::GetSystemConnector();
+    DCHECK(connector);
     connector->BindInterface(device::mojom::kServiceName, std::move(request));
   }
   // Enumerate HID devices and set client.
diff --git a/extensions/browser/api/power/power_api.cc b/extensions/browser/api/power/power_api.cc
index 264aa90..6e1e888 100644
--- a/extensions/browser/api/power/power_api.cc
+++ b/extensions/browser/api/power/power_api.cc
@@ -8,7 +8,7 @@
 #include "base/bind_helpers.h"
 #include "base/lazy_instance.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/api/power.h"
 #include "extensions/common/extension.h"
@@ -157,9 +157,8 @@
 
   device::mojom::WakeLockRequest request = mojo::MakeRequest(&wake_lock_);
 
-  DCHECK(content::ServiceManagerConnection::GetForProcess());
-  auto* connector =
-      content::ServiceManagerConnection::GetForProcess()->GetConnector();
+  auto* connector = content::GetSystemConnector();
+  DCHECK(connector);
   device::mojom::WakeLockProviderPtr wake_lock_provider;
   connector->BindInterface(device::mojom::kServiceName,
                            mojo::MakeRequest(&wake_lock_provider));
diff --git a/extensions/browser/api/serial/serial_port_manager.cc b/extensions/browser/api/serial/serial_port_manager.cc
index 85a8507..67f27da0 100644
--- a/extensions/browser/api/serial/serial_port_manager.cc
+++ b/extensions/browser/api/serial/serial_port_manager.cc
@@ -11,7 +11,7 @@
 #include "base/task/post_task.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/browser/api/serial/serial_connection.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extensions_browser_client.h"
@@ -176,11 +176,9 @@
     return;
 
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  DCHECK(content::ServiceManagerConnection::GetForProcess());
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(device::mojom::kServiceName,
-                      mojo::MakeRequest(&port_manager_));
+  DCHECK(content::GetSystemConnector());
+  content::GetSystemConnector()->BindInterface(
+      device::mojom::kServiceName, mojo::MakeRequest(&port_manager_));
   port_manager_.set_connection_error_handler(
       base::BindOnce(&SerialPortManager::OnPortManagerConnectionError,
                      weak_factory_.GetWeakPtr()));
diff --git a/extensions/browser/api/sockets_tcp/sockets_tcp_apitest.cc b/extensions/browser/api/sockets_tcp/sockets_tcp_apitest.cc
index 9f672f3..89455ad5 100644
--- a/extensions/browser/api/sockets_tcp/sockets_tcp_apitest.cc
+++ b/extensions/browser/api/sockets_tcp/sockets_tcp_apitest.cc
@@ -7,9 +7,9 @@
 #include "base/command_line.h"
 #include "base/memory/ref_counted.h"
 #include "base/strings/stringprintf.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/test/network_service_test_helper.h"
 #include "extensions/browser/api/sockets_tcp/sockets_tcp_api.h"
@@ -23,7 +23,6 @@
 #include "mojo/public/cpp/bindings/sync_call_restrictions.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/spawned_test_server/spawned_test_server.h"
-#include "services/network/public/cpp/features.h"
 #include "services/service_manager/public/cpp/connector.h"
 
 namespace extensions {
@@ -33,10 +32,8 @@
 class SocketsTcpApiTest : public ShellApiTest {
  public:
   SocketsTcpApiTest() {
-    if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
-      base::CommandLine::ForCurrentProcess()->AppendSwitch(
-          switches::kUseMockCertVerifierForTesting);
-    }
+    base::CommandLine::ForCurrentProcess()->AppendSwitch(
+        switches::kUseMockCertVerifierForTesting);
   }
 
   void SetUpOnMainThread() override {
@@ -95,17 +92,13 @@
 
 IN_PROC_BROWSER_TEST_F(SocketsTcpApiTest, SocketTcpExtensionTLS) {
   network::mojom::NetworkServiceTestPtr network_service_test;
-  // If network service is running in a utility process, the cert of the
+  // Because the network service runs in a utility process, the cert of the
   // SpawnedTestServer won't be recognized, so inject mock cert verifier through
   // the test helper interface.
-  if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
-    content::ServiceManagerConnection::GetForProcess()
-        ->GetConnector()
-        ->BindInterface(content::mojom::kNetworkServiceName,
-                        &network_service_test);
-    mojo::ScopedAllowSyncCallForTesting allow_sync_call;
-    network_service_test->MockCertVerifierSetDefaultResult(net::OK);
-  }
+  content::GetSystemConnector()->BindInterface(
+      content::mojom::kNetworkServiceName, &network_service_test);
+  mojo::ScopedAllowSyncCallForTesting allow_sync_call;
+  network_service_test->MockCertVerifierSetDefaultResult(net::OK);
 
   std::unique_ptr<net::SpawnedTestServer> test_https_server(
       new net::SpawnedTestServer(
diff --git a/extensions/browser/api/usb/usb_device_manager.cc b/extensions/browser/api/usb/usb_device_manager.cc
index e65d7c8..494b9fc 100644
--- a/extensions/browser/api/usb/usb_device_manager.cc
+++ b/extensions/browser/api/usb/usb_device_manager.cc
@@ -11,7 +11,7 @@
 #include "base/lazy_instance.h"
 #include "base/strings/utf_string_conversions.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/service_manager_connection.h"
+#include "content/public/browser/system_connector.h"
 #include "extensions/browser/api/device_permissions_manager.h"
 #include "extensions/browser/event_router_factory.h"
 #include "extensions/common/api/usb.h"
@@ -194,10 +194,8 @@
 
   // Request UsbDeviceManagerPtr from DeviceService.
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(device::mojom::kServiceName,
-                      mojo::MakeRequest(&device_manager_));
+  content::GetSystemConnector()->BindInterface(
+      device::mojom::kServiceName, mojo::MakeRequest(&device_manager_));
 
   SetUpDeviceManagerConnection();
 }
diff --git a/extensions/browser/api/web_request/web_request_api.cc b/extensions/browser/api/web_request/web_request_api.cc
index a88384de..84c2a1a 100644
--- a/extensions/browser/api/web_request/web_request_api.cc
+++ b/extensions/browser/api/web_request/web_request_api.cc
@@ -81,7 +81,6 @@
 #include "net/base/auth.h"
 #include "net/base/net_errors.h"
 #include "net/http/http_util.h"
-#include "services/network/public/cpp/features.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "url/gurl.h"
 
@@ -813,9 +812,6 @@
 
 bool WebRequestAPI::MayHaveProxies() const {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
-    return false;
-
   if (base::FeatureList::IsEnabled(
           extensions_features::kForceWebRequestProxyForTest)) {
     return true;
@@ -825,9 +821,6 @@
 }
 
 void WebRequestAPI::UpdateMayHaveProxies() {
-  if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
-    return;
-
   bool may_have_proxies = MayHaveProxies();
   if (!may_have_proxies_ && may_have_proxies) {
     content::BrowserContext::GetDefaultStoragePartition(browser_context_)
diff --git a/extensions/browser/extension_event_histogram_value.h b/extensions/browser/extension_event_histogram_value.h
index b5898a5..83471d5 100644
--- a/extensions/browser/extension_event_histogram_value.h
+++ b/extensions/browser/extension_event_histogram_value.h
@@ -457,6 +457,7 @@
   MIME_HANDLER_PRIVATE_SAVE = 436,
   RUNTIME_ON_CONNECT_NATIVE = 437,
   ACTION_ON_CLICKED = 438,
+  ACCESSIBILITY_PRIVATE_ON_SWITCH_ACCESS_COMMAND = 439,
   // Last entry: Add new entries above, then run:
   // python tools/metrics/histograms/update_extension_histograms.py
   ENUM_BOUNDARY
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc
index 9221c2c8..f078df1 100644
--- a/extensions/browser/guest_view/web_view/web_view_guest.cc
+++ b/extensions/browser/guest_view/web_view/web_view_guest.cc
@@ -66,7 +66,6 @@
 #include "net/base/escape.h"
 #include "net/base/net_errors.h"
 #include "net/cookies/canonical_cookie.h"
-#include "services/network/public/cpp/features.h"
 #include "third_party/blink/public/common/logging/logging_utils.h"
 #include "third_party/blink/public/common/mediastream/media_stream_request.h"
 #include "ui/base/models/simple_menu_model.h"
@@ -794,18 +793,9 @@
 
     // We cannot use |BrowsingDataRemover| here since it doesn't support
     // non-default StoragePartition.
-    if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
-      // Note that we've deprecated the concept of a media cache, and are now
-      // using a single cache for both purposes.
-      partition->GetNetworkContext()->ClearHttpCache(
-          remove_since, base::Time::Now(), nullptr /* ClearDataFilter */,
-          std::move(cache_removal_done_callback));
-    } else {
-      partition->ClearHttpAndMediaCaches(
-          remove_since, base::Time::Now(),
-          base::RepeatingCallback<bool(const GURL&)>(),
-          std::move(cache_removal_done_callback));
-    }
+    partition->GetNetworkContext()->ClearHttpCache(
+        remove_since, base::Time::Now(), nullptr /* ClearDataFilter */,
+        std::move(cache_removal_done_callback));
     return true;
   }
 
diff --git a/extensions/browser/renderer_startup_helper.cc b/extensions/browser/renderer_startup_helper.cc
index 1e368fe..0fdd128 100644
--- a/extensions/browser/renderer_startup_helper.cc
+++ b/extensions/browser/renderer_startup_helper.cc
@@ -30,7 +30,6 @@
 #include "extensions/common/features/feature_channel.h"
 #include "extensions/common/features/feature_session_type.h"
 #include "extensions/common/permissions/permissions_data.h"
-#include "services/network/public/cpp/features.h"
 #include "ui/base/webui/web_ui_util.h"
 #include "url/origin.h"
 
@@ -246,11 +245,6 @@
       CreateCorsOriginAccessAllowList(
           extension,
           PermissionsData::EffectiveHostPermissionsMode::kOmitTabSpecific);
-  if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
-    ExtensionsClient::Get()->AddOriginAccessPermissions(extension, true,
-                                                        &allow_list);
-  }
-
   browser_context_->SetCorsOriginAccessListForOrigin(
       extension_origin, std::move(allow_list),
       CreateCorsOriginAccessBlockList(extension), base::DoNothing::Once());
diff --git a/extensions/browser/url_loader_factory_manager.cc b/extensions/browser/url_loader_factory_manager.cc
index 1373f0a..e56a734b 100644
--- a/extensions/browser/url_loader_factory_manager.cc
+++ b/extensions/browser/url_loader_factory_manager.cc
@@ -32,7 +32,6 @@
 #include "extensions/common/manifest_handlers/content_scripts_handler.h"
 #include "extensions/common/switches.h"
 #include "extensions/common/user_script.h"
-#include "services/network/public/cpp/features.h"
 #include "services/network/public/mojom/network_context.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 #include "url/gurl.h"
@@ -379,16 +378,8 @@
     std::vector<url::Origin> request_initiators,
     bool push_to_renderer_now) {
   DCHECK(!request_initiators.empty());
-  if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
-    frame->MarkInitiatorsAsRequiringSeparateURLLoaderFactory(
-        std::move(request_initiators), push_to_renderer_now);
-  } else {
-    // TODO(lukasza): In non-NetworkService implementation of CORB, make an
-    // exception only for specific extensions (e.g. based on process id,
-    // similarly to how r585124 does it for plugins).  Doing so will likely
-    // interfere with Extensions.CrossOriginFetchFromContentScript2 Rappor
-    // metric, so this needs to wait until this metric is not needed anymore.
-  }
+  frame->MarkInitiatorsAsRequiringSeparateURLLoaderFactory(
+      std::move(request_initiators), push_to_renderer_now);
 }
 
 // If |match_about_blank| is true, then traverses parent/opener chain until the
diff --git a/extensions/common/api/automation.idl b/extensions/common/api/automation.idl
index 35f3068..4a204b3c 100644
--- a/extensions/common/api/automation.idl
+++ b/extensions/common/api/automation.idl
@@ -592,12 +592,12 @@
     // The start index of each word within the node's name. This is different
     // from wordStarts because it is not restricted to inline text boxes and can
     // be used for any type of element.
-    long[]? wordStartOffsets;
+    long[]? nonInlineTextWordStarts;
 
     // The end index of each word within the node's name. This is different
     // from wordEnds because it is not restricted to inline text boxes and can
     // be used for any type of element.
-    long[]? wordEndOffsets;
+    long[]? nonInlineTextWordEnds;
 
     // The nodes, if any, which this node is specified to control via
     // <a href="http://www.w3.org/TR/wai-aria/states_and_properties#aria-controls">
diff --git a/extensions/renderer/api/automation/automation_internal_custom_bindings.cc b/extensions/renderer/api/automation/automation_internal_custom_bindings.cc
index 1c3670d..b8a4115 100644
--- a/extensions/renderer/api/automation/automation_internal_custom_bindings.cc
+++ b/extensions/renderer/api/automation/automation_internal_custom_bindings.cc
@@ -796,7 +796,6 @@
             node->GetString16Attribute(ax::mojom::StringAttribute::kName));
         result.Set(gin::ConvertToV8(isolate, word_ends));
       });
-
   // Bindings that take a Tree ID and Node ID and string attribute name
   // and return a property of the node.
 
diff --git a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_base.cc b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_base.cc
index 4e85f0f..d769c15 100644
--- a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_base.cc
+++ b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_base.cc
@@ -18,7 +18,6 @@
 #include "extensions/common/guest_view/extensions_guest_view_messages.h"
 #include "extensions/renderer/extension_frame_helper.h"
 #include "ipc/ipc_sync_channel.h"
-#include "services/network/public/cpp/features.h"
 #include "third_party/blink/public/platform/web_url.h"
 #include "third_party/blink/public/platform/web_url_request.h"
 #include "third_party/blink/public/web/web_associated_url_loader.h"
@@ -202,12 +201,10 @@
   }
 
   auto* guest_view = GetGuestView();
-  // When the network service is enabled, subresource requests like plugins are
-  // made directly from the renderer to the network service. So we need to
-  // intercept the URLLoader and send it to the browser so that it can forward
-  // it to the plugin.
-  if (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
-      is_embedded_) {
+  // Subresource requests like plugins are made directly from the renderer to
+  // the network service. So we need to intercept the URLLoader and send it to
+  // the browser so that it can forward it to the plugin.
+  if (is_embedded_) {
     if (transferrable_url_loader_.is_null())
       return;
 
diff --git a/extensions/renderer/resources/automation/automation_node.js b/extensions/renderer/resources/automation/automation_node.js
index c22a4d3b..5fce69a 100644
--- a/extensions/renderer/resources/automation/automation_node.js
+++ b/extensions/renderer/resources/automation/automation_node.js
@@ -721,6 +721,14 @@
     return GetTableCellRowIndex(this.treeID, this.id);
   },
 
+  get nonInlineTextWordStarts() {
+    return GetWordStartOffsets(this.treeID, this.id);
+  },
+
+  get nonInlineTextWordEnds() {
+    return GetWordEndOffsets(this.treeID, this.id);
+  },
+
   doDefault: function() {
     this.performAction_('doDefault');
   },
@@ -872,14 +880,6 @@
       return impl.get(info.nodeId);
   },
 
-  wordStartOffsets: function() {
-    return GetWordStartOffsets(this.treeID, this.id);
-  },
-
-  wordEndOffsets: function() {
-    return GetWordEndOffsets(this.treeID, this.id);
-  },
-
   addEventListener: function(eventType, callback, capture) {
     this.removeEventListener(eventType, callback);
     if (!this.listeners[eventType])
@@ -1701,8 +1701,6 @@
     'toString',
     'boundsForRange',
     'languageAnnotationForStringAttribute',
-    'wordStartOffsets',
-    'wordEndOffsets',
   ],
   readonly: $Array.concat(
       publicAttributes,
@@ -1739,6 +1737,8 @@
         'tableCellRowHeaders',
         'tableCellColumnIndex',
         'tableCellRowIndex',
+        'nonInlineTextWordStarts',
+        'nonInlineTextWordEnds',
       ]),
 });
 
diff --git a/extensions/shell/browser/shell_browser_main_parts.cc b/extensions/shell/browser/shell_browser_main_parts.cc
index f6ef1c7..762d165 100644
--- a/extensions/shell/browser/shell_browser_main_parts.cc
+++ b/extensions/shell/browser/shell_browser_main_parts.cc
@@ -9,6 +9,7 @@
 #include "apps/browser_context_keyed_service_factories.h"
 #include "base/bind.h"
 #include "base/command_line.h"
+#include "base/memory/ref_counted.h"
 #include "base/task/post_task.h"
 #include "build/build_config.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
@@ -21,9 +22,9 @@
 #include "content/public/browser/child_process_security_policy.h"
 #include "content/public/browser/context_factory.h"
 #include "content/public/browser/devtools_agent_host.h"
+#include "content/public/browser/system_connector.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/result_codes.h"
-#include "content/public/common/service_manager_connection.h"
 #include "content/shell/browser/shell_devtools_manager_delegate.h"
 #include "extensions/browser/browser_context_keyed_service_factories.h"
 #include "extensions/browser/extension_system.h"
@@ -197,8 +198,9 @@
 
 #if defined(OS_CHROMEOS)
   chromeos::CrasAudioHandler::Initialize(
-      content::ServiceManagerConnection::GetForProcess()->GetConnector(),
-      new chromeos::AudioDevicesPrefHandlerImpl(local_state_.get()));
+      content::GetSystemConnector(),
+      base::MakeRefCounted<chromeos::AudioDevicesPrefHandlerImpl>(
+          local_state_.get()));
   audio_controller_.reset(new ShellAudioController());
 #endif
 
@@ -214,9 +216,7 @@
 #endif
 
   storage_monitor::StorageMonitor::Create(
-      content::ServiceManagerConnection::GetForProcess()
-          ->GetConnector()
-          ->Clone());
+      content::GetSystemConnector()->Clone());
 
   desktop_controller_.reset(
       browser_main_delegate_->CreateDesktopController(browser_context_.get()));
diff --git a/headless/lib/browser/protocol/DEPS b/headless/lib/browser/protocol/DEPS
new file mode 100644
index 0000000..9253008
--- /dev/null
+++ b/headless/lib/browser/protocol/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+  # For converting between JSON and CBOR in devtools_session_encoding.cc.
+  "+third_party/inspector_protocol/encoding",
+]
diff --git a/headless/lib/browser/protocol/headless_devtools_session.cc b/headless/lib/browser/protocol/headless_devtools_session.cc
index 51715fb..faa0dd1d 100644
--- a/headless/lib/browser/protocol/headless_devtools_session.cc
+++ b/headless/lib/browser/protocol/headless_devtools_session.cc
@@ -11,6 +11,42 @@
 #include "headless/lib/browser/protocol/headless_handler.h"
 #include "headless/lib/browser/protocol/page_handler.h"
 #include "headless/lib/browser/protocol/target_handler.h"
+#include "third_party/inspector_protocol/encoding/encoding.h"
+
+namespace {
+// TODO(johannes): This is very similar to the code in
+// content/browser/devtools/devtools_protocol_encoding. Once we have
+// the error / status propagation story settled, move the common parts
+// into a content public API.
+
+using ::inspector_protocol_encoding::span;
+using ::inspector_protocol_encoding::SpanFrom;
+using ::inspector_protocol_encoding::json::ConvertCBORToJSON;
+using ::inspector_protocol_encoding::json::ConvertJSONToCBOR;
+using IPEStatus = ::inspector_protocol_encoding::Status;
+
+// Platform allows us to inject the string<->double conversion
+// routines from base:: into the inspector_protocol JSON parser / serializer.
+class Platform : public ::inspector_protocol_encoding::json::Platform {
+ public:
+  bool StrToD(const char* str, double* result) const override {
+    return base::StringToDouble(str, result);
+  }
+
+  // Prints |value| in a format suitable for JSON.
+  std::unique_ptr<char[]> DToStr(double value) const override {
+    std::string str = base::NumberToString(value);
+    std::unique_ptr<char[]> result(new char[str.size() + 1]);
+    memcpy(result.get(), str.c_str(), str.size() + 1);
+    return result;
+  }
+};
+
+IPEStatus ConvertCBORToJSON(span<uint8_t> cbor, std::string* json) {
+  Platform platform;
+  return ConvertCBORToJSON(platform, cbor, json);
+}
+}  // namespace
 
 namespace headless {
 namespace protocol {
@@ -66,14 +102,37 @@
   handlers_[handler->name()] = std::move(handler);
 }
 
+// The following methods handle responses or notifications coming from
+// the browser to the client.
+static void SendProtocolResponseOrNotification(
+    content::DevToolsAgentHostClient* client,
+    content::DevToolsAgentHost* agent_host,
+    std::unique_ptr<protocol::Serializable> message) {
+  std::string cbor = message->serialize(/*binary=*/true);
+  if (client->UsesBinaryProtocol()) {
+    client->DispatchProtocolMessage(agent_host, cbor);
+    return;
+  }
+  std::string json;
+  IPEStatus status = ConvertCBORToJSON(SpanFrom(cbor), &json);
+  LOG_IF(ERROR, !status.ok()) << status.ToASCIIString();
+  client->DispatchProtocolMessage(agent_host, json);
+}
+
 void HeadlessDevToolsSession::sendProtocolResponse(
     int call_id,
     std::unique_ptr<Serializable> message) {
   pending_commands_.erase(call_id);
-  bool binary = client_->UsesBinaryProtocol();
-  client_->DispatchProtocolMessage(agent_host_, message->serialize(binary));
+  SendProtocolResponseOrNotification(client_, agent_host_, std::move(message));
 }
 
+void HeadlessDevToolsSession::sendProtocolNotification(
+    std::unique_ptr<Serializable> message) {
+  SendProtocolResponseOrNotification(client_, agent_host_, std::move(message));
+}
+
+void HeadlessDevToolsSession::flushProtocolNotifications() {}
+
 void HeadlessDevToolsSession::fallThrough(int call_id,
                                           const std::string& method,
                                           const std::string& message) {
@@ -81,14 +140,5 @@
   pending_commands_.erase(call_id);
   std::move(callback).Run(message);
 }
-
-void HeadlessDevToolsSession::sendProtocolNotification(
-    std::unique_ptr<Serializable> message) {
-  bool binary = client_->UsesBinaryProtocol();
-  client_->DispatchProtocolMessage(agent_host_, message->serialize(binary));
-}
-
-void HeadlessDevToolsSession::flushProtocolNotifications() {}
-
 }  // namespace protocol
 }  // namespace headless
diff --git a/ios/chrome/browser/crash_report/breakpad_helper.h b/ios/chrome/browser/crash_report/breakpad_helper.h
index ce37e434..a9698e7 100644
--- a/ios/chrome/browser/crash_report/breakpad_helper.h
+++ b/ios/chrome/browser/crash_report/breakpad_helper.h
@@ -103,6 +103,21 @@
 // state is in progress, otherwise remove the key.
 void SetDestroyingAndRebuildingIncognitoBrowserState(bool in_progress);
 
+// Sets a key indicating the view controller that was being presented, iff the
+// view controller's view was already in the view hierarchy before the BVC
+// attempted to present it. |active_view_controller| is the view controller
+// being presented by BVC. |presenting_view_controller| is
+// |active_view_controller|'s presenting view controller.
+// |parent_view_controller| is |active_view_controller|'s parent view
+// controller.
+void SetBVCPresentingActiveViewController(NSString* active_view_controller,
+                                          NSString* presenting_view_controller,
+                                          NSString* parent_view_controller);
+
+// Removes the key indicating that the BVC is presenting an active view
+// controller.
+void RemoveBVCPresentingActiveViewController();
+
 // Sets a key in browser to store the playback state of media player (audio or
 // video). This function records a new start. This function is called for each
 // stream in the media (once or twice for audio, two or three times for video).
diff --git a/ios/chrome/browser/crash_report/breakpad_helper.mm b/ios/chrome/browser/crash_report/breakpad_helper.mm
index 11f9c16..73054a7c 100644
--- a/ios/chrome/browser/crash_report/breakpad_helper.mm
+++ b/ios/chrome/browser/crash_report/breakpad_helper.mm
@@ -49,6 +49,8 @@
 NSString* const kMemoryWarningCount = @"memory_warning_count";
 NSString* const kUptimeAtRestoreInMs = @"uptime_at_restore_in_ms";
 NSString* const kUploadedInRecoveryMode = @"uploaded_in_recovery_mode";
+NSString* const kBVCPresentingActiveViewController =
+    @"bvc_presenting_active_vc";
 
 // Multiple state information are combined into one CrachReportMultiParameter
 // to save limited and finite number of ReportParameters.
@@ -339,6 +341,20 @@
   }
 }
 
+void SetBVCPresentingActiveViewController(NSString* active_view_controller,
+                                          NSString* presenting_view_controller,
+                                          NSString* parent_view_controller) {
+  NSString* formatted_value = [NSString
+      stringWithFormat:@"{activeVC:%@, presentingVC:%@, parentVC:%@}",
+                       active_view_controller, presenting_view_controller,
+                       parent_view_controller];
+  AddReportParameter(kBVCPresentingActiveViewController, formatted_value, true);
+}
+
+void RemoveBVCPresentingActiveViewController() {
+  RemoveReportParameter(kBVCPresentingActiveViewController);
+}
+
 void MediaStreamPlaybackDidStart() {
   [[CrashReportUserApplicationState sharedInstance]
       incrementValue:kVideoPlaying];
diff --git a/ios/chrome/browser/infobars/infobar_metrics_recorder.h b/ios/chrome/browser/infobars/infobar_metrics_recorder.h
index 3cc19fc..97089bc 100644
--- a/ios/chrome/browser/infobars/infobar_metrics_recorder.h
+++ b/ios/chrome/browser/infobars/infobar_metrics_recorder.h
@@ -87,6 +87,9 @@
 // Records histogram for Banner |dismissType|.
 - (void)recordBannerDismissType:(MobileMessagesBannerDismissType)dismissType;
 
+// Records histogram for Banner On Screen duration.
+- (void)recordBannerOnScreenDuration:(double)duration;
+
 // Records histogram for Modal |event|.
 - (void)recordModalEvent:(MobileMessagesModalEvent)event;
 
diff --git a/ios/chrome/browser/infobars/infobar_metrics_recorder.mm b/ios/chrome/browser/infobars/infobar_metrics_recorder.mm
index 68c744f..933f70a 100644
--- a/ios/chrome/browser/infobars/infobar_metrics_recorder.mm
+++ b/ios/chrome/browser/infobars/infobar_metrics_recorder.mm
@@ -103,6 +103,11 @@
   }
 }
 
+- (void)recordBannerOnScreenDuration:(double)duration {
+  base::TimeDelta timeDelta = base::TimeDelta::FromSecondsD(duration);
+  UMA_HISTOGRAM_MEDIUM_TIMES("Mobile.Messages.Banner.OnScreenTime", timeDelta);
+}
+
 - (void)recordModalEvent:(MobileMessagesModalEvent)event {
   switch (self.infobarType) {
     case InfobarType::kInfobarTypeConfirm:
diff --git a/ios/chrome/browser/ui/browser_view/BUILD.gn b/ios/chrome/browser/ui/browser_view/BUILD.gn
index fdf91eda..3af3e3ea 100644
--- a/ios/chrome/browser/ui/browser_view/BUILD.gn
+++ b/ios/chrome/browser/ui/browser_view/BUILD.gn
@@ -43,6 +43,7 @@
     "//ios/chrome/browser/autofill:autofill_internal",
     "//ios/chrome/browser/bookmarks",
     "//ios/chrome/browser/browser_state",
+    "//ios/chrome/browser/crash_report",
     "//ios/chrome/browser/download",
     "//ios/chrome/browser/download:features",
     "//ios/chrome/browser/feature_engagement",
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
index 4ad2948d7..dc634a7 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -32,6 +32,7 @@
 #include "ios/chrome/app/tests_hook.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
+#include "ios/chrome/browser/crash_report/breakpad_helper.h"
 #import "ios/chrome/browser/download/download_manager_tab_helper.h"
 #include "ios/chrome/browser/feature_engagement/tracker_factory.h"
 #include "ios/chrome/browser/feature_engagement/tracker_util.h"
@@ -1861,6 +1862,30 @@
     [self.sideSwipeController resetContentView];
   }
 
+  // TODO(crbug.com/959774): The logging below is to better understand a
+  // NSInvalidArgumentException crash with the note "Application tried to
+  // present modally an active controller <BrowserViewController: 0x13e88d000>".
+  // Code experiments showed that the referenced BrowserViewController is the
+  // presenter, not the presentee.
+  if (viewControllerToPresent.view.window) {
+    NSString* activeViewController =
+        NSStringFromClass([viewControllerToPresent class]);
+    NSString* presentingViewController = NSStringFromClass(
+        [viewControllerToPresent.presentingViewController class]);
+    NSString* parentViewController =
+        NSStringFromClass([viewControllerToPresent.parentViewController class]);
+    breakpad_helper::SetBVCPresentingActiveViewController(
+        activeViewController, presentingViewController, parentViewController);
+
+    ProceduralBlock finalCompletionHandlerCopy = [finalCompletionHandler copy];
+    finalCompletionHandler = ^{
+      if (finalCompletionHandlerCopy)
+        finalCompletionHandlerCopy();
+      // Remove the crash log since the presentation completed without a crash.
+      breakpad_helper::RemoveBVCPresentingActiveViewController();
+    };
+  }
+
   // TODO(crbug.com/965688): An Infobar message is currently the only presented
   // controller that allows interaction with the rest of the App while its being
   // presented. Dismiss it in case the user or system has triggered another
diff --git a/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm b/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm
index 08155e8..a5bb55f 100644
--- a/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm
+++ b/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm
@@ -83,6 +83,11 @@
 @property(nonatomic, strong) UILabel* subTitleLabel;
 // Used to build and record metrics.
 @property(nonatomic, strong) InfobarMetricsRecorder* metricsRecorder;
+// The NSTimeInterval in which the Banner appeared on screen.
+@property(nonatomic, assign) NSTimeInterval bannerAppearedTime;
+// YES if the banner on screen time metric has already been recorded for this
+// banner.
+@property(nonatomic, assign) BOOL bannerOnScreenTimeWasRecorded;
 
 @end
 
@@ -240,6 +245,14 @@
 - (void)viewDidAppear:(BOOL)animated {
   [super viewDidAppear:animated];
   [self.metricsRecorder recordBannerEvent:MobileMessagesBannerEvent::Presented];
+  self.bannerAppearedTime = [NSDate timeIntervalSinceReferenceDate];
+}
+
+- (void)viewWillDisappear:(BOOL)animated {
+  [super viewWillDisappear:animated];
+  // Call recordBannerOnScreenTime on viewWillDisappear since viewDidDisappear
+  // is called after the dismissal animation has occured.
+  [self recordBannerOnScreenTime];
 }
 
 - (void)viewDidDisappear:(BOOL)animated {
@@ -290,6 +303,7 @@
       [self.metricsRecorder
           recordBannerDismissType:MobileMessagesBannerDismissType::
                                       ExpandedToModal];
+      [self recordBannerOnScreenTime];
       [self.delegate presentInfobarModalFromBanner];
       // Since the modal has now been presented prevent any external dismissal.
       self.shouldDismissAfterTouchesEnded = NO;
@@ -393,9 +407,23 @@
   base::RecordAction(base::UserMetricsAction("MobileMessagesBannerTapped"));
   [self.metricsRecorder
       recordBannerDismissType:MobileMessagesBannerDismissType::TappedToModal];
+  [self recordBannerOnScreenTime];
   [self.delegate presentInfobarModalFromBanner];
 }
 
+// Records the banner on screen time. This method should be called as soon as
+// its know that the banner will not be visible. This might happen before
+// viewWillDissapear since presenting a Modal makes the banner invisible but
+// doesn't call viewWillDissapear.
+- (void)recordBannerOnScreenTime {
+  if (!self.bannerOnScreenTimeWasRecorded) {
+    double duration =
+        [NSDate timeIntervalSinceReferenceDate] - self.bannerAppearedTime;
+    [self.metricsRecorder recordBannerOnScreenDuration:duration];
+    self.bannerOnScreenTimeWasRecorded = YES;
+  }
+}
+
 #pragma mark - Accessibility
 
 - (NSArray*)accessibilityActions {
diff --git a/ios/chrome/browser/ui/infobars/presentation/infobar_banner_animator.h b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_animator.h
index 2c4fd1cf..e8fcb40 100644
--- a/ios/chrome/browser/ui/infobars/presentation/infobar_banner_animator.h
+++ b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_animator.h
@@ -10,7 +10,8 @@
 // Animator used to present an InfobarBanner dropping from the top of the
 // screen.
 @interface InfobarBannerAnimator
-    : NSObject <UIViewControllerAnimatedTransitioning>
+    : NSObject <UIViewControllerAnimatedTransitioning,
+                UIViewControllerInteractiveTransitioning>
 
 // YES if this animator is presenting a view controller, NO if it is dismissing
 // one.
diff --git a/ios/chrome/browser/ui/infobars/presentation/infobar_banner_animator.mm b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_animator.mm
index 820cc809..7c414e1 100644
--- a/ios/chrome/browser/ui/infobars/presentation/infobar_banner_animator.mm
+++ b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_animator.mm
@@ -15,9 +15,17 @@
   return 1;
 }
 
-// TODO(crbug.com/911864): PLACEHOLDER animation to present the InfobarBanner.
+// "This method can only be a nop if the transition is interactive and not a
+// percentDriven interactive transition." (As stated in this method public
+// interface). Since this criteria is met it NO-OPs.
 - (void)animateTransition:
     (id<UIViewControllerContextTransitioning>)transitionContext {
+}
+
+#pragma mark - UIViewControllerTransitioningDelegate
+
+- (void)startInteractiveTransition:
+    (id<UIViewControllerContextTransitioning>)transitionContext {
   // Set up the keys for the "base" view/VC and the "presented" view/VC. These
   // will be used to fetch the associated objects later.
   NSString* baseViewKey = self.presenting ? UITransitionContextFromViewKey
@@ -57,32 +65,33 @@
     presentedViewFinalFrame.origin.y = -CGRectGetWidth(containerView.bounds);
   }
 
-  // Animate using the animator's own duration value.
-  [UIView animateWithDuration:[self transitionDuration:transitionContext]
-      delay:0
-      usingSpringWithDamping:0.85
-      initialSpringVelocity:0
-      options:UIViewAnimationOptionTransitionNone
-      animations:^{
-        presentedView.frame = presentedViewFinalFrame;
-        presentedView.alpha = 1;
-      }
-      completion:^(BOOL finished) {
-        BOOL success = ![transitionContext transitionWasCancelled];
+  UIViewPropertyAnimator* animator = [[UIViewPropertyAnimator alloc]
+      initWithDuration:[self transitionDuration:transitionContext]
+          dampingRatio:0.85
+            animations:^{
+              presentedView.frame = presentedViewFinalFrame;
+              presentedView.alpha = 1;
+            }];
 
-        // If presentation failed, remove the view.
-        if (self.presenting && !success) {
-          [presentedView removeFromSuperview];
-        }
+  [animator addCompletion:^(UIViewAnimatingPosition finalPosition) {
+    BOOL success = ![transitionContext transitionWasCancelled];
 
-        // If dismiss was successful, remove the view.
-        if (!self.presenting && success) {
-          [presentedView removeFromSuperview];
-        }
+    // If presentation failed, remove the view.
+    if (self.presenting && !success) {
+      [presentedView removeFromSuperview];
+    }
 
-        // Notify UIKit that the transition has finished
-        [transitionContext completeTransition:success];
-      }];
+    // If dismiss was successful, remove the view.
+    if (!self.presenting && success) {
+      [presentedView removeFromSuperview];
+    }
+
+    // Notify UIKit that the transition has finished
+    [transitionContext finishInteractiveTransition];
+    [transitionContext completeTransition:success];
+  }];
+
+  [animator startAnimation];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/infobars/presentation/infobar_banner_transition_driver.mm b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_transition_driver.mm
index 2594313..93906a287 100644
--- a/ios/chrome/browser/ui/infobars/presentation/infobar_banner_transition_driver.mm
+++ b/ios/chrome/browser/ui/infobars/presentation/infobar_banner_transition_driver.mm
@@ -4,6 +4,7 @@
 
 #import "ios/chrome/browser/ui/infobars/presentation/infobar_banner_transition_driver.h"
 
+#include "base/mac/foundation_util.h"
 #import "ios/chrome/browser/ui/infobars/presentation/infobar_banner_animator.h"
 #import "ios/chrome/browser/ui/infobars/presentation/infobar_banner_presentation_controller.h"
 
@@ -11,6 +12,12 @@
 #error "This file requires ARC support."
 #endif
 
+@interface InfobarBannerTransitionDriver ()
+// Object that handles the animation and interactivity for the Banner
+// presentation.
+@property(nonatomic, weak) InfobarBannerAnimator* bannerAnimator;
+@end
+
 @implementation InfobarBannerTransitionDriver
 
 #pragma mark - UIViewControllerTransitioningDelegate
@@ -35,14 +42,30 @@
                              sourceController:(UIViewController*)source {
   InfobarBannerAnimator* animator = [[InfobarBannerAnimator alloc] init];
   animator.presenting = YES;
-  return animator;
+  self.bannerAnimator = animator;
+  return self.bannerAnimator;
 }
 
 - (id<UIViewControllerAnimatedTransitioning>)
     animationControllerForDismissedController:(UIViewController*)dismissed {
   InfobarBannerAnimator* animator = [[InfobarBannerAnimator alloc] init];
   animator.presenting = NO;
-  return animator;
+  self.bannerAnimator = animator;
+  return self.bannerAnimator;
+}
+
+- (id<UIViewControllerInteractiveTransitioning>)
+    interactionControllerForPresentation:
+        (id<UIViewControllerAnimatedTransitioning>)animator {
+  DCHECK_EQ(self.bannerAnimator, animator);
+  return self.bannerAnimator;
+}
+
+- (id<UIViewControllerInteractiveTransitioning>)
+    interactionControllerForDismissal:
+        (id<UIViewControllerAnimatedTransitioning>)animator {
+  DCHECK_EQ(self.bannerAnimator, animator);
+  return self.bannerAnimator;
 }
 
 @end
diff --git a/ipc/ipc_message_start.h b/ipc/ipc_message_start.h
index 480ae36..93bc399 100644
--- a/ipc/ipc_message_start.h
+++ b/ipc/ipc_message_start.h
@@ -33,7 +33,6 @@
   PrintMsgStart,
   ExtensionMsgStart,
   TextInputClientMsgStart,
-  JavaBridgeMsgStart,
   BlinkTestMsgStart,
   AccessibilityMsgStart,
   PrerenderMsgStart,
diff --git a/media/audio/audio_output_unittest.cc b/media/audio/audio_output_unittest.cc
index c649475..41e4aec 100644
--- a/media/audio/audio_output_unittest.cc
+++ b/media/audio/audio_output_unittest.cc
@@ -9,6 +9,8 @@
 #include "base/memory/aligned_memory.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/test_timeouts.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
@@ -98,7 +100,7 @@
 }
 
 // This test produces actual audio for .25 seconds on the default device.
-TEST_F(AudioOutputTest, DISABLED_Play200HzTone) {
+TEST_F(AudioOutputTest, Play200HzTone) {
   ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices());
 
   stream_params_ =
@@ -109,14 +111,30 @@
 
   SineWaveAudioSource source(1, 200.0, stream_params_.sample_rate());
 
+  // Play for 100ms.
+  const int samples_to_play = stream_params_.sample_rate() / 10;
+
   EXPECT_TRUE(stream_->Open());
   stream_->SetVolume(1.0);
+
+  // Play the stream until position gets past |samples_to_play|.
+  base::RunLoop run_loop;
+  source.set_on_more_data_callback(
+      base::BindLambdaForTesting([&source, &run_loop, samples_to_play]() {
+        if (source.pos_samples() >= samples_to_play)
+          run_loop.Quit();
+      }));
+  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+      FROM_HERE, run_loop.QuitClosure(), TestTimeouts::action_timeout());
+
   stream_->Start(&source);
-  RunMessageLoop(base::TimeDelta::FromMilliseconds(250));
+  run_loop.Run();
+
   stream_->Stop();
 
   EXPECT_FALSE(source.errors());
   EXPECT_GE(source.callbacks(), 1);
+  EXPECT_GE(source.pos_samples(), samples_to_play);
 }
 
 // Test that SetVolume() and GetVolume() work as expected.
diff --git a/media/audio/simple_sources.cc b/media/audio/simple_sources.cc
index 422c691..e16f8f5 100644
--- a/media/audio/simple_sources.cc
+++ b/media/audio/simple_sources.cc
@@ -103,14 +103,9 @@
 // SineWaveAudioSource implementation.
 
 SineWaveAudioSource::SineWaveAudioSource(int channels,
-                                         double freq, double sample_freq)
-    : channels_(channels),
-      f_(freq / sample_freq),
-      time_state_(0),
-      cap_(0),
-      callbacks_(0),
-      errors_(0) {
-}
+                                         double freq,
+                                         double sample_freq)
+    : channels_(channels), f_(freq / sample_freq) {}
 
 SineWaveAudioSource::~SineWaveAudioSource() = default;
 
@@ -120,21 +115,29 @@
                                     base::TimeTicks /* delay_timestamp */,
                                     int /* prior_frames_skipped */,
                                     AudioBus* dest) {
-  base::AutoLock auto_lock(time_lock_);
-  callbacks_++;
+  int max_frames;
 
-  // The table is filled with s(t) = kint16max*sin(Theta*t),
-  // where Theta = 2*PI*fs.
-  // We store the discrete time value |t| in a member to ensure that the
-  // next pass starts at a correct state.
-  int max_frames =
-      cap_ > 0 ? std::min(dest->frames(), cap_ - time_state_) : dest->frames();
-  for (int i = 0; i < max_frames; ++i)
-    dest->channel(0)[i] = sin(2.0 * base::kPiDouble * f_ * time_state_++);
-  for (int i = 1; i < dest->channels(); ++i) {
-    memcpy(dest->channel(i), dest->channel(0),
-           max_frames * sizeof(*dest->channel(i)));
+  {
+    base::AutoLock auto_lock(lock_);
+    callbacks_++;
+
+    // The table is filled with s(t) = kint16max*sin(Theta*t),
+    // where Theta = 2*PI*fs.
+    // We store the discrete time value |t| in a member to ensure that the
+    // next pass starts at a correct state.
+    max_frames = cap_ > 0 ? std::min(dest->frames(), cap_ - pos_samples_)
+                          : dest->frames();
+    for (int i = 0; i < max_frames; ++i)
+      dest->channel(0)[i] = sin(2.0 * base::kPiDouble * f_ * pos_samples_++);
+    for (int i = 1; i < dest->channels(); ++i) {
+      memcpy(dest->channel(i), dest->channel(0),
+             max_frames * sizeof(*dest->channel(i)));
+    }
   }
+
+  if (on_more_data_callback_)
+    on_more_data_callback_.Run();
+
   return max_frames;
 }
 
@@ -143,14 +146,14 @@
 }
 
 void SineWaveAudioSource::CapSamples(int cap) {
-  base::AutoLock auto_lock(time_lock_);
+  base::AutoLock auto_lock(lock_);
   DCHECK_GT(cap, 0);
   cap_ = cap;
 }
 
 void SineWaveAudioSource::Reset() {
-  base::AutoLock auto_lock(time_lock_);
-  time_state_ = 0;
+  base::AutoLock auto_lock(lock_);
+  pos_samples_ = 0;
 }
 
 FileSource::FileSource(const AudioParameters& params,
diff --git a/media/audio/simple_sources.h b/media/audio/simple_sources.h
index ebc3aa3..6a55993 100644
--- a/media/audio/simple_sources.h
+++ b/media/audio/simple_sources.h
@@ -36,6 +36,14 @@
   void CapSamples(int cap);
   void Reset();
 
+  // Sets a callback to be called in OnMoreData(). The callback should be set
+  // only once before SineWaveAudioSource is passed to AudioOutputStream. It
+  // will be called on the same thread on which the stream calls OnMoreData(),
+  // which is usually different from the thread where the source is created.
+  void set_on_more_data_callback(base::RepeatingClosure on_more_data_callback) {
+    on_more_data_callback_ = on_more_data_callback;
+  }
+
   // Implementation of AudioSourceCallback.
   int OnMoreData(base::TimeDelta delay,
                  base::TimeTicks timestamp,
@@ -44,17 +52,27 @@
   void OnError() override;
 
   // The number of OnMoreData() and OnError() calls respectively.
-  int callbacks() { return callbacks_; }
+  int callbacks() {
+    base::AutoLock auto_lock(lock_);
+    return callbacks_;
+  }
+  int pos_samples() {
+    base::AutoLock auto_lock(lock_);
+    return pos_samples_;
+  }
   int errors() { return errors_; }
 
  protected:
   const int channels_;
   const double f_;
-  int time_state_ GUARDED_BY(time_lock_);
-  int cap_ GUARDED_BY(time_lock_);
-  int callbacks_;
-  int errors_;
-  base::Lock time_lock_;
+
+  base::RepeatingClosure on_more_data_callback_;
+
+  base::Lock lock_;
+  int pos_samples_ GUARDED_BY(lock_) = 0;
+  int cap_ GUARDED_BY(lock_) = 0;
+  int callbacks_ GUARDED_BY(lock_) = 0;
+  int errors_ = 0;
 };
 
 class MEDIA_EXPORT FileSource : public AudioOutputStream::AudioSourceCallback,
diff --git a/media/mojo/services/watch_time_recorder.cc b/media/mojo/services/watch_time_recorder.cc
index d837bd2..2eaba1ef 100644
--- a/media/mojo/services/watch_time_recorder.cc
+++ b/media/mojo/services/watch_time_recorder.cc
@@ -42,6 +42,7 @@
   kAom = 4,         // AomVideoDecoder
   kMojo = 5,        // MojoVideoDecoder
   kDecrypting = 6,  // DecryptingVideoDecoder
+  kDav1d = 7,       // Dav1dVideoDecoder
 };
 
 static AudioDecoderName ConvertAudioDecoderNameToEnum(const std::string& name) {
@@ -78,6 +79,8 @@
       return VideoDecoderName::kAom;
     case 0xb52d52f5:
       return VideoDecoderName::kDecrypting;
+    case 0xcd46efa0:
+      return VideoDecoderName::kDav1d;
     default:
       DLOG_IF(WARNING, !name.empty())
           << "Unknown decoder name encountered; metrics need updating: "
diff --git a/media/mojo/services/watch_time_recorder_unittest.cc b/media/mojo/services/watch_time_recorder_unittest.cc
index 404c7c3..026f662 100644
--- a/media/mojo/services/watch_time_recorder_unittest.cc
+++ b/media/mojo/services/watch_time_recorder_unittest.cc
@@ -1240,7 +1240,8 @@
   const std::string kDecoderNames[] = {
       "FFmpegAudioDecoder", "FFmpegVideoDecoder",     "GpuVideoDecoder",
       "MojoVideoDecoder",   "MojoAudioDecoder",       "VpxVideoDecoder",
-      "AomVideoDecoder",    "DecryptingAudioDecoder", "DecryptingVideoDecoder"};
+      "AomVideoDecoder",    "DecryptingAudioDecoder", "DecryptingVideoDecoder",
+      "Dav1dVideoDecoder"};
   printf("%18s = 0\n", "None");
   for (const auto& name : kDecoderNames)
     printf("%18s = 0x%x\n", name.c_str(), base::PersistentHash(name));
diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc
index 6e311e2..edede57 100644
--- a/net/base/network_change_notifier.cc
+++ b/net/base/network_change_notifier.cc
@@ -8,6 +8,7 @@
 #include <unordered_set>
 
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/synchronization/lock.h"
@@ -62,10 +63,10 @@
     NetworkChangeNotifier::kInvalidNetworkHandle = -1;
 
 // NetworkState is thread safe.
-class NetworkChangeNotifier::NetworkState {
+class NetworkChangeNotifier::NetworkState
+    : public base::RefCountedThreadSafe<NetworkChangeNotifier::NetworkState> {
  public:
   NetworkState() = default;
-  ~NetworkState() = default;
 
   void GetDnsConfig(DnsConfig* config) const {
     base::AutoLock lock(lock_);
@@ -86,6 +87,9 @@
   }
 
  private:
+  friend class base::RefCountedThreadSafe<NetworkState>;
+  ~NetworkState() = default;
+
   mutable base::Lock lock_;
   DnsConfig dns_config_;
   bool set_ = false;
@@ -382,7 +386,9 @@
   if (!g_network_change_notifier) {
     *config = DnsConfig();
   } else {
-    g_network_change_notifier->network_state_->GetDnsConfig(config);
+    scoped_refptr<NetworkState> network_state =
+        g_network_change_notifier->network_state_;
+    network_state->GetDnsConfig(config);
   }
 }
 
@@ -799,7 +805,9 @@
 void NetworkChangeNotifier::SetDnsConfig(const DnsConfig& config) {
   if (!g_network_change_notifier)
     return;
-  if (g_network_change_notifier->network_state_->SetDnsConfig(config)) {
+  scoped_refptr<NetworkState> network_state =
+      g_network_change_notifier->network_state_;
+  if (network_state->SetDnsConfig(config)) {
     NotifyObserversOfDNSChange();
   } else {
     NotifyObserversOfInitialDNSConfigRead();
@@ -809,7 +817,9 @@
 void NetworkChangeNotifier::ClearDnsConfigForTesting() {
   if (!g_network_change_notifier)
     return;
-  g_network_change_notifier->network_state_->ClearDnsConfigForTesting();
+  scoped_refptr<NetworkState> network_state =
+      g_network_change_notifier->network_state_;
+  network_state->ClearDnsConfigForTesting();
 }
 
 void NetworkChangeNotifier::NotifyObserversOfIPAddressChangeImpl() {
diff --git a/net/base/network_change_notifier.h b/net/base/network_change_notifier.h
index 899ed75..8ecd7073 100644
--- a/net/base/network_change_notifier.h
+++ b/net/base/network_change_notifier.h
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/observer_list_threadsafe.h"
 #include "base/time/time.h"
 #include "net/base/net_export.h"
@@ -595,7 +596,7 @@
       network_observer_list_;
 
   // The current network state. Hosts DnsConfig, exposed via GetDnsConfig.
-  std::unique_ptr<NetworkState> network_state_;
+  scoped_refptr<NetworkState> network_state_;
 
   // Computes NetworkChange signal from IPAddress and ConnectionType signals.
   std::unique_ptr<NetworkChangeCalculator> network_change_calculator_;
diff --git a/remoting/host/DEPS b/remoting/host/DEPS
index 0452442a..a8ecaa0 100644
--- a/remoting/host/DEPS
+++ b/remoting/host/DEPS
@@ -37,4 +37,7 @@
   ".*unittest\.cc": [
     "+mojo/core/test",
   ],
+  ".*chromeos\.cc": [
+    "+ui/ozone/public",
+  ],
 }
diff --git a/remoting/host/basic_desktop_environment.cc b/remoting/host/basic_desktop_environment.cc
index 359e6e654..41de2b8 100644
--- a/remoting/host/basic_desktop_environment.cc
+++ b/remoting/host/basic_desktop_environment.cc
@@ -53,8 +53,7 @@
 std::unique_ptr<InputInjector> BasicDesktopEnvironment::CreateInputInjector() {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
 
-  return InputInjector::Create(input_task_runner(), ui_task_runner(),
-                               system_input_injector_factory());
+  return InputInjector::Create(input_task_runner(), ui_task_runner());
 }
 
 std::unique_ptr<ScreenControls>
@@ -101,14 +100,12 @@
     scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-    ui::SystemInputInjectorFactory* system_input_injector_factory,
     base::WeakPtr<ClientSessionControl> client_session_control,
     const DesktopEnvironmentOptions& options)
     : caller_task_runner_(caller_task_runner),
       video_capture_task_runner_(video_capture_task_runner),
       input_task_runner_(input_task_runner),
       ui_task_runner_(ui_task_runner),
-      system_input_injector_factory_(system_input_injector_factory),
       client_session_control_(client_session_control),
       options_(options) {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
@@ -131,13 +128,11 @@
     scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-    ui::SystemInputInjectorFactory* system_input_injector_factory)
+    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
     : caller_task_runner_(caller_task_runner),
       video_capture_task_runner_(video_capture_task_runner),
       input_task_runner_(input_task_runner),
-      ui_task_runner_(ui_task_runner),
-      system_input_injector_factory_(system_input_injector_factory) {}
+      ui_task_runner_(ui_task_runner) {}
 
 BasicDesktopEnvironmentFactory::~BasicDesktopEnvironmentFactory() = default;
 
diff --git a/remoting/host/basic_desktop_environment.h b/remoting/host/basic_desktop_environment.h
index 1c6f8e2..bb2e60d 100644
--- a/remoting/host/basic_desktop_environment.h
+++ b/remoting/host/basic_desktop_environment.h
@@ -18,10 +18,6 @@
 class SingleThreadTaskRunner;
 }
 
-namespace ui {
-class SystemInputInjectorFactory;
-}
-
 namespace webrtc {
 
 class DesktopCaptureOptions;
@@ -57,7 +53,6 @@
       scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-      ui::SystemInputInjectorFactory* system_input_injector_factory,
       base::WeakPtr<ClientSessionControl> client_session_control,
       const DesktopEnvironmentOptions& options);
 
@@ -86,10 +81,6 @@
     return *options_.desktop_capture_options();
   }
 
-  ui::SystemInputInjectorFactory* system_input_injector_factory() const {
-    return system_input_injector_factory_;
-  }
-
   const DesktopEnvironmentOptions& desktop_environment_options() const {
     return options_;
   }
@@ -108,9 +99,6 @@
   // Used to run UI code.
   scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
 
-  // Passed to InputInjector.
-  ui::SystemInputInjectorFactory* system_input_injector_factory_;
-
   // Used to send messages directly to the client session.
   base::WeakPtr<ClientSessionControl> client_session_control_;
 
@@ -126,8 +114,7 @@
       scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-      ui::SystemInputInjectorFactory* system_input_injector_factory);
+      scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
   ~BasicDesktopEnvironmentFactory() override;
 
   // DesktopEnvironmentFactory implementation.
@@ -151,10 +138,6 @@
     return ui_task_runner_;
   }
 
-  ui::SystemInputInjectorFactory* system_input_injector_factory() const {
-    return system_input_injector_factory_;
-  }
-
  private:
   // Task runner on which methods of DesktopEnvironmentFactory interface should
   // be called.
@@ -169,9 +152,6 @@
   // Used to run UI code.
   scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
 
-  // Passed to the environments built.
-  ui::SystemInputInjectorFactory* system_input_injector_factory_;
-
   DISALLOW_COPY_AND_ASSIGN(BasicDesktopEnvironmentFactory);
 };
 
diff --git a/remoting/host/chromoting_host_context.cc b/remoting/host/chromoting_host_context.cc
index c4a66d9b..853c069 100644
--- a/remoting/host/chromoting_host_context.cc
+++ b/remoting/host/chromoting_host_context.cc
@@ -36,8 +36,7 @@
     scoped_refptr<AutoThreadTaskRunner> network_task_runner,
     scoped_refptr<AutoThreadTaskRunner> video_capture_task_runner,
     scoped_refptr<AutoThreadTaskRunner> video_encode_task_runner,
-    scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
-    ui::SystemInputInjectorFactory* system_input_injector_factory)
+    scoped_refptr<net::URLRequestContextGetter> url_request_context_getter)
     : ui_task_runner_(ui_task_runner),
       audio_task_runner_(audio_task_runner),
       file_task_runner_(file_task_runner),
@@ -45,8 +44,7 @@
       network_task_runner_(network_task_runner),
       video_capture_task_runner_(video_capture_task_runner),
       video_encode_task_runner_(video_encode_task_runner),
-      url_request_context_getter_(url_request_context_getter),
-      system_input_injector_factory_(system_input_injector_factory) {}
+      url_request_context_getter_(url_request_context_getter) {}
 
 ChromotingHostContext::~ChromotingHostContext() {
   if (url_loader_factory_owner_)
@@ -58,8 +56,7 @@
   return base::WrapUnique(new ChromotingHostContext(
       ui_task_runner_, audio_task_runner_, file_task_runner_,
       input_task_runner_, network_task_runner_, video_capture_task_runner_,
-      video_encode_task_runner_, url_request_context_getter_,
-      system_input_injector_factory_));
+      video_encode_task_runner_, url_request_context_getter_));
 }
 
 scoped_refptr<AutoThreadTaskRunner> ChromotingHostContext::audio_task_runner()
@@ -113,11 +110,6 @@
   return url_loader_factory_owner_->GetURLLoaderFactory();
 }
 
-ui::SystemInputInjectorFactory*
-ChromotingHostContext::system_input_injector_factory() const {
-  return system_input_injector_factory_;
-}
-
 std::unique_ptr<ChromotingHostContext> ChromotingHostContext::Create(
     scoped_refptr<AutoThreadTaskRunner> ui_task_runner) {
 #if defined(OS_WIN)
@@ -155,8 +147,7 @@
       AutoThread::Create("ChromotingCaptureThread", ui_task_runner),
 #endif
       AutoThread::Create("ChromotingEncodeThread", ui_task_runner),
-      base::MakeRefCounted<URLRequestContextGetter>(network_task_runner),
-      nullptr));
+      base::MakeRefCounted<URLRequestContextGetter>(network_task_runner)));
 }
 
 #if defined(OS_CHROMEOS)
@@ -165,9 +156,7 @@
 std::unique_ptr<ChromotingHostContext> ChromotingHostContext::CreateForChromeOS(
     scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> file_task_runner,
-    ui::SystemInputInjectorFactory* system_input_injector_factory) {
-
+    scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) {
   // AutoThreadTaskRunner is a TaskRunner with the special property that it will
   // continue to process tasks until no references remain, at least. The
   // QuitClosure we usually pass does the simple thing of stopping the
@@ -191,8 +180,7 @@
       io_auto_task_runner,  // network_task_runner
       ui_auto_task_runner,  // video_capture_task_runner
       AutoThread::Create("ChromotingEncodeThread", file_auto_task_runner),
-      base::MakeRefCounted<URLRequestContextGetter>(io_auto_task_runner),
-      system_input_injector_factory));
+      base::MakeRefCounted<URLRequestContextGetter>(io_auto_task_runner)));
 }
 #endif  // defined(OS_CHROMEOS)
 
diff --git a/remoting/host/chromoting_host_context.h b/remoting/host/chromoting_host_context.h
index b223f27..e860c339 100644
--- a/remoting/host/chromoting_host_context.h
+++ b/remoting/host/chromoting_host_context.h
@@ -24,10 +24,6 @@
 class TransitionalURLLoaderFactoryOwner;
 }  // namespace network
 
-namespace ui {
-class SystemInputInjectorFactory;
-}  // namespace ui
-
 namespace remoting {
 
 class AutoThreadTaskRunner;
@@ -56,8 +52,7 @@
   static std::unique_ptr<ChromotingHostContext> CreateForChromeOS(
       scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> file_task_runner,
-      ui::SystemInputInjectorFactory* system_input_injector_factory);
+      scoped_refptr<base::SingleThreadTaskRunner> file_task_runner);
 #endif  // defined(OS_CHROMEOS)
 
   ~ChromotingHostContext();
@@ -98,13 +93,6 @@
 
   scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory();
 
-  // Gives the factory which builds the SystemInputInjector, which takes events
-  // and passes them to the system for dispatch.
-  //
-  // Currently only implemented on chromeos, but as mus usage comes to the
-  // desktop, this will be used everywhere.
-  ui::SystemInputInjectorFactory* system_input_injector_factory() const;
-
  private:
   ChromotingHostContext(
       scoped_refptr<AutoThreadTaskRunner> ui_task_runner,
@@ -114,8 +102,7 @@
       scoped_refptr<AutoThreadTaskRunner> network_task_runner,
       scoped_refptr<AutoThreadTaskRunner> video_capture_task_runner,
       scoped_refptr<AutoThreadTaskRunner> video_encode_task_runner,
-      scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
-      ui::SystemInputInjectorFactory* system_input_injector_factory);
+      scoped_refptr<net::URLRequestContextGetter> url_request_context_getter);
 
   // Caller-supplied UI thread. This is usually the application main thread.
   scoped_refptr<AutoThreadTaskRunner> ui_task_runner_;
@@ -145,10 +132,6 @@
   std::unique_ptr<network::TransitionalURLLoaderFactoryOwner>
       url_loader_factory_owner_;
 
-  // A factory which makes a SystemInputInjector. Currently only non-null on
-  // chromeos, though it's intended to be set everywhere mus is used.
-  ui::SystemInputInjectorFactory* system_input_injector_factory_;
-
   DISALLOW_COPY_AND_ASSIGN(ChromotingHostContext);
 };
 
diff --git a/remoting/host/desktop_process_main.cc b/remoting/host/desktop_process_main.cc
index f8be3c0..ac95b3eb 100644
--- a/remoting/host/desktop_process_main.cc
+++ b/remoting/host/desktop_process_main.cc
@@ -85,11 +85,11 @@
 
   desktop_environment_factory.reset(new SessionDesktopEnvironmentFactory(
       ui_task_runner, video_capture_task_runner, input_task_runner,
-      ui_task_runner, nullptr, inject_sas_closure, lock_workstation_closure));
+      ui_task_runner, inject_sas_closure, lock_workstation_closure));
 #else  // !defined(OS_WIN)
   desktop_environment_factory.reset(new Me2MeDesktopEnvironmentFactory(
       ui_task_runner, video_capture_task_runner, input_task_runner,
-      ui_task_runner, nullptr));
+      ui_task_runner));
 #endif  // !defined(OS_WIN)
 
   if (!desktop_process.Start(std::move(desktop_environment_factory)))
diff --git a/remoting/host/input_injector.h b/remoting/host/input_injector.h
index d9cf23b4..20169c4 100644
--- a/remoting/host/input_injector.h
+++ b/remoting/host/input_injector.h
@@ -15,10 +15,6 @@
 class SingleThreadTaskRunner;
 }  // namespace base
 
-namespace ui {
-class SystemInputInjectorFactory;
-}  // namespace ui
-
 namespace remoting {
 
 // TODO(sergeyu): Move ClipboardStub implementation to Clipboard.
@@ -31,8 +27,7 @@
   // thread.
   static std::unique_ptr<InputInjector> Create(
       scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-      ui::SystemInputInjectorFactory* chromeos_system_input_injector_factory);
+      scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
 
   // Returns true if the InputInjector returned by Create() supports
   // InjectTouchEvent() on this platform.
diff --git a/remoting/host/input_injector_chromeos.cc b/remoting/host/input_injector_chromeos.cc
index 7d23621..caf55ce 100644
--- a/remoting/host/input_injector_chromeos.cc
+++ b/remoting/host/input_injector_chromeos.cc
@@ -19,7 +19,8 @@
 #include "ui/base/ime/chromeos/input_method_manager.h"
 #include "ui/events/keycodes/dom/dom_code.h"
 #include "ui/events/keycodes/dom/keycode_converter.h"
-#include "ui/events/system_input_injector.h"
+#include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/system_input_injector.h"
 
 namespace remoting {
 
@@ -78,7 +79,7 @@
 // This class is run exclusively on the UI thread of the browser process.
 class InputInjectorChromeos::Core {
  public:
-  Core(ui::SystemInputInjectorFactory* system_input_injector_factory);
+  Core();
 
   // Mirrors the public InputInjectorChromeos interface.
   void InjectClipboardEvent(const ClipboardEvent& event);
@@ -97,16 +98,10 @@
   // display rotation settings.
   std::unique_ptr<PointTransformer> point_transformer_;
 
-  // Creates |delegate_|. We store this since Core is created on one thread,
-  // but then Start() is run on a different one.
-  ui::SystemInputInjectorFactory* system_input_injector_factory_;
-
   DISALLOW_COPY_AND_ASSIGN(Core);
 };
 
-InputInjectorChromeos::Core::Core(
-    ui::SystemInputInjectorFactory* system_input_injector_factory)
-    : system_input_injector_factory_(system_input_injector_factory) {}
+InputInjectorChromeos::Core::Core() = default;
 
 void InputInjectorChromeos::Core::InjectClipboardEvent(
     const ClipboardEvent& event) {
@@ -157,8 +152,7 @@
 
 void InputInjectorChromeos::Core::Start(
     std::unique_ptr<protocol::ClipboardStub> client_clipboard) {
-  // OK, so we now need to plumb from ChromotingHostContext to here.
-  delegate_ = system_input_injector_factory_->CreateSystemInputInjector();
+  delegate_ = ui::OzonePlatform::GetInstance()->CreateSystemInputInjector();
   DCHECK(delegate_);
 
   // Implemented by remoting::ClipboardAura.
@@ -168,11 +162,8 @@
 }
 
 InputInjectorChromeos::InputInjectorChromeos(
-    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-    ui::SystemInputInjectorFactory* system_input_injector_factory)
-    : input_task_runner_(task_runner) {
-  core_.reset(new Core(system_input_injector_factory));
-}
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+    : input_task_runner_(task_runner), core_(std::make_unique<Core>()) {}
 
 InputInjectorChromeos::~InputInjectorChromeos() {
   input_task_runner_->DeleteSoon(FROM_HERE, core_.release());
@@ -216,12 +207,10 @@
 // static
 std::unique_ptr<InputInjector> InputInjector::Create(
     scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-    ui::SystemInputInjectorFactory* system_input_injector_factory) {
+    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
   // The Ozone input injector must be called on the UI task runner of the
   // browser process.
-  return base::WrapUnique(
-      new InputInjectorChromeos(ui_task_runner, system_input_injector_factory));
+  return base::WrapUnique(new InputInjectorChromeos(ui_task_runner));
 }
 
 // static
diff --git a/remoting/host/input_injector_chromeos.h b/remoting/host/input_injector_chromeos.h
index 279e290..802edd05c 100644
--- a/remoting/host/input_injector_chromeos.h
+++ b/remoting/host/input_injector_chromeos.h
@@ -5,6 +5,8 @@
 #ifndef REMOTING_HOST_INPUT_INJECTOR_CHROMEOS_H_
 #define REMOTING_HOST_INPUT_INJECTOR_CHROMEOS_H_
 
+#include <memory>
+
 #include "base/macros.h"
 #include "base/single_thread_task_runner.h"
 #include "remoting/host/input_injector.h"
@@ -16,8 +18,7 @@
 class InputInjectorChromeos : public InputInjector {
  public:
   explicit InputInjectorChromeos(
-      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-      ui::SystemInputInjectorFactory* chromeos_system_input_injector_factory);
+      scoped_refptr<base::SingleThreadTaskRunner> task_runner);
 
   ~InputInjectorChromeos() override;
 
diff --git a/remoting/host/input_injector_mac.cc b/remoting/host/input_injector_mac.cc
index d2d32a9a..30c00e2c 100644
--- a/remoting/host/input_injector_mac.cc
+++ b/remoting/host/input_injector_mac.cc
@@ -397,8 +397,7 @@
 // static
 std::unique_ptr<InputInjector> InputInjector::Create(
     scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-    ui::SystemInputInjectorFactory* chromeos_system_input_injector_factory) {
+    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
   return base::WrapUnique(new InputInjectorMac(main_task_runner));
 }
 
diff --git a/remoting/host/input_injector_win.cc b/remoting/host/input_injector_win.cc
index 6c505a62..9f030af 100644
--- a/remoting/host/input_injector_win.cc
+++ b/remoting/host/input_injector_win.cc
@@ -458,8 +458,7 @@
 // static
 std::unique_ptr<InputInjector> InputInjector::Create(
     scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-    ui::SystemInputInjectorFactory* chromeos_system_input_injector_factory) {
+    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
   return base::WrapUnique(
       new InputInjectorWin(main_task_runner, ui_task_runner));
 }
diff --git a/remoting/host/input_injector_x11.cc b/remoting/host/input_injector_x11.cc
index 0a83808f..9975c65 100644
--- a/remoting/host/input_injector_x11.cc
+++ b/remoting/host/input_injector_x11.cc
@@ -711,8 +711,7 @@
 // static
 std::unique_ptr<InputInjector> InputInjector::Create(
     scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-    ui::SystemInputInjectorFactory* chromeos_system_input_injector_factory) {
+    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
   std::unique_ptr<InputInjectorX11> injector(
       new InputInjectorX11(main_task_runner));
   if (!injector->Init())
diff --git a/remoting/host/it2me/it2me_host.cc b/remoting/host/it2me/it2me_host.cc
index 0661bd9..e5ecca84 100644
--- a/remoting/host/it2me/it2me_host.cc
+++ b/remoting/host/it2me/it2me_host.cc
@@ -106,8 +106,7 @@
   desktop_environment_factory_.reset(new It2MeDesktopEnvironmentFactory(
       host_context_->network_task_runner(),
       host_context_->video_capture_task_runner(),
-      host_context_->input_task_runner(), host_context_->ui_task_runner(),
-      host_context_->system_input_injector_factory()));
+      host_context_->input_task_runner(), host_context_->ui_task_runner()));
 
   // Switch to the network thread to start the actual connection.
   host_context_->network_task_runner()->PostTask(
diff --git a/remoting/host/it2me/it2me_native_messaging_host_chromeos.cc b/remoting/host/it2me/it2me_native_messaging_host_chromeos.cc
index 79376bd..16c9ac0 100644
--- a/remoting/host/it2me/it2me_native_messaging_host_chromeos.cc
+++ b/remoting/host/it2me/it2me_native_messaging_host_chromeos.cc
@@ -13,41 +13,6 @@
 #include "remoting/host/chromoting_host_context.h"
 #include "remoting/host/it2me/it2me_native_messaging_host.h"
 #include "remoting/host/policy_watcher.h"
-#include "ui/events/system_input_injector.h"
-
-#if defined(USE_OZONE)
-#include "ui/ozone/public/ozone_platform.h"
-#endif
-
-namespace {
-
-#if defined(USE_OZONE)
-class OzoneSystemInputInjectorAdaptor
-    : public ::ui::SystemInputInjectorFactory {
- public:
-  std::unique_ptr<ui::SystemInputInjector> CreateSystemInputInjector()
-      override {
-    return ui::OzonePlatform::GetInstance()->CreateSystemInputInjector();
-  }
-};
-
-base::LazyInstance<OzoneSystemInputInjectorAdaptor>::Leaky
-    g_ozone_system_input_injector_adaptor = LAZY_INSTANCE_INITIALIZER;
-#endif
-
-ui::SystemInputInjectorFactory* GetInputInjector() {
-  ui::SystemInputInjectorFactory* system = ui::GetSystemInputInjectorFactory();
-  if (system)
-    return system;
-
-#if defined(USE_OZONE)
-  return g_ozone_system_input_injector_adaptor.Pointer();
-#endif
-
-  return nullptr;
-}
-
-}  // namespace
 
 namespace remoting {
 
@@ -61,8 +26,7 @@
       ChromotingHostContext::CreateForChromeOS(
           io_runnner, ui_runnner,
           base::CreateSingleThreadTaskRunnerWithTraits(
-              {base::MayBlock(), base::TaskPriority::BEST_EFFORT}),
-          GetInputInjector());
+              {base::MayBlock(), base::TaskPriority::BEST_EFFORT}));
   std::unique_ptr<PolicyWatcher> policy_watcher =
       PolicyWatcher::CreateWithPolicyService(policy_service);
   std::unique_ptr<extensions::NativeMessageHost> host(
diff --git a/remoting/host/it2me_desktop_environment.cc b/remoting/host/it2me_desktop_environment.cc
index 4203732..7f66480 100644
--- a/remoting/host/it2me_desktop_environment.cc
+++ b/remoting/host/it2me_desktop_environment.cc
@@ -31,14 +31,12 @@
     scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-    ui::SystemInputInjectorFactory* system_input_injector_factory,
     base::WeakPtr<ClientSessionControl> client_session_control,
     const DesktopEnvironmentOptions& options)
     : BasicDesktopEnvironment(caller_task_runner,
                               video_capture_task_runner,
                               input_task_runner,
                               ui_task_runner,
-                              system_input_injector_factory,
                               client_session_control,
                               options) {
   DCHECK(caller_task_runner->BelongsToCurrentThread());
@@ -79,13 +77,11 @@
     scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-    ui::SystemInputInjectorFactory* system_input_injector_factory)
+    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
     : BasicDesktopEnvironmentFactory(caller_task_runner,
                                      video_capture_task_runner,
                                      input_task_runner,
-                                     ui_task_runner,
-                                     system_input_injector_factory) {}
+                                     ui_task_runner) {}
 
 It2MeDesktopEnvironmentFactory::~It2MeDesktopEnvironmentFactory() = default;
 
@@ -96,8 +92,7 @@
 
   return base::WrapUnique(new It2MeDesktopEnvironment(
       caller_task_runner(), video_capture_task_runner(), input_task_runner(),
-      ui_task_runner(), system_input_injector_factory(), client_session_control,
-      options));
+      ui_task_runner(), client_session_control, options));
 }
 
 }  // namespace remoting
diff --git a/remoting/host/it2me_desktop_environment.h b/remoting/host/it2me_desktop_environment.h
index daf54cf..6756dc6 100644
--- a/remoting/host/it2me_desktop_environment.h
+++ b/remoting/host/it2me_desktop_environment.h
@@ -30,7 +30,6 @@
       scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-      ui::SystemInputInjectorFactory* system_input_injector_factory,
       base::WeakPtr<ClientSessionControl> client_session_control,
       const DesktopEnvironmentOptions& options);
 
@@ -54,8 +53,7 @@
       scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-      ui::SystemInputInjectorFactory* system_input_injector_factory);
+      scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
   ~It2MeDesktopEnvironmentFactory() override;
 
   // DesktopEnvironmentFactory interface.
diff --git a/remoting/host/me2me_desktop_environment.cc b/remoting/host/me2me_desktop_environment.cc
index 49a7060b..1d16dad 100644
--- a/remoting/host/me2me_desktop_environment.cc
+++ b/remoting/host/me2me_desktop_environment.cc
@@ -92,14 +92,12 @@
     scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-    ui::SystemInputInjectorFactory* system_input_injector_factory,
     base::WeakPtr<ClientSessionControl> client_session_control,
     const DesktopEnvironmentOptions& options)
     : BasicDesktopEnvironment(caller_task_runner,
                               video_capture_task_runner,
                               input_task_runner,
                               ui_task_runner,
-                              system_input_injector_factory,
                               client_session_control,
                               options) {
   DCHECK(caller_task_runner->BelongsToCurrentThread());
@@ -174,13 +172,11 @@
     scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
-    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-    ui::SystemInputInjectorFactory* system_input_injector_factory)
+    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
     : BasicDesktopEnvironmentFactory(caller_task_runner,
                                      video_capture_task_runner,
                                      input_task_runner,
-                                     ui_task_runner,
-                                     system_input_injector_factory) {}
+                                     ui_task_runner) {}
 
 Me2MeDesktopEnvironmentFactory::~Me2MeDesktopEnvironmentFactory() {
 }
@@ -191,10 +187,10 @@
   DCHECK(caller_task_runner()->BelongsToCurrentThread());
 
   std::unique_ptr<Me2MeDesktopEnvironment> desktop_environment(
-      new Me2MeDesktopEnvironment(
-          caller_task_runner(), video_capture_task_runner(),
-          input_task_runner(), ui_task_runner(),
-          system_input_injector_factory(), client_session_control, options));
+      new Me2MeDesktopEnvironment(caller_task_runner(),
+                                  video_capture_task_runner(),
+                                  input_task_runner(), ui_task_runner(),
+                                  client_session_control, options));
   if (!desktop_environment->InitializeSecurity(client_session_control)) {
     return nullptr;
   }
diff --git a/remoting/host/me2me_desktop_environment.h b/remoting/host/me2me_desktop_environment.h
index df16816b..535820b 100644
--- a/remoting/host/me2me_desktop_environment.h
+++ b/remoting/host/me2me_desktop_environment.h
@@ -33,7 +33,6 @@
       scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-      ui::SystemInputInjectorFactory* system_input_injector_factory,
       base::WeakPtr<ClientSessionControl> client_session_control,
       const DesktopEnvironmentOptions& options);
 
@@ -63,8 +62,7 @@
       scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
-      scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-      ui::SystemInputInjectorFactory* system_input_injector_factory);
+      scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
   ~Me2MeDesktopEnvironmentFactory() override;
 
   // DesktopEnvironmentFactory interface.
diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc
index f6286fd8..f916cb2 100644
--- a/remoting/host/remoting_me2me_host.cc
+++ b/remoting/host/remoting_me2me_host.cc
@@ -910,13 +910,11 @@
   if (enable_window_capture_) {
     desktop_environment_factory = new SingleWindowDesktopEnvironmentFactory(
         context_->network_task_runner(), context_->video_capture_task_runner(),
-        context_->input_task_runner(), context_->ui_task_runner(),
-        context_->system_input_injector_factory(), window_id_);
+        context_->input_task_runner(), context_->ui_task_runner(), window_id_);
   } else {
     desktop_environment_factory = new Me2MeDesktopEnvironmentFactory(
         context_->network_task_runner(), context_->video_capture_task_runner(),
-        context_->input_task_runner(), context_->ui_task_runner(),
-        context_->system_input_injector_factory());
+        context_->input_task_runner(), context_->ui_task_runner());
   }
 #endif  // !defined(REMOTING_MULTI_PROCESS)
 
diff --git a/remoting/host/single_window_desktop_environment.cc b/remoting/host/single_window_desktop_environment.cc
index b85d85e..ef666ea 100644
--- a/remoting/host/single_window_desktop_environment.cc
+++ b/remoting/host/single_window_desktop_environment.cc
@@ -33,7 +33,6 @@
       scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-      ui::SystemInputInjectorFactory* system_input_injector_factory,
       webrtc::DesktopCapturer::SourceId window_id,
       base::WeakPtr<ClientSessionControl> client_session_control,
       const DesktopEnvironmentOptions& options);
@@ -65,8 +64,8 @@
 SingleWindowDesktopEnvironment::CreateInputInjector() {
   DCHECK(caller_task_runner()->BelongsToCurrentThread());
 
-  std::unique_ptr<InputInjector> input_injector(InputInjector::Create(
-      input_task_runner(), ui_task_runner(), system_input_injector_factory()));
+  std::unique_ptr<InputInjector> input_injector(
+      InputInjector::Create(input_task_runner(), ui_task_runner()));
   return SingleWindowInputInjector::CreateForWindow(
              window_id_, std::move(input_injector));
 }
@@ -76,7 +75,6 @@
     scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-    ui::SystemInputInjectorFactory* system_input_injector_factory,
     webrtc::WindowId window_id,
     base::WeakPtr<ClientSessionControl> client_session_control,
     const DesktopEnvironmentOptions& options)
@@ -84,7 +82,6 @@
                               video_capture_task_runner,
                               input_task_runner,
                               ui_task_runner,
-                              system_input_injector_factory,
                               client_session_control,
                               options),
       window_id_(window_id) {}
@@ -94,13 +91,11 @@
     scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-    ui::SystemInputInjectorFactory* system_input_injector_factory,
     webrtc::WindowId window_id)
     : BasicDesktopEnvironmentFactory(caller_task_runner,
                                      video_capture_task_runner,
                                      input_task_runner,
-                                     ui_task_runner,
-                                     system_input_injector_factory),
+                                     ui_task_runner),
       window_id_(window_id) {}
 
 SingleWindowDesktopEnvironmentFactory::
@@ -114,8 +109,7 @@
 
   return base::WrapUnique(new SingleWindowDesktopEnvironment(
       caller_task_runner(), video_capture_task_runner(), input_task_runner(),
-      ui_task_runner(), system_input_injector_factory(), window_id_,
-      client_session_control, options));
+      ui_task_runner(), window_id_, client_session_control, options));
 }
 
 }  // namespace remoting
diff --git a/remoting/host/single_window_desktop_environment.h b/remoting/host/single_window_desktop_environment.h
index 10276ed3..83e2978d 100644
--- a/remoting/host/single_window_desktop_environment.h
+++ b/remoting/host/single_window_desktop_environment.h
@@ -22,7 +22,6 @@
       scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-      ui::SystemInputInjectorFactory* system_input_injector_factory,
       webrtc::WindowId window_id);
   ~SingleWindowDesktopEnvironmentFactory() override;
 
diff --git a/remoting/host/win/session_desktop_environment.cc b/remoting/host/win/session_desktop_environment.cc
index d959749..d4dda99b 100644
--- a/remoting/host/win/session_desktop_environment.cc
+++ b/remoting/host/win/session_desktop_environment.cc
@@ -35,8 +35,7 @@
 
   return std::make_unique<SessionInputInjectorWin>(
       input_task_runner(),
-      InputInjector::Create(input_task_runner(), ui_task_runner(),
-                            system_input_injector_factory()),
+      InputInjector::Create(input_task_runner(), ui_task_runner()),
       ui_task_runner(), inject_sas_, lock_workstation_);
 }
 
@@ -45,7 +44,6 @@
     scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-    ui::SystemInputInjectorFactory* system_input_injector_factory,
     base::WeakPtr<ClientSessionControl> client_session_control,
     const base::RepeatingClosure& inject_sas,
     const base::RepeatingClosure& lock_workstation,
@@ -54,7 +52,6 @@
                               video_capture_task_runner,
                               input_task_runner,
                               ui_task_runner,
-                              system_input_injector_factory,
                               client_session_control,
                               options),
       inject_sas_(inject_sas),
@@ -65,14 +62,12 @@
     scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-    ui::SystemInputInjectorFactory* system_input_injector_factory,
     const base::RepeatingClosure& inject_sas,
     const base::RepeatingClosure& lock_workstation)
     : Me2MeDesktopEnvironmentFactory(caller_task_runner,
                                      video_capture_task_runner,
                                      input_task_runner,
-                                     ui_task_runner,
-                                     system_input_injector_factory),
+                                     ui_task_runner),
       inject_sas_(inject_sas),
       lock_workstation_(lock_workstation) {
   DCHECK(caller_task_runner->BelongsToCurrentThread());
@@ -88,9 +83,8 @@
   std::unique_ptr<SessionDesktopEnvironment> desktop_environment(
       new SessionDesktopEnvironment(
           caller_task_runner(), video_capture_task_runner(),
-          input_task_runner(), ui_task_runner(),
-          system_input_injector_factory(), client_session_control, inject_sas_,
-          lock_workstation_, options));
+          input_task_runner(), ui_task_runner(), client_session_control,
+          inject_sas_, lock_workstation_, options));
   if (!desktop_environment->InitializeSecurity(client_session_control)) {
     return nullptr;
   }
diff --git a/remoting/host/win/session_desktop_environment.h b/remoting/host/win/session_desktop_environment.h
index 226bdc1..662c92e 100644
--- a/remoting/host/win/session_desktop_environment.h
+++ b/remoting/host/win/session_desktop_environment.h
@@ -31,7 +31,6 @@
       scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-      ui::SystemInputInjectorFactory* system_input_injector_factory,
       base::WeakPtr<ClientSessionControl> client_session_control,
       const base::RepeatingClosure& inject_sas,
       const base::RepeatingClosure& lock_workstation,
@@ -54,7 +53,6 @@
       scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
-      ui::SystemInputInjectorFactory* system_input_injector_factory,
       const base::RepeatingClosure& inject_sas,
       const base::RepeatingClosure& lock_workstation);
   ~SessionDesktopEnvironmentFactory() override;
diff --git a/remoting/protocol/channel_multiplexer_unittest.cc b/remoting/protocol/channel_multiplexer_unittest.cc
index 7b4b32e..c815812 100644
--- a/remoting/protocol/channel_multiplexer_unittest.cc
+++ b/remoting/protocol/channel_multiplexer_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/barrier_closure.h"
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/run_loop.h"
@@ -148,8 +149,9 @@
 
   StreamConnectionTester tester(host_socket.get(), client_socket.get(),
                                 kMessageSize, kMessages);
-  tester.Start();
-  base::RunLoop().Run();
+  base::RunLoop run_loop;
+  tester.Start(run_loop.QuitClosure());
+  run_loop.Run();
   tester.CheckResults();
 }
 
@@ -168,11 +170,11 @@
                                 kMessageSize, kMessages);
   StreamConnectionTester tester2(host_socket2_.get(), client_socket2_.get(),
                                  kMessageSize, kMessages);
-  tester1.Start();
-  tester2.Start();
-  while (!tester1.done() || !tester2.done()) {
-    base::RunLoop().Run();
-  }
+  base::RunLoop run_loop;
+  auto done_barrier = base::BarrierClosure(2, run_loop.QuitClosure());
+  tester1.Start(done_barrier);
+  tester2.Start(done_barrier);
+  run_loop.Run();
   tester1.CheckResults();
   tester2.CheckResults();
 }
@@ -207,14 +209,13 @@
                                  kMessageSize, kMessages);
   StreamConnectionTester tester4(client_socket4.get(), host_socket4.get(),
                                  kMessageSize, kMessages);
-  tester1.Start();
-  tester2.Start();
-  tester3.Start();
-  tester4.Start();
-  while (!tester1.done() || !tester2.done() ||
-         !tester3.done() || !tester4.done()) {
-    base::RunLoop().Run();
-  }
+  base::RunLoop run_loop;
+  auto done_barrier = base::BarrierClosure(4, run_loop.QuitClosure());
+  tester1.Start(done_barrier);
+  tester2.Start(done_barrier);
+  tester3.Start(done_barrier);
+  tester4.Start(done_barrier);
+  run_loop.Run();
   tester1.CheckResults();
   tester2.CheckResults();
   tester3.CheckResults();
diff --git a/remoting/protocol/connection_tester.cc b/remoting/protocol/connection_tester.cc
index 01b66ef2..5b149be0c 100644
--- a/remoting/protocol/connection_tester.cc
+++ b/remoting/protocol/connection_tester.cc
@@ -5,7 +5,6 @@
 #include "remoting/protocol/connection_tester.h"
 
 #include "base/bind.h"
-#include "base/threading/thread_task_runner_handle.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
@@ -23,18 +22,17 @@
                                                P2PStreamSocket* host_socket,
                                                int message_size,
                                                int message_count)
-    : task_runner_(base::ThreadTaskRunnerHandle::Get()),
-      host_socket_(host_socket),
+    : host_socket_(host_socket),
       client_socket_(client_socket),
       message_size_(message_size),
       test_data_size_(message_size * message_count),
-      done_(false),
       write_errors_(0),
       read_errors_(0) {}
 
 StreamConnectionTester::~StreamConnectionTester() = default;
 
-void StreamConnectionTester::Start() {
+void StreamConnectionTester::Start(base::OnceClosure on_done) {
+  on_done_ = std::move(on_done);
   InitBuffers();
   DoRead();
   DoWrite();
@@ -54,9 +52,7 @@
 }
 
 void StreamConnectionTester::Done() {
-  done_ = true;
-  task_runner_->PostTask(FROM_HERE,
-                         base::RunLoop::QuitCurrentWhenIdleClosureDeprecated());
+  std::move(on_done_).Run();
 }
 
 void StreamConnectionTester::InitBuffers() {
@@ -114,7 +110,7 @@
 
 void StreamConnectionTester::OnRead(int result) {
   HandleReadResult(result);
-  if (!done_)
+  if (!on_done_.is_null())
     DoRead();  // Don't try to read again when we are done reading.
 }
 
@@ -131,137 +127,6 @@
   }
 }
 
-DatagramConnectionTester::DatagramConnectionTester(
-    P2PDatagramSocket* client_socket,
-    P2PDatagramSocket* host_socket,
-    int message_size,
-    int message_count,
-    int delay_ms)
-    : task_runner_(base::ThreadTaskRunnerHandle::Get()),
-      host_socket_(host_socket),
-      client_socket_(client_socket),
-      message_size_(message_size),
-      message_count_(message_count),
-      delay_ms_(delay_ms),
-      done_(false),
-      write_errors_(0),
-      read_errors_(0),
-      packets_sent_(0),
-      packets_received_(0),
-      bad_packets_received_(0) {
-  sent_packets_.resize(message_count_);
-}
-
-DatagramConnectionTester::~DatagramConnectionTester() = default;
-
-void DatagramConnectionTester::Start() {
-  DoRead();
-  DoWrite();
-}
-
-void DatagramConnectionTester::CheckResults() {
-  EXPECT_EQ(0, write_errors_);
-  EXPECT_EQ(0, read_errors_);
-
-  EXPECT_EQ(0, bad_packets_received_);
-
-  // Verify that we've received at least one packet.
-  EXPECT_GT(packets_received_, 0);
-  VLOG(0) << "Received " << packets_received_ << " packets out of "
-          << message_count_;
-}
-
-void DatagramConnectionTester::Done() {
-  done_ = true;
-  task_runner_->PostTask(FROM_HERE,
-                         base::RunLoop::QuitCurrentWhenIdleClosureDeprecated());
-}
-
-void DatagramConnectionTester::DoWrite() {
-  if (packets_sent_ >= message_count_) {
-    Done();
-    return;
-  }
-
-  scoped_refptr<net::IOBuffer> packet(
-      base::MakeRefCounted<net::IOBuffer>(message_size_));
-  for (int i = 0; i < message_size_; ++i) {
-    packet->data()[i] = static_cast<char>(i);
-  }
-  sent_packets_[packets_sent_] = packet;
-  // Put index of this packet in the beginning of the packet body.
-  memcpy(packet->data(), &packets_sent_, sizeof(packets_sent_));
-
-  int result = client_socket_->Send(
-      packet.get(), message_size_,
-      base::Bind(&DatagramConnectionTester::OnWritten, base::Unretained(this)));
-  HandleWriteResult(result);
-}
-
-void DatagramConnectionTester::OnWritten(int result) {
-  HandleWriteResult(result);
-}
-
-void DatagramConnectionTester::HandleWriteResult(int result) {
-  if (result <= 0 && result != net::ERR_IO_PENDING) {
-    LOG(ERROR) << "Received error " << result << " when trying to write";
-    write_errors_++;
-    Done();
-  } else if (result > 0) {
-    EXPECT_EQ(message_size_, result);
-    packets_sent_++;
-    task_runner_->PostDelayedTask(
-        FROM_HERE,
-        base::BindOnce(&DatagramConnectionTester::DoWrite,
-                       base::Unretained(this)),
-        base::TimeDelta::FromMilliseconds(delay_ms_));
-  }
-}
-
-void DatagramConnectionTester::DoRead() {
-  int result = 1;
-  while (result > 0) {
-    int kReadSize = message_size_ * 2;
-    read_buffer_ = base::MakeRefCounted<net::IOBuffer>(kReadSize);
-
-    result = host_socket_->Recv(
-        read_buffer_.get(), kReadSize,
-        base::Bind(&DatagramConnectionTester::OnRead, base::Unretained(this)));
-    HandleReadResult(result);
-  };
-}
-
-void DatagramConnectionTester::OnRead(int result) {
-  HandleReadResult(result);
-  DoRead();
-}
-
-void DatagramConnectionTester::HandleReadResult(int result) {
-  if (result <= 0 && result != net::ERR_IO_PENDING) {
-    // Error will be received after the socket is closed.
-    LOG(ERROR) << "Received error " << result << " when trying to read";
-    read_errors_++;
-    Done();
-  } else if (result > 0) {
-    packets_received_++;
-    if (message_size_ != result) {
-      // Invalid packet size;
-      bad_packets_received_++;
-    } else {
-      // Validate packet body.
-      int packet_id;
-      memcpy(&packet_id, read_buffer_->data(), sizeof(packet_id));
-      if (packet_id < 0 || packet_id >= message_count_) {
-        bad_packets_received_++;
-      } else {
-        if (memcmp(read_buffer_->data(), sent_packets_[packet_id]->data(),
-                   message_size_) != 0)
-          bad_packets_received_++;
-      }
-    }
-  }
-}
-
 class MessagePipeConnectionTester::MessageSender
     : public MessagePipe::EventHandler {
  public:
diff --git a/remoting/protocol/connection_tester.h b/remoting/protocol/connection_tester.h
index 692d1a9..74b9256 100644
--- a/remoting/protocol/connection_tester.h
+++ b/remoting/protocol/connection_tester.h
@@ -9,15 +9,14 @@
 #include <memory>
 #include <vector>
 
-#include "base/memory/ref_counted.h"
+#include "base/callback.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
 #include "remoting/protocol/message_pipe.h"
 
 namespace net {
 class DrainableIOBuffer;
 class GrowableIOBuffer;
-class IOBuffer;
 }  // namespace net
 
 namespace remoting {
@@ -27,7 +26,6 @@
 
 namespace protocol {
 
-class P2PDatagramSocket;
 class P2PStreamSocket;
 
 // This class is used by unit tests to verify that a connection
@@ -41,8 +39,7 @@
                          int message_count);
   ~StreamConnectionTester();
 
-  void Start();
-  bool done() { return done_; }
+  void Start(base::OnceClosure on_done);
   void CheckResults();
 
  protected:
@@ -56,12 +53,11 @@
   void HandleReadResult(int result);
 
  private:
-  const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
   P2PStreamSocket* host_socket_;
   P2PStreamSocket* client_socket_;
   int message_size_;
   int test_data_size_;
-  bool done_;
+  base::OnceClosure on_done_;
 
   scoped_refptr<net::DrainableIOBuffer> output_buffer_;
   scoped_refptr<net::GrowableIOBuffer> input_buffer_;
@@ -70,45 +66,6 @@
   int read_errors_;
 };
 
-class DatagramConnectionTester {
- public:
-  DatagramConnectionTester(P2PDatagramSocket* client_socket,
-                           P2PDatagramSocket* host_socket,
-                           int message_size,
-                           int message_count,
-                           int delay_ms);
-  ~DatagramConnectionTester() ;
-
-  void Start();
-  void CheckResults();
-
- private:
-  void Done();
-  void DoWrite();
-  void OnWritten(int result);
-  void HandleWriteResult(int result);
-  void DoRead();
-  void OnRead(int result);
-  void HandleReadResult(int result);
-
-  const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-  P2PDatagramSocket* host_socket_;
-  P2PDatagramSocket* client_socket_;
-  int message_size_;
-  int message_count_;
-  int delay_ms_;
-  bool done_;
-
-  std::vector<scoped_refptr<net::IOBuffer> > sent_packets_;
-  scoped_refptr<net::IOBuffer> read_buffer_;
-
-  int write_errors_;
-  int read_errors_;
-  int packets_sent_;
-  int packets_received_;
-  int bad_packets_received_;
-};
-
 class MessagePipeConnectionTester : public MessagePipe::EventHandler {
  public:
   MessagePipeConnectionTester(MessagePipe* host_pipe,
diff --git a/remoting/protocol/negotiating_authenticator_unittest.cc b/remoting/protocol/negotiating_authenticator_unittest.cc
index 8bd9cb8..b33a8dd 100644
--- a/remoting/protocol/negotiating_authenticator_unittest.cc
+++ b/remoting/protocol/negotiating_authenticator_unittest.cc
@@ -142,8 +142,9 @@
     StreamConnectionTester tester(host_socket_.get(), client_socket_.get(),
                                   kMessageSize, kMessages);
 
-    tester.Start();
-    base::RunLoop().Run();
+    base::RunLoop run_loop;
+    tester.Start(run_loop.QuitClosure());
+    run_loop.Run();
     tester.CheckResults();
   }
 
diff --git a/remoting/protocol/spake2_authenticator_unittest.cc b/remoting/protocol/spake2_authenticator_unittest.cc
index 703dc42..a86ff3983 100644
--- a/remoting/protocol/spake2_authenticator_unittest.cc
+++ b/remoting/protocol/spake2_authenticator_unittest.cc
@@ -69,8 +69,9 @@
   StreamConnectionTester tester(host_socket_.get(), client_socket_.get(),
                                 kMessageSize, kMessages);
 
-  tester.Start();
-  base::RunLoop().Run();
+  base::RunLoop run_loop;
+  tester.Start(run_loop.QuitClosure());
+  run_loop.Run();
   tester.CheckResults();
 }
 
diff --git a/remoting/protocol/ssl_hmac_channel_authenticator_unittest.cc b/remoting/protocol/ssl_hmac_channel_authenticator_unittest.cc
index 2a339b9..e05c1f6 100644
--- a/remoting/protocol/ssl_hmac_channel_authenticator_unittest.cc
+++ b/remoting/protocol/ssl_hmac_channel_authenticator_unittest.cc
@@ -167,8 +167,9 @@
   StreamConnectionTester tester(host_socket_.get(), client_socket_.get(),
                                 100, 2);
 
-  tester.Start();
-  base::RunLoop().Run();
+  base::RunLoop run_loop;
+  tester.Start(run_loop.QuitClosure());
+  run_loop.Run();
   tester.CheckResults();
 }
 
diff --git a/remoting/protocol/third_party_authenticator_unittest.cc b/remoting/protocol/third_party_authenticator_unittest.cc
index c4775f4..d3bddc7 100644
--- a/remoting/protocol/third_party_authenticator_unittest.cc
+++ b/remoting/protocol/third_party_authenticator_unittest.cc
@@ -139,8 +139,9 @@
   StreamConnectionTester tester(host_socket_.get(), client_socket_.get(),
                                 kMessageSize, kMessages);
 
-  tester.Start();
-  base::RunLoop().Run();
+  base::RunLoop run_loop;
+  tester.Start(run_loop.QuitClosure());
+  run_loop.Run();
   tester.CheckResults();
 }
 
diff --git a/remoting/protocol/v2_authenticator_unittest.cc b/remoting/protocol/v2_authenticator_unittest.cc
index 64767215..12a8c63 100644
--- a/remoting/protocol/v2_authenticator_unittest.cc
+++ b/remoting/protocol/v2_authenticator_unittest.cc
@@ -67,8 +67,9 @@
   StreamConnectionTester tester(host_socket_.get(), client_socket_.get(),
                                 kMessageSize, kMessages);
 
-  tester.Start();
-  base::RunLoop().Run();
+  base::RunLoop run_loop;
+  tester.Start(run_loop.QuitClosure());
+  run_loop.Run();
   tester.CheckResults();
 }
 
diff --git a/remoting/test/it2me_standalone_host.cc b/remoting/test/it2me_standalone_host.cc
index 4c8bb7a..63c722b 100644
--- a/remoting/test/it2me_standalone_host.cc
+++ b/remoting/test/it2me_standalone_host.cc
@@ -47,8 +47,7 @@
       factory_(main_task_runner_,
                context_->video_capture_task_runner(),
                context_->input_task_runner(),
-               context_->ui_task_runner(),
-               nullptr),
+               context_->ui_task_runner()),
       connection_(base::WrapUnique(new testing::NiceMock<MockSession>())),
       session_jid_(kSessionJid),
 #if defined(OS_LINUX)
diff --git a/remoting/webapp/BUILD.gn b/remoting/webapp/BUILD.gn
index b80474e..66cd297 100644
--- a/remoting/webapp/BUILD.gn
+++ b/remoting/webapp/BUILD.gn
@@ -37,7 +37,7 @@
 desktop_remoting_webapp("webapp") {
   output_dir = "$root_build_dir/remoting/remoting-webapp.v2"
   zip_path = "$root_build_dir/remoting-webapp.v2.zip"
-  extra_files = [ "crd/remoting_client_pnacl.nmf.jinja2" ]
+  extra_files = []
 }
 
 copy("browser_test_resources") {
diff --git a/remoting/webapp/base/js/client_plugin_impl.js b/remoting/webapp/base/js/client_plugin_impl.js
index 8e0348c..a1d816f 100644
--- a/remoting/webapp/base/js/client_plugin_impl.js
+++ b/remoting/webapp/base/js/client_plugin_impl.js
@@ -114,8 +114,6 @@
 remoting.ClientPluginImpl.createPluginElement_ = function() {
   var plugin =
       /** @type {HTMLEmbedElement} */ (document.createElement('embed'));
-  plugin.src = 'remoting_client_pnacl.nmf';
-  plugin.type = 'application/x-pnacl';
   plugin.width = '0';
   plugin.height = '0';
   plugin.tabIndex = 0;  // Required, otherwise focus() doesn't work.
diff --git a/remoting/webapp/build_template.gni b/remoting/webapp/build_template.gni
index d5ed945..1638c05 100644
--- a/remoting/webapp/build_template.gni
+++ b/remoting/webapp/build_template.gni
@@ -231,19 +231,6 @@
       "$target_gen_dir/credits.html",
     ]
 
-    # Windows debug builds of remoting_client_plugin_newlib.pexe trigger OOM in
-    # arm-nacl-ld.gold.exe - enable for release builds only on Windows.
-    if (enable_nacl && (!is_win || !is_debug)) {
-      pnacl_tc = "//build/toolchain/nacl:newlib_pnacl"
-      pexe_label = "//remoting/client/plugin:remoting_client_plugin_newlib"
-      pexe_dir = get_label_info("${pexe_label}($pnacl_tc)", "root_out_dir")
-
-      extra_files += [ "$pexe_dir/remoting_client_plugin_newlib.pexe" ]
-      if (is_debug) {
-        extra_files += [ "$pexe_dir/remoting_client_plugin_newlib.pexe.debug" ]
-      }
-    }
-
     inputs = [ rebase_path("crd/manifest.json.jinja2") ] +
              remoting_version_files + rebase_path(remoting_webapp_crd_files) +
              extra_files + dr_generated_html_files
@@ -263,15 +250,6 @@
       "//remoting/webapp:credits",
     ]
 
-    # Windows debug builds of remoting_client_plugin_newlib.pexe trigger OOM in
-    # arm-nacl-ld.gold.exe - enable for release builds only on Windows.
-    if (enable_nacl && (!is_win || !is_debug)) {
-      deps += [ "${pexe_label}($pnacl_tc)" ]
-      if (is_debug) {
-        deps += [ "${pexe_label}_debug($pnacl_tc)" ]
-      }
-    }
-
     # Create a file that contains a list of all the resource files needed
     # to build the webapp. This is needed to avoid problems on platforms that
     # limit the size of a command line.
diff --git a/remoting/webapp/crd/html/butter_bar.css b/remoting/webapp/crd/html/butter_bar.css
index 5f9978a..9aeeb04 100644
--- a/remoting/webapp/crd/html/butter_bar.css
+++ b/remoting/webapp/crd/html/butter_bar.css
@@ -5,42 +5,29 @@
 
 #butter-bar {
   position: absolute;
-  top: 80px;
+  top: 0;
   left: 0;
+  bottom: 0;
+  right: 0;
   display: flex;
   justify-content: center;
-  width: 100%;
-}
-
-#butter-bar-dismiss img {
-  vertical-align: top;
-  opacity: 0.4;
-  margin-__MSG_@@bidi_start_edge__: 2px;
-  margin-__MSG_@@bidi_end_edge__: -12px;
-}
-
-#butter-bar-dimiss:hover {
-  opacity: 0.7;
+  align-items: center;
+  background-color: rgba(0,0,0,0.5);
+  z-index: 1;  /* Above the main content, but below the menu. */
 }
 
 #butter-bar > p {
-  background-color: #f9edbe;
-  border: 1px solid #f0c36d;
+  background-color: white;
+  border: 1px solid black;
   border-radius: 2px;
-  box-shadow: 0px 2px 4px rgba(0,0,0,0.2);
   color: #222;
   font-size: 12px;
   padding: 4px 16px;
   margin: 0 8px;
-}
-
-#butter-bar.red > p {
-  background-color: #f9bebe;
-  border: 1px solid #f06d6d;
+  max-width: 400px;
+  padding: 30px;
 }
 
 #butter-bar a {
-  color: inherit;
   text-decoration: underline;
-  padding-__MSG_@@bidi_start_edge__: 2px;
 }
diff --git a/remoting/webapp/crd/html/butter_bar.html b/remoting/webapp/crd/html/butter_bar.html
index 7417508..637114c9 100644
--- a/remoting/webapp/crd/html/butter_bar.html
+++ b/remoting/webapp/crd/html/butter_bar.html
@@ -4,12 +4,7 @@
 found in the LICENSE file.
 -->
 <div data-ui-mode="home">
-  <div id="butter-bar" hidden>
-    <p>
-      <span id="butter-bar-message"></span>
-      <a id="butter-bar-dismiss" href="#">
-        <img src="icon_cross.webp" class="close-icon">
-      </a>
-    </p>
+  <div id="butter-bar">
+    <p id="butter-bar-message"></p>
   </div>
 </div>
diff --git a/remoting/webapp/crd/js/butter_bar.js b/remoting/webapp/crd/js/butter_bar.js
index 7d306070..dfdda2a1 100644
--- a/remoting/webapp/crd/js/butter_bar.js
+++ b/remoting/webapp/crd/js/butter_bar.js
@@ -65,11 +65,6 @@
       var responseObj = response.getJson();
       /** @type {string} */
       var email = results[1];
-      if (email.toLocaleLowerCase().endsWith('@google.com') &&
-          !Boolean(responseObj.includeGooglers)) {
-        result.resolve();
-        return;
-      }
       /** @type {number} The index of the message to display. */
       var index = base.assertNumber(responseObj.index);
       /** @type {string} The URL of the website. */
@@ -121,12 +116,6 @@
     anchorTags[0].addEventListener(
         'click', this.onLinkClicked_.bind(this), false);
   }
-  if (dismissable) {
-    this.dismiss_.addEventListener('click', this.dismiss.bind(this), false);
-  } else {
-    this.dismiss_.hidden = true;
-    this.root_.classList.add('red');
-  }
   this.root_.hidden = false;
 }
 
diff --git a/remoting/webapp/crd/js/butter_bar_unittest.js b/remoting/webapp/crd/js/butter_bar_unittest.js
index 28a799e7..9b1b6dfc 100644
--- a/remoting/webapp/crd/js/butter_bar_unittest.js
+++ b/remoting/webapp/crd/js/butter_bar_unittest.js
@@ -88,27 +88,6 @@
   }
 });
 
-QUnit.test('should stay hidden for google.com addresses by default',
-           function(assert) {
-  this.currentMessage = 0;
-  this.percent = 100;
-  this.email = 'uSeR@gOoGlE.cOm';
-  return this.butterBar.init().then(() => {
-    assert.ok(this.butterBar.root_.hidden == true);
-  });
-});
-
-QUnit.test('should stay hidden for google.com addresses when disabled',
-           function(assert) {
-  this.currentMessage = 0;
-  this.percent = 100;
-  this.email = 'uSeR@gOoGlE.cOm';
-  this.includeGooglers = false;
-  return this.butterBar.init().then(() => {
-    assert.ok(this.butterBar.root_.hidden == true);
-  });
-});
-
 QUnit.test('should be shown for google.com addresses when enabled',
            function(assert) {
   this.currentMessage = 0;
@@ -121,40 +100,6 @@
   });
 });
 
-QUnit.test('should stay hidden if XHR fails', function(assert) {
-  this.currentMessage = undefined;
-  return this.butterBar.init().then(() => {
-    assert.ok(this.butterBar.root_.hidden == true);
-  });
-});
-
-QUnit.test('should stay hidden if index==-1', function(assert) {
-  return this.butterBar.init().then(() => {
-    assert.ok(this.butterBar.root_.hidden == true);
-  });
-});
-
-QUnit.test('should stay hidden if not selected by percentage',
-           function(assert) {
-  this.currentMessage = 0;
-  this.percent = 50;
-  this.hash = 64;
-  return this.butterBar.init().then(() => {
-    assert.ok(this.butterBar.root_.hidden == true);
-  });
-});
-
-QUnit.test('should be shown, yellow and dismissable if index==0',
-           function(assert) {
-  this.currentMessage = 0;
-  chrome.storage.sync.get.callsArgWith(1, {});
-  return this.butterBar.init().then(() => {
-    assert.ok(this.butterBar.root_.hidden == false);
-    assert.ok(this.butterBar.dismiss_.hidden == false);
-    assert.ok(!this.butterBar.root_.classList.contains('red'));
-  });
-});
-
 QUnit.test('should update storage when shown', function(assert) {
   this.currentMessage = 0;
   this.now = 123;
@@ -214,40 +159,6 @@
   });
 });
 
-QUnit.test('should stay hidden if the timeout has elapsed', function(assert) {
-  this.currentMessage = 0;
-  chrome.storage.sync.get.callsArgWith(1, {
-    "message-state": {
-      "hidden": false,
-      "index": 0,
-      "timestamp": 0,
-    }
-  });
-  this.now = remoting.ButterBar.kTimeout_+ 1;
-  return this.butterBar.init().then(() => {
-    assert.ok(this.butterBar.root_.hidden == true);
-    sinon.assert.notCalled(logWriterSpy);
-  });
-});
-
-
-QUnit.test('should stay hidden if it was previously dismissed',
-           function(assert) {
-  this.currentMessage = 0;
-  chrome.storage.sync.get.callsArgWith(1, {
-    "message-state": {
-      "hidden": true,
-      "index": 0,
-      "timestamp": 0,
-    }
-  });
-  return this.butterBar.init().then(() => {
-    assert.ok(this.butterBar.root_.hidden == true);
-    sinon.assert.notCalled(logWriterSpy);
-  });
-});
-
-
 QUnit.test('should be shown if the index has increased', function(assert) {
   var MigrationPhase = remoting.ChromotingEvent.ChromotingDotComMigration.Phase;
   var MigrationEvent = remoting.ChromotingEvent.ChromotingDotComMigration.Event;
@@ -307,33 +218,6 @@
   });
 });
 
-QUnit.test('dismiss button updates local storage', function(assert) {
-  var MigrationPhase = remoting.ChromotingEvent.ChromotingDotComMigration.Phase;
-  var MigrationEvent = remoting.ChromotingEvent.ChromotingDotComMigration.Event;
-
-  this.currentMessage = 0;
-  chrome.storage.sync.get.callsArgWith(1, {});
-  return this.butterBar.init().then(() => {
-    this.butterBar.dismiss_.click();
-    // The first call is in response to showing the message; the second is in
-    // response to dismissing the message.
-    assert.deepEqual(chrome.storage.sync.set.secondCall.args,
-                     [{
-                       "message-state": {
-                         "hidden": true,
-                         "index": 0,
-                         "timestamp": 0,
-                       }
-                     }]);
-    verifyLog(
-        assert, 0, MigrationEvent.DEPRECATION_NOTICE_IMPRESSION,
-        MigrationPhase.BETA)
-    verifyLog(
-        assert, 1, MigrationEvent.DEPRECATION_NOTICE_DISMISSAL,
-        MigrationPhase.BETA)
-  });
-});
-
 QUnit.test('clicks on upsell URL are reported', function(assert) {
   var MigrationPhase = remoting.ChromotingEvent.ChromotingDotComMigration.Phase;
   var MigrationEvent = remoting.ChromotingEvent.ChromotingDotComMigration.Event;
diff --git a/services/media_session/audio_focus_manager.cc b/services/media_session/audio_focus_manager.cc
index 88a5c61..628afb8 100644
--- a/services/media_session/audio_focus_manager.cc
+++ b/services/media_session/audio_focus_manager.cc
@@ -55,9 +55,9 @@
 
   RequestAudioFocusInternal(
       std::make_unique<AudioFocusRequest>(
-          this, std::move(request), std::move(media_session),
-          std::move(session_info), type, request_id, GetBindingSourceName(),
-          group_id),
+          weak_ptr_factory_.GetWeakPtr(), std::move(request),
+          std::move(media_session), std::move(session_info), type, request_id,
+          GetBindingSourceName(), group_id),
       type);
 
   std::move(callback).Run(request_id);
diff --git a/services/media_session/audio_focus_manager.h b/services/media_session/audio_focus_manager.h
index 4034e9e..0bdcb76 100644
--- a/services/media_session/audio_focus_manager.h
+++ b/services/media_session/audio_focus_manager.h
@@ -9,6 +9,7 @@
 #include <string>
 #include <unordered_map>
 
+#include "base/memory/weak_ptr.h"
 #include "base/threading/thread_checker.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
@@ -154,6 +155,8 @@
   // running on.
   THREAD_CHECKER(thread_checker_);
 
+  base::WeakPtrFactory<AudioFocusManager> weak_ptr_factory_{this};
+
   DISALLOW_COPY_AND_ASSIGN(AudioFocusManager);
 };
 
diff --git a/services/media_session/audio_focus_request.cc b/services/media_session/audio_focus_request.cc
index 7b90984c..016b9cf2 100644
--- a/services/media_session/audio_focus_request.cc
+++ b/services/media_session/audio_focus_request.cc
@@ -9,7 +9,7 @@
 namespace media_session {
 
 AudioFocusRequest::AudioFocusRequest(
-    AudioFocusManager* owner,
+    base::WeakPtr<AudioFocusManager> owner,
     mojom::AudioFocusRequestClientRequest request,
     mojom::MediaSessionPtr session,
     mojom::MediaSessionInfoPtr session_info,
@@ -25,7 +25,7 @@
       id_(id),
       source_name_(source_name),
       group_id_(group_id),
-      owner_(owner) {
+      owner_(std::move(owner)) {
   // Listen for mojo errors.
   binding_.set_connection_error_handler(base::BindOnce(
       &AudioFocusRequest::OnConnectionError, base::Unretained(this)));
@@ -164,7 +164,7 @@
 
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(&AudioFocusManager::AbandonAudioFocusInternal,
-                                base::Unretained(owner_), id_));
+                                owner_, id_));
 }
 
 }  // namespace media_session
diff --git a/services/media_session/audio_focus_request.h b/services/media_session/audio_focus_request.h
index 1fcb46b..e0d679e 100644
--- a/services/media_session/audio_focus_request.h
+++ b/services/media_session/audio_focus_request.h
@@ -6,6 +6,7 @@
 #define SERVICES_MEDIA_SESSION_AUDIO_FOCUS_REQUEST_H_
 
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "services/media_session/audio_focus_manager_metrics_helper.h"
 #include "services/media_session/public/mojom/audio_focus.mojom.h"
@@ -19,7 +20,7 @@
 
 class AudioFocusRequest : public mojom::AudioFocusRequestClient {
  public:
-  AudioFocusRequest(AudioFocusManager* owner,
+  AudioFocusRequest(base::WeakPtr<AudioFocusManager> owner,
                     mojom::AudioFocusRequestClientRequest request,
                     mojom::MediaSessionPtr session,
                     mojom::MediaSessionInfoPtr session_info,
@@ -92,7 +93,7 @@
   base::UnguessableToken const group_id_;
 
   // Weak pointer to the owning |AudioFocusManager| instance.
-  AudioFocusManager* const owner_;
+  const base::WeakPtr<AudioFocusManager> owner_;
 
   DISALLOW_COPY_AND_ASSIGN(AudioFocusRequest);
 };
diff --git a/storage/browser/BUILD.gn b/storage/browser/BUILD.gn
index a66b3d82..eec6df4f6 100644
--- a/storage/browser/BUILD.gn
+++ b/storage/browser/BUILD.gn
@@ -345,6 +345,8 @@
     "test/async_file_test_helper.h",
     "test/fake_blob.cc",
     "test/fake_blob.h",
+    "test/fake_blob_data_handle.cc",
+    "test/fake_blob_data_handle.h",
     "test/fake_progress_client.cc",
     "test/fake_progress_client.h",
     "test/fileapi_test_file_set.cc",
diff --git a/storage/browser/blob/blob_data_builder.cc b/storage/browser/blob/blob_data_builder.cc
index 61609cb..fec479c 100644
--- a/storage/browser/blob/blob_data_builder.cc
+++ b/storage/browser/blob/blob_data_builder.cc
@@ -17,7 +17,6 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/time/time.h"
-#include "net/disk_cache/disk_cache.h"
 #include "storage/browser/blob/blob_entry.h"
 #include "storage/browser/blob/blob_storage_registry.h"
 #include "storage/browser/blob/shareable_blob_data_item.h"
@@ -27,12 +26,6 @@
 
 namespace storage {
 
-namespace {
-
-const static int kInvalidDiskCacheSideStreamIndex = -1;
-
-}  // namespace
-
 BlobDataBuilder::FutureData::FutureData(FutureData&&) = default;
 BlobDataBuilder::FutureData& BlobDataBuilder::FutureData::operator=(
     FutureData&&) = default;
@@ -305,12 +298,10 @@
             source_item->file_system_context());
         break;
       }
-      case BlobDataItem::Type::kDiskCacheEntry: {
-        data_item = BlobDataItem::CreateDiskCacheEntry(
-            source_item->offset() + item_offset, read_size,
-            source_item->data_handle_, source_item->disk_cache_entry(),
-            source_item->disk_cache_stream_index(),
-            source_item->disk_cache_side_stream_index());
+      case BlobDataItem::Type::kReadableDataHandle: {
+        data_item = BlobDataItem::CreateReadableDataHandle(
+            source_item->data_handle_, source_item->offset() + item_offset,
+            read_size);
         break;
       }
     }
@@ -347,24 +338,11 @@
   total_size_ += length;
 }
 
-void BlobDataBuilder::AppendDiskCacheEntry(
-    scoped_refptr<DataHandle> data_handle,
-    disk_cache::Entry* disk_cache_entry,
-    int disk_cache_stream_index) {
-  AppendDiskCacheEntryWithSideData(std::move(data_handle), disk_cache_entry,
-                                   disk_cache_stream_index,
-                                   kInvalidDiskCacheSideStreamIndex);
-}
-
-void BlobDataBuilder::AppendDiskCacheEntryWithSideData(
-    scoped_refptr<DataHandle> data_handle,
-    disk_cache::Entry* disk_cache_entry,
-    int disk_cache_stream_index,
-    int disk_cache_side_stream_index) {
-  auto item = BlobDataItem::CreateDiskCacheEntry(
-      0u, disk_cache_entry->GetDataSize(disk_cache_stream_index),
-      std::move(data_handle), disk_cache_entry, disk_cache_stream_index,
-      disk_cache_side_stream_index);
+void BlobDataBuilder::AppendReadableDataHandle(
+    scoped_refptr<DataHandle> data_handle) {
+  uint64_t length = data_handle->GetSize();
+  auto item = BlobDataItem::CreateReadableDataHandle(std::move(data_handle), 0u,
+                                                     length);
 
   total_size_ += item->length();
   auto shareable_item = base::MakeRefCounted<ShareableBlobDataItem>(
diff --git a/storage/browser/blob/blob_data_builder.h b/storage/browser/blob/blob_data_builder.h
index 1c4b8388..81b7da9 100644
--- a/storage/browser/blob/blob_data_builder.h
+++ b/storage/browser/blob/blob_data_builder.h
@@ -23,10 +23,6 @@
 #include "storage/browser/blob/shareable_file_reference.h"
 #include "storage/browser/fileapi/file_system_context.h"
 
-namespace disk_cache {
-class Entry;
-}
-
 namespace storage {
 class BlobSliceTest;
 class BlobStorageContext;
@@ -145,15 +141,7 @@
       const base::Time& expected_modification_time,
       scoped_refptr<FileSystemContext> file_system_context);
 
-  void AppendDiskCacheEntry(scoped_refptr<DataHandle> data_handle,
-                            disk_cache::Entry* disk_cache_entry,
-                            int disk_cache_stream_index);
-
-  // The content of the side data is accessible with BlobReader::ReadSideData().
-  void AppendDiskCacheEntryWithSideData(scoped_refptr<DataHandle> data_handle,
-                                        disk_cache::Entry* disk_cache_entry,
-                                        int disk_cache_stream_index,
-                                        int disk_cache_side_stream_index);
+  void AppendReadableDataHandle(scoped_refptr<DataHandle> data_handle);
 
   void set_content_type(const std::string& content_type) {
     content_type_ = content_type;
diff --git a/storage/browser/blob/blob_data_item.cc b/storage/browser/blob/blob_data_item.cc
index c500cc0..22582a9a 100644
--- a/storage/browser/blob/blob_data_item.cc
+++ b/storage/browser/blob/blob_data_item.cc
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/strings/string_number_conversions.h"
+#include "net/base/net_errors.h"
 #include "storage/browser/fileapi/file_system_context.h"
 #include "third_party/blink/public/common/blob/blob_utils.h"
 
@@ -19,9 +20,35 @@
     FILE_PATH_LITERAL("_future_name_");
 }
 
-bool BlobDataItem::DataHandle::IsValid() {
-  return true;
+uint64_t BlobDataItem::DataHandle::GetSize() const {
+  return 0;
 }
+
+int BlobDataItem::DataHandle::Read(scoped_refptr<net::IOBuffer> dst_buffer,
+                                   uint64_t src_offset,
+                                   int bytes_to_read,
+                                   base::OnceCallback<void(int)> callback) {
+  return net::ERR_FILE_NOT_FOUND;
+}
+
+uint64_t BlobDataItem::DataHandle::GetSideDataSize() const {
+  return 0;
+}
+
+int BlobDataItem::DataHandle::ReadSideData(
+    scoped_refptr<net::IOBuffer> dst_buffer,
+    base::OnceCallback<void(int)> callback) {
+  return net::ERR_FILE_NOT_FOUND;
+}
+
+void BlobDataItem::DataHandle::PrintTo(::std::ostream* os) const {
+  *os << "<unknown>";
+}
+
+const char* BlobDataItem::DataHandle::BytesReadHistogramLabel() const {
+  return nullptr;
+}
+
 BlobDataItem::DataHandle::~DataHandle() = default;
 
 // static
@@ -91,19 +118,15 @@
 }
 
 // static
-scoped_refptr<BlobDataItem> BlobDataItem::CreateDiskCacheEntry(
-    uint64_t offset,
-    uint64_t length,
+scoped_refptr<BlobDataItem> BlobDataItem::CreateReadableDataHandle(
     scoped_refptr<DataHandle> data_handle,
-    disk_cache::Entry* entry,
-    int disk_cache_stream_index,
-    int disk_cache_side_stream_index) {
+    uint64_t offset,
+    uint64_t length) {
+  DCHECK_LE(offset, data_handle->GetSize());
+  DCHECK_LE(length, (data_handle->GetSize() - offset));
   auto item = base::WrapRefCounted(
-      new BlobDataItem(Type::kDiskCacheEntry, offset, length));
+      new BlobDataItem(Type::kReadableDataHandle, offset, length));
   item->data_handle_ = std::move(data_handle);
-  item->disk_cache_entry_ = entry;
-  item->disk_cache_stream_index_ = disk_cache_stream_index;
-  item->disk_cache_side_stream_index_ = disk_cache_side_stream_index;
   return item;
 }
 
@@ -195,11 +218,10 @@
     case BlobDataItem::Type::kFileFilesystem:
       *os << "kFileFilesystem, url: " << x.filesystem_url();
       break;
-    case BlobDataItem::Type::kDiskCacheEntry:
-      *os << "kDiskCacheEntry"
-          << ", disk_cache_entry_ptr: " << x.disk_cache_entry_
-          << ", disk_cache_stream_index_: " << x.disk_cache_stream_index_
-          << "}";
+    case BlobDataItem::Type::kReadableDataHandle:
+      *os << "kReadableDataHandle"
+          << ", data_handle_: ";
+      x.data_handle()->PrintTo(os);
       break;
   }
   *os << ", length: " << x.length() << ", offset: " << x.offset()
@@ -221,11 +243,8 @@
              a.expected_modification_time() == b.expected_modification_time();
     case BlobDataItem::Type::kFileFilesystem:
       return a.filesystem_url() == b.filesystem_url();
-    case BlobDataItem::Type::kDiskCacheEntry:
-      return a.disk_cache_entry() == b.disk_cache_entry() &&
-             a.disk_cache_stream_index() == b.disk_cache_stream_index() &&
-             a.disk_cache_side_stream_index() ==
-                 b.disk_cache_side_stream_index();
+    case BlobDataItem::Type::kReadableDataHandle:
+      return a.data_handle() == b.data_handle();
   }
   NOTREACHED();
   return false;
diff --git a/storage/browser/blob/blob_data_item.h b/storage/browser/blob/blob_data_item.h
index 91d5d53..bec072f 100644
--- a/storage/browser/blob/blob_data_item.h
+++ b/storage/browser/blob/blob_data_item.h
@@ -15,12 +15,9 @@
 #include "base/containers/span.h"
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
+#include "net/base/io_buffer.h"
 #include "url/gurl.h"
 
-namespace disk_cache {
-class Entry;
-}
-
 namespace storage {
 class BlobDataBuilder;
 class BlobStorageContext;
@@ -39,7 +36,7 @@
     kBytesDescription,
     kFile,
     kFileFilesystem,
-    kDiskCacheEntry
+    kReadableDataHandle,
   };
 
   // The DataHandle class is used to persist resources that are needed for
@@ -47,10 +44,48 @@
   // pending. If all blobs with this item are deleted or the item is swapped for
   // a different backend version (mem-to-disk or the reverse), then the item
   // will be destructed after all pending reads are complete.
+  //
+  // A DataHandle can also be "readable" if it overrides the size and reading
+  // virtual methods.  If the DataHandle provides this kind of encapsulated
+  // implementation then it can be added to the item using the
+  // AppendReadableDataHandle() method.
   class COMPONENT_EXPORT(STORAGE_BROWSER) DataHandle
       : public base::RefCounted<DataHandle> {
    public:
-    virtual bool IsValid();
+    // Must return the main blob data size.  Returns 0 by default.
+    virtual uint64_t GetSize() const;
+
+    // Reads the given data range into the given buffer.  If the read is
+    // completed synchronously then the number of bytes read should be returned
+    // directly.  If the read must be performed asynchronously then this
+    // method must return net::ERR_IO_PENDING and invoke the callback with the
+    // result at a later time.  The default implementation returns
+    // net::ERR_FILE_NOT_FOUND.
+    virtual int Read(scoped_refptr<net::IOBuffer> dst_buffer,
+                     uint64_t src_offset,
+                     int bytes_to_read,
+                     base::OnceCallback<void(int)> callback);
+
+    // Must return the side data size.  If there is no side data, then 0 should
+    // be returned.  Returns 0 by default.
+    virtual uint64_t GetSideDataSize() const;
+
+    // Reads the entire side data into the given buffer.  The buffer must be
+    // large enough to contain the entire side data.  If the read is completed
+    // synchronously then the number of bytes read should be returned directly.
+    // If the read must be performed asynchronously then this method must
+    // return net::ERR_IO_PENDING and invoke the callback with the result at a
+    // later time.  The default implementation returns net::ERR_FILE_NOT_FOUND.
+    virtual int ReadSideData(scoped_refptr<net::IOBuffer> dst_buffer,
+                             base::OnceCallback<void(int)> callback);
+
+    // Print a description of the readable DataHandle for debugging.
+    virtual void PrintTo(::std::ostream* os) const;
+
+    // Return the histogram label to use when calling RecordBytesRead().  If
+    // nullptr is returned then nothing will be recorded.  Returns nullptr by
+    // default.
+    virtual const char* BytesReadHistogramLabel() const;
 
    protected:
     virtual ~DataHandle();
@@ -77,13 +112,10 @@
       uint64_t length,
       base::Time expected_modification_time,
       scoped_refptr<FileSystemContext> file_system_context);
-  static scoped_refptr<BlobDataItem> CreateDiskCacheEntry(
-      uint64_t offset,
-      uint64_t length,
+  static scoped_refptr<BlobDataItem> CreateReadableDataHandle(
       scoped_refptr<DataHandle> data_handle,
-      disk_cache::Entry* entry,
-      int disk_cache_stream_index,
-      int disk_cache_side_stream_index);
+      uint64_t offset,
+      uint64_t length);
 
   Type type() const { return type_; }
   uint64_t offset() const { return offset_; }
@@ -115,27 +147,8 @@
     return expected_modification_time_;
   }
 
-  // This can return null if the underlying disk cache entry was invalidated
-  // (because the user cleared site data), so users should make sure to always
-  // check for that.
-  disk_cache::Entry* disk_cache_entry() const {
-    DCHECK_EQ(type_, Type::kDiskCacheEntry);
-    DCHECK(data_handle_);
-    return data_handle_->IsValid() ? disk_cache_entry_ : nullptr;
-  }
-
-  int disk_cache_stream_index() const {
-    DCHECK_EQ(type_, Type::kDiskCacheEntry);
-    return disk_cache_stream_index_;
-  }
-
-  int disk_cache_side_stream_index() const {
-    DCHECK_EQ(type_, Type::kDiskCacheEntry);
-    return disk_cache_side_stream_index_;
-  }
-
   DataHandle* data_handle() const {
-    DCHECK(type_ == Type::kFile || type_ == Type::kDiskCacheEntry)
+    DCHECK(type_ == Type::kFile || type_ == Type::kReadableDataHandle)
         << static_cast<int>(type_);
     return data_handle_.get();
   }
@@ -186,16 +199,7 @@
       expected_modification_time_;  // For Type::kFile and kFileFilesystem.
 
   scoped_refptr<DataHandle>
-      data_handle_;  // For Type::kFile and kDiskCacheEntry.
-
-  // This naked pointer is safe because the scope is protected by the DataHandle
-  // instance for disk cache entries during the lifetime of this BlobDataItem.
-  // Only valid if the DataHandle's IsValid method returns true.
-  // TODO(mek): Make this part of the DataHandle and abstract away cache
-  // specific logic to be part of an API exposed by DataHandle.
-  disk_cache::Entry* disk_cache_entry_;  // For Type::kDiskCacheEntry.
-  int disk_cache_stream_index_;          // For Type::kDiskCacheEntry.
-  int disk_cache_side_stream_index_;     // For Type::kDiskCacheEntry.
+      data_handle_;  // For Type::kFile and kReadableDataHandle.
 
   scoped_refptr<FileSystemContext>
       file_system_context_;  // For Type::kFileFilesystem.
diff --git a/storage/browser/blob/blob_impl.cc b/storage/browser/blob/blob_impl.cc
index 9acb4fd..bf6aa8c 100644
--- a/storage/browser/blob/blob_impl.cc
+++ b/storage/browser/blob/blob_impl.cc
@@ -12,7 +12,6 @@
 #include "base/bind.h"
 #include "base/containers/span.h"
 #include "net/base/io_buffer.h"
-#include "net/disk_cache/disk_cache.h"
 #include "storage/browser/blob/blob_data_handle.h"
 #include "storage/browser/blob/blob_data_item.h"
 #include "storage/browser/blob/blob_data_snapshot.h"
@@ -124,25 +123,22 @@
         }
 
         auto snapshot = handle.CreateSnapshot();
-        // Currently side data is supported only for single DiskCache entry
-        // blob.
+        // Currently side data is supported only for blobs with a single entry.
         const auto& items = snapshot->items();
-        if (items.size() != 1 ||
-            items[0]->type() != BlobDataItem::Type::kDiskCacheEntry) {
+        if (items.size() != 1) {
           std::move(callback).Run(base::nullopt);
           return;
         }
 
         const auto& item = items[0];
-        disk_cache::Entry* entry = item->disk_cache_entry();
-        if (!entry) {
+        if (item->type() != BlobDataItem::Type::kReadableDataHandle) {
           std::move(callback).Run(base::nullopt);
           return;
         }
-        int32_t body_size =
-            entry->GetDataSize(item->disk_cache_side_stream_index());
+
+        int32_t body_size = item->data_handle()->GetSideDataSize();
         if (body_size == 0) {
-          std::move(callback).Run(std::vector<uint8_t>());
+          std::move(callback).Run(base::nullopt);
           return;
         }
         auto io_buffer = base::MakeRefCounted<net::IOBufferWithSize>(body_size);
@@ -161,9 +157,10 @@
             },
             io_buffer, std::move(callback)));
 
-        // TODO(crbug.com/867848): Plumb BigBuffer into disk_cache::ReadData().
-        int rv = entry->ReadData(item->disk_cache_side_stream_index(), 0,
-                                 io_buffer.get(), body_size, io_callback);
+        // TODO(crbug.com/867848): Plumb BigBuffer into
+        // BlobDataItem::DataHandle::ReadSideData().
+        int rv = item->data_handle()->ReadSideData(std::move(io_buffer),
+                                                   io_callback);
         if (rv != net::ERR_IO_PENDING)
           io_callback.Run(rv);
       },
diff --git a/storage/browser/blob/blob_reader.cc b/storage/browser/blob/blob_reader.cc
index 5100695..71a48d6 100644
--- a/storage/browser/blob/blob_reader.cc
+++ b/storage/browser/blob/blob_reader.cc
@@ -20,7 +20,6 @@
 #include "base/trace_event/trace_event.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
-#include "net/disk_cache/disk_cache.h"
 #include "storage/browser/blob/blob_data_handle.h"
 #include "storage/browser/blob/blob_data_snapshot.h"
 #include "storage/browser/fileapi/file_stream_reader.h"
@@ -30,7 +29,6 @@
 
 namespace storage {
 namespace {
-const char kCacheStorageRecordBytesLabel[] = "DiskCache.CacheStorage";
 
 bool IsFileType(BlobDataItem::Type type) {
   switch (type) {
@@ -119,14 +117,9 @@
   if (items.size() != 1)
     return false;
   const BlobDataItem& item = *items.at(0);
-  if (item.type() != BlobDataItem::Type::kDiskCacheEntry)
+  if (item.type() != BlobDataItem::Type::kReadableDataHandle)
     return false;
-  const int disk_cache_side_stream_index = item.disk_cache_side_stream_index();
-  if (disk_cache_side_stream_index < 0)
-    return false;
-  if (!item.disk_cache_entry())
-    return false;
-  return item.disk_cache_entry()->GetDataSize(disk_cache_side_stream_index) > 0;
+  return item.data_handle()->GetSideDataSize() > 0;
 }
 
 BlobReader::Status BlobReader::ReadSideData(StatusCallback done) {
@@ -134,17 +127,14 @@
 
   if (!has_side_data())
     return ReportError(net::ERR_FILE_NOT_FOUND);
-  const BlobDataItem* item = blob_data_->items()[0].get();
-  const int disk_cache_side_stream_index = item->disk_cache_side_stream_index();
-  const int side_data_size =
-      item->disk_cache_entry()->GetDataSize(disk_cache_side_stream_index);
+  BlobDataItem* item = blob_data_->items()[0].get();
+  const int side_data_size = item->data_handle()->GetSideDataSize();
   side_data_ = base::MakeRefCounted<net::IOBufferWithSize>(side_data_size);
   net_error_ = net::OK;
-  const int result = item->disk_cache_entry()->ReadData(
-      disk_cache_side_stream_index, 0, side_data_.get(), side_data_size,
-      base::BindOnce(&BlobReader::DidReadDiskCacheEntrySideData,
-                     weak_factory_.GetWeakPtr(), std::move(done),
-                     side_data_size));
+  const int result = item->data_handle()->ReadSideData(
+      side_data_.get(),
+      base::BindOnce(&BlobReader::DidReadSideData, weak_factory_.GetWeakPtr(),
+                     std::move(done), side_data_size));
   if (result >= 0) {
     DCHECK_EQ(side_data_size, result);
     return Status::DONE;
@@ -154,14 +144,13 @@
   return ReportError(result);
 }
 
-void BlobReader::DidReadDiskCacheEntrySideData(StatusCallback done,
-                                               int expected_size,
-                                               int result) {
+void BlobReader::DidReadSideData(StatusCallback done,
+                                 int expected_size,
+                                 int result) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (result >= 0) {
     DCHECK_EQ(expected_size, result);
-    if (result > 0)
-      storage::RecordBytesRead(kCacheStorageRecordBytesLabel, result);
+    RecordBytesReadFromDataHandle(/* item_index= */ 0, result);
     std::move(done).Run(Status::DONE);
     return;
   }
@@ -481,13 +470,13 @@
   }
 
   // Do the reading.
-  const BlobDataItem& item = *items.at(current_item_index_);
+  BlobDataItem& item = *items.at(current_item_index_);
   if (item.type() == BlobDataItem::Type::kBytes) {
     ReadBytesItem(item, bytes_to_read);
     return Status::DONE;
   }
-  if (item.type() == BlobDataItem::Type::kDiskCacheEntry)
-    return ReadDiskCacheEntryItem(item, bytes_to_read);
+  if (item.type() == BlobDataItem::Type::kReadableDataHandle)
+    return ReadReadableDataHandle(item, bytes_to_read);
   if (!IsFileType(item.type())) {
     NOTREACHED();
     return ReportError(net::ERR_UNEXPECTED);
@@ -593,39 +582,37 @@
                        std::unique_ptr<FileStreamReader>());
 }
 
-BlobReader::Status BlobReader::ReadDiskCacheEntryItem(const BlobDataItem& item,
+BlobReader::Status BlobReader::ReadReadableDataHandle(const BlobDataItem& item,
                                                       int bytes_to_read) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!io_pending_)
       << "Can't begin IO while another IO operation is pending.";
   DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read);
+  DCHECK_EQ(item.type(), BlobDataItem::Type::kReadableDataHandle);
 
-  if (!item.disk_cache_entry())
-    return ReportError(net::ERR_CACHE_READ_FAILURE);
-  const int result = item.disk_cache_entry()->ReadData(
-      item.disk_cache_stream_index(), item.offset() + current_item_offset_,
-      read_buf_.get(), bytes_to_read,
-      base::BindOnce(&BlobReader::DidReadDiskCacheEntry,
+  const int result = item.data_handle()->Read(
+      read_buf_, item.offset() + current_item_offset_, bytes_to_read,
+      base::BindOnce(&BlobReader::DidReadReadableDataHandle,
                      weak_factory_.GetWeakPtr()));
+
   if (result >= 0) {
     AdvanceBytesRead(result);
     return Status::DONE;
   }
   if (result == net::ERR_IO_PENDING) {
-    TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobRequest::ReadDiskCacheItem", this,
-                             "uuid", blob_data_->uuid());
+    TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobRequest::ReadReadableDataHandle",
+                             this, "uuid", blob_data_->uuid());
     io_pending_ = true;
     return Status::IO_PENDING;
   }
   return ReportError(result);
 }
 
-void BlobReader::DidReadDiskCacheEntry(int result) {
+void BlobReader::DidReadReadableDataHandle(int result) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadDiskCacheItem", this, "uuid",
-                         blob_data_->uuid());
-  if (result > 0)
-    storage::RecordBytesRead(kCacheStorageRecordBytesLabel, result);
+  TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadReadableDataHandle", this,
+                         "uuid", blob_data_->uuid());
+  RecordBytesReadFromDataHandle(current_item_index_, result);
   DidReadItem(result);
 }
 
@@ -719,7 +706,7 @@
     }
     case BlobDataItem::Type::kBytes:
     case BlobDataItem::Type::kBytesDescription:
-    case BlobDataItem::Type::kDiskCacheEntry:
+    case BlobDataItem::Type::kReadableDataHandle:
       break;
   }
 
@@ -737,4 +724,14 @@
     index_to_reader_.erase(index);
 }
 
+void BlobReader::RecordBytesReadFromDataHandle(int item_index, int result) {
+  const auto& items = blob_data_->items();
+  BlobDataItem& item = *items.at(item_index);
+  DCHECK_EQ(item.type(), BlobDataItem::Type::kReadableDataHandle);
+  if (item.data_handle()->BytesReadHistogramLabel()) {
+    storage::RecordBytesRead(item.data_handle()->BytesReadHistogramLabel(),
+                             result);
+  }
+}
+
 }  // namespace storage
diff --git a/storage/browser/blob/blob_reader.h b/storage/browser/blob/blob_reader.h
index b63b6e5..312b65f 100644
--- a/storage/browser/blob/blob_reader.h
+++ b/storage/browser/blob/blob_reader.h
@@ -82,10 +82,11 @@
   Status CalculateSize(net::CompletionOnceCallback done);
 
   // Returns true when the blob has side data. CalculateSize must be called
-  // beforehand. Currently side data is supported only for single DiskCache
-  // entry blob. So it returns false when the blob has more than single data
-  // item. This side data is used to pass the V8 code cache which is stored
-  // as a side stream in the CacheStorage to the renderer. (crbug.com/581613)
+  // beforehand. Currently side data is supported only for single readable
+  // DataHandle entry blob. So it returns false when the blob has more than
+  // single data item. This side data is used to pass the V8 code cache which is
+  // stored as a side stream in the CacheStorage to the renderer.
+  // (crbug.com/581613)
   bool has_side_data() const;
 
   // Reads the side data of the blob. CalculateSize must be called beforehand.
@@ -94,7 +95,8 @@
   //   Status::NET_ERROR and the net error code is set.
   // * If this function returns Status::IO_PENDING, the done callback will be
   //   called with Status::DONE or Status::NET_ERROR.
-  // Currently side data is supported only for single DiskCache entry blob.
+  // Currently side data is supported only for single readable DataHandle entry
+  // blob.
   Status ReadSideData(StatusCallback done);
 
   // Returns the side data which has been already read with ReadSideData().
@@ -199,12 +201,10 @@
   BlobReader::Status ReadFileItem(FileStreamReader* reader, int bytes_to_read);
   void DidReadFile(int result);
   void DeleteCurrentFileReader();
-  Status ReadDiskCacheEntryItem(const BlobDataItem& item, int bytes_to_read);
-  void DidReadDiskCacheEntry(int result);
+  Status ReadReadableDataHandle(const BlobDataItem& item, int bytes_to_read);
+  void DidReadReadableDataHandle(int result);
   void DidReadItem(int result);
-  void DidReadDiskCacheEntrySideData(StatusCallback done,
-                                     int expected_size,
-                                     int result);
+  void DidReadSideData(StatusCallback done, int expected_size, int result);
   int ComputeBytesToRead() const;
   int BytesReadCompleted();
 
@@ -219,6 +219,8 @@
       const BlobDataItem& item,
       uint64_t additional_offset);
 
+  void RecordBytesReadFromDataHandle(int item_index, int result);
+
   std::unique_ptr<BlobDataHandle> blob_handle_;
   std::unique_ptr<BlobDataSnapshot> blob_data_;
   std::unique_ptr<FileStreamReaderProvider> file_stream_provider_for_testing_;
diff --git a/storage/browser/blob/blob_reader_unittest.cc b/storage/browser/blob/blob_reader_unittest.cc
index dbe8040..5ce22762 100644
--- a/storage/browser/blob/blob_reader_unittest.cc
+++ b/storage/browser/blob/blob_reader_unittest.cc
@@ -26,7 +26,6 @@
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
 #include "net/base/test_completion_callback.h"
-#include "net/disk_cache/disk_cache.h"
 #include "storage/browser/blob/blob_data_builder.h"
 #include "storage/browser/blob/blob_data_handle.h"
 #include "storage/browser/blob/blob_reader.h"
@@ -35,6 +34,7 @@
 #include "storage/browser/fileapi/file_system_context.h"
 #include "storage/browser/fileapi/file_system_file_util.h"
 #include "storage/browser/test/async_file_test_helper.h"
+#include "storage/browser/test/fake_blob_data_handle.h"
 #include "storage/browser/test/test_file_system_context.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -49,9 +49,6 @@
 namespace storage {
 namespace {
 
-const int kTestDiskCacheStreamIndex = 0;
-const int kTestDiskCacheSideStreamIndex = 1;
-
 void SaveBlobStatusAndFiles(BlobStatus* status_ptr,
                             std::vector<FileCreationInfo>* files_ptr,
                             BlobStatus status,
@@ -62,152 +59,6 @@
   }
 }
 
-// Our disk cache tests don't need a real data handle since the tests themselves
-// scope the disk cache and entries.
-class EmptyDataHandle : public storage::BlobDataBuilder::DataHandle {
- private:
-  ~EmptyDataHandle() override = default;
-};
-
-// A disk_cache::Entry that arbitrarily delays the completion of a read
-// operation to allow testing some races without flake. This is particularly
-// relevant in this unit test, which uses the always-synchronous MEMORY_CACHE.
-class DelayedReadEntry : public disk_cache::Entry {
- public:
-  explicit DelayedReadEntry(disk_cache::ScopedEntryPtr entry)
-      : entry_(std::move(entry)) {}
-  ~DelayedReadEntry() override { EXPECT_FALSE(HasPendingReadCallbacks()); }
-
-  bool HasPendingReadCallbacks() { return !pending_read_callbacks_.empty(); }
-
-  void RunPendingReadCallbacks() {
-    std::vector<base::OnceCallback<void(void)>> callbacks;
-    pending_read_callbacks_.swap(callbacks);
-    for (auto& callback : callbacks)
-      std::move(callback).Run();
-  }
-
-  // From disk_cache::Entry:
-  void Doom() override { entry_->Doom(); }
-
-  void Close() override { delete this; }  // Note this is required by the API.
-
-  std::string GetKey() const override { return entry_->GetKey(); }
-
-  base::Time GetLastUsed() const override { return entry_->GetLastUsed(); }
-
-  base::Time GetLastModified() const override {
-    return entry_->GetLastModified();
-  }
-
-  int32_t GetDataSize(int index) const override {
-    return entry_->GetDataSize(index);
-  }
-
-  int ReadData(int index,
-               int offset,
-               IOBuffer* buf,
-               int buf_len,
-               CompletionOnceCallback original_callback) override {
-    net::TestCompletionCallback callback;
-    int rv = entry_->ReadData(index, offset, buf, buf_len, callback.callback());
-    DCHECK_NE(rv, net::ERR_IO_PENDING)
-        << "Test expects to use a MEMORY_CACHE instance, which is synchronous.";
-    pending_read_callbacks_.push_back(
-        base::BindOnce(std::move(original_callback), rv));
-    return net::ERR_IO_PENDING;
-  }
-
-  int WriteData(int index,
-                int offset,
-                IOBuffer* buf,
-                int buf_len,
-                CompletionOnceCallback callback,
-                bool truncate) override {
-    return entry_->WriteData(index, offset, buf, buf_len, std::move(callback),
-                             truncate);
-  }
-
-  int ReadSparseData(int64_t offset,
-                     IOBuffer* buf,
-                     int buf_len,
-                     CompletionOnceCallback callback) override {
-    return entry_->ReadSparseData(offset, buf, buf_len, std::move(callback));
-  }
-
-  int WriteSparseData(int64_t offset,
-                      IOBuffer* buf,
-                      int buf_len,
-                      CompletionOnceCallback callback) override {
-    return entry_->WriteSparseData(offset, buf, buf_len, std::move(callback));
-  }
-
-  int GetAvailableRange(int64_t offset,
-                        int len,
-                        int64_t* start,
-                        CompletionOnceCallback callback) override {
-    return entry_->GetAvailableRange(offset, len, start, std::move(callback));
-  }
-
-  bool CouldBeSparse() const override { return entry_->CouldBeSparse(); }
-
-  void CancelSparseIO() override { entry_->CancelSparseIO(); }
-
-  net::Error ReadyForSparseIO(CompletionOnceCallback callback) override {
-    return entry_->ReadyForSparseIO(std::move(callback));
-  }
-  void SetLastUsedTimeForTest(base::Time time) override { NOTREACHED(); }
-
- private:
-  disk_cache::ScopedEntryPtr entry_;
-  std::vector<base::OnceCallback<void(void)>> pending_read_callbacks_;
-};
-
-std::unique_ptr<disk_cache::Backend> CreateInMemoryDiskCache() {
-  std::unique_ptr<disk_cache::Backend> cache;
-  net::TestCompletionCallback callback;
-  int rv = disk_cache::CreateCacheBackend(
-      net::MEMORY_CACHE, net::CACHE_BACKEND_DEFAULT, FilePath(), 0, false,
-      nullptr, &cache, callback.callback());
-  EXPECT_EQ(net::OK, callback.GetResult(rv));
-
-  return cache;
-}
-
-disk_cache::ScopedEntryPtr CreateDiskCacheEntry(disk_cache::Backend* cache,
-                                                const char* key,
-                                                const std::string& data) {
-  disk_cache::Entry* temp_entry = nullptr;
-  net::TestCompletionCallback callback;
-  int rv =
-      cache->CreateEntry(key, net::HIGHEST, &temp_entry, callback.callback());
-  if (callback.GetResult(rv) != net::OK)
-    return nullptr;
-  disk_cache::ScopedEntryPtr entry(temp_entry);
-
-  scoped_refptr<net::StringIOBuffer> iobuffer =
-      base::MakeRefCounted<net::StringIOBuffer>(data);
-  rv = entry->WriteData(kTestDiskCacheStreamIndex, 0, iobuffer.get(),
-                        iobuffer->size(), callback.callback(), false);
-  EXPECT_EQ(static_cast<int>(data.size()), callback.GetResult(rv));
-  return entry;
-}
-
-disk_cache::ScopedEntryPtr CreateDiskCacheEntryWithSideData(
-    disk_cache::Backend* cache,
-    const char* key,
-    const std::string& data,
-    const std::string& side_data) {
-  disk_cache::ScopedEntryPtr entry = CreateDiskCacheEntry(cache, key, data);
-  scoped_refptr<net::StringIOBuffer> iobuffer =
-      base::MakeRefCounted<net::StringIOBuffer>(side_data);
-  net::TestCompletionCallback callback;
-  int rv = entry->WriteData(kTestDiskCacheSideStreamIndex, 0, iobuffer.get(),
-                            iobuffer->size(), callback.callback(), false);
-  EXPECT_EQ(static_cast<int>(side_data.size()), callback.GetResult(rv));
-  return entry;
-}
-
 template <typename T>
 void SetValue(T* address, T value) {
   *address = value;
@@ -523,17 +374,12 @@
   EXPECT_EQ(0, memcmp(buffer->data(), "FileData!!!", kData.size()));
 }
 
-TEST_F(BlobReaderTest, BasicDiskCache) {
-  std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache();
-  ASSERT_TRUE(cache);
-
+TEST_F(BlobReaderTest, BasicReadableDataHandle) {
   auto b = std::make_unique<BlobDataBuilder>("uuid");
   const std::string kData = "Test Blob Data";
-  scoped_refptr<BlobDataBuilder::DataHandle> data_handle =
-      new EmptyDataHandle();
-  disk_cache::ScopedEntryPtr entry =
-      CreateDiskCacheEntry(cache.get(), "test entry", kData);
-  b->AppendDiskCacheEntry(data_handle, entry.get(), kTestDiskCacheStreamIndex);
+  auto data_handle =
+      base::MakeRefCounted<storage::FakeBlobDataHandle>(kData, "");
+  b->AppendReadableDataHandle(std::move(data_handle));
   this->InitializeReader(std::move(b));
 
   int size_result = -1;
@@ -558,20 +404,13 @@
   EXPECT_EQ(0, memcmp(buffer->data(), "Test Blob Data", kData.size()));
 }
 
-TEST_F(BlobReaderTest, DiskCacheWithSideData) {
-  std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache();
-  ASSERT_TRUE(cache);
-
+TEST_F(BlobReaderTest, ReadableDataHandleWithSideData) {
   auto b = std::make_unique<BlobDataBuilder>("uuid");
   const std::string kData = "Test Blob Data";
   const std::string kSideData = "Test side data";
-  scoped_refptr<BlobDataBuilder::DataHandle> data_handle =
-      new EmptyDataHandle();
-  disk_cache::ScopedEntryPtr entry = CreateDiskCacheEntryWithSideData(
-      cache.get(), "test entry", kData, kSideData);
-  b->AppendDiskCacheEntryWithSideData(data_handle, entry.get(),
-                                      kTestDiskCacheStreamIndex,
-                                      kTestDiskCacheSideStreamIndex);
+  auto data_handle =
+      base::MakeRefCounted<storage::FakeBlobDataHandle>(kData, kSideData);
+  b->AppendReadableDataHandle(std::move(data_handle));
   this->InitializeReader(std::move(b));
 
   int size_result = -1;
@@ -803,18 +642,13 @@
   EXPECT_EQ(0, memcmp(buffer->data(), "FileData!!!", kData.size()));
 }
 
-TEST_F(BlobReaderTest, DiskCacheAsync) {
-  std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache();
-  ASSERT_TRUE(cache);
-
+TEST_F(BlobReaderTest, ReadableDataHandleAsync) {
   auto b = std::make_unique<BlobDataBuilder>("uuid");
   const std::string kData = "Test Blob Data";
-  scoped_refptr<BlobDataBuilder::DataHandle> data_handle =
-      new EmptyDataHandle();
-  std::unique_ptr<DelayedReadEntry> delayed_read_entry(new DelayedReadEntry(
-      CreateDiskCacheEntry(cache.get(), "test entry", kData)));
-  b->AppendDiskCacheEntry(data_handle, delayed_read_entry.get(),
-                          kTestDiskCacheStreamIndex);
+  auto data_handle =
+      base::MakeRefCounted<storage::FakeBlobDataHandle>(kData, "");
+  data_handle->EnableDelayedReading();
+  b->AppendReadableDataHandle(data_handle);
   this->InitializeReader(std::move(b));
 
   int size_result = -1;
@@ -831,8 +665,8 @@
   EXPECT_EQ(BlobReader::Status::IO_PENDING,
             reader_->Read(buffer.get(), kData.size(), &bytes_read,
                           base::BindOnce(&SetValue<int>, &async_bytes_read)));
-  EXPECT_TRUE(delayed_read_entry->HasPendingReadCallbacks());
-  delayed_read_entry->RunPendingReadCallbacks();
+  EXPECT_TRUE(data_handle->HasPendingReadCallbacks());
+  data_handle->RunPendingReadCallbacks();
   EXPECT_EQ(net::OK, reader_->net_error());
   EXPECT_EQ(0, bytes_read);
   EXPECT_EQ(kData.size(), static_cast<size_t>(async_bytes_read));
@@ -882,19 +716,14 @@
   EXPECT_EQ(0, memcmp(buffer->data(), "leD", kReadLength));
 }
 
-TEST_F(BlobReaderTest, DiskCacheRange) {
-  std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache();
-  ASSERT_TRUE(cache);
-
+TEST_F(BlobReaderTest, ReadableDataHandleRange) {
   auto b = std::make_unique<BlobDataBuilder>("uuid");
   const std::string kData = "Test Blob Data";
   const uint64_t kOffset = 2;
   const uint64_t kReadLength = 3;
-  scoped_refptr<BlobDataBuilder::DataHandle> data_handle =
-      new EmptyDataHandle();
-  disk_cache::ScopedEntryPtr entry =
-      CreateDiskCacheEntry(cache.get(), "test entry", kData);
-  b->AppendDiskCacheEntry(data_handle, entry.get(), kTestDiskCacheStreamIndex);
+  auto data_handle =
+      base::MakeRefCounted<storage::FakeBlobDataHandle>(kData, "");
+  b->AppendReadableDataHandle(std::move(data_handle));
   this->InitializeReader(std::move(b));
 
   int size_result = -1;
@@ -992,9 +821,7 @@
 }
 
 TEST_F(BlobReaderTest, MixedContent) {
-  // Includes data, a file, and a disk cache entry.
-  std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache();
-  ASSERT_TRUE(cache);
+  // Includes data, a file, and a data handle entry.
 
   auto b = std::make_unique<BlobDataBuilder>("uuid");
   const std::string kData1("Hello ");
@@ -1006,14 +833,12 @@
   const base::Time kTime = base::Time::Now();
   const FilePath kData1Path = FilePath::FromUTF8Unsafe("/fake/file.txt");
 
-  disk_cache::ScopedEntryPtr entry3 =
-      CreateDiskCacheEntry(cache.get(), "test entry", kData3);
+  auto data_handle =
+      base::MakeRefCounted<storage::FakeBlobDataHandle>(kData3, "");
 
   b->AppendFile(kData1Path, 0, kData1.size(), kTime);
   b->AppendData(kData2);
-  b->AppendDiskCacheEntry(
-      scoped_refptr<BlobDataBuilder::DataHandle>(new EmptyDataHandle()),
-      entry3.get(), kTestDiskCacheStreamIndex);
+  b->AppendReadableDataHandle(std::move(data_handle));
   b->AppendData(kData4);
 
   this->InitializeReader(std::move(b));
diff --git a/storage/browser/blob/blob_storage_context.cc b/storage/browser/blob/blob_storage_context.cc
index 57aba5d5..705aaa4 100644
--- a/storage/browser/blob/blob_storage_context.cc
+++ b/storage/browser/blob/blob_storage_context.cc
@@ -533,7 +533,7 @@
         }
         case BlobDataItem::Type::kBytesDescription:
         case BlobDataItem::Type::kFileFilesystem:
-        case BlobDataItem::Type::kDiskCacheEntry:
+        case BlobDataItem::Type::kReadableDataHandle:
           NOTREACHED();
           break;
       }
diff --git a/storage/browser/blob/blob_storage_context_unittest.cc b/storage/browser/blob/blob_storage_context_unittest.cc
index e2b3523..275588e 100644
--- a/storage/browser/blob/blob_storage_context_unittest.cc
+++ b/storage/browser/blob/blob_storage_context_unittest.cc
@@ -24,11 +24,11 @@
 #include "base/time/time.h"
 #include "net/base/io_buffer.h"
 #include "net/base/test_completion_callback.h"
-#include "net/disk_cache/disk_cache.h"
 #include "storage/browser/blob/blob_data_builder.h"
 #include "storage/browser/blob/blob_data_handle.h"
 #include "storage/browser/blob/blob_data_item.h"
 #include "storage/browser/blob/blob_data_snapshot.h"
+#include "storage/browser/test/fake_blob_data_handle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using FileCreationInfo = storage::BlobMemoryController::FileCreationInfo;
@@ -37,8 +37,6 @@
 namespace {
 using base::TestSimpleTaskRunner;
 
-const int kTestDiskCacheStreamIndex = 0;
-
 const std::string kBlobStorageDirectory = "blob_storage";
 const size_t kTestBlobStorageIPCThresholdBytes = 20;
 const size_t kTestBlobStorageMaxSharedMemoryBytes = 50;
@@ -48,43 +46,6 @@
 const uint64_t kTestBlobStorageMinFileSizeBytes = 10;
 const uint64_t kTestBlobStorageMaxFileSizeBytes = 100;
 
-// Our disk cache tests don't need a real data handle since the tests themselves
-// scope the disk cache and entries.
-class EmptyDataHandle : public storage::BlobDataBuilder::DataHandle {
- private:
-  ~EmptyDataHandle() override = default;
-};
-
-std::unique_ptr<disk_cache::Backend> CreateInMemoryDiskCache() {
-  std::unique_ptr<disk_cache::Backend> cache;
-  net::TestCompletionCallback callback;
-  int rv = disk_cache::CreateCacheBackend(
-      net::MEMORY_CACHE, net::CACHE_BACKEND_DEFAULT, base::FilePath(), 0, false,
-      nullptr, &cache, callback.callback());
-  EXPECT_EQ(net::OK, callback.GetResult(rv));
-
-  return cache;
-}
-
-disk_cache::ScopedEntryPtr CreateDiskCacheEntry(disk_cache::Backend* cache,
-                                                const char* key,
-                                                const std::string& data) {
-  disk_cache::Entry* temp_entry = nullptr;
-  net::TestCompletionCallback callback;
-  int rv =
-      cache->CreateEntry(key, net::HIGHEST, &temp_entry, callback.callback());
-  if (callback.GetResult(rv) != net::OK)
-    return nullptr;
-  disk_cache::ScopedEntryPtr entry(temp_entry);
-
-  scoped_refptr<net::StringIOBuffer> iobuffer =
-      base::MakeRefCounted<net::StringIOBuffer>(data);
-  rv = entry->WriteData(kTestDiskCacheStreamIndex, 0, iobuffer.get(),
-                        iobuffer->size(), callback.callback(), false);
-  EXPECT_EQ(static_cast<int>(data.size()), callback.GetResult(rv));
-  return entry;
-}
-
 void SaveBlobStatus(BlobStatus* status_ptr, BlobStatus status) {
   *status_ptr = status;
 }
@@ -492,20 +453,14 @@
   base::RunLoop().RunUntilIdle();
 }
 
-TEST_F(BlobStorageContextTest, BuildDiskCacheBlob) {
-  scoped_refptr<BlobDataBuilder::DataHandle>
-      data_handle = new EmptyDataHandle();
+TEST_F(BlobStorageContextTest, BuildReadableDataHandleBlob) {
+  const std::string kTestBlobData = "Test Blob Data";
+  auto data_handle =
+      base::MakeRefCounted<storage::FakeBlobDataHandle>(kTestBlobData, "");
 
   {
     BlobStorageContext context;
 
-    std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache();
-    ASSERT_TRUE(cache);
-
-    const std::string kTestBlobData = "Test Blob Data";
-    disk_cache::ScopedEntryPtr entry =
-        CreateDiskCacheEntry(cache.get(), "test entry", kTestBlobData);
-
     const std::string kId1Prime("id1.prime");
     BlobDataBuilder canonicalized_blob_data(kId1Prime);
     canonicalized_blob_data.AppendData(kTestBlobData.c_str());
@@ -513,8 +468,7 @@
     const std::string kId1("id1");
     auto builder = std::make_unique<BlobDataBuilder>(kId1);
 
-    builder->AppendDiskCacheEntry(data_handle, entry.get(),
-                                  kTestDiskCacheStreamIndex);
+    builder->AppendReadableDataHandle(data_handle);
 
     std::unique_ptr<BlobDataSnapshot> builder_data = builder->CreateSnapshot();
     std::unique_ptr<BlobDataHandle> blob_data_handle =
@@ -618,12 +572,9 @@
 
   auto blob_data3_builder = std::make_unique<BlobDataBuilder>(kId3);
   blob_data3_builder->AppendData("Data4");
-  std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache();
-  ASSERT_TRUE(cache);
-  disk_cache::ScopedEntryPtr disk_cache_entry =
-      CreateDiskCacheEntry(cache.get(), "another key", "Data5");
-  blob_data3_builder->AppendDiskCacheEntry(
-      new EmptyDataHandle(), disk_cache_entry.get(), kTestDiskCacheStreamIndex);
+  auto data_handle =
+      base::MakeRefCounted<storage::FakeBlobDataHandle>("Data5", "");
+  blob_data3_builder->AppendReadableDataHandle(std::move(data_handle));
   std::unique_ptr<BlobDataSnapshot> blob_data3 =
       blob_data3_builder->CreateSnapshot();
 
@@ -733,7 +684,7 @@
 namespace {
 constexpr size_t kTotalRawBlobs = 200;
 constexpr size_t kTotalSlicedBlobs = 100;
-constexpr char kTestDiskCacheData[] = "Test Blob Data";
+constexpr char kTestDataHandleData[] = "Test Blob Data";
 
 // Appends data and data types that depend on the index. This is designed to
 // exercise all types of combinations of data, future data, files, future files,
@@ -743,7 +694,7 @@
     std::vector<BlobDataBuilder::FutureData>* future_datas,
     std::vector<BlobDataBuilder::FutureFile>* future_files,
     size_t index,
-    disk_cache::Entry* cache_entry) {
+    scoped_refptr<storage::BlobDataItem::DataHandle> data_handle) {
   size_t size = 0;
   // We can't have both future data and future files, so split those up.
   if (index % 2 != 0) {
@@ -768,11 +719,8 @@
     size += 20u;
   }
   if (index % 3 != 0) {
-    scoped_refptr<BlobDataBuilder::DataHandle> disk_cache_data_handle =
-        new EmptyDataHandle();
-    builder->AppendDiskCacheEntry(disk_cache_data_handle, cache_entry,
-                                  kTestDiskCacheStreamIndex);
-    size += strlen(kTestDiskCacheData);
+    builder->AppendReadableDataHandle(data_handle);
+    size += strlen(kTestDataHandleData);
   }
   return size;
 }
@@ -809,10 +757,8 @@
       std::make_unique<BlobStorageContext>(temp_dir_.GetPath(), file_runner_);
 
   SetTestMemoryLimits();
-  std::unique_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache();
-  ASSERT_TRUE(cache);
-  disk_cache::ScopedEntryPtr entry =
-      CreateDiskCacheEntry(cache.get(), "test entry", kTestDiskCacheData);
+  auto data_handle = base::MakeRefCounted<storage::FakeBlobDataHandle>(
+      kTestDataHandleData, "");
 
   // This tests mixed blob content with both synchronous and asynchronous
   // construction. Blobs should also be paged to disk during execution.
@@ -826,7 +772,7 @@
     future_files.emplace_back();
     auto& builder = *builders.back();
     size_t size = AppendDataInBuilder(&builder, &future_datas.back(),
-                                      &future_files.back(), i, entry.get());
+                                      &future_files.back(), i, data_handle);
     EXPECT_NE(0u, size);
     sizes.push_back(size);
   }
diff --git a/storage/browser/blob/blob_url_request_job.cc b/storage/browser/blob/blob_url_request_job.cc
index 88bd83f..c4390c0c 100644
--- a/storage/browser/blob/blob_url_request_job.cc
+++ b/storage/browser/blob/blob_url_request_job.cc
@@ -24,7 +24,6 @@
 #include "base/trace_event/trace_event.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
-#include "net/disk_cache/disk_cache.h"
 #include "net/http/http_request_headers.h"
 #include "net/http/http_response_headers.h"
 #include "net/http/http_response_info.h"
diff --git a/storage/browser/blob/view_blob_internals_job.cc b/storage/browser/blob/view_blob_internals_job.cc
index e405ff85..c80b9327 100644
--- a/storage/browser/blob/view_blob_internals_job.cc
+++ b/storage/browser/blob/view_blob_internals_job.cc
@@ -6,6 +6,7 @@
 
 #include <stddef.h>
 #include <stdint.h>
+#include <sstream>
 
 #include "base/bind.h"
 #include "base/compiler_specific.h"
@@ -22,7 +23,6 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "net/base/escape.h"
 #include "net/base/net_errors.h"
-#include "net/disk_cache/disk_cache.h"
 #include "net/url_request/url_request.h"
 #include "storage/browser/blob/blob_data_item.h"
 #include "storage/browser/blob/blob_entry.h"
@@ -273,13 +273,13 @@
               out);
         }
         break;
-      case BlobDataItem::Type::kDiskCacheEntry:
-        AddHTMLListItem(kType, "disk cache entry", out);
-        if (item.disk_cache_entry())
-          AddHTMLListItem(kURL, item.disk_cache_entry()->GetKey(), out);
-        else
-          AddHTMLListItem(kURL, "Broken", out);
+      case BlobDataItem::Type::kReadableDataHandle: {
+        AddHTMLListItem(kType, "readable data handle", out);
+        std::stringstream ss;
+        item.data_handle()->PrintTo(&ss);
+        AddHTMLListItem(kURL, ss.str(), out);
         break;
+      }
       case BlobDataItem::Type::kBytesDescription:
         AddHTMLListItem(kType, "pending data", out);
         break;
diff --git a/storage/browser/test/fake_blob_data_handle.cc b/storage/browser/test/fake_blob_data_handle.cc
new file mode 100644
index 0000000..3add0f4
--- /dev/null
+++ b/storage/browser/test/fake_blob_data_handle.cc
@@ -0,0 +1,75 @@
+// Copyright 2019 The Chromium 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 "storage/browser/test/fake_blob_data_handle.h"
+
+#include "base/bind.h"
+#include "net/base/net_errors.h"
+
+namespace storage {
+
+FakeBlobDataHandle::FakeBlobDataHandle(std::string body_data,
+                                       std::string side_data)
+    : body_data_(std::move(body_data)), side_data_(std::move(side_data)) {}
+
+void FakeBlobDataHandle::EnableDelayedReading() {
+  delayed_reading_ = true;
+}
+
+bool FakeBlobDataHandle::HasPendingReadCallbacks() const {
+  return !pending_read_callbacks_.empty();
+}
+
+void FakeBlobDataHandle::RunPendingReadCallbacks() {
+  std::vector<base::OnceClosure> list = std::move(pending_read_callbacks_);
+  for (auto& cb : list) {
+    std::move(cb).Run();
+  }
+}
+
+uint64_t FakeBlobDataHandle::GetSize() const {
+  return body_data_.size();
+}
+
+int FakeBlobDataHandle::Read(scoped_refptr<net::IOBuffer> dst_buffer,
+                             uint64_t src_offset,
+                             int bytes_to_read,
+                             base::OnceCallback<void(int)> callback) {
+  if (src_offset >= body_data_.size())
+    return net::ERR_FAILED;
+
+  int num_bytes =
+      std::min(static_cast<int>(body_data_.size() - src_offset), bytes_to_read);
+  memcpy(dst_buffer->data(), body_data_.data() + src_offset, num_bytes);
+
+  if (delayed_reading_)
+    return PendingCallback(std::move(callback), num_bytes);
+
+  return num_bytes;
+}
+
+uint64_t FakeBlobDataHandle::GetSideDataSize() const {
+  return side_data_.size();
+}
+
+int FakeBlobDataHandle::ReadSideData(scoped_refptr<net::IOBuffer> dst_buffer,
+                                     base::OnceCallback<void(int)> callback) {
+  memcpy(dst_buffer->data(), side_data_.data(), side_data_.size());
+
+  if (delayed_reading_)
+    return PendingCallback(std::move(callback), side_data_.size());
+
+  return side_data_.size();
+}
+
+FakeBlobDataHandle::~FakeBlobDataHandle() = default;
+
+int FakeBlobDataHandle::PendingCallback(base::OnceCallback<void(int)> callback,
+                                        int result) {
+  pending_read_callbacks_.push_back(
+      base::BindOnce(std::move(callback), result));
+  return net::ERR_IO_PENDING;
+}
+
+}  // namespace storage
diff --git a/storage/browser/test/fake_blob_data_handle.h b/storage/browser/test/fake_blob_data_handle.h
new file mode 100644
index 0000000..4763530
--- /dev/null
+++ b/storage/browser/test/fake_blob_data_handle.h
@@ -0,0 +1,46 @@
+// Copyright 2019 The Chromium 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 STORAGE_BROWSER_TEST_FAKE_BLOB_DATA_HANDLE_H_
+#define STORAGE_BROWSER_TEST_FAKE_BLOB_DATA_HANDLE_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "storage/browser/blob/blob_data_item.h"
+
+namespace storage {
+
+class FakeBlobDataHandle : public BlobDataItem::DataHandle {
+ public:
+  FakeBlobDataHandle(std::string body_data, std::string side_data);
+
+  void EnableDelayedReading();
+  bool HasPendingReadCallbacks() const;
+  void RunPendingReadCallbacks();
+
+  uint64_t GetSize() const override;
+  int Read(scoped_refptr<net::IOBuffer> dst_buffer,
+           uint64_t src_offset,
+           int bytes_to_read,
+           base::OnceCallback<void(int)> callback) override;
+
+  uint64_t GetSideDataSize() const override;
+  int ReadSideData(scoped_refptr<net::IOBuffer> dst_buffer,
+                   base::OnceCallback<void(int)> callback) override;
+
+ private:
+  ~FakeBlobDataHandle() override;
+
+  int PendingCallback(base::OnceCallback<void(int)> callback, int result);
+
+  const std::string body_data_;
+  const std::string side_data_;
+  std::vector<base::OnceClosure> pending_read_callbacks_;
+  bool delayed_reading_ = false;
+};
+
+}  // namespace storage
+
+#endif  // STORAGE_BROWSER_TEST_FAKE_BLOB_DATA_HANDLE_H_
diff --git a/styleguide/c++/c++.md b/styleguide/c++/c++.md
index 6b4aaf1..a624a86 100644
--- a/styleguide/c++/c++.md
+++ b/styleguide/c++/c++.md
@@ -18,11 +18,13 @@
 
 Blink code in `third_party/WebKit` uses [Blink style](blink-c++.md).
 
-## C++11 features
+## Modern C++ features
 
-Google style has adopted most C++11 features, but Chromium has a more
-restricted set. The status of C++11 features in Chromium is tracked in the
-separate [C++11 use in Chromium](https://chromium-cpp.appspot.com/) page.
+Some features of C++ remain forbidden, even as Chromium adopts newer versions
+of the C++ language and standard library. These should be similar to those
+allowed in Google style, but may occasionally differ. The status of modern C++
+features in Chromium is tracked in the separate
+[C++ use in Chromium](https://chromium-cpp.appspot.com/) page.
 
 ## Naming
 
diff --git a/styleguide/c++/c++11.html b/styleguide/c++/c++11.html
index 9fbb544f..b174dec 100644
--- a/styleguide/c++/c++11.html
+++ b/styleguide/c++/c++11.html
@@ -7,7 +7,7 @@
 <html>
 <head>
 <meta charset="utf-8">
-<title>C++11 and C++14 use in Chromium</title>
+<title>Modern C++ use in Chromium</title>
 <link rel="stylesheet" href="c++11.css">
 <style>
 table tbody tr td:first-child {
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json
index e19dabc..494cf9aa 100644
--- a/testing/buildbot/chromium.gpu.fyi.json
+++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -15,6 +15,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -39,6 +40,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -60,6 +62,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -81,6 +84,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -102,6 +106,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -122,6 +127,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -150,6 +156,7 @@
         "name": "angle_perftests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -181,6 +188,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -209,6 +217,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -239,6 +248,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -270,6 +280,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -299,6 +310,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -328,6 +340,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -355,6 +368,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -379,6 +393,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -400,6 +415,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -421,6 +437,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -442,6 +459,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -462,6 +480,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -490,6 +509,7 @@
         "name": "angle_perftests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -521,6 +541,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -549,6 +570,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -579,6 +601,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -610,6 +633,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -639,6 +663,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -668,6 +693,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -695,6 +721,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -717,6 +744,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -737,6 +765,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -756,6 +785,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -775,6 +805,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -791,6 +822,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -824,6 +856,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -853,6 +886,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -881,6 +915,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -907,6 +942,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -931,6 +967,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -953,6 +990,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -974,6 +1012,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -995,6 +1034,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -1013,6 +1053,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -1048,6 +1089,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -1079,6 +1121,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -1109,6 +1152,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -1137,6 +1181,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -1161,6 +1206,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -1188,6 +1234,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -1209,6 +1256,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -1231,6 +1279,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -1252,6 +1301,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -1273,6 +1323,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -1295,6 +1346,7 @@
         "name": "gl_tests_passthrough",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -1318,6 +1370,7 @@
         "name": "gles2_conform_d3d11_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -1340,6 +1393,7 @@
         "name": "gles2_conform_d3d9_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -1363,6 +1417,7 @@
         "name": "gles2_conform_gl_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -1386,6 +1441,7 @@
         "name": "video_decode_accelerator_d3d11_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -1409,6 +1465,7 @@
         "name": "video_decode_accelerator_d3d9_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -1437,6 +1494,7 @@
         "name": "angle_perftests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -1468,6 +1526,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -1498,6 +1557,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -1529,6 +1589,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -1558,6 +1619,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -1587,6 +1649,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -1616,6 +1679,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -1645,6 +1709,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -1672,6 +1737,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -1693,6 +1759,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -1715,6 +1782,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -1736,6 +1804,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -1757,6 +1826,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -1779,6 +1849,7 @@
         "name": "gl_tests_passthrough",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -1802,6 +1873,7 @@
         "name": "gles2_conform_d3d11_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -1824,6 +1896,7 @@
         "name": "gles2_conform_d3d9_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -1847,6 +1920,7 @@
         "name": "gles2_conform_gl_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -1870,6 +1944,7 @@
         "name": "video_decode_accelerator_d3d11_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -1893,6 +1968,7 @@
         "name": "video_decode_accelerator_d3d9_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -1916,6 +1992,7 @@
         "name": "video_decode_accelerator_gl_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -1944,6 +2021,7 @@
         "name": "angle_perftests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -1975,6 +2053,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -2004,6 +2083,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -2032,6 +2112,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -2061,6 +2142,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -2092,6 +2174,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -2121,6 +2204,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -2150,6 +2234,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -2179,6 +2264,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -2208,6 +2294,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -2237,6 +2324,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -2266,6 +2354,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -2300,6 +2389,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "P",
@@ -2342,6 +2432,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "P",
@@ -2383,6 +2474,7 @@
         "name": "angle_perftests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "P",
@@ -2421,6 +2513,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "P",
@@ -2467,6 +2560,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "P",
@@ -2513,6 +2607,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "P",
@@ -2559,6 +2654,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "P",
@@ -2604,6 +2700,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "P",
@@ -2650,6 +2747,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "P",
@@ -2692,6 +2790,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "P",
@@ -2733,6 +2832,7 @@
         "name": "angle_perftests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "P",
@@ -2771,6 +2871,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "P",
@@ -2817,6 +2918,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "P",
@@ -2863,6 +2965,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "P",
@@ -2909,6 +3012,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "P",
@@ -2954,6 +3058,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "P",
@@ -3000,6 +3105,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "N",
@@ -3042,6 +3148,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "N",
@@ -3082,6 +3189,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "N",
@@ -3122,6 +3230,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "N",
@@ -3162,6 +3271,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "N",
@@ -3203,6 +3313,7 @@
         "name": "angle_perftests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "N",
@@ -3232,6 +3343,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "N",
@@ -3262,6 +3374,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "N",
@@ -3292,6 +3405,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "N",
@@ -3322,6 +3436,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "N",
@@ -3356,6 +3471,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "N",
@@ -3393,6 +3509,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "N",
@@ -3446,6 +3563,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "N",
@@ -3492,6 +3610,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "N",
@@ -3523,6 +3642,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "N",
@@ -3553,6 +3673,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "N",
@@ -3584,6 +3705,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "N",
@@ -3620,6 +3742,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -3660,6 +3783,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -3700,6 +3824,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -3740,6 +3865,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -3782,6 +3908,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -3812,6 +3939,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -3842,6 +3970,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -3872,6 +4001,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -3906,6 +4036,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -3943,6 +4074,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -3996,6 +4128,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -4042,6 +4175,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -4073,6 +4207,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -4103,6 +4238,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -4134,6 +4270,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -4170,6 +4307,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -4210,6 +4348,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -4266,6 +4405,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -4294,6 +4434,7 @@
         "name": "angle_perftests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -4322,6 +4463,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -4351,6 +4493,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -4380,6 +4523,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -4409,6 +4553,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -4442,6 +4587,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -4478,6 +4624,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -4530,6 +4677,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -4575,6 +4723,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -4605,6 +4754,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -4634,6 +4784,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -4664,6 +4815,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -4695,6 +4847,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -4730,6 +4883,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -4770,6 +4924,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -4810,6 +4965,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -4850,6 +5006,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -4892,6 +5049,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -4922,6 +5080,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -4952,6 +5111,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -4982,6 +5142,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -5016,6 +5177,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -5053,6 +5215,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -5106,6 +5269,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -5152,6 +5316,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -5183,6 +5348,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -5213,6 +5379,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -5244,6 +5411,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "L",
@@ -5280,6 +5448,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -5322,6 +5491,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -5362,6 +5532,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -5402,6 +5573,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -5442,6 +5614,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -5483,6 +5656,7 @@
         "name": "angle_perftests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -5512,6 +5686,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -5542,6 +5717,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -5572,6 +5748,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -5602,6 +5779,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -5636,6 +5814,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -5673,6 +5852,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -5726,6 +5906,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -5772,6 +5953,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -5803,6 +5985,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -5833,6 +6016,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -5864,6 +6048,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -5900,6 +6085,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -5940,6 +6126,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -5980,6 +6167,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -6020,6 +6208,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -6061,6 +6250,7 @@
         "name": "angle_perftests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -6090,6 +6280,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -6120,6 +6311,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -6150,6 +6342,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -6180,6 +6373,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -6214,6 +6408,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -6251,6 +6446,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -6304,6 +6500,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -6350,6 +6547,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -6381,6 +6579,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -6411,6 +6610,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -6442,6 +6642,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "M",
@@ -6500,6 +6701,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "P",
@@ -6533,6 +6735,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "P",
@@ -6572,6 +6775,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "P",
@@ -6622,6 +6826,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -6667,6 +6872,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -6712,6 +6918,7 @@
               "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
             }
           ],
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -6749,6 +6956,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -6772,6 +6980,7 @@
         "name": "dawn_end2end_wire_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -6797,6 +7006,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -6820,6 +7030,7 @@
         "name": "dawn_end2end_wire_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -6845,6 +7056,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -6867,6 +7079,7 @@
         "name": "dawn_end2end_wire_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -6891,6 +7104,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -6915,6 +7129,7 @@
         "name": "dawn_end2end_wire_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -6941,6 +7156,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -6965,6 +7181,7 @@
         "name": "dawn_end2end_wire_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -6991,6 +7208,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -7014,6 +7232,7 @@
         "name": "dawn_end2end_wire_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -7039,6 +7258,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -7062,6 +7282,7 @@
         "name": "dawn_end2end_wire_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -7108,6 +7329,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -7129,6 +7351,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -7150,6 +7373,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -7171,6 +7395,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -7191,6 +7416,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -7208,6 +7434,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -7238,6 +7465,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -7266,6 +7494,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -7294,6 +7523,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -7322,6 +7552,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -7354,6 +7585,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -7389,6 +7621,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -7440,6 +7673,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -7484,6 +7718,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -7513,6 +7748,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -7541,6 +7777,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -7569,6 +7806,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -7598,6 +7836,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -7626,6 +7865,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-18.3.3",
@@ -7647,6 +7887,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-18.3.3",
@@ -7668,6 +7909,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-18.3.3",
@@ -7688,6 +7930,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-18.3.3",
@@ -7705,6 +7948,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-18.3.3",
@@ -7735,6 +7979,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-18.3.3",
@@ -7763,6 +8008,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-18.3.3",
@@ -7791,6 +8037,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-18.3.3",
@@ -7819,6 +8066,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-18.3.3",
@@ -7851,6 +8099,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-18.3.3",
@@ -7886,6 +8135,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-18.3.3",
@@ -7937,6 +8187,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-18.3.3",
@@ -7981,6 +8232,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-18.3.3",
@@ -8010,6 +8262,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-18.3.3",
@@ -8038,6 +8291,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-18.3.3",
@@ -8068,6 +8322,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-18.3.3",
@@ -8097,6 +8352,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-18.3.3",
@@ -8126,6 +8382,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-18.3.3",
@@ -8153,6 +8410,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-410.78",
@@ -8177,6 +8435,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-410.78",
@@ -8198,6 +8457,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-410.78",
@@ -8223,6 +8483,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-410.78",
@@ -8244,6 +8505,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-410.78",
@@ -8265,6 +8527,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-410.78",
@@ -8285,6 +8548,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-410.78",
@@ -8302,6 +8566,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-410.78",
@@ -8330,6 +8595,7 @@
         "name": "angle_perftests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-410.78",
@@ -8357,6 +8623,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-410.78",
@@ -8385,6 +8652,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-410.78",
@@ -8413,6 +8681,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-410.78",
@@ -8441,6 +8710,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-410.78",
@@ -8473,6 +8743,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-410.78",
@@ -8508,6 +8779,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-410.78",
@@ -8559,6 +8831,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-410.78",
@@ -8603,6 +8876,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-410.78",
@@ -8632,6 +8906,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-410.78",
@@ -8660,6 +8935,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-410.78",
@@ -8690,6 +8966,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-410.78",
@@ -8721,6 +8998,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-410.78",
@@ -8750,6 +9028,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-410.78",
@@ -8779,6 +9058,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-410.78",
@@ -8807,6 +9087,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -8828,6 +9109,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -8849,6 +9131,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -8870,6 +9153,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -8890,6 +9174,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -8907,6 +9192,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -8934,6 +9220,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:1912",
@@ -8958,6 +9245,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:1912",
@@ -8985,6 +9273,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -9007,6 +9296,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -9033,6 +9323,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -9055,6 +9346,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -9076,6 +9368,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -9094,6 +9387,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -9125,6 +9419,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -9154,6 +9449,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -9183,6 +9479,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -9212,6 +9509,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -9245,6 +9543,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -9281,6 +9580,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -9333,6 +9633,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -9378,6 +9679,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -9408,6 +9710,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -9437,6 +9740,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -9468,6 +9772,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -9498,6 +9803,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -9528,6 +9834,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -9556,6 +9863,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -9580,6 +9888,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -9601,6 +9910,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -9626,6 +9936,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -9659,6 +9970,7 @@
         "name": "vulkan_content_browsertests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -9680,6 +9992,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -9701,6 +10014,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -9721,6 +10035,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -9738,6 +10053,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -9768,6 +10084,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -9796,6 +10113,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -9824,6 +10142,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -9852,6 +10171,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -9884,6 +10204,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -9919,6 +10240,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -9970,6 +10292,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -10014,6 +10337,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -10043,6 +10367,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -10071,6 +10396,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -10101,6 +10427,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -10132,6 +10459,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -10161,6 +10489,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -10190,6 +10519,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -10217,6 +10547,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10241,6 +10572,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10262,6 +10594,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10287,6 +10620,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10308,6 +10642,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10329,6 +10664,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10349,6 +10685,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10366,6 +10703,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10394,6 +10732,7 @@
         "name": "angle_perftests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10421,6 +10760,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10449,6 +10789,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10477,6 +10818,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10505,6 +10847,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10537,6 +10880,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10572,6 +10916,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10623,6 +10968,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10667,6 +11013,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10696,6 +11043,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10724,6 +11072,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10754,6 +11103,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10785,6 +11135,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10814,6 +11165,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10843,6 +11195,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10870,6 +11223,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10894,6 +11248,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10915,6 +11270,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10940,6 +11296,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10961,6 +11318,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -10982,6 +11340,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -11002,6 +11361,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -11019,6 +11379,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -11051,6 +11412,7 @@
         "results_handler": "layout tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -11102,6 +11464,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -11130,6 +11493,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -11158,6 +11522,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -11182,6 +11547,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -11206,6 +11572,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -11230,6 +11597,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -11254,6 +11622,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -11278,6 +11647,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -11302,6 +11672,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -11326,6 +11697,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -11349,6 +11721,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -11376,6 +11749,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -11412,6 +11786,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -11449,6 +11824,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -11483,6 +11859,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -11516,6 +11893,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -11549,6 +11927,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -11579,6 +11958,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -11613,6 +11993,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -11643,6 +12024,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -11686,6 +12068,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -11727,6 +12110,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -11768,6 +12152,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -11809,6 +12194,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -11854,6 +12240,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -11902,6 +12289,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -11966,6 +12354,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -12023,6 +12412,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -12065,6 +12455,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -12106,6 +12497,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -12149,6 +12541,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -12191,6 +12584,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -12231,6 +12625,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -12267,6 +12662,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -12304,6 +12700,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -12338,6 +12735,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -12371,6 +12769,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -12404,6 +12803,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -12434,6 +12834,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -12468,6 +12869,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -12498,6 +12900,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -12541,6 +12944,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -12582,6 +12986,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -12623,6 +13028,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -12664,6 +13070,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -12709,6 +13116,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -12757,6 +13165,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -12821,6 +13230,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -12878,6 +13288,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -12920,6 +13331,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -12961,6 +13373,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -13004,6 +13417,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -13046,6 +13460,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -13086,6 +13501,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -13122,6 +13538,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -13159,6 +13576,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -13193,6 +13611,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -13226,6 +13645,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -13259,6 +13679,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -13289,6 +13710,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -13323,6 +13745,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -13353,6 +13776,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -13396,6 +13820,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -13437,6 +13862,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -13478,6 +13904,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -13519,6 +13946,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -13564,6 +13992,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -13612,6 +14041,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -13676,6 +14106,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -13733,6 +14164,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -13775,6 +14207,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -13816,6 +14249,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -13859,6 +14293,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -13901,6 +14336,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -13941,6 +14377,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -13963,6 +14400,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -13983,6 +14421,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14002,6 +14441,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14021,6 +14461,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14037,6 +14478,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14057,6 +14499,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14073,6 +14516,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14102,6 +14546,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14129,6 +14574,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14156,6 +14602,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14183,6 +14630,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14214,6 +14662,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14248,6 +14697,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14298,6 +14748,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14341,6 +14792,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14369,6 +14821,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14396,6 +14849,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14423,6 +14877,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14449,6 +14904,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14473,6 +14929,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14498,6 +14955,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14520,6 +14978,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14541,6 +15000,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14562,6 +15022,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14580,6 +15041,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14602,6 +15064,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14633,6 +15096,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14662,6 +15126,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14691,6 +15156,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14720,6 +15186,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14753,6 +15220,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14789,6 +15257,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14841,6 +15310,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14886,6 +15356,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14916,6 +15387,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14945,6 +15417,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -14976,6 +15449,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -15006,6 +15480,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -15034,6 +15509,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -15059,6 +15535,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -15085,6 +15562,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -15108,6 +15586,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -15130,6 +15609,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -15152,6 +15632,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -15171,6 +15652,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -15194,6 +15676,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -15226,6 +15709,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -15256,6 +15740,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -15286,6 +15771,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -15316,6 +15802,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -15350,6 +15837,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -15387,6 +15875,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -15440,6 +15929,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -15486,6 +15976,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -15517,6 +16008,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -15547,6 +16039,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -15579,6 +16072,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -15610,6 +16104,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -15639,6 +16134,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -15664,6 +16160,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -15690,6 +16187,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -15713,6 +16211,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -15735,6 +16234,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -15757,6 +16257,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -15776,6 +16277,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -15799,6 +16301,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -15831,6 +16334,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -15861,6 +16365,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -15891,6 +16396,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -15921,6 +16427,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -15955,6 +16462,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -15992,6 +16500,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -16045,6 +16554,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -16091,6 +16601,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -16122,6 +16633,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -16152,6 +16664,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -16184,6 +16697,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -16215,6 +16729,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -16244,6 +16759,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16272,6 +16788,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16301,6 +16818,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16327,6 +16845,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16352,6 +16871,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16377,6 +16897,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16399,6 +16920,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16425,6 +16947,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16447,6 +16970,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16483,6 +17007,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16516,6 +17041,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16549,6 +17075,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16582,6 +17109,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16622,6 +17150,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16678,6 +17207,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16727,6 +17257,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16761,6 +17292,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16794,6 +17326,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16830,6 +17363,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16865,6 +17399,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16897,6 +17432,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16919,6 +17455,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16942,6 +17479,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16962,6 +17500,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -16981,6 +17520,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -17000,6 +17540,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -17016,6 +17557,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -17036,6 +17578,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -17052,6 +17595,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -17081,6 +17625,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -17108,6 +17653,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -17135,6 +17681,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -17162,6 +17709,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -17193,6 +17741,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -17227,6 +17776,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -17277,6 +17827,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -17320,6 +17871,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -17340,6 +17892,7 @@
         "name": "rendering_representative_perf_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -17367,6 +17920,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -17394,6 +17948,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -17423,6 +17978,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -17451,6 +18007,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -17477,6 +18034,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -17501,6 +18059,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -17523,6 +18082,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -17544,6 +18104,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -17565,6 +18126,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -17583,6 +18145,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -17605,6 +18168,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -17623,6 +18187,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -17654,6 +18219,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -17683,6 +18249,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -17712,6 +18279,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -17741,6 +18309,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -17774,6 +18343,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -17810,6 +18380,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -17862,6 +18433,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -17907,6 +18479,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -17937,6 +18510,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -17966,6 +18540,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -17995,6 +18570,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -18023,6 +18599,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -18047,6 +18624,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -18069,6 +18647,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -18090,6 +18669,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -18111,6 +18691,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -18129,6 +18710,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -18151,6 +18733,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -18169,6 +18752,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -18200,6 +18784,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -18229,6 +18814,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -18258,6 +18844,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -18287,6 +18874,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -18320,6 +18908,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -18356,6 +18945,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -18408,6 +18998,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -18453,6 +19044,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -18483,6 +19075,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -18512,6 +19105,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -18539,6 +19133,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -18563,6 +19158,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -18588,6 +19184,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -18610,6 +19207,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -18631,6 +19229,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -18652,6 +19251,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -18670,6 +19270,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -18692,6 +19293,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -18710,6 +19312,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -18741,6 +19344,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -18770,6 +19374,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -18799,6 +19404,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -18828,6 +19434,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -18861,6 +19468,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -18897,6 +19505,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -18949,6 +19558,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -18994,6 +19604,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -19016,6 +19627,7 @@
         "name": "rendering_representative_perf_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -19045,6 +19657,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -19074,6 +19687,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -19105,6 +19719,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -19135,6 +19750,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -19163,6 +19779,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -19187,6 +19804,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -19212,6 +19830,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -19234,6 +19853,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -19255,6 +19875,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -19276,6 +19897,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -19294,6 +19916,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -19316,6 +19939,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -19334,6 +19958,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -19365,6 +19990,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -19394,6 +20020,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -19423,6 +20050,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -19452,6 +20080,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -19485,6 +20114,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -19521,6 +20151,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -19573,6 +20204,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -19618,6 +20250,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -19648,6 +20281,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -19677,6 +20311,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -19708,6 +20343,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -19738,6 +20374,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -19767,6 +20404,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -19792,6 +20430,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -19817,6 +20456,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -19846,6 +20486,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -19869,6 +20510,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -19892,6 +20534,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -19918,6 +20561,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:679e",
@@ -19942,6 +20586,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:679e",
@@ -19967,6 +20612,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:679e",
@@ -19989,6 +20635,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:679e",
@@ -20010,6 +20657,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:679e",
@@ -20031,6 +20679,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:679e",
@@ -20049,6 +20698,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:679e",
@@ -20080,6 +20730,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:679e",
@@ -20109,6 +20760,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:679e",
@@ -20138,6 +20790,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:679e",
@@ -20167,6 +20820,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:679e",
@@ -20200,6 +20854,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:679e",
@@ -20236,6 +20891,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:679e",
@@ -20288,6 +20944,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:679e",
@@ -20333,6 +20990,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:679e",
@@ -20363,6 +21021,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:679e",
@@ -20392,6 +21051,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:679e",
@@ -20423,6 +21083,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:679e",
@@ -20453,6 +21114,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:679e",
@@ -20482,6 +21144,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -20504,6 +21167,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -20537,6 +21201,7 @@
         "name": "vulkan_content_browsertests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -20557,6 +21222,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -20574,6 +21240,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -20608,6 +21275,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -20659,6 +21327,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -20688,6 +21357,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -20718,6 +21388,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -20747,6 +21418,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-ubuntu-stable",
@@ -20774,6 +21446,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -20796,6 +21469,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -20829,6 +21503,7 @@
         "name": "vulkan_content_browsertests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -20849,6 +21524,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -20866,6 +21542,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -20894,6 +21571,7 @@
         "name": "angle_perftests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -20925,6 +21603,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -20976,6 +21655,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -20996,6 +21676,7 @@
         "name": "test_buildbucket_api_gpu_use_cases",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -21023,6 +21704,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -21053,6 +21735,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -21082,6 +21765,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -21109,6 +21793,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -21129,6 +21814,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -21145,6 +21831,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -21165,6 +21852,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -21181,6 +21869,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -21214,6 +21903,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -21264,6 +21954,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -21292,6 +21983,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -21321,6 +22013,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -21347,6 +22040,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -21369,6 +22063,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -21387,6 +22082,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -21409,6 +22105,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -21427,6 +22124,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -21462,6 +22160,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -21514,6 +22213,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -21544,6 +22244,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -21575,6 +22276,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -21603,6 +22305,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -21625,6 +22328,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -21643,6 +22347,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -21665,6 +22370,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -21683,6 +22389,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -21718,6 +22425,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -21747,6 +22455,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
@@ -22342,6 +23051,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -22372,6 +23082,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -22402,6 +23113,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -22433,6 +23145,7 @@
         "name": "gl_tests_passthrough",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -22462,6 +23175,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -22493,6 +23207,7 @@
         "name": "gles2_conform_d3d9_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -22525,6 +23240,7 @@
         "name": "gles2_conform_gl_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -22551,6 +23267,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -22577,6 +23294,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -22609,6 +23327,7 @@
         "name": "video_decode_accelerator_d3d9_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -22641,6 +23360,7 @@
         "name": "video_decode_accelerator_gl_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -22671,6 +23391,7 @@
         "name": "xr_browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -22708,6 +23429,7 @@
         "name": "angle_perftests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -22748,6 +23470,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -22786,6 +23509,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -22845,6 +23569,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -22883,6 +23608,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -22921,6 +23647,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -22959,6 +23686,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -22997,6 +23725,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23035,6 +23764,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23073,6 +23803,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23111,6 +23842,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23149,6 +23881,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23187,6 +23920,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23223,6 +23957,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23244,6 +23979,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23266,6 +24002,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23287,6 +24024,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23308,6 +24046,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23330,6 +24069,7 @@
         "name": "gl_tests_passthrough",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23350,6 +24090,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23370,6 +24111,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23392,6 +24134,7 @@
         "name": "gles2_conform_d3d9_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23415,6 +24158,7 @@
         "name": "gles2_conform_gl_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23432,6 +24176,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23449,6 +24194,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23472,6 +24218,7 @@
         "name": "video_decode_accelerator_d3d11_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23495,6 +24242,7 @@
         "name": "video_decode_accelerator_d3d9_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23518,6 +24266,7 @@
         "name": "video_decode_accelerator_gl_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23539,6 +24288,7 @@
         "name": "xr_browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23569,6 +24319,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23597,6 +24348,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23625,6 +24377,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23653,6 +24406,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23685,6 +24439,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23720,6 +24475,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23771,6 +24527,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23815,6 +24572,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23844,6 +24602,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23872,6 +24631,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23900,6 +24660,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23929,6 +24690,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23958,6 +24720,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -23987,6 +24750,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24016,6 +24780,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24045,6 +24810,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24072,6 +24838,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24093,6 +24860,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24115,6 +24883,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24136,6 +24905,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24160,6 +24930,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24181,6 +24952,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24203,6 +24975,7 @@
         "name": "gl_tests_passthrough",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24223,6 +24996,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24243,6 +25017,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24265,6 +25040,7 @@
         "name": "gles2_conform_d3d9_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24288,6 +25064,7 @@
         "name": "gles2_conform_gl_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24305,6 +25082,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24322,6 +25100,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24345,6 +25124,7 @@
         "name": "video_decode_accelerator_d3d11_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24368,6 +25148,7 @@
         "name": "video_decode_accelerator_d3d9_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24391,6 +25172,7 @@
         "name": "video_decode_accelerator_gl_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24412,6 +25194,7 @@
         "name": "xr_browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24440,6 +25223,7 @@
         "name": "angle_perftests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24467,6 +25251,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24495,6 +25280,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24523,6 +25309,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24551,6 +25338,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24583,6 +25371,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24618,6 +25407,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24647,6 +25437,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24697,6 +25488,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24741,6 +25533,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24762,6 +25555,7 @@
         "name": "rendering_representative_perf_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24790,6 +25584,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24818,6 +25613,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24847,6 +25643,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24876,6 +25673,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24907,6 +25705,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24936,6 +25735,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24965,6 +25765,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -24994,6 +25795,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -25023,6 +25825,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -25052,6 +25855,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -25081,6 +25885,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -25108,6 +25913,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25130,6 +25936,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25153,6 +25960,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25175,6 +25983,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25200,6 +26009,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25222,6 +26032,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25245,6 +26056,7 @@
         "name": "gl_tests_passthrough",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25266,6 +26078,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25287,6 +26100,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25310,6 +26124,7 @@
         "name": "gles2_conform_d3d9_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25334,6 +26149,7 @@
         "name": "gles2_conform_gl_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25352,6 +26168,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25370,6 +26187,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25394,6 +26212,7 @@
         "name": "video_decode_accelerator_d3d11_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25418,6 +26237,7 @@
         "name": "video_decode_accelerator_d3d9_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25440,6 +26260,7 @@
         "name": "xr_browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25469,6 +26290,7 @@
         "name": "angle_perftests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25497,6 +26319,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25526,6 +26349,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25555,6 +26379,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25584,6 +26409,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25617,6 +26443,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25653,6 +26480,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25705,6 +26533,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25750,6 +26579,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25779,6 +26609,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25809,6 +26640,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25838,6 +26670,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25869,6 +26702,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25901,6 +26735,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25933,6 +26768,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25963,6 +26799,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -25993,6 +26830,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -26023,6 +26861,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -26053,6 +26892,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:5912-24.20.100.6286",
@@ -26087,6 +26927,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -26114,6 +26955,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26136,6 +26978,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26159,6 +27002,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26181,6 +27025,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26206,6 +27051,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26228,6 +27074,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26251,6 +27098,7 @@
         "name": "gl_tests_passthrough",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26272,6 +27120,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26293,6 +27142,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26316,6 +27166,7 @@
         "name": "gles2_conform_d3d9_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26340,6 +27191,7 @@
         "name": "gles2_conform_gl_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26358,6 +27210,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26376,6 +27229,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26400,6 +27254,7 @@
         "name": "video_decode_accelerator_d3d11_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26424,6 +27279,7 @@
         "name": "video_decode_accelerator_d3d9_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26448,6 +27304,7 @@
         "name": "video_decode_accelerator_gl_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26470,6 +27327,7 @@
         "name": "xr_browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26501,6 +27359,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26530,6 +27389,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26559,6 +27419,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26588,6 +27449,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26621,6 +27483,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26657,6 +27520,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26709,6 +27573,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26754,6 +27619,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26784,6 +27650,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26813,6 +27680,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26844,6 +27712,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26874,6 +27743,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26904,6 +27774,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26934,6 +27805,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26964,6 +27836,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -26994,6 +27867,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:699f",
@@ -27022,6 +27896,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27043,6 +27918,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27065,6 +27941,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27086,6 +27963,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27110,6 +27988,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27131,6 +28010,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27153,6 +28033,7 @@
         "name": "gl_tests_passthrough",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27173,6 +28054,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27193,6 +28075,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27215,6 +28098,7 @@
         "name": "gles2_conform_d3d9_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27238,6 +28122,7 @@
         "name": "gles2_conform_gl_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27255,6 +28140,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27272,6 +28158,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27295,6 +28182,7 @@
         "name": "video_decode_accelerator_d3d11_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27318,6 +28206,7 @@
         "name": "video_decode_accelerator_d3d9_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27339,6 +28228,7 @@
         "name": "xr_browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27367,6 +28257,7 @@
         "name": "angle_perftests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27394,6 +28285,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27422,6 +28314,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27450,6 +28343,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27478,6 +28372,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27510,6 +28405,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27545,6 +28441,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27596,6 +28493,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27640,6 +28538,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27668,6 +28567,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27689,6 +28589,7 @@
         "name": "rendering_representative_perf_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27717,6 +28618,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27745,6 +28647,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27775,6 +28678,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27806,6 +28710,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27837,6 +28742,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27866,6 +28772,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27895,6 +28802,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27924,6 +28832,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27953,6 +28862,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -27980,6 +28890,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28002,6 +28913,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28025,6 +28937,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28047,6 +28960,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28072,6 +28986,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28094,6 +29009,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28118,6 +29034,7 @@
         "name": "dawn_end2end_wire_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28140,6 +29057,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28163,6 +29081,7 @@
         "name": "gl_tests_passthrough",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28184,6 +29103,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28205,6 +29125,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28228,6 +29149,7 @@
         "name": "gles2_conform_d3d9_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28252,6 +29174,7 @@
         "name": "gles2_conform_gl_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28270,6 +29193,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28288,6 +29212,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28312,6 +29237,7 @@
         "name": "video_decode_accelerator_d3d11_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28336,6 +29262,7 @@
         "name": "video_decode_accelerator_d3d9_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28360,6 +29287,7 @@
         "name": "video_decode_accelerator_gl_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28382,6 +29310,7 @@
         "name": "xr_browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28413,6 +29342,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28442,6 +29372,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28471,6 +29402,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28500,6 +29432,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28533,6 +29466,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28569,6 +29503,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28621,6 +29556,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28666,6 +29602,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28696,6 +29633,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28725,6 +29663,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28756,6 +29695,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28788,6 +29728,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28818,6 +29759,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28848,6 +29790,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28878,6 +29821,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28908,6 +29852,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28938,6 +29883,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28968,6 +29914,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:2184",
@@ -28996,6 +29943,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29026,6 +29974,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29057,6 +30006,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29087,6 +30037,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29120,6 +30071,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29150,6 +30102,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29181,6 +30134,7 @@
         "name": "gl_tests_passthrough",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29210,6 +30164,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29239,6 +30194,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29270,6 +30226,7 @@
         "name": "gles2_conform_d3d9_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29302,6 +30259,7 @@
         "name": "gles2_conform_gl_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29328,6 +30286,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29354,6 +30313,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29386,6 +30346,7 @@
         "name": "video_decode_accelerator_d3d11_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29418,6 +30379,7 @@
         "name": "video_decode_accelerator_d3d9_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29450,6 +30412,7 @@
         "name": "video_decode_accelerator_gl_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29480,6 +30443,7 @@
         "name": "xr_browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29517,6 +30481,7 @@
         "name": "angle_perftests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29553,6 +30518,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29590,6 +30556,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29627,6 +30594,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29664,6 +30632,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29705,6 +30674,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29749,6 +30719,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29787,6 +30758,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29846,6 +30818,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29899,6 +30872,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29929,6 +30903,7 @@
         "name": "rendering_representative_perf_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -29966,6 +30941,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30003,6 +30979,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30041,6 +31018,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30079,6 +31057,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30119,6 +31098,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30157,6 +31137,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30195,6 +31176,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30233,6 +31215,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30271,6 +31254,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30309,6 +31293,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30347,6 +31332,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30387,6 +31373,7 @@
         "name": "xr.webxr.static",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30413,6 +31400,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "intel-hd-630-win10-stable",
@@ -30441,6 +31429,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30474,6 +31463,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30507,6 +31497,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30540,6 +31531,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30573,6 +31565,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30606,6 +31599,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30639,6 +31633,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30672,6 +31667,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30705,6 +31701,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30738,6 +31735,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30771,6 +31769,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30804,6 +31803,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30836,6 +31836,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -30872,6 +31873,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -30896,6 +31898,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -30918,6 +31921,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -30949,6 +31953,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -30979,6 +31984,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31009,6 +32015,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31037,6 +32044,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31059,6 +32067,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31082,6 +32091,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31104,6 +32114,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31126,6 +32137,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31149,6 +32161,7 @@
         "name": "gl_tests_passthrough",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31170,6 +32183,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31191,6 +32205,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31214,6 +32229,7 @@
         "name": "gles2_conform_d3d9_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31238,6 +32254,7 @@
         "name": "gles2_conform_gl_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31256,6 +32273,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31274,6 +32292,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31298,6 +32317,7 @@
         "name": "video_decode_accelerator_d3d11_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31322,6 +32342,7 @@
         "name": "video_decode_accelerator_d3d9_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31346,6 +32367,7 @@
         "name": "video_decode_accelerator_gl_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31377,6 +32399,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31406,6 +32429,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31435,6 +32459,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31464,6 +32489,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31497,6 +32523,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31533,6 +32560,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31585,6 +32613,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31630,6 +32659,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31660,6 +32690,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31689,6 +32720,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31718,6 +32750,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31748,6 +32781,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31778,6 +32812,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31808,6 +32843,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31836,6 +32872,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31858,6 +32895,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31881,6 +32919,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31903,6 +32942,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31928,6 +32968,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31950,6 +32991,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31973,6 +33015,7 @@
         "name": "gl_tests_passthrough",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -31994,6 +33037,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32015,6 +33059,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32038,6 +33083,7 @@
         "name": "gles2_conform_d3d9_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32062,6 +33108,7 @@
         "name": "gles2_conform_gl_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32080,6 +33127,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32098,6 +33146,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32122,6 +33171,7 @@
         "name": "video_decode_accelerator_d3d11_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32146,6 +33196,7 @@
         "name": "video_decode_accelerator_d3d9_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32170,6 +33221,7 @@
         "name": "video_decode_accelerator_gl_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32201,6 +33253,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32230,6 +33283,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32259,6 +33313,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32288,6 +33343,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32321,6 +33377,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32357,6 +33414,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32409,6 +33467,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32454,6 +33513,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32484,6 +33544,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32513,6 +33574,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32544,6 +33606,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32574,6 +33637,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32604,6 +33668,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32634,6 +33699,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32664,6 +33730,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -32692,6 +33759,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -32723,6 +33791,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -32755,6 +33824,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -32786,6 +33856,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -32820,6 +33891,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -32851,6 +33923,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -32883,6 +33956,7 @@
         "name": "gl_tests_passthrough",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -32913,6 +33987,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -32943,6 +34018,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -32975,6 +34051,7 @@
         "name": "gles2_conform_d3d9_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33008,6 +34085,7 @@
         "name": "gles2_conform_gl_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33035,6 +34113,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33062,6 +34141,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33095,6 +34175,7 @@
         "name": "video_decode_accelerator_d3d11_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33128,6 +34209,7 @@
         "name": "video_decode_accelerator_d3d9_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33161,6 +34243,7 @@
         "name": "video_decode_accelerator_gl_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33201,6 +34284,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33239,6 +34323,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33277,6 +34362,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33315,6 +34401,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33357,6 +34444,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33402,6 +34490,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33463,6 +34552,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33517,6 +34607,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33556,6 +34647,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33594,6 +34686,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33634,6 +34727,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33673,6 +34767,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33712,6 +34807,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33751,6 +34847,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33790,6 +34887,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33829,6 +34927,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33868,6 +34967,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33906,6 +35006,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -33931,6 +35032,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6613",
@@ -33959,6 +35061,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -33990,6 +35093,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34022,6 +35126,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34053,6 +35158,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34087,6 +35193,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34118,6 +35225,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34150,6 +35258,7 @@
         "name": "gl_tests_passthrough",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34180,6 +35289,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34210,6 +35320,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34242,6 +35353,7 @@
         "name": "gles2_conform_d3d9_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34275,6 +35387,7 @@
         "name": "gles2_conform_gl_test",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34302,6 +35415,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34329,6 +35443,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34362,6 +35477,7 @@
         "name": "video_decode_accelerator_d3d11_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34395,6 +35511,7 @@
         "name": "video_decode_accelerator_d3d9_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34428,6 +35545,7 @@
         "name": "video_decode_accelerator_gl_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34468,6 +35586,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34506,6 +35625,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34544,6 +35664,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34582,6 +35703,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34624,6 +35746,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34669,6 +35792,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34730,6 +35854,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34784,6 +35909,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34823,6 +35949,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34861,6 +35988,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34901,6 +36029,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34940,6 +36069,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -34979,6 +36109,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -35018,6 +36149,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -35057,6 +36189,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -35096,6 +36229,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -35135,6 +36269,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -35173,6 +36308,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -35207,6 +36343,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -35241,6 +36378,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -35275,6 +36413,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -35309,6 +36448,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -35343,6 +36483,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -35377,6 +36518,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -35411,6 +36553,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -35445,6 +36588,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -35479,6 +36623,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -35513,6 +36658,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -35547,6 +36693,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
@@ -35580,6 +36727,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "10de:1cb3-24.21.14.1195",
diff --git a/testing/buildbot/chromium.gpu.json b/testing/buildbot/chromium.gpu.json
index d12e912..e6f0c88 100644
--- a/testing/buildbot/chromium.gpu.json
+++ b/testing/buildbot/chromium.gpu.json
@@ -21,6 +21,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -50,6 +51,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -79,6 +81,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -108,6 +111,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -141,6 +145,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -177,6 +182,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -221,6 +227,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -252,6 +259,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -281,6 +289,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -311,6 +320,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "device_os": "MMB29Q",
@@ -347,6 +357,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -368,6 +379,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -389,6 +401,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -419,6 +432,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -447,6 +461,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -475,6 +490,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -503,6 +519,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -535,6 +552,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -570,6 +588,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -613,6 +632,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -642,6 +662,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -670,6 +691,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -698,6 +720,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -726,6 +749,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -751,6 +775,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -772,6 +797,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -793,6 +819,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -823,6 +850,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -851,6 +879,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -879,6 +908,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -907,6 +937,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -939,6 +970,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -974,6 +1006,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -1017,6 +1050,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -1046,6 +1080,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -1074,6 +1109,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -1102,6 +1138,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -1131,6 +1168,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -1157,6 +1195,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -1179,6 +1218,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -1201,6 +1241,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -1232,6 +1273,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -1261,6 +1303,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -1290,6 +1333,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -1319,6 +1363,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -1352,6 +1397,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -1388,6 +1434,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -1432,6 +1479,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -1462,6 +1510,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -1491,6 +1540,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -1520,6 +1570,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-ubuntu-stable",
@@ -1547,6 +1598,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -1567,6 +1619,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -1586,6 +1639,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -1615,6 +1669,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -1642,6 +1697,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -1669,6 +1725,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -1696,6 +1753,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -1727,6 +1785,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -1761,6 +1820,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -1803,6 +1863,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -1831,6 +1892,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -1858,6 +1920,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -1885,6 +1948,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -1911,6 +1975,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -1934,6 +1999,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -1954,6 +2020,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -1973,6 +2040,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -2002,6 +2070,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -2029,6 +2098,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -2056,6 +2126,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -2083,6 +2154,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -2114,6 +2186,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -2148,6 +2221,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -2190,6 +2264,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -2218,6 +2293,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -2245,6 +2321,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -2272,6 +2349,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
@@ -2298,6 +2376,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -2320,6 +2399,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -2341,6 +2421,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -2372,6 +2453,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -2401,6 +2483,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -2430,6 +2513,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -2459,6 +2543,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -2492,6 +2577,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -2528,6 +2614,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -2572,6 +2659,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -2602,6 +2690,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -2631,6 +2720,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -2660,6 +2750,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -2688,6 +2779,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -2713,6 +2805,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -2735,6 +2828,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -2756,6 +2850,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -2787,6 +2882,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -2816,6 +2912,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -2845,6 +2942,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -2874,6 +2972,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -2907,6 +3006,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -2943,6 +3043,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -2987,6 +3088,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -3017,6 +3119,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -3046,6 +3149,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -3075,6 +3179,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "1002:6821",
@@ -3103,6 +3208,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3124,6 +3230,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3146,6 +3253,7 @@
         "name": "gl_tests_passthrough",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3166,6 +3274,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3189,6 +3298,7 @@
         "name": "video_decode_accelerator_d3d11_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3210,6 +3320,7 @@
         "name": "xr_browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3240,6 +3351,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3268,6 +3380,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3296,6 +3409,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3324,6 +3438,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3356,6 +3471,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3391,6 +3507,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3434,6 +3551,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3463,6 +3581,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3491,6 +3610,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3519,6 +3639,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3546,6 +3667,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3579,6 +3701,7 @@
         "name": "tab_capture_end2end_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3609,6 +3732,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3640,6 +3764,7 @@
         "name": "gl_tests_passthrough",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3669,6 +3794,7 @@
         },
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3701,6 +3827,7 @@
         "name": "video_decode_accelerator_d3d11_unittest",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3731,6 +3858,7 @@
         "name": "xr_browser_tests",
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3770,6 +3898,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3807,6 +3936,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3844,6 +3974,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3881,6 +4012,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3922,6 +4054,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -3966,6 +4099,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -4018,6 +4152,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -4056,6 +4191,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -4093,6 +4229,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
@@ -4130,6 +4267,7 @@
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
           "dimension_sets": [
             {
               "gpu": "nvidia-quadro-p400-win10-stable",
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 18c67884..99ca4c4 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -2100,6 +2100,9 @@
   {
     'name': 'chromium.gpu',
     'forbid_script_tests': True,
+    'mixins': [
+      'swarming_containment_auto',
+    ],
     'machines': {
       'Android Release (Nexus 5X)': {
         'browser_config': 'android-chromium',
@@ -2231,6 +2234,9 @@
   {
     'name': 'chromium.gpu.fyi',
     'forbid_script_tests': True,
+    'mixins': [
+      'swarming_containment_auto',
+    ],
     'machines': {
       # BEGIN Fake builder used as mirror targets for ANGLE's GPU tryservers
       'ANGLE GPU Linux Release (Intel HD 630)': {
diff --git a/third_party/.gitignore b/third_party/.gitignore
index 08759082..98e7974 100644
--- a/third_party/.gitignore
+++ b/third_party/.gitignore
@@ -79,6 +79,7 @@
 /flatbuffers/src
 /fontconfig/src
 /freetype/src
+/fuchsia-sdk/images
 /fuchsia-sdk/sdk
 /gestures/gestures
 /gles1_conform
diff --git a/third_party/android_build_tools/bundletool/README.chromium b/third_party/android_build_tools/bundletool/README.chromium
index 2d052b007..b67f498a8 100644
--- a/third_party/android_build_tools/bundletool/README.chromium
+++ b/third_party/android_build_tools/bundletool/README.chromium
@@ -1,6 +1,6 @@
 Name: Android SDK bundletool
 Short Name:  bundletool
-Version: 0.9.0
+Version: 0.10.0
 License: Apache Version 2.0
 License File: NOT_SHIPPED
 Security Critical: No
diff --git a/third_party/android_build_tools/bundletool/cipd.yaml b/third_party/android_build_tools/bundletool/cipd.yaml
index ce339a8..9d91c8ab 100644
--- a/third_party/android_build_tools/bundletool/cipd.yaml
+++ b/third_party/android_build_tools/bundletool/cipd.yaml
@@ -2,16 +2,12 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-# Remember to increment the versions for the commands in this comment block.
-# Before creating a new CIPD package run the following to make sure the tag you
-# are adding does not already exist (otherwise you break the build):
-# cipd describe chromium/third_party/android_tools_bundletool -version "version:0.9.0-cr0"
 # To create CIPD package run the following command.
-# cipd create --pkg-def cipd.yaml -tag version:0.9.0-cr0
+# cipd create --pkg-def cipd.yaml
 package: chromium/third_party/android_tools_bundletool
 description: Android SDK tool to manage App Bundles
 # TODO(https://crbug.com/950727): Remove this and go back to symlinks once
 # swarming isolation works properly with symlinks.
 install_mode: copy
 data:
-  - file: bundletool-all-0.9.0.jar
+  - file: bundletool-all-0.10.0.jar
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom
index bdc6eec0..b4c58258 100644
--- a/third_party/blink/public/mojom/web_feature/web_feature.mojom
+++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -2314,6 +2314,8 @@
   kV8CallSiteAPIGetThisSloppyCall = 2925,
   kBuiltInModuleToast = 2926,
   kLargestContentfulPaintExplicitlyRequested = 2927,
+  kPageLifecycleTransitionsOptIn = 2928,
+  kPageLifecycleTransitionsOptOut = 2929,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/renderer/bindings/core/v8/script_controller.cc b/third_party/blink/renderer/bindings/core/v8/script_controller.cc
index c4f700f..ad6fca3 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_controller.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_controller.cc
@@ -319,20 +319,18 @@
       !GetFrame()->GetDocument()->CanExecuteScripts(kAboutToExecuteScript))
     return v8::Local<v8::Value>();
 
-  // TODO(dcheng): Clean this up to not use ScriptState, to match
-  // executeScriptInIsolatedWorld.
-  ScriptState* script_state = ToScriptStateForMainWorld(GetFrame());
-  if (!script_state)
-    return v8::Local<v8::Value>();
+  // |context| should be initialized already due to the MainWorldProxy() call.
+  v8::Local<v8::Context> context =
+      window_proxy_manager_->MainWorldProxy()->ContextIfInitialized();
+
+  v8::Context::Scope scope(context);
   v8::EscapableHandleScope handle_scope(GetIsolate());
-  ScriptState::Scope scope(script_state);
 
   if (GetFrame()->Loader().StateMachine()->IsDisplayingInitialEmptyDocument())
     GetFrame()->Loader().DidAccessInitialDocument();
 
   v8::Local<v8::Value> object = ExecuteScriptAndReturnValue(
-      script_state->GetContext(), source_code, base_url, sanitize_script_errors,
-      fetch_options);
+      context, source_code, base_url, sanitize_script_errors, fetch_options);
 
   if (object.IsEmpty())
     return v8::Local<v8::Value>();
diff --git a/third_party/blink/renderer/build/scripts/core/css/css_properties.py b/third_party/blink/renderer/build/scripts/core/css/css_properties.py
index b59c228b..6d6fed286 100755
--- a/third_party/blink/renderer/build/scripts/core/css/css_properties.py
+++ b/third_party/blink/renderer/build/scripts/core/css/css_properties.py
@@ -50,6 +50,9 @@
     if property_to_check['mutable']:
         assert property_to_check['field_template'] == 'monotonic_flag', \
             'mutable keyword only implemented for monotonic_flag'
+    if property_to_check['alias_for']:
+        assert not property_to_check['is_internal'], \
+            'Internal aliases is not supported'
 
 
 class CSSProperties(object):
diff --git a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_properties.h.tmpl b/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_properties.h.tmpl
index 3ed5c5f..8ded050 100644
--- a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_properties.h.tmpl
+++ b/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_properties.h.tmpl
@@ -38,6 +38,7 @@
   (property.is_property and 'kProperty' or ''),
   (property.inherited and 'kInherited' or ''),
   (property.visited and 'kVisited' or ''),
+  (property.is_internal and 'kInternal' or ''),
 ] | reject('==', '') | join(' | ') %}
 {% set ctor_args = (not is_alias and [property_id, flags, separator] or []) %}
 // {{property.name}}
diff --git a/third_party/blink/renderer/core/accessibility/apply_dark_mode.cc b/third_party/blink/renderer/core/accessibility/apply_dark_mode.cc
index e51695c..60fa9980 100644
--- a/third_party/blink/renderer/core/accessibility/apply_dark_mode.cc
+++ b/third_party/blink/renderer/core/accessibility/apply_dark_mode.cc
@@ -53,7 +53,8 @@
   dark_mode_settings.grayscale = frame_settings.GetDarkModeGrayscale();
   dark_mode_settings.contrast = frame_settings.GetDarkModeContrast();
   dark_mode_settings.image_policy = frame_settings.GetDarkModeImagePolicy();
-  dark_mode_settings.text_policy = frame_settings.GetDarkModeTextPolicy();
+  dark_mode_settings.text_brightness_threshold =
+      frame_settings.GetDarkModeTextBrightnessThreshold();
   dark_mode_settings.image_grayscale_percent =
       frame_settings.GetDarkModeImageGrayscale();
   return dark_mode_settings;
diff --git a/third_party/blink/renderer/core/animation/interpolation_effect_test.cc b/third_party/blink/renderer/core/animation/interpolation_effect_test.cc
index ea6fb6f..4c238c6 100644
--- a/third_party/blink/renderer/core/animation/interpolation_effect_test.cc
+++ b/third_party/blink/renderer/core/animation/interpolation_effect_test.cc
@@ -86,6 +86,9 @@
           CubicBezierTimingFunction::EaseType::EASE),
       0.5, 1.5, 0.5, 1.5);
 
+  // ease = cubicBezier(0.25, 0.1, 0.25, 1)
+  // ease(0.5) = 0.8024033877399112
+
   HeapVector<Member<Interpolation>> active_interpolations;
   interpolation_effect->GetActiveInterpolations(
       -0.5, kInterpolationTestDuration, active_interpolations);
@@ -106,14 +109,14 @@
                                                 active_interpolations);
   EXPECT_EQ(2ul, active_interpolations.size());
   EXPECT_FLOAT_EQ(10, GetInterpolableNumber(active_interpolations.at(0)));
-  EXPECT_FLOAT_EQ(5.0282884f,
+  EXPECT_FLOAT_EQ(5.0120169f,
                   GetInterpolableNumber(active_interpolations.at(1)));
 
   interpolation_effect->GetActiveInterpolations(
       1, kInterpolationTestDuration * 1000, active_interpolations);
   EXPECT_EQ(2ul, active_interpolations.size());
   EXPECT_FLOAT_EQ(10, GetInterpolableNumber(active_interpolations.at(0)));
-  EXPECT_FLOAT_EQ(5.0120168f,
+  EXPECT_FLOAT_EQ(5.0120169f,
                   GetInterpolableNumber(active_interpolations.at(1)));
 
   interpolation_effect->GetActiveInterpolations(1.5, kInterpolationTestDuration,
diff --git a/third_party/blink/renderer/core/animation/keyframe_effect_model_test.cc b/third_party/blink/renderer/core/animation/keyframe_effect_model_test.cc
index 832f4f3..65014abc 100644
--- a/third_party/blink/renderer/core/animation/keyframe_effect_model_test.cc
+++ b/third_party/blink/renderer/core/animation/keyframe_effect_model_test.cc
@@ -68,8 +68,10 @@
     EXPECT_TRUE(typed_value->GetInterpolableValue().IsList());
     const InterpolableList* list =
         ToInterpolableList(&typed_value->GetInterpolableValue());
-    EXPECT_FLOAT_EQ(expected_value,
-                    ToInterpolableNumber(list->Get(0))->Value());
+    // Lengths are computed in logical units, which are quantized to 64ths of
+    // a pixel.
+    EXPECT_NEAR(expected_value, ToInterpolableNumber(list->Get(0))->Value(),
+                /*abs_error=*/0.02);
   }
 
   void ExpectNonInterpolableValue(const String& expected_value,
@@ -204,10 +206,11 @@
   keyframes[1]->SetComposite(EffectModel::kCompositeReplace);
   auto* effect = MakeGarbageCollected<StringKeyframeEffectModel>(keyframes);
   HeapVector<Member<Interpolation>> values;
+  // CubicBezier(0.42, 0, 1, 1)(0.6) = 0.4291197695757142.
   effect->Sample(0, 0.6, kDuration, values);
-  ExpectLengthValue(3.8579516, values.at(0));
+  ExpectLengthValue(3.85824, values.at(0));
   effect->Sample(0, 0.6, kDuration * 100, values);
-  ExpectLengthValue(3.8582394, values.at(0));
+  ExpectLengthValue(3.85824, values.at(0));
 }
 
 TEST_F(AnimationKeyframeEffectModel, CompositeCubicBezier) {
@@ -216,12 +219,13 @@
   keyframes[0]->SetComposite(EffectModel::kCompositeReplace);
   keyframes[0]->SetEasing(CubicBezierTimingFunction::Create(0.42, 0, 0.58, 1));
   keyframes[1]->SetComposite(EffectModel::kCompositeReplace);
+  // CubicBezier(0.42, 0, 0.58, 1)(0.6) = 0.6681161300485039.
   auto* effect = MakeGarbageCollected<StringKeyframeEffectModel>(keyframes);
   HeapVector<Member<Interpolation>> values;
   effect->Sample(0, 0.6, kDuration, values);
-  ExpectLengthValue(4.3363357, values.at(0));
+  ExpectLengthValue(4.336232, values.at(0));
   effect->Sample(0, 0.6, kDuration * 1000, values);
-  ExpectLengthValue(4.3362322, values.at(0));
+  ExpectLengthValue(4.336232, values.at(0));
 }
 
 TEST_F(AnimationKeyframeEffectModel, ExtrapolateReplaceNonInterpolable) {
diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5
index d4f8003..69cafcd 100644
--- a/third_party/blink/renderer/core/css/css_properties.json5
+++ b/third_party/blink/renderer/core/css/css_properties.json5
@@ -5363,6 +5363,7 @@
     },
     {
       name: "-internal-effective-zoom",
+      property_methods: ["ParseSingleValue"],
       inherited: true,
       field_template: "primitive",
       type_name: "float",
diff --git a/third_party/blink/renderer/core/css/css_test_helpers.cc b/third_party/blink/renderer/core/css/css_test_helpers.cc
index ccc601ba..e4fd4c73 100644
--- a/third_party/blink/renderer/core/css/css_test_helpers.cc
+++ b/third_party/blink/renderer/core/css/css_test_helpers.cc
@@ -9,7 +9,12 @@
 #include "third_party/blink/renderer/core/css/css_rule_list.h"
 #include "third_party/blink/renderer/core/css/css_style_sheet.h"
 #include "third_party/blink/renderer/core/css/css_variable_data.h"
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_parser_local_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_property_parser.h"
 #include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
+#include "third_party/blink/renderer/core/css/properties/css_property_ref.h"
+#include "third_party/blink/renderer/core/css/properties/longhand.h"
 #include "third_party/blink/renderer/core/css/property_descriptor.h"
 #include "third_party/blink/renderer/core/css/property_registration.h"
 #include "third_party/blink/renderer/core/css/property_registry.h"
@@ -87,5 +92,20 @@
   return MakeGarbageCollected<CSSCustomIdentValue>(s);
 }
 
+const CSSValue* ParseLonghand(Document& document,
+                              const CSSProperty& property,
+                              const String& value) {
+  const auto* longhand = DynamicTo<Longhand>(property);
+  if (!longhand)
+    return nullptr;
+
+  const auto* context = MakeGarbageCollected<CSSParserContext>(document);
+  CSSParserLocalContext local_context;
+  auto tokens = CSSTokenizer(value).TokenizeToEOF();
+  CSSParserTokenRange range(tokens);
+
+  return longhand->ParseSingleValue(range, *context, local_context);
+}
+
 }  // namespace css_test_helpers
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_test_helpers.h b/third_party/blink/renderer/core/css/css_test_helpers.h
index 7897fdf6..3a9c1ef 100644
--- a/third_party/blink/renderer/core/css/css_test_helpers.h
+++ b/third_party/blink/renderer/core/css/css_test_helpers.h
@@ -15,6 +15,7 @@
 class CSSStyleSheet;
 class CSSVariableData;
 class CSSValue;
+class CSSProperty;
 
 namespace css_test_helpers {
 
@@ -50,6 +51,9 @@
 
 scoped_refptr<CSSVariableData> CreateVariableData(String);
 const CSSValue* CreateCustomIdent(AtomicString);
+const CSSValue* ParseLonghand(Document& document,
+                              const CSSProperty&,
+                              const String& value);
 
 }  // namespace css_test_helpers
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/properties/css_property.h b/third_party/blink/renderer/core/css/properties/css_property.h
index 4d8c48ed..a0e823e 100644
--- a/third_party/blink/renderer/core/css/properties/css_property.h
+++ b/third_party/blink/renderer/core/css/properties/css_property.h
@@ -45,6 +45,7 @@
   bool IsLonghand() const { return flags_ & kLonghand; }
   bool IsInherited() const { return flags_ & kInherited; }
   bool IsVisited() const { return flags_ & kVisited; }
+  bool IsInternal() const { return flags_ & kInternal; }
 
   bool IsRepeated() const { return repetition_separator_ != '\0'; }
   char RepetitionSeparator() const { return repetition_separator_; }
@@ -101,7 +102,8 @@
     // are permitted in :visited styles. They are used to handle and store the
     // computed value as seen by painting (as opposed to the computed value
     // seen by CSSOM, which is represented by the unvisited property).
-    kVisited = 1 << 7
+    kVisited = 1 << 7,
+    kInternal = 1 << 8
   };
 
   constexpr CSSProperty(CSSPropertyID property_id,
diff --git a/third_party/blink/renderer/core/css/properties/css_property_test.cc b/third_party/blink/renderer/core/css/properties/css_property_test.cc
index b4da9b2..80cbc05c 100644
--- a/third_party/blink/renderer/core/css/properties/css_property_test.cc
+++ b/third_party/blink/renderer/core/css/properties/css_property_test.cc
@@ -5,11 +5,8 @@
 #include "third_party/blink/renderer/core/css/properties/css_property.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/core/css/css_property_names.h"
-#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
-#include "third_party/blink/renderer/core/css/parser/css_parser_local_context.h"
-#include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
+#include "third_party/blink/renderer/core/css/css_test_helpers.h"
 #include "third_party/blink/renderer/core/css/properties/css_property_instances.h"
-#include "third_party/blink/renderer/core/css/properties/longhand.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
 #include "third_party/blink/renderer/core/style/data_equivalency.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
@@ -46,10 +43,15 @@
   EXPECT_FALSE(property.IsWebExposed());
 }
 
+TEST_F(CSSPropertyTest, InternalEffectiveZoomCanBeParsed) {
+  const CSSValue* value = css_test_helpers::ParseLonghand(
+      GetDocument(), GetCSSPropertyInternalEffectiveZoom(), "1.2");
+  ASSERT_TRUE(value);
+  EXPECT_EQ("1.2", value->CssText());
+}
+
 TEST_F(CSSPropertyTest, VisitedPropertiesCanParseValues) {
   scoped_refptr<ComputedStyle> initial_style = ComputedStyle::Create();
-  const auto* context = MakeGarbageCollected<CSSParserContext>(GetDocument());
-  CSSParserLocalContext local_context;
 
   // Count the number of 'visited' properties seen.
   size_t num_visited = 0;
@@ -65,20 +67,14 @@
         *initial_style, nullptr /* layout_object */, nullptr /* node */,
         false /* allow_visited_style */);
     ASSERT_TRUE(initial_value);
-
-    // Tokenize that value, and parse it using both the regular property, and
-    // the accompanying 'visited' property.
     String css_text = initial_value->CssText();
-    auto tokens = CSSTokenizer(css_text).TokenizeToEOF();
 
-    CSSParserTokenRange regular_range(tokens);
-    const CSSValue* parsed_regular_value =
-        To<Longhand>(property).ParseSingleValue(regular_range, *context,
-                                                local_context);
-    CSSParserTokenRange visited_range(tokens);
-    const CSSValue* parsed_visited_value =
-        To<Longhand>(*visited).ParseSingleValue(visited_range, *context,
-                                                local_context);
+    // Parse the initial value using both the regular property, and the
+    // accompanying 'visited' property.
+    const CSSValue* parsed_regular_value = css_test_helpers::ParseLonghand(
+        GetDocument(), property, initial_value->CssText());
+    const CSSValue* parsed_visited_value = css_test_helpers::ParseLonghand(
+        GetDocument(), *visited, initial_value->CssText());
 
     // The properties should have identical parsing behavior.
     EXPECT_TRUE(DataEquivalent(parsed_regular_value, parsed_visited_value));
diff --git a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
index 59b2657..47e99b6 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
@@ -2882,6 +2882,14 @@
   state.SetEffectiveZoom(StyleBuilderConverter::ConvertZoom(state, value));
 }
 
+const CSSValue* InternalEffectiveZoom::ParseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext& context,
+    const CSSParserLocalContext& local_context) const {
+  ValueRange value_range = kValueRangeNonNegative;
+  return css_property_parser_helpers::ConsumeNumber(range, value_range);
+}
+
 void InternalVisitedColor::ApplyValue(StyleResolverState& state,
                                       const CSSValue& value) const {
   auto* identifier_value = DynamicTo<CSSIdentifierValue>(value);
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index 7fc20caf..fa6a279 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -6050,48 +6050,23 @@
 using resource_coordinator::mojom::InterventionPolicy;
 using resource_coordinator::mojom::PolicyControlledIntervention;
 
-typedef bool (*InterventionPolicyGetter)(const FeatureContext*);
-struct InterventionPolicyGetters {
-  InterventionPolicyGetter opt_in_getter;
-  InterventionPolicyGetter opt_out_getter;
-};
-
-// A helper function for setting intervention policy values on a frame en masse.
+// A helper function for setting intervention policy values on a frame.
 void SetInitialInterventionPolicies(
     DocumentResourceCoordinator* document_resource_coordinator,
-    const ExecutionContext* context) {
-  DEFINE_STATIC_LOCAL(Vector<InterventionPolicyGetters>,
-                      kInterventionPolicyGetters, ());
-  if (kInterventionPolicyGetters.IsEmpty()) {
-    InterventionPolicyGetters getters = {
-        &RuntimeEnabledFeatures::PageLifecycleTransitionsOptInEnabled,
-        &RuntimeEnabledFeatures::PageLifecycleTransitionsOptOutEnabled};
-    kInterventionPolicyGetters.push_back(getters);
-    const wtf_size_t kInterventionPolicyGettersSize = 1;
-    static_assert(
-        kInterventionPolicyGettersSize ==
-            static_cast<wtf_size_t>(PolicyControlledIntervention::kMaxValue) +
-                1,
-        "kInterventionPolicyGetters array must be kept in sync with "
-        "mojom::PolicyControlledIntervention enum.");
+    ExecutionContext* context) {
+  // An explicit opt-out overrides an explicit opt-in if both are present.
+  InterventionPolicy policy = InterventionPolicy::kDefault;
+  if (RuntimeEnabledFeatures::PageLifecycleTransitionsOptOutEnabled(context)) {
+    policy = InterventionPolicy::kOptOut;
+    UseCounter::Count(context, WebFeature::kPageLifecycleTransitionsOptOut);
+  } else if (RuntimeEnabledFeatures::PageLifecycleTransitionsOptInEnabled(
+                 context)) {
+    policy = InterventionPolicy::kOptIn;
+    UseCounter::Count(context, WebFeature::kPageLifecycleTransitionsOptIn);
   }
-  // Note that these must be emitted in order, as the *last* policy being set
-  // is used as a sentinel in the browser-side logic to infer that the frame has
-  // transmitted all of its policy data.
-  for (wtf_size_t i = 0; i < kInterventionPolicyGetters.size(); ++i) {
-    bool opt_in = (*kInterventionPolicyGetters[i].opt_in_getter)(context);
-    bool opt_out = (*kInterventionPolicyGetters[i].opt_out_getter)(context);
 
-    // An explicit opt-out overrides an explicit opt-in if both are present.
-    InterventionPolicy policy = InterventionPolicy::kDefault;
-    if (opt_out)
-      policy = InterventionPolicy::kOptOut;
-    else if (opt_in)
-      policy = InterventionPolicy::kOptIn;
-
-    document_resource_coordinator->SetInterventionPolicy(
-        static_cast<PolicyControlledIntervention>(i), policy);
-  }
+  document_resource_coordinator->SetInterventionPolicy(
+      PolicyControlledIntervention::kPageLifecycleTransitions, policy);
 }
 
 }  // namespace
diff --git a/third_party/blink/renderer/core/frame/settings.json5 b/third_party/blink/renderer/core/frame/settings.json5
index b467de7..e80e5f8 100644
--- a/third_party/blink/renderer/core/frame/settings.json5
+++ b/third_party/blink/renderer/core/frame/settings.json5
@@ -913,9 +913,9 @@
       invalidate: "Paint",
     },
     {
-      name: "darkModeTextPolicy",
-      initial: "DarkModeTextPolicy::kInvertAll",
-      type: "DarkModeTextPolicy",
+      name: "darkModeTextBrightnessThreshold",
+      initial: "256",
+      type: "int",
       invalidate: "Paint",
     },
     {
diff --git a/third_party/blink/renderer/core/frame/use_counter_helper.h b/third_party/blink/renderer/core/frame/use_counter_helper.h
index 8b0145a..12c769b 100644
--- a/third_party/blink/renderer/core/frame/use_counter_helper.h
+++ b/third_party/blink/renderer/core/frame/use_counter_helper.h
@@ -136,6 +136,8 @@
   void Trace(blink::Visitor*);
 
  private:
+  friend class UseCounterHelperTest;
+
   // Notifies that a feature is newly counted to |m_observers|. This shouldn't
   // be called when the counter is disabled by |m_muteCount| or when |m_context|
   // if kDisabledContext.
diff --git a/third_party/blink/renderer/core/frame/use_counter_helper_test.cc b/third_party/blink/renderer/core/frame/use_counter_helper_test.cc
index b474fc4..dac11709 100644
--- a/third_party/blink/renderer/core/frame/use_counter_helper_test.cc
+++ b/third_party/blink/renderer/core/frame/use_counter_helper_test.cc
@@ -4,6 +4,8 @@
 
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/mojom/use_counter/css_property_id.mojom-blink.h"
+#include "third_party/blink/renderer/core/css/css_property_names.h"
+#include "third_party/blink/renderer/core/css/properties/css_property.h"
 #include "third_party/blink/renderer/core/dom/shadow_root.h"
 #include "third_party/blink/renderer/core/frame/deprecation.h"
 #include "third_party/blink/renderer/core/html/html_html_element.h"
@@ -40,6 +42,15 @@
     Page::InsertOrdinaryPageForTesting(&dummy_->GetPage());
   }
 
+  int ToSampleId(CSSPropertyID property) const {
+    return UseCounterHelper::MapCSSPropertyIdToCSSSampleIdForHistogram(
+        property);
+  }
+
+  bool IsInternal(CSSPropertyID property) const {
+    return CSSProperty::Get(property).IsInternal();
+  }
+
  protected:
   LocalFrame* GetFrame() { return &dummy_->GetFrame(); }
   void SetIsViewSource() { dummy_->GetDocument().SetIsViewSource(true); }
@@ -434,4 +445,35 @@
   EXPECT_TRUE(document.IsUseCounted(feature));
 }
 
+TEST_F(UseCounterHelperTest, UniqueCSSSampleIds) {
+  HashSet<int> ids;
+
+  for (CSSPropertyID property : CSSPropertyIDList()) {
+    if (IsInternal(property))
+      continue;
+    EXPECT_FALSE(ids.Contains(ToSampleId(property)));
+    ids.insert(ToSampleId(property));
+  }
+
+  for (CSSPropertyID property : kCSSPropertyAliasList) {
+    EXPECT_FALSE(ids.Contains(ToSampleId(property)));
+    ids.insert(ToSampleId(property));
+  }
+}
+
+TEST_F(UseCounterHelperTest, MaximumCSSSampleId) {
+  int max_sample_id = 0;
+
+  for (CSSPropertyID property : CSSPropertyIDList()) {
+    if (IsInternal(property))
+      continue;
+    max_sample_id = std::max(max_sample_id, ToSampleId(property));
+  }
+
+  for (CSSPropertyID property : kCSSPropertyAliasList)
+    max_sample_id = std::max(max_sample_id, ToSampleId(property));
+
+  EXPECT_EQ(mojom::blink::kMaximumCSSSampleId, max_sample_id);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
index 30bbf9efa..cc47277 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -318,6 +318,12 @@
   if (!context_)
     return nullptr;
 
+  // Since the |context_| is created, free the transparent image,
+  // |transparent_image_| created for this canvas if it exists.
+  if (transparent_image_.get()) {
+    transparent_image_.reset();
+  }
+
   context_creation_was_blocked_ = false;
 
   probe::DidCreateCanvasContext(&GetDocument());
@@ -1252,7 +1258,7 @@
   }
 
   if (!context_) {
-    scoped_refptr<Image> result = CreateTransparentImage(Size());
+    scoped_refptr<Image> result = GetTransparentImage();
     *status = result ? kNormalSourceImageStatus : kInvalidSourceImageStatus;
     return result;
   }
@@ -1261,7 +1267,7 @@
     *status = kNormalSourceImageStatus;
     scoped_refptr<Image> result = context_->GetImage(hint);
     if (!result)
-      result = CreateTransparentImage(Size());
+      result = GetTransparentImage();
     *status = result ? kNormalSourceImageStatus : kInvalidSourceImageStatus;
     return result;
   }
@@ -1277,7 +1283,7 @@
     if (ResourceProvider())
       image = ResourceProvider()->Snapshot();
     else
-      image = CreateTransparentImage(Size());
+      image = GetTransparentImage();
   } else {
     if (canvas_heuristic_parameters::kDisableAccelerationToAvoidReadbacks &&
         !RuntimeEnabledFeatures::Canvas2dFixedRenderingModeEnabled() &&
@@ -1288,7 +1294,7 @@
     }
     image = RenderingContext()->GetImage(hint);
     if (!image)
-      image = CreateTransparentImage(Size());
+      image = GetTransparentImage();
   }
 
   if (image)
@@ -1554,6 +1560,12 @@
   return (type == CanvasRenderingContext::kContextImageBitmap);
 }
 
+scoped_refptr<Image> HTMLCanvasElement::GetTransparentImage() {
+  if (!transparent_image_ || transparent_image_.get()->Size() != Size())
+    transparent_image_ = CreateTransparentImage(Size());
+  return transparent_image_;
+}
+
 cc::Layer* HTMLCanvasElement::ContentsCcLayer() const {
   if (surface_layer_bridge_)
     return surface_layer_bridge_->GetCcLayer();
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.h b/third_party/blink/renderer/core/html/canvas/html_canvas_element.h
index 90131dd..0eff66e 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.h
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.h
@@ -49,6 +49,7 @@
 #include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_types.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_types_3d.h"
+#include "third_party/blink/renderer/platform/graphics/image.h"
 #include "third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.h"
 #include "third_party/blink/renderer/platform/graphics/surface_layer_bridge.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
@@ -69,7 +70,6 @@
 class GraphicsContext;
 class HitTestCanvasResult;
 class HTMLCanvasElement;
-class Image;
 class ImageBitmapOptions;
 class IntSize;
 
@@ -354,6 +354,9 @@
   // ImageBitmapRenderingContextBase.
   bool HasImageBitmapContext() const;
 
+  // Returns the transparent image resource for this canvas.
+  scoped_refptr<Image> GetTransparentImage();
+
   CanvasRenderingContext* GetCanvasRenderingContextInternal(
       const String&,
       const CanvasContextCreationAttributesCore&);
@@ -404,6 +407,7 @@
 
   mutable bool gpu_readback_invoked_in_current_frame_;
   int gpu_readback_successive_frames_;
+  scoped_refptr<Image> transparent_image_ = nullptr;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/media/html_video_element.cc b/third_party/blink/renderer/core/html/media/html_video_element.cc
index 03f91e77..dbb186e 100644
--- a/third_party/blink/renderer/core/html/media/html_video_element.cc
+++ b/third_party/blink/renderer/core/html/media/html_video_element.cc
@@ -399,6 +399,8 @@
     return;
   }
 
+  std::unique_ptr<UserGestureIndicator> gesture =
+      LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
   webkitEnterFullscreen();
 }
 
diff --git a/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc b/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc
index b6ea07b9..c8505727 100644
--- a/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc
+++ b/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc
@@ -158,4 +158,30 @@
   EXPECT_FALSE(Video()->paused());
 }
 
+TEST_F(VideoAutoFullscreen, OnPlayTriggersFullscreenWithoutGesture) {
+  Video()->SetSrc("http://example.com/foo.mp4");
+  {
+    std::unique_ptr<UserGestureIndicator> user_gesture_scope =
+        LocalFrame::NotifyUserActivation(GetFrame(),
+                                         UserGestureToken::kNewGesture);
+    Video()->Play();
+  }
+  MakeGarbageCollected<WaitForEvent>(Video(), event_type_names::kPlay);
+  test::RunPendingTasks();
+
+  EXPECT_TRUE(Video()->IsFullscreen());
+
+  GetWebView()->ExitFullscreen(*GetFrame());
+  test::RunPendingTasks();
+
+  EXPECT_TRUE(Video()->paused());
+  EXPECT_FALSE(Video()->IsFullscreen());
+
+  Video()->Play();
+  test::RunPendingTasks();
+
+  EXPECT_FALSE(Video()->paused());
+  EXPECT_TRUE(Video()->IsFullscreen());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc
index 3459d43..b735a108 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc
@@ -554,7 +554,12 @@
           // removed entirely. However, when the first collapsible space is
           // 'nowrap', and the following collapsed space is 'wrap', the
           // collapsed space needs to create a break opportunity.
-          AppendGeneratedBreakOpportunity(layout_object);
+          // Note that we don't need to generate a break opportunity right
+          // after a forced break.
+          if (item->Type() != NGInlineItem::kControl ||
+              text_[item->StartOffset()] != kNewlineCharacter) {
+            AppendGeneratedBreakOpportunity(layout_object);
+          }
         }
       }
     } else {
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc
index a7bb0ee..a7a5e66a 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/core/dom/dom_token_list.h"
 #include "third_party/blink/renderer/core/dom/element_traversal.h"
 #include "third_party/blink/renderer/core/dom/text.h"
+#include "third_party/blink/renderer/core/html_names.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_child_layout_context.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
@@ -1520,6 +1521,24 @@
   EXPECT_EQ(String(u"foo\u200Bbar"), GetText());
 }
 
+TEST_F(NGInlineNodeTest, CollapsibleSpaceFollowingBRWithNoWrapStyle) {
+  SetupHtml("t", "<div id=t><span style=white-space:pre><br></span> </div>");
+  EXPECT_EQ("\n", GetText());
+
+  GetDocument().QuerySelector("span")->removeAttribute(html_names::kStyleAttr);
+  UpdateAllLifecyclePhasesForTest();
+  EXPECT_EQ("\n", GetText());
+}
+
+TEST_F(NGInlineNodeTest, CollapsibleSpaceFollowingNewlineWithPreStyle) {
+  SetupHtml("t", "<div id=t><span style=white-space:pre>\n</span> </div>");
+  EXPECT_EQ("\n", GetText());
+
+  GetDocument().QuerySelector("span")->removeAttribute(html_names::kStyleAttr);
+  UpdateAllLifecyclePhasesForTest();
+  EXPECT_EQ("", GetText());
+}
+
 #if SEGMENT_BREAK_TRANSFORMATION_FOR_EAST_ASIAN_WIDTH
 // https://crbug.com/879088
 TEST_F(NGInlineNodeTest, RemoveSegmentBreakFromJapaneseInRelayout) {
diff --git a/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.cc b/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.cc
index 09c595a..0e86521 100644
--- a/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.cc
+++ b/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.cc
@@ -133,6 +133,9 @@
 void TextFragmentAnchor::PerformPreRafActions() {}
 
 void TextFragmentAnchor::DidCompleteLoad() {
+  if (search_finished_)
+    return;
+
   // If there is a pending layout we'll finish the search from Invoke.
   if (!frame_->View()->NeedsLayout()) {
     metrics_->ReportMetrics();
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
index 9123ffd..7a27b344 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -1240,8 +1240,8 @@
   }
 }
 
-static FloatRoundedRect ToClipRect(const PhysicalRect& rect) {
-  return FloatRoundedRect(FloatRect(PixelSnappedIntRect(rect)));
+static FloatRoundedRect ToSnappedClipRect(const PhysicalRect& rect) {
+  return FloatRoundedRect(PixelSnappedIntRect(rect));
 }
 
 void FragmentPaintPropertyTreeBuilder::UpdateFragmentClip() {
@@ -1249,10 +1249,10 @@
 
   if (NeedsPaintPropertyUpdate()) {
     if (context_.fragment_clip) {
+      const auto& clip_rect = ToSnappedClipRect(*context_.fragment_clip);
       OnUpdateClip(properties_->UpdateFragmentClip(
           *context_.current.clip,
-          ClipPaintPropertyNode::State{context_.current.transform,
-                                       ToClipRect(*context_.fragment_clip)}));
+          ClipPaintPropertyNode::State{context_.current.transform, clip_rect}));
     } else {
       OnClearClip(properties_->ClearFragmentClip());
     }
@@ -1280,11 +1280,11 @@
       // object must be a container for absolute position descendants, and will
       // copy from in-flow context later at updateOutOfFlowContext() step.
       DCHECK(object_.CanContainAbsolutePositionObjects());
+      const auto& clip_rect = ToSnappedClipRect(
+          ToLayoutBox(object_).ClipRect(context_.current.paint_offset));
       OnUpdateClip(properties_->UpdateCssClip(
           *context_.current.clip,
-          ClipPaintPropertyNode::State{context_.current.transform,
-                                       ToClipRect(ToLayoutBox(object_).ClipRect(
-                                           context_.current.paint_offset))}));
+          ClipPaintPropertyNode::State{context_.current.transform, clip_rect}));
     } else {
       OnClearClip(properties_->ClearCssClip());
     }
@@ -1311,8 +1311,7 @@
     } else {
       ClipPaintPropertyNode::State state;
       state.local_transform_space = context_.current.transform;
-      state.clip_rect =
-          FloatRoundedRect(FloatRect(*fragment_data_.ClipPathBoundingBox()));
+      state.clip_rect = FloatRoundedRect(*fragment_data_.ClipPathBoundingBox());
       state.clip_path = fragment_data_.ClipPathPath();
       OnUpdateClip(properties_->UpdateClipPathClip(*context_.current.clip,
                                                    std::move(state)));
@@ -1470,12 +1469,11 @@
   if (NeedsOverflowControlsClip()) {
     // Clip overflow controls to the border box rect. Not wrapped with
     // OnUpdateClip() because this clip doesn't affect descendants.
+    const auto& clip_rect = ToSnappedClipRect(PhysicalRect(
+        context_.current.paint_offset, ToLayoutBox(object_).Size()));
     properties_->UpdateOverflowControlsClip(
         *context_.current.clip,
-        ClipPaintPropertyNode::State{
-            context_.current.transform,
-            ToClipRect(PhysicalRect(context_.current.paint_offset,
-                                    ToLayoutBox(object_).Size()))});
+        ClipPaintPropertyNode::State{context_.current.transform, clip_rect});
   } else {
     properties_->ClearOverflowControlsClip();
   }
@@ -1590,12 +1588,13 @@
           state.clip_rect.SetRect(adjusted_rect);
         }
       } else if (object_.IsBox()) {
-        state.clip_rect = ToClipRect(ToLayoutBox(object_).OverflowClipRect(
-            context_.current.paint_offset));
-        state.clip_rect_excluding_overlay_scrollbars =
-            ToClipRect(ToLayoutBox(object_).OverflowClipRect(
+        state.clip_rect =
+            ToSnappedClipRect(ToLayoutBox(object_).OverflowClipRect(
+                context_.current.paint_offset));
+        state.clip_rect_excluding_overlay_scrollbars = FloatClipRect(
+            FloatRect(PixelSnappedIntRect(ToLayoutBox(object_).OverflowClipRect(
                 context_.current.paint_offset,
-                kExcludeOverlayScrollbarSizeForHitTesting));
+                kExcludeOverlayScrollbarSizeForHitTesting))));
       } else {
         DCHECK(object_.IsSVGViewportContainer());
         const auto& viewport_container = ToLayoutSVGViewportContainer(object_);
@@ -2994,10 +2993,10 @@
         old_fragment_clip = properties->FragmentClip();
       const base::Optional<PhysicalRect>& new_fragment_clip =
           new_fragment_contexts.back().fragment_clip;
-      fragments_changed =
-          !!old_fragment_clip != !!new_fragment_clip ||
-          (old_fragment_clip && new_fragment_clip &&
-           old_fragment_clip->ClipRect() != ToClipRect(*new_fragment_clip));
+      fragments_changed = !!old_fragment_clip != !!new_fragment_clip ||
+                          (old_fragment_clip && new_fragment_clip &&
+                           old_fragment_clip->ClipRect() !=
+                               ToSnappedClipRect(*new_fragment_clip));
     }
 
     InitFragmentPaintProperties(
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
index 49664ab..8f2d375 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
@@ -308,7 +308,7 @@
                   ->VerticalScrollbar()
                   ->IsOverlayScrollbar());
 
-  EXPECT_EQ(FloatRoundedRect(10, 10, 93, 93),
+  EXPECT_EQ(FloatClipRect(FloatRect(10, 10, 93, 93)),
             overflow_clip->ClipRectExcludingOverlayScrollbars());
 }
 
@@ -336,7 +336,7 @@
                   ->VerticalScrollbar()
                   ->IsOverlayScrollbar());
 
-  EXPECT_EQ(FloatRoundedRect(10, 10, 94, 93),
+  EXPECT_EQ(FloatClipRect(FloatRect(10, 10, 94, 93)),
             overflow_clip->ClipRectExcludingOverlayScrollbars());
 }
 
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn
index be8b68d1..09a6c481 100644
--- a/third_party/blink/renderer/modules/BUILD.gn
+++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -4,6 +4,7 @@
 
 import("//build/config/chromecast_build.gni")
 import("//build/split_static_library.gni")
+import("//testing/libfuzzer/fuzzer_test.gni")
 import("//third_party/blink/renderer/bindings/bindings.gni")
 import("//third_party/blink/renderer/bindings/modules/v8/generated.gni")
 import("//third_party/blink/renderer/bindings/modules/v8/v8.gni")
@@ -459,3 +460,21 @@
     "accessibility/testing/data/",
   ]
 }
+
+if (use_libfuzzer) {
+  fuzzer_test("media_capabilities_fuzzer") {
+    sources = [
+      "media_capabilities/media_capabilities_fuzzer.cc",
+    ]
+
+    seed_corpus = "media_capabilities/fuzzer_seed_corpus"
+
+    deps = [
+      ":modules",
+      "//third_party/blink/renderer/modules/media_capabilities:fuzzer_media_configuration_proto",
+      "//third_party/blink/renderer/platform:blink_fuzzer_test_support",
+      "//third_party/libprotobuf-mutator",
+      "//third_party/protobuf:protobuf_lite",
+    ]
+  }
+}
diff --git a/third_party/blink/renderer/modules/DEPS b/third_party/blink/renderer/modules/DEPS
index 3122bc0..c4366b29 100644
--- a/third_party/blink/renderer/modules/DEPS
+++ b/third_party/blink/renderer/modules/DEPS
@@ -19,3 +19,10 @@
     "+third_party/blink/renderer/modules",
     "-web",
 ]
+
+specific_include_rules = {
+    "media_capabilities_fuzzer.cc": [
+        "+testing/libfuzzer/proto/lpm_interface.h",
+        "+third_party/protobuf/src/google/protobuf/repeated_field.h",
+    ]
+}
\ No newline at end of file
diff --git a/third_party/blink/renderer/modules/media_capabilities/BUILD.gn b/third_party/blink/renderer/modules/media_capabilities/BUILD.gn
index 572bd5d4..4774828 100644
--- a/third_party/blink/renderer/modules/media_capabilities/BUILD.gn
+++ b/third_party/blink/renderer/modules/media_capabilities/BUILD.gn
@@ -3,6 +3,8 @@
 # found in the LICENSE file.
 
 import("//third_party/blink/renderer/modules/modules.gni")
+import("//third_party/libprotobuf-mutator/fuzzable_proto_library.gni")
+import("//third_party/protobuf/proto_library.gni")
 
 blink_modules_sources("media_capabilities") {
   sources = [
@@ -14,3 +16,9 @@
     "worker_navigator_media_capabilities.h",
   ]
 }
+
+fuzzable_proto_library("fuzzer_media_configuration_proto") {
+  sources = [
+    "fuzzer_media_configuration.proto",
+  ]
+}
diff --git a/third_party/blink/renderer/modules/media_capabilities/DEPS b/third_party/blink/renderer/modules/media_capabilities/DEPS
index 70ac253..5e42cc2e 100644
--- a/third_party/blink/renderer/modules/media_capabilities/DEPS
+++ b/third_party/blink/renderer/modules/media_capabilities/DEPS
@@ -9,4 +9,5 @@
     "+third_party/blink/renderer/modules/encryptedmedia",
     "+third_party/blink/renderer/modules/media_capabilities",
     "+third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.h",
+    "+third_party/blink/renderer/modules/modules_export.h",
 ]
diff --git a/third_party/blink/renderer/modules/media_capabilities/fuzzer_media_configuration.proto b/third_party/blink/renderer/modules/media_capabilities/fuzzer_media_configuration.proto
new file mode 100644
index 0000000..63a6384a
--- /dev/null
+++ b/third_party/blink/renderer/modules/media_capabilities/fuzzer_media_configuration.proto
@@ -0,0 +1,92 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+package mc_fuzzer;
+
+message MediaDecodingConfigProto {
+  message VideoConfigProto {
+    // String describing mime-type and codecs (e.g. 'video/webm; codecs="vp8"').
+    optional string content_type = 1;
+
+    // Width of the video in pixels.
+    optional uint32 width = 2;
+
+    // Height of the video in pixels.
+    optional uint32 height = 3;
+
+    // Bitrate for 1 second of video in bits-per-second.
+    optional uint32 bitrate = 4;
+
+    // String representing the videos frames-per-second (e.g. "60").
+    optional string framerate = 5;
+  }
+  optional VideoConfigProto video = 1;
+
+  message AudioConfigProto {
+    // String describing mime-type and codecs (e.g. 'audio/webm;
+    // codecs="vorbis"').
+    optional string content_type = 1;
+
+    // String representing number of audio channels (e.g. '5.1').
+    optional string channels = 2;
+
+    // Bitrate for 1 second of audio in bits-per-second.
+    optional uint32 bitrate = 3;
+
+    // Number of audio samples-per-second.
+    optional uint32 samplerate = 4;
+  }
+  optional AudioConfigProto audio = 2;
+
+  // What type of decoding is it?
+  enum MediaDecodingType {
+    FILE = 0;
+    MEDIA_SOURCE = 1;
+  }
+  optional MediaDecodingType type = 3;
+
+  // For detailed descriptions see
+  // https://wicg.github.io/media-capabilities/#dictdef-mediacapabilitieskeysystemconfiguration
+  message KeySystemConfig {
+    // Levels of requirement for various MediaKeys features.
+    enum MediaKeysRequirement {
+      REQUIRED = 0;
+      // NOTE, NOT_REQUIRED maps to "OPTIONAL" in the spec, but OPTIONAL causes
+      // conflict with macros in Windows.h
+      NOT_REQUIRED = 1;
+      NOT_ALLOWED = 2;
+    }
+
+    // Types of media keys sessions.
+    enum MediaKeySessionType {
+      TEMPORARY = 0;
+      PERSISTENT_LICENSE = 1;
+    }
+
+    // Name of the key system to use in decoding.
+    optional string key_system = 1;
+
+    // Indicates the format of accompanying Initialization Data.
+    optional string init_data_type = 2;
+
+    // The robustness level associated with the audio content type.
+    optional string audio_robustness = 3;
+
+    // The robustness level associated with the video content type.
+    optional string video_robustness = 4;
+
+    // Whether use of a Distinctive Identifier(s) is required.
+    optional MediaKeysRequirement distinctive_identifier = 5
+        [default = NOT_REQUIRED];
+
+    // Whether the ability to persist state is required.
+    optional MediaKeysRequirement persistent_state = 6 [default = NOT_REQUIRED];
+
+    // A list of MediaKeySessionTypes that must be supported.
+    repeated MediaKeySessionType session_types = 7;
+  }
+  optional KeySystemConfig key_system_config = 4;
+}
\ No newline at end of file
diff --git a/third_party/blink/renderer/modules/media_capabilities/fuzzer_seed_corpus/full_audio_video_eme.textproto b/third_party/blink/renderer/modules/media_capabilities/fuzzer_seed_corpus/full_audio_video_eme.textproto
new file mode 100644
index 0000000..4b8bc193
--- /dev/null
+++ b/third_party/blink/renderer/modules/media_capabilities/fuzzer_seed_corpus/full_audio_video_eme.textproto
@@ -0,0 +1,21 @@
+type: FILE
+video {
+    content_type: 'video/mp4; codecs="avc1.4d401e"'
+    width: 800
+    height: 600
+    bitrate: 3000
+    framerate: "24"
+  }
+audio {
+    content_type: 'audio/mp4; codecs="mp4a.40.2"'
+    channels: "5.1"
+    bitrate: 1000
+    samplerate: 4400
+  }
+key_system_config {
+    key_system: 'com.widevine.alpha'
+    video_robustness: 'HW_SECURE_ALL'
+    distinctive_identifier: REQUIRED
+    persistent_state: REQUIRED
+    session_types: [PERSISTENT_LICENSE]
+  }
\ No newline at end of file
diff --git a/third_party/blink/renderer/modules/media_capabilities/fuzzer_seed_corpus/minimal_audio_video_eme.textproto b/third_party/blink/renderer/modules/media_capabilities/fuzzer_seed_corpus/minimal_audio_video_eme.textproto
new file mode 100644
index 0000000..af90f9c6
--- /dev/null
+++ b/third_party/blink/renderer/modules/media_capabilities/fuzzer_seed_corpus/minimal_audio_video_eme.textproto
@@ -0,0 +1,14 @@
+type: MEDIA_SOURCE
+video {
+    content_type: 'video/webm; codecs="vp09.00.10.08"'
+    width: 800
+    height: 600
+    bitrate: 3000
+    framerate: "24"
+  }
+audio {
+    content_type: 'audio/webm; codecs="opus"'
+  }
+key_system_config {
+    key_system: 'org.w3.clearkey'
+  }
\ No newline at end of file
diff --git a/third_party/blink/renderer/modules/media_capabilities/media_capabilities.h b/third_party/blink/renderer/modules/media_capabilities/media_capabilities.h
index 50a9fbe..f04d0ce7 100644
--- a/third_party/blink/renderer/modules/media_capabilities/media_capabilities.h
+++ b/third_party/blink/renderer/modules/media_capabilities/media_capabilities.h
@@ -7,6 +7,7 @@
 
 #include "media/base/video_codecs.h"  // for media::VideoCodecProfile
 #include "media/mojo/interfaces/video_decode_perf_history.mojom-blink.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/heap/visitor.h"
 
@@ -22,7 +23,7 @@
 struct WebMediaDecodingConfiguration;
 struct WebVideoConfiguration;
 
-class MediaCapabilities final : public ScriptWrappable {
+class MODULES_EXPORT MediaCapabilities final : public ScriptWrappable {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
diff --git a/third_party/blink/renderer/modules/media_capabilities/media_capabilities_fuzzer.cc b/third_party/blink/renderer/modules/media_capabilities/media_capabilities_fuzzer.cc
new file mode 100644
index 0000000..4f30381c
--- /dev/null
+++ b/third_party/blink/renderer/modules/media_capabilities/media_capabilities_fuzzer.cc
@@ -0,0 +1,138 @@
+// Copyright 2019 The Chromium 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 "testing/libfuzzer/proto/lpm_interface.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/core/frame/settings.h"
+#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
+#include "third_party/blink/renderer/modules/media_capabilities/fuzzer_media_configuration.pb.h"
+#include "third_party/blink/renderer/modules/media_capabilities/media_capabilities.h"
+#include "third_party/blink/renderer/modules/media_capabilities/media_decoding_configuration.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/testing/blink_fuzzer_test_support.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+#include "third_party/protobuf/src/google/protobuf/repeated_field.h"
+
+namespace blink {
+
+String MediaKeysRequirementToString(
+    mc_fuzzer::MediaDecodingConfigProto_KeySystemConfig_MediaKeysRequirement
+        proto_requirement) {
+  switch (proto_requirement) {
+    case mc_fuzzer::
+        MediaDecodingConfigProto_KeySystemConfig_MediaKeysRequirement_REQUIRED:
+      return "required";
+    case mc_fuzzer::
+        MediaDecodingConfigProto_KeySystemConfig_MediaKeysRequirement_NOT_REQUIRED:
+      return "optional";
+    case mc_fuzzer::
+        MediaDecodingConfigProto_KeySystemConfig_MediaKeysRequirement_NOT_ALLOWED:
+      return "not-allowed";
+  }
+  return "";
+}
+
+Vector<String> MediaSessionTypeToVector(
+    const ::google::protobuf::RepeatedField<int>& proto_session_types) {
+  Vector<String> result;
+  for (auto& proto_session_type : proto_session_types) {
+    String session_type;
+    switch (proto_session_type) {
+      case mc_fuzzer::
+          MediaDecodingConfigProto_KeySystemConfig_MediaKeySessionType_TEMPORARY:
+        session_type = "temporary";
+        break;
+      case mc_fuzzer::
+          MediaDecodingConfigProto_KeySystemConfig_MediaKeySessionType_PERSISTENT_LICENSE:
+        session_type = "persistent-license";
+        break;
+    }
+    result.push_back(session_type);
+  }
+  return result;
+}
+
+MediaDecodingConfiguration* MakeConfiguration(
+    const mc_fuzzer::MediaDecodingConfigProto& proto) {
+  Persistent<MediaDecodingConfiguration> config =
+      MediaDecodingConfiguration::Create();
+  if (proto.has_video()) {
+    config->setVideo(VideoConfiguration::Create());
+    config->video()->setContentType(proto.video().content_type().c_str());
+    config->video()->setWidth(proto.video().width());
+    config->video()->setHeight(proto.video().height());
+    config->video()->setBitrate(proto.video().bitrate());
+    config->video()->setFramerate(proto.video().framerate().c_str());
+  }
+
+  if (proto.has_audio()) {
+    config->setAudio(AudioConfiguration::Create());
+    config->audio()->setContentType(proto.audio().content_type().c_str());
+    config->audio()->setChannels(proto.audio().channels().c_str());
+    config->audio()->setBitrate(proto.audio().bitrate());
+    config->audio()->setSamplerate(proto.audio().samplerate());
+  }
+
+  switch (proto.type()) {
+    case mc_fuzzer::MediaDecodingConfigProto_MediaDecodingType_FILE:
+      config->setType("file");
+      break;
+    case mc_fuzzer::MediaDecodingConfigProto_MediaDecodingType_MEDIA_SOURCE:
+      config->setType("media-source");
+      break;
+  }
+  if (proto.has_key_system_config()) {
+    config->setKeySystemConfiguration(
+        MediaCapabilitiesKeySystemConfiguration::Create());
+    config->keySystemConfiguration()->setKeySystem(
+        String::FromUTF8(proto.key_system_config().key_system().c_str()));
+    config->keySystemConfiguration()->setInitDataType(
+        String::FromUTF8(proto.key_system_config().init_data_type().c_str()));
+    config->keySystemConfiguration()->setAudioRobustness(
+        String::FromUTF8(proto.key_system_config().audio_robustness().c_str()));
+    config->keySystemConfiguration()->setVideoRobustness(
+        String::FromUTF8(proto.key_system_config().video_robustness().c_str()));
+    config->keySystemConfiguration()->setDistinctiveIdentifier(
+        MediaKeysRequirementToString(
+            proto.key_system_config().distinctive_identifier()));
+    config->keySystemConfiguration()->setPersistentState(
+        MediaKeysRequirementToString(
+            proto.key_system_config().persistent_state()));
+    config->keySystemConfiguration()->setSessionTypes(
+        MediaSessionTypeToVector(proto.key_system_config().session_types()));
+  }
+  return config;
+}
+
+DEFINE_TEXT_PROTO_FUZZER(const mc_fuzzer::MediaDecodingConfigProto& proto) {
+  static BlinkFuzzerTestSupport test_support = BlinkFuzzerTestSupport();
+  static DummyPageHolder* page_holder = []() {
+    auto page_holder = std::make_unique<DummyPageHolder>();
+    page_holder->GetFrame().GetSettings()->SetScriptEnabled(true);
+    return page_holder.release();
+  }();
+
+  MediaDecodingConfiguration* config = MakeConfiguration(proto);
+
+  ScriptState* script_state =
+      ToScriptStateForMainWorld(&page_holder->GetFrame());
+  ScriptState::Scope scope(script_state);
+
+  auto* media_capabilities = MakeGarbageCollected<MediaCapabilities>();
+  media_capabilities->decodingInfo(script_state, config);
+
+  // Request a V8 GC. Oilpan will be invoked by the GC epilogue.
+  //
+  // Multiple GCs may be required to ensure everything is collected (due to
+  // a chain of persistent handles), so some objects may not be collected until
+  // a subsequent iteration. This is slow enough as is, so we compromise on one
+  // major GC, as opposed to the 5 used in V8GCController for unit tests.
+  V8PerIsolateData::MainThreadIsolate()->RequestGarbageCollectionForTesting(
+      v8::Isolate::kFullGarbageCollection);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/xr/xr_reference_space_event.idl b/third_party/blink/renderer/modules/xr/xr_reference_space_event.idl
index 7a290ac..3e58aae 100644
--- a/third_party/blink/renderer/modules/xr/xr_reference_space_event.idl
+++ b/third_party/blink/renderer/modules/xr/xr_reference_space_event.idl
@@ -6,7 +6,7 @@
 [
     SecureContext,
     Exposed=Window,
-    OriginTrialEnabled=WebXR,
+    RuntimeEnabled=WebXR,
     Constructor(DOMString type, XRReferenceSpaceEventInit eventInitDict)
 ] interface XRReferenceSpaceEvent : Event {
   [SameObject] readonly attribute XRReferenceSpace referenceSpace;
diff --git a/third_party/blink/renderer/platform/animation/timing_function_test.cc b/third_party/blink/renderer/platform/animation/timing_function_test.cc
index e1282ff..ae9527f8 100644
--- a/third_party/blink/renderer/platform/animation/timing_function_test.cc
+++ b/third_party/blink/renderer/platform/animation/timing_function_test.cc
@@ -362,8 +362,8 @@
   scoped_refptr<TimingFunction> cubic_ease_timing =
       CubicBezierTimingFunction::Preset(
           CubicBezierTimingFunction::EaseType::EASE);
-  EXPECT_NEAR(0.418, cubic_ease_timing->Evaluate(0.25, tolerance), tolerance);
-  EXPECT_NEAR(0.805, cubic_ease_timing->Evaluate(0.50, tolerance), tolerance);
+  EXPECT_NEAR(0.409, cubic_ease_timing->Evaluate(0.25, tolerance), tolerance);
+  EXPECT_NEAR(0.802, cubic_ease_timing->Evaluate(0.50, tolerance), tolerance);
   EXPECT_NEAR(0.960, cubic_ease_timing->Evaluate(0.75, tolerance), tolerance);
 
   scoped_refptr<TimingFunction> cubic_ease_in_timing =
@@ -371,25 +371,25 @@
           CubicBezierTimingFunction::EaseType::EASE_IN);
   EXPECT_NEAR(0.093, cubic_ease_in_timing->Evaluate(0.25, tolerance),
               tolerance);
-  EXPECT_NEAR(0.305, cubic_ease_in_timing->Evaluate(0.50, tolerance),
+  EXPECT_NEAR(0.315, cubic_ease_in_timing->Evaluate(0.50, tolerance),
               tolerance);
-  EXPECT_NEAR(0.620, cubic_ease_in_timing->Evaluate(0.75, tolerance),
+  EXPECT_NEAR(0.622, cubic_ease_in_timing->Evaluate(0.75, tolerance),
               tolerance);
 
   scoped_refptr<TimingFunction> cubic_ease_out_timing =
       CubicBezierTimingFunction::Preset(
           CubicBezierTimingFunction::EaseType::EASE_OUT);
-  EXPECT_NEAR(0.379, cubic_ease_out_timing->Evaluate(0.25, tolerance),
+  EXPECT_NEAR(0.378, cubic_ease_out_timing->Evaluate(0.25, tolerance),
               tolerance);
-  EXPECT_NEAR(0.694, cubic_ease_out_timing->Evaluate(0.50, tolerance),
+  EXPECT_NEAR(0.685, cubic_ease_out_timing->Evaluate(0.50, tolerance),
               tolerance);
-  EXPECT_NEAR(0.906, cubic_ease_out_timing->Evaluate(0.75, tolerance),
+  EXPECT_NEAR(0.907, cubic_ease_out_timing->Evaluate(0.75, tolerance),
               tolerance);
 
   scoped_refptr<TimingFunction> cubic_ease_in_out_timing =
       CubicBezierTimingFunction::Preset(
           CubicBezierTimingFunction::EaseType::EASE_IN_OUT);
-  EXPECT_NEAR(0.128, cubic_ease_in_out_timing->Evaluate(0.25, tolerance),
+  EXPECT_NEAR(0.129, cubic_ease_in_out_timing->Evaluate(0.25, tolerance),
               tolerance);
   EXPECT_NEAR(0.500, cubic_ease_in_out_timing->Evaluate(0.50, tolerance),
               tolerance);
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
index 800a2f9..15d9e66 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
@@ -431,7 +431,9 @@
   for (const auto* current_clip = &guest.Clip().Unalias();
        current_clip != &home_clip;
        current_clip = SafeUnalias(current_clip->Parent())) {
-    if (!current_clip || current_clip->HasDirectCompositingReasons())
+    // If we had direct compositing reasons on a clip node, we would want to
+    // return false here.
+    if (!current_clip)
       return false;
     if (!IsNonCompositingAncestorOf(
             home.Transform().Unalias(),
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
index 65b934a..8277835 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
@@ -704,19 +704,26 @@
 }
 
 TEST_P(PaintArtifactCompositorTest, NestedClips) {
-  auto clip1 = CreateClip(c0(), t0(), FloatRoundedRect(100, 100, 700, 700),
-                          CompositingReason::kOverflowScrollingTouch);
-  auto clip2 = CreateClip(*clip1, t0(), FloatRoundedRect(200, 200, 700, 700),
-                          CompositingReason::kOverflowScrollingTouch);
+  auto transform1 =
+      CreateTransform(t0(), TransformationMatrix(), FloatPoint3D(),
+                      CompositingReason::kWillChangeTransform);
+  auto clip1 =
+      CreateClip(c0(), *transform1, FloatRoundedRect(100, 100, 700, 700));
+
+  auto transform2 =
+      CreateTransform(*transform1, TransformationMatrix(), FloatPoint3D(),
+                      CompositingReason::kWillChangeTransform);
+  auto clip2 =
+      CreateClip(*clip1, *transform2, FloatRoundedRect(200, 200, 700, 700));
 
   TestPaintArtifact artifact;
-  artifact.Chunk(t0(), *clip1, e0())
+  artifact.Chunk(*transform1, *clip1, e0())
       .RectDrawing(FloatRect(300, 350, 100, 100), Color::kWhite);
-  artifact.Chunk(t0(), *clip2, e0())
+  artifact.Chunk(*transform2, *clip2, e0())
       .RectDrawing(FloatRect(300, 350, 100, 100), Color::kLightGray);
-  artifact.Chunk(t0(), *clip1, e0())
+  artifact.Chunk(*transform1, *clip1, e0())
       .RectDrawing(FloatRect(300, 350, 100, 100), Color::kDarkGray);
-  artifact.Chunk(t0(), *clip2, e0())
+  artifact.Chunk(*transform2, *clip2, e0())
       .RectDrawing(FloatRect(300, 350, 100, 100), Color::kBlack);
   Update(artifact.Build());
 
@@ -762,22 +769,27 @@
 }
 
 TEST_P(PaintArtifactCompositorTest, NestedClipsWithAlias) {
-  auto real_clip1 = CreateClip(c0(), t0(), FloatRoundedRect(100, 100, 700, 700),
-                               CompositingReason::kOverflowScrollingTouch);
+  auto transform1 =
+      CreateTransform(t0(), TransformationMatrix(), FloatPoint3D(),
+                      CompositingReason::kWillChangeTransform);
+  auto real_clip1 =
+      CreateClip(c0(), *transform1, FloatRoundedRect(100, 100, 700, 700));
   auto clip1 = ClipPaintPropertyNode::CreateAlias(*real_clip1);
+  auto transform2 =
+      CreateTransform(*transform1, TransformationMatrix(), FloatPoint3D(),
+                      CompositingReason::kWillChangeTransform);
   auto real_clip2 =
-      CreateClip(*clip1, t0(), FloatRoundedRect(200, 200, 700, 700),
-                 CompositingReason::kOverflowScrollingTouch);
+      CreateClip(*clip1, *transform2, FloatRoundedRect(200, 200, 700, 700));
   auto clip2 = ClipPaintPropertyNode::CreateAlias(*real_clip2);
 
   TestPaintArtifact artifact;
-  artifact.Chunk(t0(), *clip1, e0())
+  artifact.Chunk(*transform1, *clip1, e0())
       .RectDrawing(FloatRect(300, 350, 100, 100), Color::kWhite);
-  artifact.Chunk(t0(), *clip2, e0())
+  artifact.Chunk(*transform2, *clip2, e0())
       .RectDrawing(FloatRect(300, 350, 100, 100), Color::kLightGray);
-  artifact.Chunk(t0(), *clip1, e0())
+  artifact.Chunk(*transform1, *clip1, e0())
       .RectDrawing(FloatRect(300, 350, 100, 100), Color::kDarkGray);
-  artifact.Chunk(t0(), *clip2, e0())
+  artifact.Chunk(*transform2, *clip2, e0())
       .RectDrawing(FloatRect(300, 350, 100, 100), Color::kBlack);
   Update(artifact.Build());
 
diff --git a/third_party/blink/renderer/platform/graphics/dark_mode_color_classifier.cc b/third_party/blink/renderer/platform/graphics/dark_mode_color_classifier.cc
index 1eec760..ed59d5c5 100644
--- a/third_party/blink/renderer/platform/graphics/dark_mode_color_classifier.cc
+++ b/third_party/blink/renderer/platform/graphics/dark_mode_color_classifier.cc
@@ -7,6 +7,20 @@
 namespace blink {
 namespace {
 
+// Determine perceived brightness of a color.
+//
+// Based on this algorithm suggested by the W3:
+// https://www.w3.org/TR/AERT/#color-contrast
+//
+// We don't use HSL or HSV here because perceived brightness is a function of
+// hue as well as lightness/value.
+int CalculateColorBrightness(const Color& color) {
+  int weighted_red = color.Red() * 299;
+  int weighted_green = color.Green() * 587;
+  int weighted_blue = color.Blue() * 114;
+  return (weighted_red + weighted_green + weighted_blue) / 1000;
+}
+
 class SimpleColorClassifier : public DarkModeColorClassifier {
  public:
   static std::unique_ptr<SimpleColorClassifier> NeverInvert() {
@@ -29,12 +43,18 @@
 
 class InvertLowBrightnessColorsClassifier : public DarkModeColorClassifier {
  public:
-  bool ShouldInvertColor(const Color& color) override {
-    if (color == Color::kWhite) {
-      return false;
-    }
-    return true;
+  InvertLowBrightnessColorsClassifier(int brightness_threshold)
+      : brightness_threshold_(brightness_threshold) {
+    DCHECK_GT(brightness_threshold_, 0);
+    DCHECK_LT(brightness_threshold_, 256);
   }
+
+  bool ShouldInvertColor(const Color& color) override {
+    return CalculateColorBrightness(color) < brightness_threshold_;
+  }
+
+ private:
+  int brightness_threshold_;
 };
 
 }  // namespace
@@ -63,13 +83,18 @@
 std::unique_ptr<DarkModeColorClassifier>
 DarkModeColorClassifier::MakeTextColorClassifier(
     const DarkModeSettings& settings) {
-  if (settings.text_policy == DarkModeTextPolicy::kInvertAll)
-    return SimpleColorClassifier::AlwaysInvert();
+  DCHECK_LE(settings.text_brightness_threshold, 256);
+  DCHECK_GE(settings.text_brightness_threshold, 0);
 
-  // Throw an error in debug mode if new values are added to the enum without
-  // updating this method.
-  DCHECK_EQ(settings.text_policy, DarkModeTextPolicy::kInvertDarkOnly);
-  return std::make_unique<InvertLowBrightnessColorsClassifier>();
+  // The value should be between 0 and 256, but check for values outside that
+  // range here to preserve correct behavior in non-debug builds.
+  if (settings.text_brightness_threshold >= 256)
+    return SimpleColorClassifier::AlwaysInvert();
+  if (settings.text_brightness_threshold <= 0)
+    return SimpleColorClassifier::NeverInvert();
+
+  return std::make_unique<InvertLowBrightnessColorsClassifier>(
+      settings.text_brightness_threshold);
 }
 
 DarkModeColorClassifier::~DarkModeColorClassifier() {}
diff --git a/third_party/blink/renderer/platform/graphics/dark_mode_filter.cc b/third_party/blink/renderer/platform/graphics/dark_mode_filter.cc
index b065b37..7a57279 100644
--- a/third_party/blink/renderer/platform/graphics/dark_mode_filter.cc
+++ b/third_party/blink/renderer/platform/graphics/dark_mode_filter.cc
@@ -31,7 +31,7 @@
     return;
 
   DCHECK_EQ(a.image_policy, b.image_policy);
-  DCHECK_EQ(a.text_policy, b.text_policy);
+  DCHECK_EQ(a.text_brightness_threshold, b.text_brightness_threshold);
   DCHECK_EQ(a.grayscale, b.grayscale);
   DCHECK(AreFloatsEqual(a.contrast, b.contrast));
   DCHECK(AreFloatsEqual(a.image_grayscale_percent, b.image_grayscale_percent));
diff --git a/third_party/blink/renderer/platform/graphics/dark_mode_filter_test.cc b/third_party/blink/renderer/platform/graphics/dark_mode_filter_test.cc
index f0dad9e..0edf0d2 100644
--- a/third_party/blink/renderer/platform/graphics/dark_mode_filter_test.cc
+++ b/third_party/blink/renderer/platform/graphics/dark_mode_filter_test.cc
@@ -51,5 +51,30 @@
   EXPECT_TRUE(filter.ShouldInvertTextColor(Color::kBlack));
 }
 
+TEST(DarkModeFilterTest, ApplyFilterToDarkTextOnly) {
+  DarkModeFilter filter;
+
+  DarkModeSettings settings;
+  settings.mode = DarkMode::kSimpleInvertForTesting;
+  settings.text_brightness_threshold = 200;
+  filter.UpdateSettings(settings);
+
+  EXPECT_FALSE(filter.ShouldInvertTextColor(Color::kWhite));
+  EXPECT_TRUE(filter.ShouldInvertTextColor(Color::kBlack));
+
+  EXPECT_FALSE(filter.ShouldInvertTextColor(Color(
+      settings.text_brightness_threshold, settings.text_brightness_threshold,
+      settings.text_brightness_threshold)));
+
+  EXPECT_TRUE(filter.ShouldInvertTextColor(
+      Color(settings.text_brightness_threshold - 5,
+            settings.text_brightness_threshold - 5,
+            settings.text_brightness_threshold - 5)));
+  EXPECT_FALSE(filter.ShouldInvertTextColor(
+      Color(settings.text_brightness_threshold + 5,
+            settings.text_brightness_threshold + 5,
+            settings.text_brightness_threshold + 5)));
+}
+
 }  // namespace
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/dark_mode_settings.h b/third_party/blink/renderer/platform/graphics/dark_mode_settings.h
index 5ffb283..4206cdb 100644
--- a/third_party/blink/renderer/platform/graphics/dark_mode_settings.h
+++ b/third_party/blink/renderer/platform/graphics/dark_mode_settings.h
@@ -33,13 +33,6 @@
   kFilterByBackground,
 };
 
-// If adding new values to this enum, also update the logic in
-// DarkModeFilter::ShouldInvertTextColor().
-enum class DarkModeTextPolicy {
-  kInvertAll,
-  kInvertDarkOnly,
-};
-
 // New variables added to this struct should also be added to
 // BuildDarkModeSettings() in
 //   //src/third_party/blink/renderer/core/accessibility/apply_dark_mode.h
@@ -49,7 +42,11 @@
   float image_grayscale_percent = 0.0;  // Valid range from 0.0 to 1.0
   float contrast = 0.0;                 // Valid range from -1.0 to 1.0
   DarkModeImagePolicy image_policy = DarkModeImagePolicy::kFilterAll;
-  DarkModeTextPolicy text_policy = DarkModeTextPolicy::kInvertAll;
+
+  // Text colors with brightness below this threshold will be inverted, and
+  // above it will be left as in the original, non-dark-mode page.  Set to 256
+  // to always invert text color or to 0 to never invert text color.
+  int text_brightness_threshold = 256;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.cc b/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.cc
index 82ee23a..67c3b45 100644
--- a/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.cc
@@ -46,17 +46,13 @@
                   String::Format("%p", state_.local_transform_space.get()));
   json->SetString("rect", state_.clip_rect.ToString());
   if (state_.clip_rect_excluding_overlay_scrollbars) {
-    json->SetString("rectExcludingOverlayScrollbars",
-                    state_.clip_rect_excluding_overlay_scrollbars->ToString());
+    json->SetString(
+        "rectExcludingOverlayScrollbars",
+        state_.clip_rect_excluding_overlay_scrollbars->Rect().ToString());
   }
   if (state_.clip_path) {
     json->SetBoolean("hasClipPath", true);
   }
-  if (state_.direct_compositing_reasons != CompositingReason::kNone) {
-    json->SetString(
-        "directCompositingReasons",
-        CompositingReason::ToString(state_.direct_compositing_reasons));
-  }
   return json;
 }
 
diff --git a/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h b/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h
index ffe70115..b4094008 100644
--- a/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h
+++ b/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h
@@ -34,18 +34,16 @@
   struct State {
     scoped_refptr<const TransformPaintPropertyNode> local_transform_space;
     FloatRoundedRect clip_rect;
-    base::Optional<FloatRoundedRect> clip_rect_excluding_overlay_scrollbars;
+    base::Optional<FloatClipRect> clip_rect_excluding_overlay_scrollbars;
     scoped_refptr<const RefCountedPath> clip_path;
-    CompositingReasons direct_compositing_reasons = CompositingReason::kNone;
 
     PaintPropertyChangeType ComputeChange(const State& other) const {
       if (local_transform_space != other.local_transform_space ||
           clip_rect != other.clip_rect || clip_path != other.clip_path) {
         return PaintPropertyChangeType::kChangedOnlyValues;
       }
-      if (direct_compositing_reasons != other.direct_compositing_reasons ||
-          clip_rect_excluding_overlay_scrollbars !=
-              other.clip_rect_excluding_overlay_scrollbars) {
+      if (clip_rect_excluding_overlay_scrollbars !=
+          other.clip_rect_excluding_overlay_scrollbars) {
         return PaintPropertyChangeType::kChangedOnlyNonRerasterValues;
       }
       return PaintPropertyChangeType::kUnchanged;
@@ -112,18 +110,14 @@
     return *Unalias().state_.local_transform_space;
   }
   const FloatRoundedRect& ClipRect() const { return state_.clip_rect; }
-  const FloatRoundedRect& ClipRectExcludingOverlayScrollbars() const {
+  const FloatClipRect ClipRectExcludingOverlayScrollbars() const {
     return state_.clip_rect_excluding_overlay_scrollbars
                ? *state_.clip_rect_excluding_overlay_scrollbars
-               : state_.clip_rect;
+               : FloatClipRect(state_.clip_rect);
   }
 
   const RefCountedPath* ClipPath() const { return state_.clip_path.get(); }
 
-  bool HasDirectCompositingReasons() const {
-    return state_.direct_compositing_reasons != CompositingReason::kNone;
-  }
-
   std::unique_ptr<JSONObject> ToJSON() const;
 
   // Returns memory usage of the clip cache of this node plus ancestors.
diff --git a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc
index 97f7bc51..e3db5d0 100644
--- a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc
@@ -317,7 +317,7 @@
   FloatClipRect clip_rect(
       UNLIKELY(clip_behavior == kExcludeOverlayScrollbarSizeForHitTesting)
           ? clip_node.ClipRectExcludingOverlayScrollbars()
-          : clip_node.ClipRect());
+          : FloatClipRect(clip_node.ClipRect()));
   if (clip_node.ClipPath())
     clip_rect.ClearIsTight();
   return clip_rect;
diff --git a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc
index 125c5f7..0fc92e1 100644
--- a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc
@@ -344,7 +344,7 @@
   clip_state.local_transform_space = &t0();
   clip_state.clip_rect = FloatRoundedRect(10, 10, 50, 50);
   clip_state.clip_rect_excluding_overlay_scrollbars =
-      FloatRoundedRect(10, 10, 45, 43);
+      FloatClipRect(FloatRect(10, 10, 45, 43));
   auto clip = ClipPaintPropertyNode::Create(c0(), std::move(clip_state));
   local_state.SetClip(*clip);
 
diff --git a/third_party/blink/renderer/platform/testing/paint_property_test_helpers.h b/third_party/blink/renderer/platform/testing/paint_property_test_helpers.h
index f4f343c..2c582402b 100644
--- a/third_party/blink/renderer/platform/testing/paint_property_test_helpers.h
+++ b/third_party/blink/renderer/platform/testing/paint_property_test_helpers.h
@@ -155,12 +155,10 @@
 inline scoped_refptr<ClipPaintPropertyNode> CreateClip(
     const ClipPaintPropertyNode& parent,
     const TransformPaintPropertyNode& local_transform_space,
-    const FloatRoundedRect& clip_rect,
-    CompositingReasons compositing_reasons = CompositingReason::kNone) {
+    const FloatRoundedRect& clip_rect) {
   ClipPaintPropertyNode::State state;
   state.local_transform_space = &local_transform_space;
   state.clip_rect = clip_rect;
-  state.direct_compositing_reasons = compositing_reasons;
   return ClipPaintPropertyNode::Create(parent, std::move(state));
 }
 
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
index c1fcfba..d1d490a 100755
--- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
+++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -581,6 +581,15 @@
     },
     {
         'paths': [
+            'third_party/blink/renderer/modules/media_capabilities/media_capabilities_fuzzer.cc',
+        ],
+        'allowed': [
+            'mc_fuzzer::.+',
+            'google::protobuf::RepeatedField',
+        ]
+    },
+    {
+        'paths': [
             'third_party/blink/renderer/modules/mediacapturefromelement/',
         ],
         'allowed': [
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 724e9d70..bb8595f 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -6039,7 +6039,6 @@
 crbug.com/865432 [ Linux ] virtual/omt-worker-fetch/external/wpt/workers/modules/dedicated-worker-import-blob-url.any.worker.html [ Timeout Pass ]
 crbug.com/867532 [ Linux ] virtual/omt-worker-fetch/external/wpt/workers/modules/dedicated-worker-import-data-url.any.worker.html [ Timeout Pass ]
 crbug.com/867532 [ Linux ] virtual/omt-worker-fetch/external/wpt/workers/modules/dedicated-worker-import.any.worker.html [ Timeout Pass ]
-crbug.com/962726 [ Linux Win ] external/wpt/event-timing/timingconditions.html [ Crash Pass ]
 crbug.com/937170 [ Linux Win7 ] external/wpt/IndexedDB/interleaved-cursors-large.html [ Pass Timeout ]
 crbug.com/937991 [ Win7 Release ] http/tests/devtools/cache-storage/cache-data.js [ Pass Timeout ]
 
@@ -6162,3 +6161,5 @@
 crbug.com/976045 [ Win ] fast/scrolling/unscrollable-layer-subpixel-size-with-negative-overflow.html [ Pass Failure ]
 crbug.com/976045 [ Win ] virtual/scroll_customization/fast/scrolling/unscrollable-layer-subpixel-size-with-negative-overflow.html [ Pass Failure ]
 crbug.com/976045 [ Win ] virtual/fractional_scrolling/fast/scrolling/unscrollable-layer-subpixel-size-with-negative-overflow.html [ Pass Failure ]
+crbug.com/976157 inspector-protocol/runtime/runtime-console-basic-functions.js [ Pass Failure ]
+crbug.com/977379 [ Mac10.10 ] fast/events/before-unload-return-value-from-listener.html [ Pass Timeout Failure ]
diff --git a/third_party/blink/web_tests/animations/direction-and-fill/animation-direction-reverse-timing-functions.html b/third_party/blink/web_tests/animations/direction-and-fill/animation-direction-reverse-timing-functions.html
index 18114a0..449780a4 100644
--- a/third_party/blink/web_tests/animations/direction-and-fill/animation-direction-reverse-timing-functions.html
+++ b/third_party/blink/web_tests/animations/direction-and-fill/animation-direction-reverse-timing-functions.html
@@ -33,7 +33,7 @@
     .alternate-reverse {
       animation-direction: alternate-reverse;
     }
-    
+
     @keyframes move1 {
       from { left: 0px; }
       to { left: 200px; }
@@ -53,29 +53,33 @@
   test(function() {
     const epsilon = 0.002;
 
+    // ease = cubicBezier(0.25, 0.1, 0.25, 1)
+    // ease(0.1) = 0.0947963055884654 ==> position = 18.9593
+    // ease(0.9) = 0.9943164775463438 ==> position = 198.863
+
     box1.style.animationDelay = '-0.2s';
-    assert_approx_equals(computedLeft(box1), 18.6525, epsilon, 'early box1');
+    assert_approx_equals(computedLeft(box1), 18.9593, epsilon, 'early box1');
 
     box2.style.animationDelay = '-0.2s';
-    assert_approx_equals(computedLeft(box2), 18.6525, epsilon, 'early box2');
+    assert_approx_equals(computedLeft(box2), 18.9593, epsilon, 'early box2');
 
     box3.style.animationDelay = '-0.2s';
-    assert_approx_equals(computedLeft(box3), 198.864, epsilon, 'early box3');
+    assert_approx_equals(computedLeft(box3), 198.863, epsilon, 'early box3');
 
     box4.style.animationDelay = '-0.2s';
-    assert_approx_equals(computedLeft(box4), 198.864, epsilon, 'early box4');
+    assert_approx_equals(computedLeft(box4), 198.863, epsilon, 'early box4');
 
 
     box1.style.animationDelay = '-2.2s';
-    assert_approx_equals(computedLeft(box1), 18.6525, epsilon, 'late box1');
+    assert_approx_equals(computedLeft(box1), 18.9593, epsilon, 'late box1');
 
     box2.style.animationDelay = '-2.2s';
-    assert_approx_equals(computedLeft(box2), 198.864, epsilon, 'late box2');
+    assert_approx_equals(computedLeft(box2), 198.863, epsilon, 'late box2');
 
     box3.style.animationDelay = '-2.2s';
-    assert_approx_equals(computedLeft(box3), 198.864, epsilon, 'late box3');
+    assert_approx_equals(computedLeft(box3), 198.863, epsilon, 'late box3');
 
     box4.style.animationDelay = '-2.2s';
-    assert_approx_equals(computedLeft(box4), 18.6525, epsilon, 'late box4');
+    assert_approx_equals(computedLeft(box4), 18.9593, epsilon, 'late box4');
   }, "animation-direction works with timing functions");
 </script>
diff --git a/third_party/blink/web_tests/animations/reverse-transition-with-easing.html b/third_party/blink/web_tests/animations/reverse-transition-with-easing.html
index 94b3599b..4a71ea0a 100644
--- a/third_party/blink/web_tests/animations/reverse-transition-with-easing.html
+++ b/third_party/blink/web_tests/animations/reverse-transition-with-easing.html
@@ -39,7 +39,8 @@
   animation.currentTime = 0;
   assert_equals(getComputedStyle(box).width, '100px', 'width at transition start');
   animation.currentTime = 400;
-  assert_px_approx_equals(getComputedStyle(box).width, 168.531, 0.01, 'width mid-forward');
+  // cubicBezier(0.25, 0.1, 0.25, 1)(0.4) = 0.68254
+  assert_px_approx_equals(getComputedStyle(box).width, 168.254, 0.01, 'width mid-forward');
 
   // Reverse the animation.
   box.className = '';
@@ -48,9 +49,20 @@
   animation.pause();  // The animation is replaced, so pause it again.
 
   animation.currentTime = 0;
-  assert_px_approx_equals(getComputedStyle(box).width, 168.531, 0.01, 'width after className');
+  assert_px_approx_equals(getComputedStyle(box).width, 168.254, 0.01, 'width after className');
+
+  // https://drafts.csswg.org/css-transitions-1/#reversing
+  // Reversing an animation.
+  // reverse shortening factor = output of timing function = 0.68254
+  // start time = (now)
+  // end time = (now) + duration * shortening factor = (now) + 682.54ms
+  // start value = 168.254
+  // end value = 100
+  // progress = 200 / (end time - start time) = 0.2930
+  // timing output = cubicBezier(0.25, 0.1, 0.25, 1)(0.2930) = 0.49939
+  // Expected position = (end value - start value) * timing output + start value = 134.165.
   animation.currentTime = 200;
-  assert_px_approx_equals(getComputedStyle(box).width, 134.438, 0.01, 'width mid-reverse');
+  assert_px_approx_equals(getComputedStyle(box).width, 134.165, 0.01, 'width mid-reverse');
 
   // Go forward again.  This tests the reversingAdjustedStartValue is set
   // properly the first time it's reversed.
@@ -60,9 +72,22 @@
   animation.pause();  // The animation is replaced, so pause it again.
 
   animation.currentTime = 0;
-  assert_px_approx_equals(getComputedStyle(box).width, 134.438, 0.01, 'width after second reverse');
+  assert_px_approx_equals(getComputedStyle(box).width, 134.165, 0.01, 'width after second reverse');
+
+  // reverse shortening factor
+  //    = (output of timing function) * (old shortening factor) +
+  //      (1 - old shortening factor) = 0.65831
+  // start time = (now)
+  // end time = (now) + duration * shortening factor = (now) + 658.31ms
+  // start value = 134.168
+  // end value = 200
+  // progress = 400 / (end time - start time) = 0.60761
+  // timing output = cubicBezier(0.25, 0.1, 0.25, 1)(0.6076) = 0.89032
+  // Expected position = (end value - start value) * timing output + start value = 192.779
+  // Accumulated a bit of round off error at this stage of the calculation. Relaxing the tolerance.
   animation.currentTime = 400;
-  assert_px_approx_equals(getComputedStyle(box).width, 193.016, 0.01, 'width mid-second-reverse');
+  assert_px_approx_equals(getComputedStyle(box).width, 192.779, 0.02, 'width mid-second-reverse');
+
   animation.currentTime = 800;
   assert_equals(getComputedStyle(box).width, '200px', 'width at end');
 
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
index 0f85382b..512e2dd 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
@@ -87119,6 +87119,18 @@
      {}
     ]
    ],
+   "css/css-variables/variable-reference-visited.html": [
+    [
+     "css/css-variables/variable-reference-visited.html",
+     [
+      [
+       "/css/css-variables/variable-reference-visited-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-variables/variable-reference-without-whitespace.html": [
     [
      "css/css-variables/variable-reference-without-whitespace.html",
@@ -143642,6 +143654,9 @@
    "css/css-variables/variable-presentation-attribute-expected.txt": [
     []
    ],
+   "css/css-variables/variable-reference-visited-ref.html": [
+    []
+   ],
    "css/css-variables/wide-keyword-fallback-ref.html": [
     []
    ],
@@ -158447,6 +158462,9 @@
    "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/OWNERS": [
     []
    ],
+   "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/aborted-parser.window-expected.txt": [
+    []
+   ],
    "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-side-effects-ignore-opens-during-unload.window-expected.txt": [
     []
    ],
@@ -159608,7 +159626,7 @@
    "lifecycle/META.yml": [
     []
    ],
-   "lifecycle/resources/foo.txt": [
+   "lifecycle/resources/beacon.py": [
     []
    ],
    "lifecycle/resources/subframe.html": [
@@ -171596,6 +171614,9 @@
    "web-animations/animation-model/keyframe-effects/effect-value-replaced-animations-expected.txt": [
     []
    ],
+   "web-animations/animation-model/keyframe-effects/effect-value-transformed-distance-expected.txt": [
+    []
+   ],
    "web-animations/interfaces/Animatable/animate-expected.txt": [
     []
    ],
@@ -171692,9 +171713,6 @@
    "web-animations/timing-model/animations/setting-the-timeline-of-an-animation-expected.txt": [
     []
    ],
-   "web-animations/timing-model/time-transformations/transformed-progress-expected.txt": [
-    []
-   ],
    "web-locks/META.yml": [
     []
    ],
@@ -245347,6 +245365,18 @@
      {}
     ]
    ],
+   "largest-contentful-paint/observe-image.html": [
+    [
+     "largest-contentful-paint/observe-image.html",
+     {}
+    ]
+   ],
+   "largest-contentful-paint/observe-text.html": [
+    [
+     "largest-contentful-paint/observe-text.html",
+     {}
+    ]
+   ],
    "layout-instability/buffer-layout-shift.html": [
     [
      "layout-instability/buffer-layout-shift.html",
@@ -293841,8 +293871,13 @@
        [
         "script",
         "websocket.sub.js"
+       ],
+       [
+        "timeout",
+        "long"
        ]
-      ]
+      ],
+      "timeout": "long"
      }
     ]
    ],
@@ -344797,7 +344832,7 @@
    "support"
   ],
   "css/css-easing/cubic-bezier-timing-functions-output-expected.txt": [
-   "8e41c9ca3f348827919bc8f4ad8ef59311eba947",
+   "b022577ffc139ed60d27fa47e36cbc30a1ed6174",
    "support"
   ],
   "css/css-easing/cubic-bezier-timing-functions-output.html": [
@@ -387712,6 +387747,14 @@
    "866d6e649d3bd1186c9b157b8d32db7e6cc7470b",
    "testharness"
   ],
+  "css/css-variables/variable-reference-visited-ref.html": [
+   "8647be19a8ccb033bc569fb9d1e1e444428f1655",
+   "support"
+  ],
+  "css/css-variables/variable-reference-visited.html": [
+   "eb414679b97ed78aee5053280c2fe33d2da2dc15",
+   "reftest"
+  ],
   "css/css-variables/variable-reference-without-whitespace.html": [
    "35d558892e2af2e34a1df445fab02b791689bf56",
    "reftest"
@@ -433088,6 +433131,10 @@
    "b2f05cf056d54a0602a55a8dda7c67cb94883055",
    "testharness"
   ],
+  "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/aborted-parser.window-expected.txt": [
+   "b1c010efde04fa3f3dbf9847a80f3967dd061ec9",
+   "support"
+  ],
   "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/aborted-parser.window.js": [
    "1d94de8a7c9f28dfab32111deb664d9921437e46",
    "testharness"
@@ -435952,6 +435999,14 @@
    "64756bf195fc3319d9dd21abad4c5d86fa266cfe",
    "testharness"
   ],
+  "largest-contentful-paint/observe-image.html": [
+   "f98912085aaf2677f4dbd85fba37c4b7f49ac5c2",
+   "testharness"
+  ],
+  "largest-contentful-paint/observe-text.html": [
+   "77ed06e2aa1fb99d1199b9e3b6e99620037ef959",
+   "testharness"
+  ],
   "layout-instability/buffer-layout-shift.html": [
    "c1d0dc6d6eb971f39c913a78423aad046dd18a04",
    "testharness"
@@ -435981,11 +436036,11 @@
    "testharness"
   ],
   "lifecycle/freeze.html": [
-   "88e32c9d3b01eb2622ce90699548d95fba5eb960",
+   "a2a9a7d3f147da9069bde019ec5940a213fbae79",
    "testharness"
   ],
-  "lifecycle/resources/foo.txt": [
-   "403d01060821820b9d3a772b28a826698c8796e6",
+  "lifecycle/resources/beacon.py": [
+   "8718b84386b56bdaf2e189a5f12041aa8b62c555",
    "support"
   ],
   "lifecycle/resources/subframe.html": [
@@ -436005,7 +436060,7 @@
    "support"
   ],
   "lifecycle/resources/window.html": [
-   "69fdbc0986633793d501a4bddfee9e88f76e1348",
+   "a7659af423d545683182ae750ecaadd195d273c0",
    "support"
   ],
   "lifecycle/set-composited-layer-position-ref.html": [
@@ -472565,7 +472620,7 @@
    "support"
   ],
   "tools/wpt/run.py": [
-   "0d7fa2233d64a6b5ee942038bc9a81ca33304938",
+   "fec2afc9a365b9daa813cfe6463060958a4a7a1b",
    "support"
   ],
   "tools/wpt/testfiles.py": [
@@ -475109,7 +475164,7 @@
    "testharness"
   ],
   "web-animations/animation-model/animation-types/interpolation-per-property-expected.txt": [
-   "fcd3230d7008e19079af1f0124e9b3a7339bd57f",
+   "286b089e58ddfadc3b66379ec1b059f2ac05aee5",
    "support"
   ],
   "web-animations/animation-model/animation-types/interpolation-per-property.html": [
@@ -475184,8 +475239,12 @@
    "d40a01fdd2a8c13649383d9cc1a8483ce84be902",
    "testharness"
   ],
+  "web-animations/animation-model/keyframe-effects/effect-value-transformed-distance-expected.txt": [
+   "d9a6c37685ddb3aa2ceb4561f4b452d9acf227e3",
+   "support"
+  ],
   "web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html": [
-   "6ad9cd2aca3260f5a247c6b6f4d1c31c39030dc8",
+   "a33d6d4f24676356b59b6b431968d8486df50615",
    "testharness"
   ],
   "web-animations/interfaces/Animatable/animate-expected.txt": [
@@ -475544,10 +475603,6 @@
    "4d3cc7950b09bdffc826dfa9ffd885e6dea5e9ac",
    "testharness"
   ],
-  "web-animations/timing-model/time-transformations/transformed-progress-expected.txt": [
-   "b6d3b22e2ae1fa543fb9e70a8be5b1d18a30468b",
-   "support"
-  ],
   "web-animations/timing-model/time-transformations/transformed-progress.html": [
    "960e333c09268f68d23ba2d0208202f8262ec3ef",
    "testharness"
diff --git a/third_party/blink/web_tests/external/wpt/css/css-easing/cubic-bezier-timing-functions-output-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-easing/cubic-bezier-timing-functions-output-expected.txt
index 8e41c9c..b022577 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-easing/cubic-bezier-timing-functions-output-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/css-easing/cubic-bezier-timing-functions-output-expected.txt
@@ -1,7 +1,7 @@
 This is a testharness.js-based test.
-FAIL cubic-bezier easing with input progress greater than 1 assert_approx_equals: The left of the animation should be approximately 98.8706654939602 at 230ms expected 98.8706654939602 +/- 0.01 but got 98.3585
-FAIL cubic-bezier easing with input progress greater than 1 and where the tangent on the upper boundary is infinity assert_approx_equals: The left of the animation should be approximately 106.31755608768113 at 230ms expected 106.31755608768113 +/- 0.01 but got 107.559
-FAIL cubic-bezier easing with input progress less than 0 assert_approx_equals: The left of the animation should be approximately -16.589193103032184 at 10ms expected -16.589193103032184 +/- 0.01 but got -18.0387
-FAIL cubic-bezier easing with input progress less than 0 and where the tangent on the lower boundary is infinity assert_approx_equals: The left of the animation should be approximately -6.317556087681108 at 770ms expected -6.317556087681108 +/- 0.01 but got -7.55879
+PASS cubic-bezier easing with input progress greater than 1
+FAIL cubic-bezier easing with input progress greater than 1 and where the tangent on the upper boundary is infinity assert_approx_equals: The left of the animation should be approximately 100 at 240ms expected 100 +/- 0.01 but got 99.5248
+PASS cubic-bezier easing with input progress less than 0
+PASS cubic-bezier easing with input progress less than 0 and where the tangent on the lower boundary is infinity
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/element-timing/css-generated-text.html b/third_party/blink/web_tests/external/wpt/element-timing/css-generated-text.html
new file mode 100644
index 0000000..1e3a812
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/element-timing/css-generated-text.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Element Timing: observe generated CSS text</title>
+<style>
+p::before {
+  content: "Generated text prefix";
+}
+body {
+  margin: 20px;
+}
+</style>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/element-timing-helpers.js"></script>
+<p elementtiming='my_text' id='text_id'></p>
+<script>
+  async_test(function (t) {
+    const beforeRender = performance.now();
+    if (!window.PerformanceElementTiming) {
+      assert_unreached("PerformanceElementTiming is not implemented");
+    }
+    const observer = new PerformanceObserver(
+      t.step_func_done(function(entryList) {
+        assert_equals(entryList.getEntries().length, 1);
+        const entry = entryList.getEntries()[0];
+        checkTextElement(entry, 'my_text', 'text_id', beforeRender, document.getElementById('text_id'));
+        assert_equals(entry.intersectionRect.left, 20, 'left should be 20.');
+        assert_equals(entry.intersectionRect.top, 20, 'top should be 20.');
+        // Try a lower bound of height=10, width=80 for the generated text.
+        assert_greater_than_equal(entry.intersectionRect.right, 100);
+        assert_greater_than_equal(entry.intersectionRect.bottom, 30);
+      })
+    );
+    observer.observe({type: 'element', buffered: true});
+  }, 'Generated text content is observable.');
+</script>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/element-timing/observe-shadow-image.html b/third_party/blink/web_tests/external/wpt/element-timing/observe-shadow-image.html
index 12bda472..3e1960d 100644
--- a/third_party/blink/web_tests/external/wpt/element-timing/observe-shadow-image.html
+++ b/third_party/blink/web_tests/external/wpt/element-timing/observe-shadow-image.html
@@ -11,8 +11,6 @@
 <script src="resources/element-timing-helpers.js"></script>
 <div id='target'></div>
 <script>
-  let beforeRender;
-  let img;
   async_test(function (t) {
     if (!window.PerformanceElementTiming) {
       assert_unreached("PerformanceElementTiming is not implemented");
@@ -27,13 +25,12 @@
     // in time for it to observe the element timing.
     window.onload = () => {
       // Add image of width equal to 100 and height equal to 100.
-      img = document.createElement('img');
+      const img = document.createElement('img');
       img.src = 'resources/square100.png';
       img.setAttribute('elementtiming', 'my_image');
       img.setAttribute('id', 'my_id');
-      const shadowRoot = document.getElementById('target').attachShadow({mode: 'closed'});
+      const shadowRoot = document.getElementById('target').attachShadow({mode: 'open'});
       shadowRoot.appendChild(img);
-      beforeRender = performance.now();
       t.step_timeout(() => {
         // Assume entry was not dispatched, so test passes.
         t.done();
diff --git a/third_party/blink/web_tests/external/wpt/element-timing/observe-shadow-text.html b/third_party/blink/web_tests/external/wpt/element-timing/observe-shadow-text.html
new file mode 100644
index 0000000..cc0cf0b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/element-timing/observe-shadow-text.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Element Timing: do not observe text in shadow tree</title>
+<style>
+body {
+  margin: 0;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/element-timing-helpers.js"></script>
+<div id='target'></div>
+<script>
+  async_test(function (t) {
+    if (!window.PerformanceElementTiming) {
+      assert_unreached("PerformanceElementTiming is not implemented");
+    }
+    const observer = new PerformanceObserver(
+      t.step_func_done(function(entryList) {
+        assert_unreached('Should not observe text elements in shadow trees!');
+      })
+    );
+    observer.observe({entryTypes: ['element']});
+    // We add the text during onload to be sure that the observer is registered
+    // in time for it to observe the element timing.
+    window.onload = () => {
+      // Add text of width equal to 100 and height equal to 100.
+      const text = document.createElement('p');
+      text.innerHTML = 'Text';
+      text.setAttribute('elementtiming', 'my_text');
+      const shadowRoot = document.getElementById('target').attachShadow({mode: 'open'});
+      shadowRoot.appendChild(text);
+      t.step_timeout(() => {
+        // Assume entry was not dispatched, so test passes.
+        t.done();
+      }, 500);
+    };
+  }, 'Text in shadow tree with elementtiming attribute is not observable.');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/element-timing/observe-text.html b/third_party/blink/web_tests/external/wpt/element-timing/observe-text.html
index 16382eda..4508db3 100644
--- a/third_party/blink/web_tests/external/wpt/element-timing/observe-text.html
+++ b/third_party/blink/web_tests/external/wpt/element-timing/observe-text.html
@@ -25,11 +25,11 @@
         assert_equals(entryList.getEntries().length, 1);
         const entry = entryList.getEntries()[0];
         checkTextElement(entry, 'my_text', 'text_id', beforeRender, paragraph);
-        assert_equals(entry.intersectionRect.left, 20);
+        assert_equals(entry.intersectionRect.left, 20, 'left should be 20.');
         // Text box size will vary from device to device, so try lower bounding height by 12, width by 100.
         assert_greater_than_equal(entry.intersectionRect.right, 120);
 
-        assert_equals(entry.intersectionRect.top, 20);
+        assert_equals(entry.intersectionRect.top, 20, 'top should be 20.');
         assert_greater_than_equal(entry.intersectionRect.bottom, 32);
       })
     );
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/interpolation-per-property-expected.txt b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/interpolation-per-property-expected.txt
index fcd3230..286b089e 100644
--- a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/interpolation-per-property-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/interpolation-per-property-expected.txt
@@ -38,8 +38,8 @@
 PASS background-clip uses discrete animation when animating between "padding-box" and "content-box" with keyframe easing
 PASS background-image (type: discrete) has testInterpolation function
 FAIL background-image uses discrete animation when animating between "url("http://localhost/test-1")" and "url("http://localhost/test-2")" with linear easing assert_equals: The value should be url("http://localhost/test-1") at 499ms expected "url(\"http://localhost/test-1\")" but got "-webkit-cross-fade(url(\"http://localhost/test-1\"), url(\"http://localhost/test-2\"), 0.499)"
-FAIL background-image uses discrete animation when animating between "url("http://localhost/test-1")" and "url("http://localhost/test-2")" with effect easing assert_equals: The value should be url("http://localhost/test-1") at 940ms expected "url(\"http://localhost/test-1\")" but got "-webkit-cross-fade(url(\"http://localhost/test-1\"), url(\"http://localhost/test-2\"), 0.427878)"
-FAIL background-image uses discrete animation when animating between "url("http://localhost/test-1")" and "url("http://localhost/test-2")" with keyframe easing assert_equals: The value should be url("http://localhost/test-1") at 940ms expected "url(\"http://localhost/test-1\")" but got "-webkit-cross-fade(url(\"http://localhost/test-1\"), url(\"http://localhost/test-2\"), 0.427878)"
+FAIL background-image uses discrete animation when animating between "url("http://localhost/test-1")" and "url("http://localhost/test-2")" with effect easing assert_equals: The value should be url("http://localhost/test-1") at 940ms expected "url(\"http://localhost/test-1\")" but got "-webkit-cross-fade(url(\"http://localhost/test-1\"), url(\"http://localhost/test-2\"), 0.428259)"
+FAIL background-image uses discrete animation when animating between "url("http://localhost/test-1")" and "url("http://localhost/test-2")" with keyframe easing assert_equals: The value should be url("http://localhost/test-1") at 940ms expected "url(\"http://localhost/test-1\")" but got "-webkit-cross-fade(url(\"http://localhost/test-1\"), url(\"http://localhost/test-2\"), 0.428259)"
 PASS background-origin (type: discrete) has testInterpolation function
 PASS background-origin uses discrete animation when animating between "padding-box" and "content-box" with linear easing
 PASS background-origin uses discrete animation when animating between "padding-box" and "content-box" with effect easing
@@ -68,24 +68,24 @@
 PASS border-collapse uses discrete animation when animating between "collapse" and "separate" with keyframe easing
 PASS border-image-outset (type: discrete) has testInterpolation function
 FAIL border-image-outset uses discrete animation when animating between "1 2 3 4" and "5 6 7 8" with linear easing assert_equals: The value should be 1 2 3 4 at 499ms expected "1 2 3 4" but got "2.996 3.996 4.996 5.996"
-FAIL border-image-outset uses discrete animation when animating between "1 2 3 4" and "5 6 7 8" with effect easing assert_equals: The value should be 1 2 3 4 at 940ms expected "1 2 3 4" but got "2.71151 3.71151 4.71151 5.71151"
-FAIL border-image-outset uses discrete animation when animating between "1 2 3 4" and "5 6 7 8" with keyframe easing assert_equals: The value should be 1 2 3 4 at 940ms expected "1 2 3 4" but got "2.71151 3.71151 4.71151 5.71151"
+FAIL border-image-outset uses discrete animation when animating between "1 2 3 4" and "5 6 7 8" with effect easing assert_equals: The value should be 1 2 3 4 at 940ms expected "1 2 3 4" but got "2.71304 3.71304 4.71304 5.71304"
+FAIL border-image-outset uses discrete animation when animating between "1 2 3 4" and "5 6 7 8" with keyframe easing assert_equals: The value should be 1 2 3 4 at 940ms expected "1 2 3 4" but got "2.71304 3.71304 4.71304 5.71304"
 PASS border-image-repeat (type: discrete) has testInterpolation function
 PASS border-image-repeat uses discrete animation when animating between "stretch repeat" and "round space" with linear easing
 PASS border-image-repeat uses discrete animation when animating between "stretch repeat" and "round space" with effect easing
 PASS border-image-repeat uses discrete animation when animating between "stretch repeat" and "round space" with keyframe easing
 PASS border-image-slice (type: discrete) has testInterpolation function
 FAIL border-image-slice uses discrete animation when animating between "1 2 3 4" and "5 6 7 8" with linear easing assert_equals: The value should be 1 2 3 4 at 499ms expected "1 2 3 4" but got "2.996 3.996 4.996 5.996"
-FAIL border-image-slice uses discrete animation when animating between "1 2 3 4" and "5 6 7 8" with effect easing assert_equals: The value should be 1 2 3 4 at 940ms expected "1 2 3 4" but got "2.71151 3.71151 4.71151 5.71151"
-FAIL border-image-slice uses discrete animation when animating between "1 2 3 4" and "5 6 7 8" with keyframe easing assert_equals: The value should be 1 2 3 4 at 940ms expected "1 2 3 4" but got "2.71151 3.71151 4.71151 5.71151"
+FAIL border-image-slice uses discrete animation when animating between "1 2 3 4" and "5 6 7 8" with effect easing assert_equals: The value should be 1 2 3 4 at 940ms expected "1 2 3 4" but got "2.71304 3.71304 4.71304 5.71304"
+FAIL border-image-slice uses discrete animation when animating between "1 2 3 4" and "5 6 7 8" with keyframe easing assert_equals: The value should be 1 2 3 4 at 940ms expected "1 2 3 4" but got "2.71304 3.71304 4.71304 5.71304"
 PASS border-image-source (type: discrete) has testInterpolation function
 FAIL border-image-source uses discrete animation when animating between "url("http://localhost/test-1")" and "url("http://localhost/test-2")" with linear easing assert_equals: The value should be url("http://localhost/test-1") at 499ms expected "url(\"http://localhost/test-1\")" but got "-webkit-cross-fade(url(\"http://localhost/test-1\"), url(\"http://localhost/test-2\"), 0.499)"
-FAIL border-image-source uses discrete animation when animating between "url("http://localhost/test-1")" and "url("http://localhost/test-2")" with effect easing assert_equals: The value should be url("http://localhost/test-1") at 940ms expected "url(\"http://localhost/test-1\")" but got "-webkit-cross-fade(url(\"http://localhost/test-1\"), url(\"http://localhost/test-2\"), 0.427878)"
-FAIL border-image-source uses discrete animation when animating between "url("http://localhost/test-1")" and "url("http://localhost/test-2")" with keyframe easing assert_equals: The value should be url("http://localhost/test-1") at 940ms expected "url(\"http://localhost/test-1\")" but got "-webkit-cross-fade(url(\"http://localhost/test-1\"), url(\"http://localhost/test-2\"), 0.427878)"
+FAIL border-image-source uses discrete animation when animating between "url("http://localhost/test-1")" and "url("http://localhost/test-2")" with effect easing assert_equals: The value should be url("http://localhost/test-1") at 940ms expected "url(\"http://localhost/test-1\")" but got "-webkit-cross-fade(url(\"http://localhost/test-1\"), url(\"http://localhost/test-2\"), 0.428259)"
+FAIL border-image-source uses discrete animation when animating between "url("http://localhost/test-1")" and "url("http://localhost/test-2")" with keyframe easing assert_equals: The value should be url("http://localhost/test-1") at 940ms expected "url(\"http://localhost/test-1\")" but got "-webkit-cross-fade(url(\"http://localhost/test-1\"), url(\"http://localhost/test-2\"), 0.428259)"
 PASS border-image-width (type: discrete) has testInterpolation function
 FAIL border-image-width uses discrete animation when animating between "1 2 3 4" and "5 6 7 8" with linear easing assert_equals: The value should be 1 2 3 4 at 499ms expected "1 2 3 4" but got "2.996 3.996 4.996 5.996"
-FAIL border-image-width uses discrete animation when animating between "1 2 3 4" and "5 6 7 8" with effect easing assert_equals: The value should be 1 2 3 4 at 940ms expected "1 2 3 4" but got "2.71151 3.71151 4.71151 5.71151"
-FAIL border-image-width uses discrete animation when animating between "1 2 3 4" and "5 6 7 8" with keyframe easing assert_equals: The value should be 1 2 3 4 at 940ms expected "1 2 3 4" but got "2.71151 3.71151 4.71151 5.71151"
+FAIL border-image-width uses discrete animation when animating between "1 2 3 4" and "5 6 7 8" with effect easing assert_equals: The value should be 1 2 3 4 at 940ms expected "1 2 3 4" but got "2.71304 3.71304 4.71304 5.71304"
+FAIL border-image-width uses discrete animation when animating between "1 2 3 4" and "5 6 7 8" with keyframe easing assert_equals: The value should be 1 2 3 4 at 940ms expected "1 2 3 4" but got "2.71304 3.71304 4.71304 5.71304"
 PASS border-left-color (type: color) has testInterpolation function
 PASS border-left-color supports animating as color of rgb()
 PASS border-left-color supports animating as color of #RGB
@@ -417,8 +417,8 @@
 PASS lighting-color supports animating as color of hsla()
 PASS list-style-image (type: discrete) has testInterpolation function
 FAIL list-style-image uses discrete animation when animating between "url("http://localhost/test-1")" and "url("http://localhost/test-2")" with linear easing assert_equals: The value should be url("http://localhost/test-1") at 499ms expected "url(\"http://localhost/test-1\")" but got "-webkit-cross-fade(url(\"http://localhost/test-1\"), url(\"http://localhost/test-2\"), 0.499)"
-FAIL list-style-image uses discrete animation when animating between "url("http://localhost/test-1")" and "url("http://localhost/test-2")" with effect easing assert_equals: The value should be url("http://localhost/test-1") at 940ms expected "url(\"http://localhost/test-1\")" but got "-webkit-cross-fade(url(\"http://localhost/test-1\"), url(\"http://localhost/test-2\"), 0.427878)"
-FAIL list-style-image uses discrete animation when animating between "url("http://localhost/test-1")" and "url("http://localhost/test-2")" with keyframe easing assert_equals: The value should be url("http://localhost/test-1") at 940ms expected "url(\"http://localhost/test-1\")" but got "-webkit-cross-fade(url(\"http://localhost/test-1\"), url(\"http://localhost/test-2\"), 0.427878)"
+FAIL list-style-image uses discrete animation when animating between "url("http://localhost/test-1")" and "url("http://localhost/test-2")" with effect easing assert_equals: The value should be url("http://localhost/test-1") at 940ms expected "url(\"http://localhost/test-1\")" but got "-webkit-cross-fade(url(\"http://localhost/test-1\"), url(\"http://localhost/test-2\"), 0.428259)"
+FAIL list-style-image uses discrete animation when animating between "url("http://localhost/test-1")" and "url("http://localhost/test-2")" with keyframe easing assert_equals: The value should be url("http://localhost/test-1") at 940ms expected "url(\"http://localhost/test-1\")" but got "-webkit-cross-fade(url(\"http://localhost/test-1\"), url(\"http://localhost/test-2\"), 0.428259)"
 PASS list-style-position (type: discrete) has testInterpolation function
 PASS list-style-position uses discrete animation when animating between "inside" and "outside" with linear easing
 PASS list-style-position uses discrete animation when animating between "inside" and "outside" with effect easing
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance-expected.txt b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance-expected.txt
new file mode 100644
index 0000000..d9a6c37
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance-expected.txt
@@ -0,0 +1,31 @@
+This is a testharness.js-based test.
+PASS A step-start function on a keyframe affects the resulting style
+PASS A steps(1, start) function on a keyframe affects the resulting style
+PASS A steps(2, start) function on a keyframe affects the resulting style
+PASS A step-end function on a keyframe affects the resulting style
+PASS A steps(1) function on a keyframe affects the resulting style
+PASS A steps(1, end) function on a keyframe affects the resulting style
+PASS A steps(2, end) function on a keyframe affects the resulting style
+PASS A linear function on a keyframe affects the resulting style
+PASS A ease function on a keyframe affects the resulting style
+PASS A ease-in function on a keyframe affects the resulting style
+PASS A ease-in-out function on a keyframe affects the resulting style
+PASS A ease-out function on a keyframe affects the resulting style
+PASS A easing function which produces values greater than 1 on a keyframe affects the resulting style
+PASS A easing function which produces values less than 1 on a keyframe affects the resulting style
+PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a step-start function does not alter the result
+PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a steps(1, start) function does not alter the result
+PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a steps(2, start) function does not alter the result
+PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a step-end function does not alter the result
+PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a steps(1) function does not alter the result
+PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a steps(1, end) function does not alter the result
+PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a steps(2, end) function does not alter the result
+PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a linear function does not alter the result
+PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a ease function does not alter the result
+PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a ease-in function does not alter the result
+PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a ease-in-out function does not alter the result
+PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a ease-out function does not alter the result
+FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a easing function which produces values greater than 1 does not alter the result assert_equals: The 'width' of the animated elements should be equal at 250ms expected "100px" but got "102.406px"
+PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a easing function which produces values less than 1 does not alter the result
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html
index 6ad9cd2a..a33d6d4 100644
--- a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html
+++ b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html
@@ -35,7 +35,7 @@
                             : 100 + params.easingFunction(portion) * 100;
       assert_approx_equals(parseFloat(getComputedStyle(target).width),
                            expectedWidth,
-                           0.01,
+                           0.02,
                            'The width should be approximately ' +
                            `${expectedWidth} at ${sampleTime}ms`);
     }
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/timing-model/time-transformations/transformed-progress-expected.txt b/third_party/blink/web_tests/external/wpt/web-animations/timing-model/time-transformations/transformed-progress-expected.txt
deleted file mode 100644
index b6d3b22..0000000
--- a/third_party/blink/web_tests/external/wpt/web-animations/timing-model/time-transformations/transformed-progress-expected.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-This is a testharness.js-based test.
-PASS Transformed progress for step-start function
-PASS Transformed progress for steps(1, start) function
-PASS Transformed progress for steps(2, start) function
-PASS Transformed progress for step-end function
-PASS Transformed progress for steps(1) function
-PASS Transformed progress for steps(1, end) function
-PASS Transformed progress for steps(2, end) function
-PASS Transformed progress for linear function
-FAIL Transformed progress for ease function assert_approx_equals: The progress should be approximately 0.40851059137130497 at 250ms expected 0.40851059137130497 +/- 0.01 but got 0.41869212962962965
-PASS Transformed progress for ease-in function
-PASS Transformed progress for ease-in-out function
-PASS Transformed progress for ease-out function
-PASS Transformed progress for easing function which produces values greater than 1
-PASS Transformed progress for easing function which produces values less than 1
-PASS Test bounds point of step-start easing
-PASS Test bounds point of step-start easing with reverse direction
-PASS Test bounds point of step-start easing with iterationStart not at a transition point
-PASS Test bounds point of step-start easing with iterationStart and delay
-PASS Test bounds point of step-start easing with iterationStart and reverse direction
-PASS Test bounds point of step(4, start) easing with iterationStart 0.75 and delay
-PASS Test bounds point of step-start easing with alternate direction
-PASS Test bounds point of step-start easing with alternate-reverse direction
-PASS Test bounds point of step-end easing
-PASS Test bounds point of step-end easing with iterationStart and delay
-PASS Test bounds point of step-end easing with iterationStart not at a transition point
-PASS Test bounds point of steps(jump-both) easing
-PASS Test bounds point of steps(jump-both) easing with iterationStart and delay
-PASS Test bounds point of steps(jump-both) easing with iterationStart not at a transition point
-PASS Test bounds point of steps(jump-none) easing
-PASS Test bounds point of steps(jump-none) easing with iterationStart and delay
-PASS Test bounds point of steps(jump-none) easing with iterationStart not at a transition point
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/websockets/remove-own-iframe-during-onerror.window.js b/third_party/blink/web_tests/external/wpt/websockets/remove-own-iframe-during-onerror.window.js
index 55fa686c..31c21b4 100644
--- a/third_party/blink/web_tests/external/wpt/websockets/remove-own-iframe-during-onerror.window.js
+++ b/third_party/blink/web_tests/external/wpt/websockets/remove-own-iframe-during-onerror.window.js
@@ -1,4 +1,5 @@
 // META: script=websocket.sub.js
+// META: timeout=long
 
 async_test(t => {
   window.wsurl = 'wss://' + __SERVER__NAME + ':' + __SECURE__PORT +
diff --git a/third_party/blink/web_tests/inspector-protocol/runtime/runtime-console-basic-functions-expected.txt b/third_party/blink/web_tests/inspector-protocol/runtime/runtime-console-basic-functions-expected.txt
index 6206cac..84f65e3 100644
--- a/third_party/blink/web_tests/inspector-protocol/runtime/runtime-console-basic-functions-expected.txt
+++ b/third_party/blink/web_tests/inspector-protocol/runtime/runtime-console-basic-functions-expected.txt
@@ -1,878 +1,10 @@
 Tests ConsoleOM APIs with standard argument behavior.
-Testing console.log with required args 
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
-                className : Object
-                description : Object
-                objectId : <string>
-                preview : {
-                    description : Object
-                    overflow : false
-                    properties : [
-                        [0] : {
-                            name : a
-                            type : number
-                            value : 3
-                        }
-                        [1] : {
-                            name : b
-                            type : string
-                            value : hello
-                        }
-                    ]
-                    type : object
-                }
-                type : object
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : log
-    }
-    sessionId : <string>
-}
-Testing console.debug with required args 
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
-                className : Object
-                description : Object
-                objectId : <string>
-                preview : {
-                    description : Object
-                    overflow : false
-                    properties : [
-                        [0] : {
-                            name : a
-                            type : number
-                            value : 3
-                        }
-                        [1] : {
-                            name : b
-                            type : string
-                            value : hello
-                        }
-                    ]
-                    type : object
-                }
-                type : object
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : debug
-    }
-    sessionId : <string>
-}
-Testing console.info with required args 
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
-                className : Object
-                description : Object
-                objectId : <string>
-                preview : {
-                    description : Object
-                    overflow : false
-                    properties : [
-                        [0] : {
-                            name : a
-                            type : number
-                            value : 3
-                        }
-                        [1] : {
-                            name : b
-                            type : string
-                            value : hello
-                        }
-                    ]
-                    type : object
-                }
-                type : object
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : info
-    }
-    sessionId : <string>
-}
-Testing console.error with required args 
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
-                className : Object
-                description : Object
-                objectId : <string>
-                preview : {
-                    description : Object
-                    overflow : false
-                    properties : [
-                        [0] : {
-                            name : a
-                            type : number
-                            value : 3
-                        }
-                        [1] : {
-                            name : b
-                            type : string
-                            value : hello
-                        }
-                    ]
-                    type : object
-                }
-                type : object
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : error
-    }
-    sessionId : <string>
-}
-Testing console.warn with required args 
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
-                className : Object
-                description : Object
-                objectId : <string>
-                preview : {
-                    description : Object
-                    overflow : false
-                    properties : [
-                        [0] : {
-                            name : a
-                            type : number
-                            value : 3
-                        }
-                        [1] : {
-                            name : b
-                            type : string
-                            value : hello
-                        }
-                    ]
-                    type : object
-                }
-                type : object
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : warning
-    }
-    sessionId : <string>
-}
-Testing console.dir with required args 
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
-                className : Object
-                description : Object
-                objectId : <string>
-                preview : {
-                    description : Object
-                    overflow : false
-                    properties : [
-                        [0] : {
-                            name : a
-                            type : number
-                            value : 3
-                        }
-                        [1] : {
-                            name : b
-                            type : string
-                            value : hello
-                        }
-                    ]
-                    type : object
-                }
-                type : object
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : dir
-    }
-    sessionId : <string>
-}
-Testing console.dirxml with required args 
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
-                className : Object
-                description : Object
-                objectId : <string>
-                preview : {
-                    description : Object
-                    overflow : false
-                    properties : [
-                        [0] : {
-                            name : a
-                            type : number
-                            value : 3
-                        }
-                        [1] : {
-                            name : b
-                            type : string
-                            value : hello
-                        }
-                    ]
-                    type : object
-                }
-                type : object
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : dirxml
-    }
-    sessionId : <string>
-}
-Testing console.table with required args 
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
-                className : Object
-                description : Object
-                objectId : <string>
-                preview : {
-                    description : Object
-                    overflow : false
-                    properties : [
-                        [0] : {
-                            name : a
-                            type : number
-                            value : 3
-                        }
-                        [1] : {
-                            name : b
-                            type : string
-                            value : hello
-                        }
-                    ]
-                    type : object
-                }
-                type : object
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : table
-    }
-    sessionId : <string>
-}
-Testing console.trace with optional args 
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
-                className : Object
-                description : Object
-                objectId : <string>
-                preview : {
-                    description : Object
-                    overflow : false
-                    properties : [
-                        [0] : {
-                            name : a
-                            type : number
-                            value : 3
-                        }
-                        [1] : {
-                            name : b
-                            type : string
-                            value : hello
-                        }
-                    ]
-                    type : object
-                }
-                type : object
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : trace
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : console.trace
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : trace
-    }
-    sessionId : <string>
-}
-Testing console.clear with optional args 
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
-                className : Object
-                description : Object
-                objectId : <string>
-                preview : {
-                    description : Object
-                    overflow : false
-                    properties : [
-                        [0] : {
-                            name : a
-                            type : number
-                            value : 3
-                        }
-                        [1] : {
-                            name : b
-                            type : string
-                            value : hello
-                        }
-                    ]
-                    type : object
-                }
-                type : object
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : clear
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : console.clear
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : clear
-    }
-    sessionId : <string>
-}
-Testing console.group with optional args 
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
-                className : Object
-                description : Object
-                objectId : <string>
-                preview : {
-                    description : Object
-                    overflow : false
-                    properties : [
-                        [0] : {
-                            name : a
-                            type : number
-                            value : 3
-                        }
-                        [1] : {
-                            name : b
-                            type : string
-                            value : hello
-                        }
-                    ]
-                    type : object
-                }
-                type : object
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : startGroup
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : console.group
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : startGroup
-    }
-    sessionId : <string>
-}
-Testing console.groupCollapsed with optional args 
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
-                className : Object
-                description : Object
-                objectId : <string>
-                preview : {
-                    description : Object
-                    overflow : false
-                    properties : [
-                        [0] : {
-                            name : a
-                            type : number
-                            value : 3
-                        }
-                        [1] : {
-                            name : b
-                            type : string
-                            value : hello
-                        }
-                    ]
-                    type : object
-                }
-                type : object
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : startGroupCollapsed
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : console.groupCollapsed
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : startGroupCollapsed
-    }
-    sessionId : <string>
-}
-Testing console.groupEnd with optional args 
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
-                className : Object
-                description : Object
-                objectId : <string>
-                preview : {
-                    description : Object
-                    overflow : false
-                    properties : [
-                        [0] : {
-                            name : a
-                            type : number
-                            value : 3
-                        }
-                        [1] : {
-                            name : b
-                            type : string
-                            value : hello
-                        }
-                    ]
-                    type : object
-                }
-                type : object
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : endGroup
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
-                type : string
-                value : console.groupEnd
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : endGroup
-    }
-    sessionId : <string>
-}
 Testing console.log with required args inside page context
 {
     method : Runtime.consoleAPICalled
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
                 className : Object
                 description : Object
                 objectId : <string>
@@ -919,16 +51,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
                 className : Object
                 description : Object
                 objectId : <string>
@@ -975,16 +97,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
                 className : Object
                 description : Object
                 objectId : <string>
@@ -1031,16 +143,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
                 className : Object
                 description : Object
                 objectId : <string>
@@ -1087,16 +189,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
                 className : Object
                 description : Object
                 objectId : <string>
@@ -1143,16 +235,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
                 className : Object
                 description : Object
                 objectId : <string>
@@ -1199,16 +281,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
                 className : Object
                 description : Object
                 objectId : <string>
@@ -1255,16 +327,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
                 className : Object
                 description : Object
                 objectId : <string>
@@ -1311,61 +373,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
-                className : Object
-                description : Object
-                objectId : <string>
-                preview : {
-                    description : Object
-                    overflow : false
-                    properties : [
-                        [0] : {
-                            name : a
-                            type : number
-                            value : 3
-                        }
-                        [1] : {
-                            name : b
-                            type : string
-                            value : hello
-                        }
-                    ]
-                    type : object
-                }
-                type : object
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : trace
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
                 type : string
                 value : console.trace
             }
@@ -1393,61 +400,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
-                className : Object
-                description : Object
-                objectId : <string>
-                preview : {
-                    description : Object
-                    overflow : false
-                    properties : [
-                        [0] : {
-                            name : a
-                            type : number
-                            value : 3
-                        }
-                        [1] : {
-                            name : b
-                            type : string
-                            value : hello
-                        }
-                    ]
-                    type : object
-                }
-                type : object
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : clear
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
                 type : string
                 value : console.clear
             }
@@ -1475,61 +427,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
-                className : Object
-                description : Object
-                objectId : <string>
-                preview : {
-                    description : Object
-                    overflow : false
-                    properties : [
-                        [0] : {
-                            name : a
-                            type : number
-                            value : 3
-                        }
-                        [1] : {
-                            name : b
-                            type : string
-                            value : hello
-                        }
-                    ]
-                    type : object
-                }
-                type : object
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : startGroup
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
                 type : string
                 value : console.group
             }
@@ -1557,61 +454,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
-                className : Object
-                description : Object
-                objectId : <string>
-                preview : {
-                    description : Object
-                    overflow : false
-                    properties : [
-                        [0] : {
-                            name : a
-                            type : number
-                            value : 3
-                        }
-                        [1] : {
-                            name : b
-                            type : string
-                            value : hello
-                        }
-                    ]
-                    type : object
-                }
-                type : object
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : startGroupCollapsed
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
                 type : string
                 value : console.groupCollapsed
             }
@@ -1639,61 +481,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
-                className : Object
-                description : Object
-                objectId : <string>
-                preview : {
-                    description : Object
-                    overflow : false
-                    properties : [
-                        [0] : {
-                            name : a
-                            type : number
-                            value : 3
-                        }
-                        [1] : {
-                            name : b
-                            type : string
-                            value : hello
-                        }
-                    ]
-                    type : object
-                }
-                type : object
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : endGroup
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
                 type : string
                 value : console.groupEnd
             }
@@ -1721,16 +508,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
                 className : Object
                 description : Object
                 objectId : <string>
@@ -1777,16 +554,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
                 className : Object
                 description : Object
                 objectId : <string>
@@ -1833,16 +600,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
                 className : Object
                 description : Object
                 objectId : <string>
@@ -1889,16 +646,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
                 className : Object
                 description : Object
                 objectId : <string>
@@ -1945,16 +692,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
                 className : Object
                 description : Object
                 objectId : <string>
@@ -2001,16 +738,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
                 className : Object
                 description : Object
                 objectId : <string>
@@ -2057,16 +784,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
                 className : Object
                 description : Object
                 objectId : <string>
@@ -2113,16 +830,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
                 className : Object
                 description : Object
                 objectId : <string>
@@ -2169,61 +876,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
-                className : Object
-                description : Object
-                objectId : <string>
-                preview : {
-                    description : Object
-                    overflow : false
-                    properties : [
-                        [0] : {
-                            name : a
-                            type : number
-                            value : 3
-                        }
-                        [1] : {
-                            name : b
-                            type : string
-                            value : hello
-                        }
-                    ]
-                    type : object
-                }
-                type : object
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : trace
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
                 type : string
                 value : console.trace
             }
@@ -2251,61 +903,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
-                className : Object
-                description : Object
-                objectId : <string>
-                preview : {
-                    description : Object
-                    overflow : false
-                    properties : [
-                        [0] : {
-                            name : a
-                            type : number
-                            value : 3
-                        }
-                        [1] : {
-                            name : b
-                            type : string
-                            value : hello
-                        }
-                    ]
-                    type : object
-                }
-                type : object
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : clear
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
                 type : string
                 value : console.clear
             }
@@ -2333,61 +930,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
-                className : Object
-                description : Object
-                objectId : <string>
-                preview : {
-                    description : Object
-                    overflow : false
-                    properties : [
-                        [0] : {
-                            name : a
-                            type : number
-                            value : 3
-                        }
-                        [1] : {
-                            name : b
-                            type : string
-                            value : hello
-                        }
-                    ]
-                    type : object
-                }
-                type : object
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : startGroup
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
                 type : string
                 value : console.group
             }
@@ -2415,61 +957,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
-                className : Object
-                description : Object
-                objectId : <string>
-                preview : {
-                    description : Object
-                    overflow : false
-                    properties : [
-                        [0] : {
-                            name : a
-                            type : number
-                            value : 3
-                        }
-                        [1] : {
-                            name : b
-                            type : string
-                            value : hello
-                        }
-                    ]
-                    type : object
-                }
-                type : object
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : startGroupCollapsed
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
                 type : string
                 value : console.groupCollapsed
             }
@@ -2497,61 +984,6 @@
     params : {
         args : [
             [0] : {
-                description : 10
-                type : number
-                value : 10
-            }
-            [1] : {
-                description : Infinity
-                type : number
-                unserializableValue : Infinity
-            }
-            [2] : {
-                className : Object
-                description : Object
-                objectId : <string>
-                preview : {
-                    description : Object
-                    overflow : false
-                    properties : [
-                        [0] : {
-                            name : a
-                            type : number
-                            value : 3
-                        }
-                        [1] : {
-                            name : b
-                            type : string
-                            value : hello
-                        }
-                    ]
-                    type : object
-                }
-                type : object
-            }
-        ]
-        executionContextId : <number>
-        stackTrace : {
-            callFrames : [
-                [0] : {
-                    columnNumber : 8
-                    functionName : 
-                    lineNumber : 0
-                    scriptId : <string>
-                    url : 
-                }
-            ]
-        }
-        timestamp : <number>
-        type : endGroup
-    }
-    sessionId : <string>
-}
-{
-    method : Runtime.consoleAPICalled
-    params : {
-        args : [
-            [0] : {
                 type : string
                 value : console.groupEnd
             }
diff --git a/third_party/blink/web_tests/inspector-protocol/runtime/runtime-console-basic-functions.js b/third_party/blink/web_tests/inspector-protocol/runtime/runtime-console-basic-functions.js
index f47ecd55..dfc6e60 100644
--- a/third_party/blink/web_tests/inspector-protocol/runtime/runtime-console-basic-functions.js
+++ b/third_party/blink/web_tests/inspector-protocol/runtime/runtime-console-basic-functions.js
@@ -28,43 +28,38 @@
     'groupEnd'
   ];
   const configs = [
-    undefined,
     pageContextId,
     frameContextId
   ];
 
   dp.Runtime.onConsoleAPICalled(result => testRunner.log(result));
 
-  for (const config of configs) {
-    for (const func of console_argsRequired)
-      await testConsoleFunctions(func, true, config);
+  for (const contextId of configs) {
+    for (const func of console_argsRequired) {
+      logConsoleTestMethod(func, true, contextId);
+      await dp.Runtime.evaluate({ expression: `console.${func}({a:3, b:"hello"})`, contextId });
+    }
 
-    for (const func of console_argsOptional)
-      await testConsoleFunctions(func, false, config);
+    for (const func of console_argsOptional) {
+      logConsoleTestMethod(func, false, contextId);
+      await dp.Runtime.evaluate({ expression: `console.${func}()`, contextId });
+    }
   }
 
   testRunner.completeTest();
 
-
-
-  async function testConsoleFunctions(func, required, contextId) {
-    logConsoleTestMethod(func, required, contextId);
-    await dp.Runtime.evaluate({ expression: `console.${func}(10, Infinity, {a:3, b:"hello"})`, contextId });
-    await dp.Runtime.evaluate({ expression: `console.${func}()`, contextId });
-  }
-
   function logConsoleTestMethod(func, required, contextId) {
     const context = getContextType(contextId);
     const contextString = context ? `inside ${context} context` : '';
-    const argType = required ? "required" : "optional";
+    const argType = required ? 'required' : 'optional';
     testRunner.log(`Testing console.${func} with ${argType} args ${contextString}`);
   }
 
   function getContextType(contextId) {
     if (contextId === pageContextId) {
-      return "page";
+      return 'page';
     } else if (contextId === frameContextId) {
-      return "frame";
+      return 'frame';
     }
   }
 });
\ No newline at end of file
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance-expected.txt
deleted file mode 100644
index f188544..0000000
--- a/third_party/blink/web_tests/platform/linux/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance-expected.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-This is a testharness.js-based test.
-PASS A step-start function on a keyframe affects the resulting style
-PASS A steps(1, start) function on a keyframe affects the resulting style
-PASS A steps(2, start) function on a keyframe affects the resulting style
-PASS A step-end function on a keyframe affects the resulting style
-PASS A steps(1) function on a keyframe affects the resulting style
-PASS A steps(1, end) function on a keyframe affects the resulting style
-PASS A steps(2, end) function on a keyframe affects the resulting style
-PASS A linear function on a keyframe affects the resulting style
-FAIL A ease function on a keyframe affects the resulting style assert_approx_equals: The width should be approximately 109.47963055884654 at 1100ms expected 109.47963055884654 +/- 0.01 but got 109.312
-PASS A ease-in function on a keyframe affects the resulting style
-FAIL A ease-in-out function on a keyframe affects the resulting style assert_approx_equals: The width should be approximately 101.97224534417684 at 1100ms expected 101.97224534417684 +/- 0.01 but got 101.953
-FAIL A ease-out function on a keyframe affects the resulting style assert_approx_equals: The width should be approximately 116.05721544376388 at 1100ms expected 116.05721544376388 +/- 0.01 but got 116.078
-FAIL A easing function which produces values greater than 1 on a keyframe affects the resulting style assert_approx_equals: The width should be approximately 171.60874310990272 at 1100ms expected 171.60874310990272 +/- 0.01 but got 172.219
-FAIL A easing function which produces values less than 1 on a keyframe affects the resulting style assert_approx_equals: The width should be approximately 77.13128857063907 at 1100ms expected 77.13128857063907 +/- 0.01 but got 76.9531
-PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a step-start function does not alter the result
-PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a steps(1, start) function does not alter the result
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a steps(2, start) function does not alter the result assert_equals: The 'width' of the animated elements should be equal at 0ms expected "50.3438px" but got "50px"
-PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a step-end function does not alter the result
-PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a steps(1) function does not alter the result
-PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a steps(1, end) function does not alter the result
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a steps(2, end) function does not alter the result assert_equals: The 'width' of the animated elements should be equal at 500ms expected "50.3438px" but got "50px"
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a linear function does not alter the result assert_equals: The 'width' of the animated elements should be equal at 250ms expected "25.0938px" but got "25px"
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a ease function does not alter the result assert_equals: The 'width' of the animated elements should be equal at 250ms expected "41.875px" but got "41.8594px"
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a ease-in function does not alter the result assert_equals: The 'width' of the animated elements should be equal at 250ms expected "8.95312px" but got "9.32812px"
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a ease-in-out function does not alter the result assert_equals: The 'width' of the animated elements should be equal at 250ms expected "12.9375px" but got "12.875px"
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a ease-out function does not alter the result assert_equals: The 'width' of the animated elements should be equal at 250ms expected "38.0469px" but got "37.9688px"
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a easing function which produces values greater than 1 does not alter the result assert_equals: The 'width' of the animated elements should be equal at 250ms expected "100px" but got "102.406px"
-PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a easing function which produces values less than 1 does not alter the result
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance-expected.txt
deleted file mode 100644
index f188544..0000000
--- a/third_party/blink/web_tests/platform/mac/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance-expected.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-This is a testharness.js-based test.
-PASS A step-start function on a keyframe affects the resulting style
-PASS A steps(1, start) function on a keyframe affects the resulting style
-PASS A steps(2, start) function on a keyframe affects the resulting style
-PASS A step-end function on a keyframe affects the resulting style
-PASS A steps(1) function on a keyframe affects the resulting style
-PASS A steps(1, end) function on a keyframe affects the resulting style
-PASS A steps(2, end) function on a keyframe affects the resulting style
-PASS A linear function on a keyframe affects the resulting style
-FAIL A ease function on a keyframe affects the resulting style assert_approx_equals: The width should be approximately 109.47963055884654 at 1100ms expected 109.47963055884654 +/- 0.01 but got 109.312
-PASS A ease-in function on a keyframe affects the resulting style
-FAIL A ease-in-out function on a keyframe affects the resulting style assert_approx_equals: The width should be approximately 101.97224534417684 at 1100ms expected 101.97224534417684 +/- 0.01 but got 101.953
-FAIL A ease-out function on a keyframe affects the resulting style assert_approx_equals: The width should be approximately 116.05721544376388 at 1100ms expected 116.05721544376388 +/- 0.01 but got 116.078
-FAIL A easing function which produces values greater than 1 on a keyframe affects the resulting style assert_approx_equals: The width should be approximately 171.60874310990272 at 1100ms expected 171.60874310990272 +/- 0.01 but got 172.219
-FAIL A easing function which produces values less than 1 on a keyframe affects the resulting style assert_approx_equals: The width should be approximately 77.13128857063907 at 1100ms expected 77.13128857063907 +/- 0.01 but got 76.9531
-PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a step-start function does not alter the result
-PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a steps(1, start) function does not alter the result
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a steps(2, start) function does not alter the result assert_equals: The 'width' of the animated elements should be equal at 0ms expected "50.3438px" but got "50px"
-PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a step-end function does not alter the result
-PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a steps(1) function does not alter the result
-PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a steps(1, end) function does not alter the result
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a steps(2, end) function does not alter the result assert_equals: The 'width' of the animated elements should be equal at 500ms expected "50.3438px" but got "50px"
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a linear function does not alter the result assert_equals: The 'width' of the animated elements should be equal at 250ms expected "25.0938px" but got "25px"
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a ease function does not alter the result assert_equals: The 'width' of the animated elements should be equal at 250ms expected "41.875px" but got "41.8594px"
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a ease-in function does not alter the result assert_equals: The 'width' of the animated elements should be equal at 250ms expected "8.95312px" but got "9.32812px"
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a ease-in-out function does not alter the result assert_equals: The 'width' of the animated elements should be equal at 250ms expected "12.9375px" but got "12.875px"
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a ease-out function does not alter the result assert_equals: The 'width' of the animated elements should be equal at 250ms expected "38.0469px" but got "37.9688px"
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a easing function which produces values greater than 1 does not alter the result assert_equals: The 'width' of the animated elements should be equal at 250ms expected "100px" but got "102.406px"
-PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a easing function which produces values less than 1 does not alter the result
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance-expected.txt
deleted file mode 100644
index ca92b67..0000000
--- a/third_party/blink/web_tests/platform/win/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance-expected.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-This is a testharness.js-based test.
-PASS A step-start function on a keyframe affects the resulting style
-PASS A steps(1, start) function on a keyframe affects the resulting style
-PASS A steps(2, start) function on a keyframe affects the resulting style
-PASS A step-end function on a keyframe affects the resulting style
-PASS A steps(1) function on a keyframe affects the resulting style
-PASS A steps(1, end) function on a keyframe affects the resulting style
-PASS A steps(2, end) function on a keyframe affects the resulting style
-PASS A linear function on a keyframe affects the resulting style
-FAIL A ease function on a keyframe affects the resulting style assert_approx_equals: The width should be approximately 109.47963055884654 at 1100ms expected 109.47963055884654 +/- 0.01 but got 109.313
-PASS A ease-in function on a keyframe affects the resulting style
-FAIL A ease-in-out function on a keyframe affects the resulting style assert_approx_equals: The width should be approximately 101.97224534417684 at 1100ms expected 101.97224534417684 +/- 0.01 but got 101.953
-FAIL A ease-out function on a keyframe affects the resulting style assert_approx_equals: The width should be approximately 116.05721544376388 at 1100ms expected 116.05721544376388 +/- 0.01 but got 116.078
-FAIL A easing function which produces values greater than 1 on a keyframe affects the resulting style assert_approx_equals: The width should be approximately 171.60874310990272 at 1100ms expected 171.60874310990272 +/- 0.01 but got 172.219
-FAIL A easing function which produces values less than 1 on a keyframe affects the resulting style assert_approx_equals: The width should be approximately 77.13128857063907 at 1100ms expected 77.13128857063907 +/- 0.01 but got 76.9531
-PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a step-start function does not alter the result
-PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a steps(1, start) function does not alter the result
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a steps(2, start) function does not alter the result assert_equals: The 'width' of the animated elements should be equal at 0ms expected "50.3438px" but got "50px"
-PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a step-end function does not alter the result
-PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a steps(1) function does not alter the result
-PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a steps(1, end) function does not alter the result
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a steps(2, end) function does not alter the result assert_equals: The 'width' of the animated elements should be equal at 500ms expected "50.3438px" but got "50px"
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a linear function does not alter the result assert_equals: The 'width' of the animated elements should be equal at 250ms expected "25.0938px" but got "25px"
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a ease function does not alter the result assert_equals: The 'width' of the animated elements should be equal at 250ms expected "41.875px" but got "41.8594px"
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a ease-in function does not alter the result assert_equals: The 'width' of the animated elements should be equal at 250ms expected "8.95313px" but got "9.32813px"
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a ease-in-out function does not alter the result assert_equals: The 'width' of the animated elements should be equal at 250ms expected "12.9375px" but got "12.875px"
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a ease-out function does not alter the result assert_equals: The 'width' of the animated elements should be equal at 250ms expected "38.0469px" but got "37.9688px"
-FAIL Linear-equivalent cubic-bezier keyframe easing applied to an effect with a easing function which produces values greater than 1 does not alter the result assert_equals: The 'width' of the animated elements should be equal at 250ms expected "100px" but got "102.406px"
-PASS Linear-equivalent cubic-bezier keyframe easing applied to an effect with a easing function which produces values less than 1 does not alter the result
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/transitions/cubic-bezier-overflow-length-expected.txt b/third_party/blink/web_tests/transitions/cubic-bezier-overflow-length-expected.txt
index 6934b6c..8d4204a3 100644
--- a/third_party/blink/web_tests/transitions/cubic-bezier-overflow-length-expected.txt
+++ b/third_party/blink/web_tests/transitions/cubic-bezier-overflow-length-expected.txt
@@ -1,11 +1,11 @@
 PASS - "left" property for "box2" element at 0.1s saw something close to: -55
-PASS - "left" property for "box3" element at 0.1s saw something close to: -106
+PASS - "left" property for "box3" element at 0.1s saw something close to: -110
 PASS - "left" property for "box4" element at 0.15s saw something close to: 513
-PASS - "left" property for "box1" element at 0.5s saw something close to: 488
+PASS - "left" property for "box1" element at 0.5s saw something close to: 489
 PASS - "left" property for "box2" element at 0.5s saw something close to: 145
-PASS - "left" property for "box3" element at 0.5s saw something close to: -441
+PASS - "left" property for "box3" element at 0.5s saw something close to: -443
 PASS - "left" property for "box4" element at 0.5s saw something close to: 200
 PASS - "left" property for "box4" element at 0.8s saw something close to: -98
-PASS - "left" property for "box1" element at 0.95s saw something close to: 440
-PASS - "left" property for "box2" element at 0.95s saw something close to: 432
+PASS - "left" property for "box1" element at 0.95s saw something close to: 442
+PASS - "left" property for "box2" element at 0.95s saw something close to: 435
 
diff --git a/third_party/blink/web_tests/transitions/cubic-bezier-overflow-length.html b/third_party/blink/web_tests/transitions/cubic-bezier-overflow-length.html
index b1c4c04..7cfe3b84 100644
--- a/third_party/blink/web_tests/transitions/cubic-bezier-overflow-length.html
+++ b/third_party/blink/web_tests/transitions/cubic-bezier-overflow-length.html
@@ -20,13 +20,13 @@
     <script>
       const expectedValues = [
         // [time, element-id, property, expected-value, tolerance]
-        [0.50, "box1", "left", 488, 4],
-        [0.95, "box1", "left", 440, 4],
+        [0.50, "box1", "left", 489, 4],
+        [0.95, "box1", "left", 442, 4],
         [0.10, "box2", "left", -55, 4],
         [0.50, "box2", "left", 145, 4],
-        [0.95, "box2", "left", 432, 4],
-        [0.10, "box3", "left", -106, 4],
-        [0.50, "box3", "left", -441, 4],
+        [0.95, "box2", "left", 435, 4],
+        [0.10, "box3", "left", -110, 4],
+        [0.50, "box3", "left", -443, 4],
         [0.15, "box4", "left", 513, 4],
         [0.50, "box4", "left", 200, 4],
         [0.80, "box4", "left", -98, 4],
@@ -48,4 +48,4 @@
     </div>
     <div id="result"></div>
   </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/transitions/opacity-transform-transitions-inside-iframe-expected.png b/third_party/blink/web_tests/transitions/opacity-transform-transitions-inside-iframe-expected.png
index a41878a..0cc6e8a0 100644
--- a/third_party/blink/web_tests/transitions/opacity-transform-transitions-inside-iframe-expected.png
+++ b/third_party/blink/web_tests/transitions/opacity-transform-transitions-inside-iframe-expected.png
Binary files differ
diff --git a/third_party/closure_compiler/externs/accessibility_private.js b/third_party/closure_compiler/externs/accessibility_private.js
index 4d56450..b1081c7 100644
--- a/third_party/closure_compiler/externs/accessibility_private.js
+++ b/third_party/closure_compiler/externs/accessibility_private.js
@@ -61,6 +61,13 @@
   TAP4: 'tap4',
 };
 
+/** @enum {string} */
+chrome.accessibilityPrivate.SwitchAccessCommand = {
+  SELECT: 'select',
+  NEXT: 'next',
+  PREVIOUS: 'previous'
+}
+
 /**
  * @enum {string}
  */
@@ -296,6 +303,13 @@
 chrome.accessibilityPrivate.onSelectToSpeakStateChangeRequested;
 
 /**
+ * Called when Chrome OS captures a key event that corresponds to a Switch
+ * Access command.
+ * @type {!ChromeEvent}
+ */
+chrome.accessibilityPrivate.onSwitchAccessCommand;
+
+/**
  * Called when an internal component within accessibility wants to force speech
  * output for an accessibility extension. Do not use without approval from
  * accessibility owners.
diff --git a/third_party/closure_compiler/externs/automation.js b/third_party/closure_compiler/externs/automation.js
index a7b9f8f..848c221 100644
--- a/third_party/closure_compiler/externs/automation.js
+++ b/third_party/closure_compiler/externs/automation.js
@@ -652,17 +652,18 @@
 chrome.automation.AutomationNode.prototype.wordEnds;
 
 /**
- * The start and end index of each word within the node's name. Different from wordStarts and wordEnds because they're not restricted to inline text boxes and can be used for any type of element.
+ * The start index of each word within the node's name. This is different from wordStarts because it is not restricted to inline text boxes and can be used for any type of element.
  * @type {(!Array<number>|undefined)}
- * @see https://developer.chrome.com/extensions/automation#type-wordStartOffsets
+ * @see https://developer.chrome.com/extensions/automation#type-nonInlineTextWordStarts
  */
-chrome.automation.AutomationNode.prototype.wordStartOffsets;
+chrome.automation.AutomationNode.prototype.nonInlineTextWordStarts;
 
 /**
+ * The end index of each word within the node's name. This is different from wordEnds because it is not restricted to inline text boxes and can be used for any type of element.
  * @type {(!Array<number>|undefined)}
- * @see https://developer.chrome.com/extensions/automation#type-wordEndOffsets
+ * @see https://developer.chrome.com/extensions/automation#type-nonInlineTextWordEnds
  */
-chrome.automation.AutomationNode.prototype.wordEndOffsets;
+chrome.automation.AutomationNode.prototype.nonInlineTextWordEnds;
 
 /**
  * The nodes, if any, which this node is specified to control via <a href="http://www.w3.org/TR/wai-aria/states_and_properties#aria-controls"> <code>aria-controls</code></a>.
diff --git a/third_party/closure_compiler/externs/bookmark_manager_private.js b/third_party/closure_compiler/externs/bookmark_manager_private.js
index eb74345..3089f776 100644
--- a/third_party/closure_compiler/externs/bookmark_manager_private.js
+++ b/third_party/closure_compiler/externs/bookmark_manager_private.js
@@ -74,8 +74,10 @@
  * @param {!Array<string>} idList An array of string-valued ids.
  * @param {number} dragNodeIndex The index of the dragged node in |idList|
  * @param {boolean} isFromTouch True if the drag was initiated from touch.
+ * @param {number} offsetX The offset X of the event
+ * @param {number} offsetY The offset Y of the event
  */
-chrome.bookmarkManagerPrivate.startDrag = function(idList, dragNodeIndex, isFromTouch) {};
+chrome.bookmarkManagerPrivate.startDrag = function(idList, dragNodeIndex, isFromTouch, offsetX, offsetY) {};
 
 /**
  * Performs the drop action of the drag and drop session.
diff --git a/tools/ipc_fuzzer/message_tools/message_list.cc b/tools/ipc_fuzzer/message_tools/message_list.cc
index df0f9acd..f94bd9bc 100644
--- a/tools/ipc_fuzzer/message_tools/message_list.cc
+++ b/tools/ipc_fuzzer/message_tools/message_list.cc
@@ -64,7 +64,6 @@
 
 
 #if !defined(OS_ANDROID)
-  exemptions.push_back(JavaBridgeMsgStart);
   exemptions.push_back(MediaPlayerMsgStart);
   exemptions.push_back(EncryptedMediaMsgStart);
   exemptions.push_back(GinJavaBridgeMsgStart);
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 5501a38b..5fc3cc1 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -18345,6 +18345,7 @@
   <int value="436" label="MIME_HANDLER_PRIVATE_SAVE"/>
   <int value="437" label="RUNTIME_ON_CONNECT_NATIVE"/>
   <int value="438" label="ACTION_ON_CLICKED"/>
+  <int value="439" label="ACCESSIBILITY_PRIVATE_ON_SWITCH_ACCESS_COMMAND"/>
 </enum>
 
 <enum name="ExtensionFileWriteResult">
@@ -23689,6 +23690,8 @@
   <int value="2925" label="V8CallSiteAPIGetThisSloppyCall"/>
   <int value="2926" label="BuiltInModuleToast"/>
   <int value="2927" label="LargestContentfulPaintExplicitlyRequested"/>
+  <int value="2928" label="PageLifecycleTransitionsOptIn"/>
+  <int value="2929" label="PageLifecycleTransitionsOptOut"/>
 </enum>
 
 <enum name="FeaturePolicyAllowlistType">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index e85bd7f9..a63b1fb 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -1824,9 +1824,11 @@
   </summary>
 </histogram>
 
-<histogram name="Android.DeviceSize.LargestDisplaySize" units="dp">
+<histogram name="Android.DeviceSize.LargestDisplaySize" units="dp"
+    expires_after="M83">
   <owner>twellington@chromium.org</owner>
   <owner>tedchoc@chromium.org</owner>
+  <owner>chrome-android-app@chromium.org</owner>
   <summary>
     Records the largest display dimension in dp during deferred startup. The
     display size is not affected by Android N multi-window mode. Clamped at
@@ -1835,9 +1837,10 @@
 </histogram>
 
 <histogram name="Android.DeviceSize.SmallestDisplaySize" units="dp"
-    expires_after="M77">
+    expires_after="M83">
   <owner>twellington@chromium.org</owner>
   <owner>tedchoc@chromium.org</owner>
+  <owner>chrome-android-app@chromium.org</owner>
   <summary>
     Records the smallest display dimension in dp during deferred startup. The
     display size is not affected by Android N multi-window mode. Clamped at 0 to
@@ -2239,7 +2242,10 @@
   </summary>
 </histogram>
 
-<histogram name="Android.HistoryPage.OpenSelected" expires_after="M77">
+<histogram name="Android.HistoryPage.OpenSelected">
+  <obsolete>
+    Deprecated 7/2019. No longer tracked.
+  </obsolete>
   <owner>twellington@chromium.org</owner>
   <summary>
     The number of selected items the user opened in new tabs from the native
@@ -2247,7 +2253,10 @@
   </summary>
 </histogram>
 
-<histogram name="Android.HistoryPage.RemoveSelected" expires_after="M78">
+<histogram name="Android.HistoryPage.RemoveSelected">
+  <obsolete>
+    Deprecated 7/2019. No longer tracked.
+  </obsolete>
   <owner>twellington@chromium.org</owner>
   <summary>
     The number of selected items the user removed from the native Android
@@ -3186,8 +3195,9 @@
 </histogram>
 
 <histogram name="Android.Survey.DownloadRequested" enum="BooleanRequested"
-    expires_after="M77">
+    expires_after="M84">
   <owner>twellington@chromium.org</owner>
+  <owner>chrome-android-app@chromium.org</owner>
   <summary>
     Recorded when a survey download is requested. If the client already has
     successfully downloaded a survey, 'not requested' is recorded.
@@ -3195,13 +3205,14 @@
 </histogram>
 
 <histogram name="Android.Survey.DownloadResponseCode"
-    enum="SurveyDownloadResponseCodes" expires_after="M77">
+    enum="SurveyDownloadResponseCodes" expires_after="M84">
   <owner>twellington@chromium.org</owner>
+  <owner>chrome-android-app@chromium.org</owner>
   <summary>The response code of the completed survey download request.</summary>
 </histogram>
 
 <histogram name="Android.Survey.InfoBarClosingState"
-    enum="InfoBarClosingStates" expires_after="M77">
+    enum="InfoBarClosingStates" expires_after="M84">
   <owner>twellington@chromium.org</owner>
   <summary>
     If the infobar was visible when it was closed and if it was closed directly
@@ -3210,16 +3221,18 @@
 </histogram>
 
 <histogram name="Android.Survey.ShowSurvey" enum="BooleanSuccess"
-    expires_after="M77">
+    expires_after="M84">
   <owner>twellington@chromium.org</owner>
+  <owner>chrome-android-app@chromium.org</owner>
   <summary>
     Whether or not the survey was successfully shown after its download.
   </summary>
 </histogram>
 
 <histogram name="Android.Survey.SurveyFilteringResults"
-    enum="SurveyFilteringResult" expires_after="M77">
+    enum="SurveyFilteringResult" expires_after="M84">
   <owner>twellington@chromium.org</owner>
+  <owner>chrome-android-app@chromium.org</owner>
   <summary>
     The result of the survey filtering process. Each enum represents a different
     filter that caught the user. This is recorded on cold starts when we check
@@ -19412,6 +19425,52 @@
   </summary>
 </histogram>
 
+<histogram name="CompositorLatency" units="microseconds"
+    expires_after="2020-08-31">
+  <owner>sadrul@chromium.org</owner>
+  <owner>graphics-dev@chromium.org</owner>
+  <summary>
+    Tracks the duration of stages in the pipeline while processing a single
+    frame on the multithread compositor, when the Main frame did not miss its
+    deadline.
+
+    A Main frame that missed its deadline is a frame such that
+    SubmitCompositorFrame happened before a commit and activation happened. E.g.
+    BeginImplFrame1 -&gt; BeginMainFrame1 -&gt; SubmitCompositorFrame -&gt;
+    BeginImplFrame2 -&gt; Commit1 -&gt; Activate1 -&gt; SubmitCompositorFrame
+  </summary>
+</histogram>
+
+<histogram name="CompositorLatency.MissedFrame" units="microseconds"
+    expires_after="2020-08-31">
+  <owner>sadrul@chromium.org</owner>
+  <owner>graphics-dev@chromium.org</owner>
+  <summary>
+    Tracks the duration of stages in the pipeline while processing a single
+    frame on the multithread compositor, when the Main frame missed its
+    deadline.
+
+    A Main frame that missed its deadline is a frame such that
+    SubmitCompositorFrame happened before a commit and activation happened. E.g.
+    BeginImplFrame1 -&gt; BeginMainFrame1 -&gt; SubmitCompositorFrame -&gt;
+    BeginImplFrame2 -&gt; Commit1 -&gt; Activate1 -&gt; SubmitCompositorFrame
+  </summary>
+</histogram>
+
+<histogram name="CompositorLatency.MissedFrame.LatencyIncrease"
+    units="microseconds" expires_after="2020-08-31">
+  <owner>sadrul@chromium.org</owner>
+  <owner>graphics-dev@chromium.org</owner>
+  <summary>
+    The latency increase of an abnormally long activation stage on the
+    multithread thread compositor pipeline when the frame is missed.
+
+    These latency increases are determined by comparing the stage duration to
+    the times from past non-missed frames. These times are also reported to
+    &quot;CompositorLatency.MissedFrame.&lt;StageName&gt;&quot;
+  </summary>
+</histogram>
+
 <histogram name="Conflicts.ConfirmedBadModules" units="modules"
     expires_after="2018-08-30">
   <owner>chrisha@chromium.org</owner>
@@ -45672,7 +45731,8 @@
   </summary>
 </histogram>
 
-<histogram name="GPU.Output.MaxLuminance" units="lumens" expires_after="M77">
+<histogram name="GPU.Output.MaxLuminance" units="lumens"
+    expires_after="2020-06-30">
   <owner>hubbe@chromium.org</owner>
   <owner>media-dev@chromium.org</owner>
   <summary>
@@ -45987,7 +46047,7 @@
 </histogram>
 
 <histogram name="GPU.TextureR16Ext_LuminanceF16" enum="GpuTextureResultR16_L16"
-    expires_after="M77">
+    expires_after="M79">
   <owner>hubbe@chromium.org</owner>
   <owner>rijubrata.bhaumik@intel.com</owner>
   <owner>media-dev@chromium.org</owner>
@@ -55190,7 +55250,7 @@
 </histogram>
 
 <histogram name="Media.DXVAVDA.UseD3D11" enum="DXVADXVersion"
-    expires_after="2019-06-30">
+    expires_after="2020-06-30">
   <owner>liberato@chromium.org</owner>
   <owner>tmathmeyer@chromium.org</owner>
   <owner>sandersd@chromium.org</owner>
@@ -55301,7 +55361,7 @@
 </histogram>
 
 <histogram name="Media.EME.EncryptedEvent" enum="BooleanEncryptedEvent"
-    expires_after="M77">
+    expires_after="M84">
   <owner>xhwang@chromium.org</owner>
   <summary>
     Whether EME encrypted event has been fired. Every time a WebMediaPlayerImpl
@@ -55998,7 +56058,7 @@
 </histogram>
 
 <histogram base="true" name="Media.Learning.BinaryThreshold.Aggregate"
-    enum="ConfusionMatrix" expires_after="2019-06-30">
+    enum="ConfusionMatrix" expires_after="2019-10-30">
 <!-- Name completed by histogram_suffixes
      name="Media.Learning.BinaryThreshold" -->
 
@@ -56020,7 +56080,7 @@
 </histogram>
 
 <histogram base="true" name="Media.Learning.BinaryThreshold.ByFeature"
-    enum="MegaConfusionMatrix" expires_after="2019-06-30">
+    enum="MegaConfusionMatrix" expires_after="2019-10-30">
 <!-- Name completed by histogram_suffixes
      name="Media.Learning.BinaryThreshold" -->
 
@@ -56045,7 +56105,7 @@
 </histogram>
 
 <histogram base="true" name="Media.Learning.BinaryThreshold.ByTrainingWeight"
-    enum="MegaConfusionMatrix" expires_after="2019-06-30">
+    enum="MegaConfusionMatrix" expires_after="2019-10-30">
 <!-- Name completed by histogram_suffixes
      name="Media.Learning.BinaryThreshold" -->
 
@@ -62059,6 +62119,17 @@
   <summary>Records Infobar Banner events.</summary>
 </histogram>
 
+<histogram name="Mobile.Messages.Banner.OnScreenTime" units="ms"
+    expires_after="2020-02-01">
+  <owner>sczs@chromium.org</owner>
+  <owner>thegreenfrog@google.com</owner>
+  <summary>
+    Records the time an Infobar (Messages) Banner is visible on screen. Used to
+    know how long it takes a user to act on the banner before it gets
+    auto-dismissed.
+  </summary>
+</histogram>
+
 <histogram base="true" name="Mobile.Messages.Modal.Event"
     enum="MobileMessagesModalEvent" expires_after="2020-02-01">
 <!-- Name completed by histogram_suffixes name="Mobile.Messages.Type" -->
@@ -66092,8 +66163,10 @@
 </histogram>
 
 <histogram name="Net.AlternativeProxyFailed" enum="NetErrorCodes"
-    expires_after="M77">
+    expires_after="M82">
   <owner>tbansal@chromium.org</owner>
+  <owner>rajendrant@chromium.org</owner>
+  <owner>robertogden@chromium.org</owner>
   <summary>
     Positive net error codes that failed alternative proxy requests end with.
     Recorded when an alternative job fails, whether or not the main job
@@ -71373,8 +71446,10 @@
 </histogram>
 
 <histogram name="Net.QuicAlternativeProxy.Usage"
-    enum="QuicAlternativeProxyUsage" expires_after="M77">
+    enum="QuicAlternativeProxyUsage" expires_after="M82">
   <owner>tbansal@chromium.org</owner>
+  <owner>rajendrant@chromium.org</owner>
+  <owner>robertogden@chromium.org</owner>
   <summary>
     Breakdown of how requests which could potentially make use of an alternative
     QUIC proxy server use or don't use the QUIC server.
@@ -122609,6 +122684,52 @@
   <summary>Number of retries until the final response was recorded.</summary>
 </histogram>
 
+<histogram name="SingleThreadedCompositorLatency" units="microseconds"
+    expires_after="2020-08-31">
+  <owner>sadrul@chromium.org</owner>
+  <owner>graphics-dev@chromium.org</owner>
+  <summary>
+    Tracks the duration of stages in the pipeline while processing a single
+    frame on the single thread compositor, where the Main frame did not miss its
+    deadline.
+
+    A Main frame that missed its deadline is a frame such that
+    SubmitCompositorFrame happened before a commit and activation happened. E.g.
+    BeginImplFrame1 -&gt; BeginMainFrame1 -&gt; SubmitCompositorFrame -&gt;
+    BeginImplFrame2 -&gt; Commit1 -&gt; Activate1 -&gt; SubmitCompositorFrame
+  </summary>
+</histogram>
+
+<histogram name="SingleThreadedCompositorLatency.MissedFrame"
+    units="microseconds" expires_after="2020-08-31">
+  <owner>sadrul@chromium.org</owner>
+  <owner>graphics-dev@chromium.org</owner>
+  <summary>
+    Tracks the duration of stages in the pipeline while processing a single
+    frame on the single thread compositor, where the Main frame missed its
+    deadline.
+
+    A Main frame that missed its deadline is a frame such that
+    SubmitCompositorFrame happened before a commit and activation happened. E.g.
+    BeginImplFrame1 -&gt; BeginMainFrame1 -&gt; SubmitCompositorFrame -&gt;
+    BeginImplFrame2 -&gt; Commit1 -&gt; Activate1 -&gt; SubmitCompositorFrame
+  </summary>
+</histogram>
+
+<histogram name="SingleThreadedCompositorLatency.MissedFrame.LatencyIncrease"
+    units="microseconds" expires_after="2020-08-31">
+  <owner>sadrul@chromium.org</owner>
+  <owner>graphics-dev@chromium.org</owner>
+  <summary>
+    The latency increase of an abnormally long activation stage on the single
+    thread compositor pipeline when the frame is missed.
+
+    These latency increases are determined by comparing the stage duration to
+    the times from past non-missed frames. These times are also reported to
+    &quot;SingleThreadedCompositorLatency.MissedFrame.&lt;StageName&gt;&quot;
+  </summary>
+</histogram>
+
 <histogram name="SingleWebsitePreferences.NavigatedFromToReset"
     enum="SettingsNavigationSources" expires_after="M78">
   <owner>pshmakov@chromium.org</owner>
@@ -150481,6 +150602,36 @@
   <affected-histogram name="CloudPrint.UrlFetcherUploadSize"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="CompositorLatencyStages" separator=".">
+  <suffix name="Activation" label="The duration of the activation stage."/>
+  <suffix name="BeginImplFrameToSendBeginMainFrame"
+      label="The time from when the Impl frame is started to when
+             BeginMainFrame is sent."/>
+  <suffix name="Commit" label="The duration of the commit stage."/>
+  <suffix name="EndActivateToSubmitCompositorFrame"
+      label="The time from when an activation is complete to the next
+             SubmitCompositorFrame."/>
+  <suffix name="EndCommitToActivation"
+      label="The time from when a commit is complete to the beginning of the
+             next activation."/>
+  <suffix name="SendBeginMainFrameToCommit"
+      label="The time from when the BeginMainFrame is sent to the beginning
+             of the commit."/>
+  <suffix name="TotalLatency"
+      label="The total time starting from BeginImplFrame to when
+             SubmitCompositorFrame is done with updates from the MainThread
+             (i.e. the time it takes for BeginImplFrame, BeginMainFrame,
+             Commit, Activate, and SubmitCompositorFrame)."/>
+  <suffix name="Unknown" label="The unknown stage"/>
+  <affected-histogram name="CompositorLatency"/>
+  <affected-histogram name="CompositorLatency.MissedFrame"/>
+  <affected-histogram name="CompositorLatency.MissedFrame.LatencyIncrease"/>
+  <affected-histogram name="SingleThreadedCompositorLatency"/>
+  <affected-histogram name="SingleThreadedCompositorLatency.MissedFrame"/>
+  <affected-histogram
+      name="SingleThreadedCompositorLatency.MissedFrame.LatencyIncrease"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="CompositorPendingTreeType" separator=".">
   <suffix name="Impl" label="Impl side invalidation initiated pending tree"/>
   <suffix name="Main" label="Commit initiated pending tree"/>
@@ -154939,16 +155090,9 @@
   <affected-histogram name="Memory.Coordinator.TotalPrivate"/>
 </histogram_suffixes>
 
-<histogram_suffixes name="MixedContentDownloadInitiator" separator=".">
-  <suffix base="true" name="InitiatorInsecure"/>
-  <suffix base="true" name="InitiatorSecure"/>
-  <suffix base="true" name="InitiatorUnknown"/>
-  <affected-histogram name="Download.InsecureBlocking.Extensions"/>
-</histogram_suffixes>
-
-<histogram_suffixes name="MixedContentDownloadInitiator" separator=".">
-  <suffix base="true" name="DownloadInsecure"/>
-  <suffix base="true" name="DownloadSecure"/>
+<histogram_suffixes name="MixedContentDownloadDownloadSecurity" separator=".">
+  <suffix name="DownloadInsecure"/>
+  <suffix name="DownloadSecure"/>
   <affected-histogram
       name="Download.InsecureBlocking.Extensions.InitiatorInsecure"/>
   <affected-histogram
@@ -154957,6 +155101,13 @@
       name="Download.InsecureBlocking.Extensions.InitiatorUnknown"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="MixedContentDownloadInitiatorSecurity" separator=".">
+  <suffix base="true" name="InitiatorInsecure"/>
+  <suffix base="true" name="InitiatorSecure"/>
+  <suffix base="true" name="InitiatorUnknown"/>
+  <affected-histogram name="Download.InsecureBlocking.Extensions"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="Mobile.DefaultBrowser.SystemDefaultBrowser.Type"
     separator=".">
   <suffix name="ChromeNotSystem"
diff --git a/ui/base/x/x11_util.cc b/ui/base/x/x11_util.cc
index 11f9ce2..151525f4 100644
--- a/ui/base/x/x11_util.cc
+++ b/ui/base/x/x11_util.cc
@@ -1499,19 +1499,20 @@
   VisualID visual_id = use_argb && transparent_visual_id_
                            ? transparent_visual_id_
                            : system_visual_id_;
-  XVisualData& visual_data = *visuals_[visual_id];
-  const XVisualInfo& visual_info = visual_data.visual_info;
 
-  bool is_default_visual = visual_id == default_visual_id_;
+  bool success =
+      GetVisualInfoImpl(visual_id, visual, depth, colormap, using_argb_visual);
+  DCHECK(success);
+}
 
-  if (visual)
-    *visual = visual_info.visual;
-  if (depth)
-    *depth = visual_info.depth;
-  if (colormap)
-    *colormap = is_default_visual ? CopyFromParent : visual_data.GetColormap();
-  if (using_argb_visual)
-    *using_argb_visual = use_argb;
+bool XVisualManager::GetVisualInfo(VisualID visual_id,
+                                   Visual** visual,
+                                   int* depth,
+                                   Colormap* colormap,
+                                   bool* using_argb_visual) {
+  base::AutoLock lock(lock_);
+  return GetVisualInfoImpl(visual_id, visual, depth, colormap,
+                           using_argb_visual);
 }
 
 bool XVisualManager::OnGPUInfoChanged(bool software_rendering,
@@ -1538,6 +1539,30 @@
          (using_software_rendering_ || have_gpu_argb_visual_);
 }
 
+bool XVisualManager::GetVisualInfoImpl(VisualID visual_id,
+                                       Visual** visual,
+                                       int* depth,
+                                       Colormap* colormap,
+                                       bool* using_argb_visual) {
+  auto it = visuals_.find(visual_id);
+  if (it == visuals_.end())
+    return false;
+  XVisualData& visual_data = *it->second;
+  const XVisualInfo& visual_info = visual_data.visual_info;
+
+  bool is_default_visual = visual_id == default_visual_id_;
+
+  if (visual)
+    *visual = visual_info.visual;
+  if (depth)
+    *depth = visual_info.depth;
+  if (colormap)
+    *colormap = is_default_visual ? CopyFromParent : visual_data.GetColormap();
+  if (using_argb_visual)
+    *using_argb_visual = visual_id == transparent_visual_id_;
+  return true;
+}
+
 XVisualManager::XVisualData::XVisualData(XVisualInfo visual_info)
     : visual_info(visual_info), colormap_(CopyFromParent) {}
 
diff --git a/ui/base/x/x11_util_internal.h b/ui/base/x/x11_util_internal.h
index e26d3afa..0b74133 100644
--- a/ui/base/x/x11_util_internal.h
+++ b/ui/base/x/x11_util_internal.h
@@ -61,7 +61,13 @@
                              Visual** visual,
                              int* depth,
                              Colormap* colormap,
-                             bool* using_argb_visual);
+                             bool* visual_is_argb);
+
+  bool GetVisualInfo(VisualID visual_id,
+                     Visual** visual,
+                     int* depth,
+                     Colormap* colormap,
+                     bool* visual_is_argb);
 
   // Called by GpuDataManagerImplPrivate when GPUInfo becomes available.  It is
   // necessary for the GPU process to find out which visuals are best for GL
@@ -94,6 +100,12 @@
 
   XVisualManager();
 
+  bool GetVisualInfoImpl(VisualID visual_id,
+                         Visual** visual,
+                         int* depth,
+                         Colormap* colormap,
+                         bool* visual_is_argb);
+
   mutable base::Lock lock_;
 
   std::unordered_map<VisualID, std::unique_ptr<XVisualData>> visuals_;
diff --git a/ui/events/BUILD.gn b/ui/events/BUILD.gn
index 90feab1..cebbd52 100644
--- a/ui/events/BUILD.gn
+++ b/ui/events/BUILD.gn
@@ -206,7 +206,6 @@
     "keyboard_hook.h",
     "null_event_targeter.h",
     "scoped_target_handler.h",
-    "system_input_injector.h",
     "win/events_win_utils.h",
     "win/system_event_state_lookup.h",
   ]
@@ -236,7 +235,6 @@
     "mac/keyboard_hook_mac.mm",
     "null_event_targeter.cc",
     "scoped_target_handler.cc",
-    "system_input_injector.cc",
     "win/events_win.cc",
     "win/events_win_utils.cc",
     "win/keyboard_hook_win_base.cc",
diff --git a/ui/events/ozone/evdev/event_factory_evdev.h b/ui/events/ozone/evdev/event_factory_evdev.h
index 78eb09610..22c3f9fe 100644
--- a/ui/events/ozone/evdev/event_factory_evdev.h
+++ b/ui/events/ozone/evdev/event_factory_evdev.h
@@ -21,9 +21,9 @@
 #include "ui/events/ozone/evdev/mouse_button_map_evdev.h"
 #include "ui/events/ozone/gamepad/gamepad_event.h"
 #include "ui/events/platform/platform_event_source.h"
-#include "ui/events/system_input_injector.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gfx/sequential_id_generator.h"
+#include "ui/ozone/public/system_input_injector.h"
 
 namespace gfx {
 class PointF;
diff --git a/ui/events/ozone/evdev/input_injector_evdev.h b/ui/events/ozone/evdev/input_injector_evdev.h
index 8d35b30..eeda613b 100644
--- a/ui/events/ozone/evdev/input_injector_evdev.h
+++ b/ui/events/ozone/evdev/input_injector_evdev.h
@@ -8,7 +8,7 @@
 #include "base/macros.h"
 #include "ui/events/ozone/evdev/event_dispatch_callback.h"
 #include "ui/events/ozone/evdev/events_ozone_evdev_export.h"
-#include "ui/events/system_input_injector.h"
+#include "ui/ozone/public/system_input_injector.h"
 
 namespace ui {
 
diff --git a/ui/events/system_input_injector.cc b/ui/events/system_input_injector.cc
deleted file mode 100644
index bbeb84d..0000000
--- a/ui/events/system_input_injector.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/events/system_input_injector.h"
-
-
-namespace ui {
-
-namespace {
-SystemInputInjectorFactory* override_factory_ = nullptr;
-}  // namespace
-
-void SetSystemInputInjectorFactory(SystemInputInjectorFactory* factory) {
-  DCHECK(!factory || !override_factory_);
-  override_factory_ = factory;
-}
-
-SystemInputInjectorFactory* GetSystemInputInjectorFactory() {
-  return override_factory_;
-}
-
-}  // namespace ui
diff --git a/ui/gfx/geometry/cubic_bezier.cc b/ui/gfx/geometry/cubic_bezier.cc
index e42d893d7..b9d21b8 100644
--- a/ui/gfx/geometry/cubic_bezier.cc
+++ b/ui/gfx/geometry/cubic_bezier.cc
@@ -11,12 +11,19 @@
 
 namespace gfx {
 
+namespace {
+
+const int kMaxNewtonIterations = 4;
+
+}  // namespace
+
 static const double kBezierEpsilon = 1e-7;
 
 CubicBezier::CubicBezier(double p1x, double p1y, double p2x, double p2y) {
   InitCoefficients(p1x, p1y, p2x, p2y);
   InitGradients(p1x, p1y, p2x, p2y);
   InitRange(p1y, p2y);
+  InitSpline();
 }
 
 CubicBezier::CubicBezier(const CubicBezier& other) = default;
@@ -34,6 +41,13 @@
   cy_ = 3.0 * p1y;
   by_ = 3.0 * (p2y - p1y) - cy_;
   ay_ = 1.0 - cy_ - by_;
+
+#ifndef NDEBUG
+  // Bezier curves with x-coordinates outside the range [0,1] for internal
+  // control points may have multiple values for t for a given value of x.
+  // In this case, calls to SolveCurveX may produce ambiguous results.
+  monotonically_increasing_ = p1x >= 0 && p1x <= 1 && p2x >= 0 && p2x <= 1;
+#endif
 }
 
 void CubicBezier::InitGradients(double p1x,
@@ -132,6 +146,13 @@
   range_max_ = std::max(std::max(range_max_, sol1), sol2);
 }
 
+void CubicBezier::InitSpline() {
+  double delta_t = 1.0 / (CUBIC_BEZIER_SPLINE_SAMPLES - 1);
+  for (int i = 0; i < CUBIC_BEZIER_SPLINE_SAMPLES; i++) {
+    spline_samples_[i] = SampleCurveX(i * delta_t);
+  }
+}
+
 double CubicBezier::GetDefaultEpsilon() {
   return kBezierEpsilon;
 }
@@ -142,27 +163,43 @@
 
   double t0;
   double t1;
-  double t2;
+  double t2 = x;
   double x2;
   double d2;
   int i;
 
-  // First try a few iterations of Newton's method -- normally very fast.
-  for (t2 = x, i = 0; i < 8; i++) {
+#ifndef NDEBUG
+  DCHECK(monotonically_increasing_);
+#endif
+
+  // Linear interpolation of spline curve for initial guess.
+  double delta_t = 1.0 / (CUBIC_BEZIER_SPLINE_SAMPLES - 1);
+  for (i = 1; i < CUBIC_BEZIER_SPLINE_SAMPLES; i++) {
+    if (x <= spline_samples_[i]) {
+      t1 = delta_t * i;
+      t0 = t1 - delta_t;
+      t2 = t0 + (t1 - t0) * (x - spline_samples_[i - 1]) /
+                    (spline_samples_[i] - spline_samples_[i - 1]);
+      break;
+    }
+  }
+
+  // Perform a few iterations of Newton's method -- normally very fast.
+  // See https://en.wikipedia.org/wiki/Newton%27s_method.
+  double newton_epsilon = std::min(kBezierEpsilon, epsilon);
+  for (i = 0; i < kMaxNewtonIterations; i++) {
     x2 = SampleCurveX(t2) - x;
-    if (fabs(x2) < epsilon)
+    if (fabs(x2) < newton_epsilon)
       return t2;
     d2 = SampleCurveDerivativeX(t2);
-    if (fabs(d2) < 1e-6)
+    if (fabs(d2) < kBezierEpsilon)
       break;
     t2 = t2 - x2 / d2;
   }
+  if (fabs(x2) < epsilon)
+    return t2;
 
   // Fall back to the bisection method for reliability.
-  t0 = 0.0;
-  t1 = 1.0;
-  t2 = x;
-
   while (t0 < t1) {
     x2 = SampleCurveX(t2);
     if (fabs(x2 - x) < epsilon)
@@ -171,7 +208,7 @@
       t0 = t2;
     else
       t1 = t2;
-    t2 = (t1 - t0) * .5 + t0;
+    t2 = (t1 + t0) * .5;
   }
 
   // Failure.
diff --git a/ui/gfx/geometry/cubic_bezier.h b/ui/gfx/geometry/cubic_bezier.h
index dcda5798..7b82c94 100644
--- a/ui/gfx/geometry/cubic_bezier.h
+++ b/ui/gfx/geometry/cubic_bezier.h
@@ -10,6 +10,8 @@
 
 namespace gfx {
 
+#define CUBIC_BEZIER_SPLINE_SAMPLES 11
+
 class GEOMETRY_EXPORT CubicBezier {
  public:
   CubicBezier(double p1x, double p1y, double p2x, double p2y);
@@ -73,6 +75,7 @@
   void InitCoefficients(double p1x, double p1y, double p2x, double p2y);
   void InitGradients(double p1x, double p1y, double p2x, double p2y);
   void InitRange(double p1y, double p2y);
+  void InitSpline();
 
   double ax_;
   double bx_;
@@ -88,6 +91,14 @@
   double range_min_;
   double range_max_;
 
+  double spline_samples_[CUBIC_BEZIER_SPLINE_SAMPLES];
+
+#ifndef NDEBUG
+  // Guard against attempted to solve for t given x in the event that the curve
+  // may have multiple values for t for some values of x in [0, 1].
+  bool monotonically_increasing_;
+#endif
+
   DISALLOW_ASSIGN(CubicBezier);
 };
 
diff --git a/ui/gfx/geometry/cubic_bezier_unittest.cc b/ui/gfx/geometry/cubic_bezier_unittest.cc
index 74ccb6d..f3f4686 100644
--- a/ui/gfx/geometry/cubic_bezier_unittest.cc
+++ b/ui/gfx/geometry/cubic_bezier_unittest.cc
@@ -226,5 +226,34 @@
   EXPECT_NEAR(-1.6, cubic_oor.GetY2(), epsilon);
 }
 
+void validateSolver(const CubicBezier& cubic_bezier) {
+  const double epsilon = 1e-7;
+  const double precision = 1e-5;
+  for (double t = 0; t <= 1; t += 0.05) {
+    double x = cubic_bezier.SampleCurveX(t);
+    double root = cubic_bezier.SolveCurveX(x, epsilon);
+    EXPECT_NEAR(t, root, precision);
+  }
+}
+
+TEST(CubicBezierTest, CommonEasingFunctions) {
+  validateSolver(CubicBezier(0.25, 0.1, 0.25, 1));  // ease
+  validateSolver(CubicBezier(0.42, 0, 1, 1));       // ease-in
+  validateSolver(CubicBezier(0, 0, 0.58, 1));       // ease-out
+  validateSolver(CubicBezier(0.42, 0, 0.58, 1));    // ease-in-out
+}
+
+TEST(CubicBezierTest, LinearEquivalentBeziers) {
+  validateSolver(CubicBezier(0.0, 0.0, 0.0, 0.0));
+  validateSolver(CubicBezier(1.0, 1.0, 1.0, 1.0));
+}
+
+TEST(CubicBezierTest, ControlPointsOutsideUnitSquare) {
+  validateSolver(CubicBezier(0.3, 1.5, 0.8, 1.5));
+  validateSolver(CubicBezier(0.4, -0.8, 0.7, 1.7));
+  validateSolver(CubicBezier(0.7, -2.0, 1.0, -1.5));
+  validateSolver(CubicBezier(0, 4, 1, -3));
+}
+
 }  // namespace
 }  // namespace gfx
diff --git a/ui/gfx/platform_font_skia.cc b/ui/gfx/platform_font_skia.cc
index 307af4b7..da9a78d 100644
--- a/ui/gfx/platform_font_skia.cc
+++ b/ui/gfx/platform_font_skia.cc
@@ -339,17 +339,17 @@
     } else {
       // Some Skia fonts manager do not compute the average character size
       // (e.g. Direct Write). The following code computes the average character
-      // width the same way blink (e.g. PlatformFont) does. Use the width of the
-      // letter 'x' when available, otherwise use the max character width.
+      // width the same way Blink (e.g. SimpleFontData) does. Use the width of
+      // the letter 'x' when available, otherwise use the max character width.
       SkGlyphID glyph = typeface_->unicharToGlyph('x');
       if (glyph != kUnsupportedGlyph) {
         SkScalar sk_width;
         font.getWidths(&glyph, 1, &sk_width);
-        average_width_pixels_ = SkScalarCeilToInt(sk_width);
+        average_width_pixels_ = SkScalarToDouble(sk_width);
       }
       if (!average_width_pixels_) {
         if (metrics.fMaxCharWidth) {
-          average_width_pixels_ = SkScalarCeilToInt(metrics.fMaxCharWidth);
+          average_width_pixels_ = SkScalarToDouble(metrics.fMaxCharWidth);
         } else {
           // Older version of the DirectWrite API doesn't implement support for
           // max char width. Fall back on a multiple of the ascent. This is
diff --git a/ui/gfx/x/x11_atom_cache.cc b/ui/gfx/x/x11_atom_cache.cc
index 2c87436..9cd921e 100644
--- a/ui/gfx/x/x11_atom_cache.cc
+++ b/ui/gfx/x/x11_atom_cache.cc
@@ -180,6 +180,9 @@
     "_NET_FRAME_EXTENTS",
     "_NET_SUPPORTED",
     "_NET_SUPPORTING_WM_CHECK",
+    "_NET_SYSTEM_TRAY_OPCODE",
+    "_NET_SYSTEM_TRAY_S0",
+    "_NET_SYSTEM_TRAY_VISUAL",
     "_NET_WM_BYPASS_COMPOSITOR",
     "_NET_WM_CM_S0",
     "_NET_WM_DESKTOP",
@@ -210,6 +213,7 @@
     "_NET_WORKAREA",
     "_SCREENSAVER_STATUS",
     "_SCREENSAVER_VERSION",
+    "_XEMBED_INFO",
     "application/octet-stream",
     "application/vnd.chromium.test",
     "chromium/filename",
diff --git a/ui/native_theme/common_theme.cc b/ui/native_theme/common_theme.cc
index e7f06ef..4893693 100644
--- a/ui/native_theme/common_theme.cc
+++ b/ui/native_theme/common_theme.cc
@@ -42,37 +42,96 @@
 
   if (base_theme->SystemDarkModeEnabled()) {
     switch (color_id) {
-      case NativeTheme::kColorId_LabelEnabledColor:
-      case NativeTheme::kColorId_TextfieldDefaultColor:
-      case NativeTheme::kColorId_EnabledMenuItemForegroundColor:
-      case NativeTheme::kColorId_SelectedMenuItemForegroundColor:
-      case NativeTheme::kColorId_HighlightedMenuItemForegroundColor:
-        return gfx::kGoogleGrey200;
-      case NativeTheme::kColorId_UnfocusedBorderColor:
-        return SK_ColorTRANSPARENT;
-      case NativeTheme::kColorId_ButtonEnabledColor:
-      case NativeTheme::kColorId_ButtonHoverColor:
-        return gfx::kGoogleGrey200;
-      case NativeTheme::kColorId_FocusedMenuItemBackgroundColor:
-      case NativeTheme::kColorId_FocusedHighlightedMenuItemBackgroundColor:
-        return SkColorSetA(SK_ColorWHITE, 0x20);
-      case NativeTheme::kColorId_MenuBackgroundColor:
-      case NativeTheme::kColorId_BubbleBackground:
+      // Dialogs
+      case NativeTheme::kColorId_WindowBackground:
       case NativeTheme::kColorId_DialogBackground:
+      case NativeTheme::kColorId_BubbleBackground:
         return color_utils::AlphaBlend(SK_ColorWHITE, gfx::kGoogleGrey900,
                                        0.04f);
       case NativeTheme::kColorId_BubbleFooterBackground:
         return SkColorSetRGB(0x32, 0x36, 0x39);
+
+      // FocusableBorder
+      case NativeTheme::kColorId_FocusedBorderColor:
+        return SkColorSetA(gfx::kGoogleBlue300, 0x66);
+      case NativeTheme::kColorId_UnfocusedBorderColor:
+        return SK_ColorTRANSPARENT;
+
+      // Button
+      case NativeTheme::kColorId_ButtonEnabledColor:
+      case NativeTheme::kColorId_ButtonHoverColor:
+        return gfx::kGoogleGrey200;
       case NativeTheme::kColorId_ProminentButtonColor:
         return gfx::kGoogleBlue300;
-      case NativeTheme::kColorId_TextOnProminentButtonColor:
-        return gfx::kGoogleGrey900;
       case NativeTheme::kColorId_ProminentButtonDisabledColor:
         return gfx::kGoogleGrey800;
+      case NativeTheme::kColorId_TextOnProminentButtonColor:
+        return gfx::kGoogleGrey900;
       case NativeTheme::kColorId_ButtonBorderColor:
         return gfx::kGoogleGrey700;
-      case NativeTheme::kColorId_TextfieldSelectionColor:
+
+      // MenuItem
+      case NativeTheme::kColorId_EnabledMenuItemForegroundColor:
+      case NativeTheme::kColorId_SelectedMenuItemForegroundColor:
+      case NativeTheme::kColorId_HighlightedMenuItemForegroundColor:
+        return gfx::kGoogleGrey200;
+      case NativeTheme::kColorId_FocusedMenuItemBackgroundColor:
+      case NativeTheme::kColorId_FocusedHighlightedMenuItemBackgroundColor:
+        return SkColorSetA(SK_ColorWHITE, 0x20);
+      case NativeTheme::kColorId_MenuSeparatorColor:
+        return SkColorSetA(gfx::kGoogleGrey800, 0xCC);
+      case NativeTheme::kColorId_MenuBackgroundColor:
+        return color_utils::AlphaBlend(SK_ColorWHITE, gfx::kGoogleGrey900,
+                                       0.04f);
+      case NativeTheme::kColorId_HighlightedMenuItemBackgroundColor:
+        return SkColorSetRGB(0x32, 0x36, 0x39);
+      case NativeTheme::kColorId_MenuItemAlertBackgroundColorMax:
+        return SkColorSetA(gfx::kGoogleGrey100, 0x1A);
+      case NativeTheme::kColorId_MenuItemAlertBackgroundColorMin:
+        return SkColorSetA(gfx::kGoogleGrey100, 0x4D);
+
+      // Label
+      case NativeTheme::kColorId_LabelEnabledColor:
+        return gfx::kGoogleGrey200;
       case NativeTheme::kColorId_LabelTextSelectionColor:
+        return color_utils::AlphaBlend(
+            SK_ColorWHITE,
+            GetAuraColor(
+                NativeTheme::kColorId_LabelTextSelectionBackgroundFocused,
+                base_theme),
+            SkAlpha{0xDD});
+      case NativeTheme::kColorId_LabelTextSelectionBackgroundFocused:
+        return SkColorSetA(gfx::kGoogleBlue700, 0xCC);
+
+      // Link
+      case NativeTheme::kColorId_LinkEnabled:
+      case NativeTheme::kColorId_LinkPressed:
+        return gfx::kGoogleBlue300;
+
+      // Separator
+      case NativeTheme::kColorId_SeparatorColor:
+        return SkColorSetA(gfx::kGoogleGrey800, 0xCC);
+
+      // Textfield
+      case NativeTheme::kColorId_TextfieldDefaultColor:
+        return gfx::kGoogleGrey200;
+      case NativeTheme::kColorId_TextfieldDefaultBackground:
+        return SkColorSetA(SK_ColorBLACK, 0x4D);
+      case NativeTheme::kColorId_TextfieldSelectionColor:
+        return color_utils::AlphaBlend(
+            SK_ColorWHITE,
+            GetAuraColor(
+                NativeTheme::kColorId_LabelTextSelectionBackgroundFocused,
+                base_theme),
+            SkAlpha{0xDD});
+      case NativeTheme::kColorId_TextfieldSelectionBackgroundFocused:
+        return SkColorSetA(gfx::kGoogleBlue700, 0xCC);
+
+      // Tree
+      case NativeTheme::kColorId_TreeBackground:
+        return gfx::kGoogleGrey800;
+      case NativeTheme::kColorId_TreeText:
+        return SkColorSetA(SK_ColorWHITE, 0xDD);
       case NativeTheme::kColorId_TreeSelectionBackgroundFocused:
       case NativeTheme::kColorId_TreeSelectionBackgroundUnfocused:
         return color_utils::AlphaBlend(
@@ -81,32 +140,19 @@
                 NativeTheme::kColorId_LabelTextSelectionBackgroundFocused,
                 base_theme),
             SkAlpha{0xDD});
-      case NativeTheme::kColorId_MenuSeparatorColor:
-      case NativeTheme::kColorId_SeparatorColor:
-        return SkColorSetA(gfx::kGoogleGrey800, 0xCC);
-      case NativeTheme::kColorId_TextfieldDefaultBackground:
-        return SkColorSetA(SK_ColorBLACK, 0x4D);
-      case NativeTheme::kColorId_LinkEnabled:
-      case NativeTheme::kColorId_LinkPressed:
+
+      // Material spinner/throbber
+      case NativeTheme::kColorId_ThrobberSpinningColor:
         return gfx::kGoogleBlue300;
-      case NativeTheme::kColorId_HighlightedMenuItemBackgroundColor:
-        return SkColorSetRGB(0x32, 0x36, 0x39);
-      case NativeTheme::kColorId_MenuItemAlertBackgroundColorMax:
-        return SkColorSetA(gfx::kGoogleGrey100, 0x1A);
-      case NativeTheme::kColorId_MenuItemAlertBackgroundColorMin:
-        return SkColorSetA(gfx::kGoogleGrey100, 0x4D);
-      case NativeTheme::kColorId_TreeBackground:
-        return gfx::kGoogleGrey800;
-      case NativeTheme::kColorId_TreeText:
-        return SkColorSetA(SK_ColorWHITE, 0xDD);
+
+      // Alert icon colors
       case NativeTheme::kColorId_AlertSeverityLow:
         return gfx::kGoogleGreen300;
       case NativeTheme::kColorId_AlertSeverityMedium:
         return gfx::kGoogleYellow300;
       case NativeTheme::kColorId_AlertSeverityHigh:
         return gfx::kGoogleRed300;
-      case NativeTheme::kColorId_ThrobberSpinningColor:
-        return gfx::kGoogleBlue300;
+
       case NativeTheme::kColorId_DefaultIconColor:
         return gfx::kGoogleGrey500;
       default:
diff --git a/ui/native_theme/native_theme_dark_aura.cc b/ui/native_theme/native_theme_dark_aura.cc
index bccba2f2..10b06b8 100644
--- a/ui/native_theme/native_theme_dark_aura.cc
+++ b/ui/native_theme/native_theme_dark_aura.cc
@@ -5,6 +5,7 @@
 #include "ui/native_theme/native_theme_dark_aura.h"
 
 #include "ui/gfx/color_palette.h"
+#include "ui/native_theme/common_theme.h"
 
 namespace ui {
 
@@ -14,120 +15,11 @@
 }
 
 SkColor NativeThemeDarkAura::GetSystemColor(ColorId color_id) const {
-  constexpr SkColor kTextSelectionBackgroundFocused =
-      SkColorSetA(gfx::kGoogleBlue700, 0xCC);
+  return GetAuraColor(color_id, this);
+}
 
-  switch (color_id) {
-    // Window
-    case kColorId_WindowBackground:
-    case kColorId_DialogBackground:
-    case kColorId_BubbleBackground:
-    case kColorId_BubbleFooterBackground:
-      return SK_ColorBLACK;
-
-    // Button
-    case kColorId_ButtonEnabledColor:
-      return gfx::kGoogleGrey200;
-    case kColorId_ProminentButtonFocusedColor:
-      return gfx::kGoogleBlue400;
-    case kColorId_ProminentButtonColor:
-      return gfx::kGoogleBlue300;
-
-    // Label
-    case kColorId_LabelEnabledColor:
-    case kColorId_LabelTextSelectionColor:
-      return SK_ColorWHITE;
-    case kColorId_LabelTextSelectionBackgroundFocused:
-      return kTextSelectionBackgroundFocused;
-
-    // Link
-    case kColorId_LinkEnabled:
-    case kColorId_LinkPressed:
-      return gfx::kGoogleBlue300;
-
-    // Textfield
-    case kColorId_TextfieldDefaultColor:
-    case kColorId_TextfieldSelectionColor:
-      return SK_ColorWHITE;
-    case kColorId_TextfieldDefaultBackground:
-      return SkColorSetRGB(0x62, 0x62, 0x62);
-    case kColorId_TextfieldSelectionBackgroundFocused:
-      return kTextSelectionBackgroundFocused;
-
-    // FocusableBorder
-    case kColorId_FocusedBorderColor:
-      return SkColorSetA(gfx::kGoogleBlue300, 0x66);
-
-    // Alert icons
-    case kColorId_AlertSeverityLow:
-      return gfx::kGoogleGreen300;
-    case kColorId_AlertSeverityMedium:
-      return gfx::kGoogleYellow300;
-    case kColorId_AlertSeverityHigh:
-      return gfx::kGoogleRed300;
-
-    // Intentional pass-throughs to NativeThemeAura.
-    case kColorId_LabelDisabledColor:
-    case kColorId_TextOnProminentButtonColor:
-    case kColorId_ButtonPressedShade:
-    case kColorId_ProminentButtonDisabledColor:
-    case kColorId_ButtonBorderColor:
-    case kColorId_DefaultIconColor:
-      return NativeThemeAura::GetSystemColor(color_id);
-
-    // Any other color is not defined and shouldn't be used in a dark theme.
-    case kColorId_UnfocusedBorderColor:
-    case kColorId_ButtonDisabledColor:
-    case kColorId_ButtonHoverColor:
-    case kColorId_EnabledMenuItemForegroundColor:
-    case kColorId_DisabledMenuItemForegroundColor:
-    case kColorId_SelectedMenuItemForegroundColor:
-    case kColorId_FocusedMenuItemBackgroundColor:
-    case kColorId_TouchableMenuItemLabelColor:
-    case kColorId_ActionableSubmenuVerticalSeparatorColor:
-    case kColorId_MenuItemMinorTextColor:
-    case kColorId_MenuSeparatorColor:
-    case kColorId_MenuBackgroundColor:
-    case kColorId_MenuBorderColor:
-    case kColorId_HighlightedMenuItemBackgroundColor:
-    case kColorId_HighlightedMenuItemForegroundColor:
-    case kColorId_FocusedHighlightedMenuItemBackgroundColor:
-    case kColorId_MenuItemAlertBackgroundColorMax:
-    case kColorId_MenuItemAlertBackgroundColorMin:
-    case kColorId_LinkDisabled:
-    case kColorId_TabBottomBorder:
-    case kColorId_TabTitleColorActive:
-    case kColorId_TabTitleColorInactive:
-    case kColorId_TextfieldReadOnlyColor:
-    case kColorId_TextfieldReadOnlyBackground:
-    case kColorId_TooltipBackground:
-    case kColorId_TooltipText:
-    case kColorId_TreeBackground:
-    case kColorId_TreeText:
-    case kColorId_TreeSelectedText:
-    case kColorId_TreeSelectedTextUnfocused:
-    case kColorId_TreeSelectionBackgroundFocused:
-    case kColorId_TreeSelectionBackgroundUnfocused:
-    case kColorId_TableBackground:
-    case kColorId_TableText:
-    case kColorId_TableSelectedText:
-    case kColorId_TableSelectedTextUnfocused:
-    case kColorId_TableSelectionBackgroundFocused:
-    case kColorId_TableSelectionBackgroundUnfocused:
-    case kColorId_TableGroupingIndicatorColor:
-    case kColorId_TableHeaderText:
-    case kColorId_TableHeaderBackground:
-    case kColorId_TableHeaderSeparator:
-    case kColorId_SeparatorColor:
-    case kColorId_ThrobberSpinningColor:
-    case kColorId_ThrobberWaitingColor:
-    case kColorId_ThrobberLightColor:
-    case kColorId_NumColors:
-      return gfx::kPlaceholderColor;
-  }
-
-  NOTREACHED();
-  return gfx::kPlaceholderColor;
+bool NativeThemeDarkAura::SystemDarkModeEnabled() const {
+  return true;
 }
 
 NativeThemeDarkAura::NativeThemeDarkAura() : NativeThemeAura(false) {}
diff --git a/ui/native_theme/native_theme_dark_aura.h b/ui/native_theme/native_theme_dark_aura.h
index 980df049..a24ab3e04 100644
--- a/ui/native_theme/native_theme_dark_aura.h
+++ b/ui/native_theme/native_theme_dark_aura.h
@@ -17,8 +17,9 @@
  public:
   static NativeThemeDarkAura* instance();
 
-  // Overridden from NativeThemeBase:
+  // NativeThemeAura:
   SkColor GetSystemColor(ColorId color_id) const override;
+  bool SystemDarkModeEnabled() const override;
 
  private:
   friend class base::NoDestructor<NativeThemeDarkAura>;
diff --git a/ui/ozone/BUILD.gn b/ui/ozone/BUILD.gn
index 625e4e0..6edc889 100644
--- a/ui/ozone/BUILD.gn
+++ b/ui/ozone/BUILD.gn
@@ -95,6 +95,7 @@
     "public/surface_factory_ozone.h",
     "public/surface_ozone_canvas.h",
     "public/swap_completion_callback.h",
+    "public/system_input_injector.h",
   ]
 
   defines = [ "IS_OZONE_BASE_IMPL" ]
diff --git a/ui/ozone/platform/cast/ozone_platform_cast.cc b/ui/ozone/platform/cast/ozone_platform_cast.cc
index 5a6d635..5eca91a 100644
--- a/ui/ozone/platform/cast/ozone_platform_cast.cc
+++ b/ui/ozone/platform/cast/ozone_platform_cast.cc
@@ -19,7 +19,6 @@
 #include "ui/events/ozone/evdev/event_factory_evdev.h"
 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
 #include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h"
-#include "ui/events/system_input_injector.h"
 #include "ui/ozone/platform/cast/overlay_manager_cast.h"
 #include "ui/ozone/platform/cast/platform_window_cast.h"
 #include "ui/ozone/platform/cast/surface_factory_cast.h"
@@ -27,6 +26,7 @@
 #include "ui/ozone/public/gpu_platform_support_host.h"
 #include "ui/ozone/public/input_controller.h"
 #include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/system_input_injector.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 
 using chromecast::CastEglPlatform;
diff --git a/ui/ozone/platform/headless/ozone_platform_headless.cc b/ui/ozone/platform/headless/ozone_platform_headless.cc
index 85279dd..1bf25803 100644
--- a/ui/ozone/platform/headless/ozone_platform_headless.cc
+++ b/ui/ozone/platform/headless/ozone_platform_headless.cc
@@ -13,7 +13,6 @@
 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
 #include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h"
 #include "ui/events/platform/platform_event_source.h"
-#include "ui/events/system_input_injector.h"
 #include "ui/ozone/common/stub_overlay_manager.h"
 #include "ui/ozone/platform/headless/headless_native_display_delegate.h"
 #include "ui/ozone/platform/headless/headless_surface_factory.h"
@@ -24,6 +23,7 @@
 #include "ui/ozone/public/input_controller.h"
 #include "ui/ozone/public/ozone_platform.h"
 #include "ui/ozone/public/ozone_switches.h"
+#include "ui/ozone/public/system_input_injector.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 
 namespace ui {
diff --git a/ui/ozone/platform/magma/ozone_platform_magma.cc b/ui/ozone/platform/magma/ozone_platform_magma.cc
index 32df102..e5b661b 100644
--- a/ui/ozone/platform/magma/ozone_platform_magma.cc
+++ b/ui/ozone/platform/magma/ozone_platform_magma.cc
@@ -15,7 +15,6 @@
 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
 #include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h"
 #include "ui/events/platform/platform_event_source.h"
-#include "ui/events/system_input_injector.h"
 #include "ui/ozone/common/stub_overlay_manager.h"
 #include "ui/ozone/platform/magma/magma_surface_factory.h"
 #include "ui/ozone/platform/magma/magma_window.h"
@@ -25,6 +24,7 @@
 #include "ui/ozone/public/input_controller.h"
 #include "ui/ozone/public/ozone_platform.h"
 #include "ui/ozone/public/ozone_switches.h"
+#include "ui/ozone/public/system_input_injector.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 
 namespace ui {
diff --git a/ui/ozone/platform/scenic/ozone_platform_scenic.cc b/ui/ozone/platform/scenic/ozone_platform_scenic.cc
index 0635e97..237f106 100644
--- a/ui/ozone/platform/scenic/ozone_platform_scenic.cc
+++ b/ui/ozone/platform/scenic/ozone_platform_scenic.cc
@@ -17,7 +17,6 @@
 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
 #include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h"
 #include "ui/events/platform/platform_event_source.h"
-#include "ui/events/system_input_injector.h"
 #include "ui/ozone/common/stub_overlay_manager.h"
 #include "ui/ozone/platform/scenic/scenic_gpu_host.h"
 #include "ui/ozone/platform/scenic/scenic_gpu_service.h"
@@ -32,6 +31,7 @@
 #include "ui/ozone/public/interfaces/scenic_gpu_service.mojom.h"
 #include "ui/ozone/public/ozone_platform.h"
 #include "ui/ozone/public/ozone_switches.h"
+#include "ui/ozone/public/system_input_injector.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 
 namespace ui {
diff --git a/ui/ozone/platform/wayland/ozone_platform_wayland.cc b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
index cf3d999..17bb667 100644
--- a/ui/ozone/platform/wayland/ozone_platform_wayland.cc
+++ b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
@@ -14,7 +14,6 @@
 #include "ui/base/buildflags.h"
 #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
-#include "ui/events/system_input_injector.h"
 #include "ui/gfx/linux/client_native_pixmap_dmabuf.h"
 #include "ui/ozone/common/stub_overlay_manager.h"
 #include "ui/ozone/platform/wayland/gpu/drm_render_node_path_finder.h"
@@ -28,6 +27,7 @@
 #include "ui/ozone/public/gpu_platform_support_host.h"
 #include "ui/ozone/public/input_controller.h"
 #include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/system_input_injector.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 
 #if BUILDFLAG(USE_XKBCOMMON)
diff --git a/ui/ozone/platform/windows/ozone_platform_windows.cc b/ui/ozone/platform/windows/ozone_platform_windows.cc
index 0d3e71b..5d7a8e746 100644
--- a/ui/ozone/platform/windows/ozone_platform_windows.cc
+++ b/ui/ozone/platform/windows/ozone_platform_windows.cc
@@ -15,7 +15,6 @@
 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
 #include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h"
 #include "ui/events/platform/platform_event_source.h"
-#include "ui/events/system_input_injector.h"
 #include "ui/ozone/common/stub_overlay_manager.h"
 #include "ui/ozone/platform/windows/windows_surface_factory.h"
 #include "ui/ozone/platform/windows/windows_window.h"
@@ -25,6 +24,7 @@
 #include "ui/ozone/public/input_controller.h"
 #include "ui/ozone/public/ozone_platform.h"
 #include "ui/ozone/public/ozone_switches.h"
+#include "ui/ozone/public/system_input_injector.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 
 namespace ui {
diff --git a/ui/ozone/platform/x11/ozone_platform_x11.cc b/ui/ozone/platform/x11/ozone_platform_x11.cc
index ec40bcc..7aa963e0 100644
--- a/ui/ozone/platform/x11/ozone_platform_x11.cc
+++ b/ui/ozone/platform/x11/ozone_platform_x11.cc
@@ -13,7 +13,6 @@
 #include "ui/display/fake/fake_display_delegate.h"
 #include "ui/events/devices/x11/touch_factory_x11.h"
 #include "ui/events/platform/x11/x11_event_source_libevent.h"
-#include "ui/events/system_input_injector.h"
 #include "ui/gfx/x/x11.h"
 #include "ui/ozone/common/stub_overlay_manager.h"
 #include "ui/ozone/platform/x11/x11_clipboard.h"
@@ -25,6 +24,7 @@
 #include "ui/ozone/public/gpu_platform_support_host.h"
 #include "ui/ozone/public/input_controller.h"
 #include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/system_input_injector.h"
 #include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 
diff --git a/ui/events/system_input_injector.h b/ui/ozone/public/system_input_injector.h
similarity index 63%
rename from ui/events/system_input_injector.h
rename to ui/ozone/public/system_input_injector.h
index f508fd3..d8213ef 100644
--- a/ui/events/system_input_injector.h
+++ b/ui/ozone/public/system_input_injector.h
@@ -2,16 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef UI_EVENTS_SYSTEM_INPUT_INJECTOR_H_
-#define UI_EVENTS_SYSTEM_INPUT_INJECTOR_H_
+#ifndef UI_OZONE_PUBLIC_SYSTEM_INPUT_INJECTOR_H_
+#define UI_OZONE_PUBLIC_SYSTEM_INPUT_INJECTOR_H_
 
-#include <memory>
-
+#include "base/component_export.h"
 #include "base/macros.h"
 #include "ui/events/event.h"
-#include "ui/events/events_export.h"
 #include "ui/events/keycodes/dom/keycode_converter.h"
-#include "ui/gfx/geometry/point_f.h"
 
 namespace gfx {
 class PointF;
@@ -21,7 +18,7 @@
 
 // Interface exposed for remoting to convert its events from the network to
 // native events.
-class EVENTS_EXPORT SystemInputInjector {
+class COMPONENT_EXPORT(OZONE) SystemInputInjector {
  public:
   SystemInputInjector() {}
   virtual ~SystemInputInjector() {}
@@ -52,26 +49,6 @@
   DISALLOW_COPY_AND_ASSIGN(SystemInputInjector);
 };
 
-class EVENTS_EXPORT SystemInputInjectorFactory {
- public:
-  virtual std::unique_ptr<SystemInputInjector> CreateSystemInputInjector() = 0;
-
- protected:
-  ~SystemInputInjectorFactory() {}
-};
-
-// Sets a global SystemInputInjectorFactory which is used in remoting instead
-// of requesting the usual Ozone version.
-//
-// This is placed in //ui/events not just since it's event related, but also
-// because its one of the few places that both //remoting/ and //ui/ozone can
-// depend on.
-EVENTS_EXPORT void SetSystemInputInjectorFactory(
-    SystemInputInjectorFactory* factory);
-
-// Returns the override input injector factory, or null if neither are set.
-EVENTS_EXPORT SystemInputInjectorFactory* GetSystemInputInjectorFactory();
-
 }  // namespace ui
 
-#endif  // UI_EVENTS_SYSTEM_INPUT_INJECTOR_H_
+#endif  // UI_OZONE_PUBLIC_SYSTEM_INPUT_INJECTOR_H_
diff --git a/ui/views/linux_ui/status_icon_linux.cc b/ui/views/linux_ui/status_icon_linux.cc
index c3d1ce1..e861e157 100644
--- a/ui/views/linux_ui/status_icon_linux.cc
+++ b/ui/views/linux_ui/status_icon_linux.cc
@@ -12,7 +12,13 @@
 
 StatusIconLinux::~StatusIconLinux() = default;
 
-void StatusIconLinux::RefreshPlatformContextMenu() {
+void StatusIconLinux::RefreshPlatformContextMenu() {}
+
+void StatusIconLinux::OnSetDelegate() {}
+
+void StatusIconLinux::SetDelegate(Delegate* delegate) {
+  delegate_ = delegate;
+  OnSetDelegate();
 }
 
 }  // namespace views
diff --git a/ui/views/linux_ui/status_icon_linux.h b/ui/views/linux_ui/status_icon_linux.h
index 652e436f..6bfa71ac0 100644
--- a/ui/views/linux_ui/status_icon_linux.h
+++ b/ui/views/linux_ui/status_icon_linux.h
@@ -34,7 +34,7 @@
     virtual ui::MenuModel* GetMenuModel() const = 0;
 
     // This should be called at most once by the implementation.
-    virtual void OnImplInitialized(bool success) = 0;
+    virtual void OnImplInitializationFailed() = 0;
 
    protected:
     virtual ~Delegate();
@@ -43,7 +43,7 @@
   StatusIconLinux();
   virtual ~StatusIconLinux();
 
-  virtual void SetImage(const gfx::ImageSkia& image) = 0;
+  virtual void SetIcon(const gfx::ImageSkia& image) = 0;
   virtual void SetToolTip(const base::string16& tool_tip) = 0;
 
   // Invoked after a call to SetContextMenu() to let the platform-specific
@@ -56,8 +56,11 @@
   // need to manually refresh it when the menu model changes.
   virtual void RefreshPlatformContextMenu();
 
+  virtual void OnSetDelegate();
+
+  void SetDelegate(Delegate* delegate);
+
   Delegate* delegate() { return delegate_; }
-  void set_delegate(Delegate* delegate) { delegate_ = delegate; }
 
  protected:
   Delegate* delegate_ = nullptr;
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
index 4c6ea1a0..efe92fed 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
@@ -48,6 +48,7 @@
 #include "ui/events/keyboard_hook.h"
 #include "ui/events/keycodes/dom/dom_code.h"
 #include "ui/events/platform/platform_event_source.h"
+#include "ui/events/x/events_x_utils.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/size_conversions.h"
 #include "ui/gfx/image/image_skia.h"
@@ -1497,9 +1498,13 @@
   Visual* visual = CopyFromParent;
   int depth = CopyFromParent;
   Colormap colormap = CopyFromParent;
-  ui::XVisualManager::GetInstance()->ChooseVisualForWindow(
-      enable_transparent_visuals, &visual, &depth, &colormap,
-      &use_argb_visual_);
+  ui::XVisualManager* visual_manager = ui::XVisualManager::GetInstance();
+  if (!visual_id_ ||
+      !visual_manager->GetVisualInfo(visual_id_, &visual, &depth, &colormap,
+                                     &use_argb_visual_)) {
+    visual_manager->ChooseVisualForWindow(enable_transparent_visuals, &visual,
+                                          &depth, &colormap, &use_argb_visual_);
+  }
 
   if (colormap != CopyFromParent) {
     attribute_mask |= CWColormap;
@@ -1691,7 +1696,8 @@
   // Disable compositing on tooltips as a workaround for
   // https://crbug.com/442111.
   CreateCompositor(viz::FrameSinkId(),
-                   params.type == Widget::InitParams::TYPE_TOOLTIP);
+                   params.force_software_compositing ||
+                       params.type == Widget::InitParams::TYPE_TOOLTIP);
 
   if (ui::IsSyncExtensionAvailable()) {
     compositor_observer_ = std::make_unique<SwapWithNewSizeObserverHelper>(
@@ -2109,6 +2115,23 @@
 
   UpdateWMUserTime(event);
 
+  // We can lose track of the window's position when the window is reparented.
+  // When the parent window is moved, we won't get an event, so the window's
+  // position relative to the root window will get out-of-sync.  We can re-sync
+  // when getting pointer events (EnterNotify, LeaveNotify, ButtonPress,
+  // ButtonRelease, MotionNotify) which include the pointer location both
+  // relative to this window and relative to the root window, so we can
+  // calculate this window's position from that information.
+  gfx::Point window_point = ui::EventLocationFromXEvent(*xev);
+  gfx::Point root_point = ui::EventSystemLocationFromXEvent(*xev);
+  if (!window_point.IsOrigin() && !root_point.IsOrigin()) {
+    gfx::Point window_origin = gfx::Point() + (root_point - window_point);
+    if (bounds_in_pixels_.origin() != window_origin) {
+      bounds_in_pixels_.set_origin(window_origin);
+      OnHostMovedInPixels(window_origin);
+    }
+  }
+
   // May want to factor CheckXEventForConsistency(xev); into a common location
   // since it is called here.
   switch (xev->type) {
@@ -2549,6 +2572,11 @@
   return {};
 }
 
+void DesktopWindowTreeHostX11::SetVisualId(VisualID visual_id) {
+  DCHECK_EQ(xwindow_, 0UL);
+  visual_id_ = visual_id;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // DesktopWindowTreeHost, public:
 
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
index 92f49c67..4717440a 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
@@ -91,6 +91,10 @@
   // Returns a map of KeyboardEvent code to KeyboardEvent key values.
   base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override;
 
+  // This must be called before the window is created, because the visual cannot
+  // be changed after.
+  void SetVisualId(VisualID visual_id);
+
  protected:
   // Overridden from DesktopWindowTreeHost:
   void Init(const Widget::InitParams& params) override;
@@ -472,6 +476,8 @@
   bool configure_counter_value_is_extended_ = false;
   std::unique_ptr<CompositorObserver> compositor_observer_;
 
+  VisualID visual_id_ = 0;
+
   base::WeakPtrFactory<DesktopWindowTreeHostX11> close_widget_factory_{this};
   base::WeakPtrFactory<DesktopWindowTreeHostX11> weak_factory_{this};
 
diff --git a/ui/views/widget/widget.h b/ui/views/widget/widget.h
index 8a073d7..5c275ae 100644
--- a/ui/views/widget/widget.h
+++ b/ui/views/widget/widget.h
@@ -294,7 +294,6 @@
     std::string wm_class_class;
 
     // If true then the widget uses software compositing. Defaults to false.
-    // Only used on Windows.
     bool force_software_compositing;
 
     // Used if widget is not activatable to do determine if mouse events should
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_siminfo.js b/ui/webui/resources/cr_components/chromeos/network/network_siminfo.js
index 41bcfa3a..ed4ec31 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_siminfo.js
+++ b/ui/webui/resources/cr_components/chromeos/network/network_siminfo.js
@@ -178,10 +178,9 @@
   getDeviceStateProperties_: function() {
     this.networkConfigProxy_.getDeviceStateList().then(response => {
       const devices = response.result;
+      const kCellular = chromeos.networkConfig.mojom.NetworkType.kCellular;
       this.deviceStateProperties_ =
-          devices.find(
-              device => device.type == OncMojo.NetworkType.kCellular) ||
-          null;
+          devices.find(device => device.type == kCellular) || null;
       if (!this.deviceStateProperties_) {
         return;
       }
diff --git a/ui/webui/resources/cr_elements/chromeos/network/cr_network_list_item.html b/ui/webui/resources/cr_elements/chromeos/network/cr_network_list_item.html
index e43533e..91dfb899 100644
--- a/ui/webui/resources/cr_elements/chromeos/network/cr_network_list_item.html
+++ b/ui/webui/resources/cr_elements/chromeos/network/cr_network_list_item.html
@@ -67,7 +67,7 @@
         <iron-icon icon="[[item.polymerIcon]]"></iron-icon>
       </template>
       <div id="divText" class="layout horizontal flex">
-        <div>[[ariaLabel]]</div>
+        <div aria-hidden="true">[[getItemName_(item)]]</div>
         <div id="networkStateText"
             hidden$="[[!isStateTextVisible_(networkState)]]"
             connected$="[[isConnected_(networkState)]]">
diff --git a/ui/webui/resources/cr_elements/chromeos/network/cr_network_list_item.js b/ui/webui/resources/cr_elements/chromeos/network/cr_network_list_item.js
index b9a8384..03c02da5 100644
--- a/ui/webui/resources/cr_elements/chromeos/network/cr_network_list_item.js
+++ b/ui/webui/resources/cr_elements/chromeos/network/cr_network_list_item.js
@@ -43,7 +43,11 @@
       reflectToAttribute: true,
     },
 
-    /** Expose the itemName so it can be used as a label for a11y.  */
+    /**
+     * Expose the itemName so it can be used as a label for a11y.  It will be
+     * added as an attribute on this top-level cr-network-list-item, and can
+     * be used by any sub-element which applies it.
+     */
     ariaLabel: {
       type: String,
       notify: true,
diff --git a/ui/webui/resources/cr_elements/chromeos/network/cr_network_select.js b/ui/webui/resources/cr_elements/chromeos/network/cr_network_select.js
index 52899343..6124a2b1 100644
--- a/ui/webui/resources/cr_elements/chromeos/network/cr_network_select.js
+++ b/ui/webui/resources/cr_elements/chromeos/network/cr_network_select.js
@@ -88,10 +88,11 @@
   attached: function() {
     this.refreshNetworks();
 
-    /** @const */ const INTERVAL_MS = 10 * 1000;
-    this.networkConfigProxy_.requestNetworkScan(OncMojo.NetworkType.kAll);
+    const INTERVAL_MS = 10 * 1000;
+    const kAll = chromeos.networkConfig.mojom.NetworkType.kAll;
+    this.networkConfigProxy_.requestNetworkScan(kAll);
     this.scanIntervalId_ = window.setInterval(function() {
-      this.networkConfigProxy_.requestNetworkScan(OncMojo.NetworkType.kAll);
+      this.networkConfigProxy_.requestNetworkScan(kAll);
     }.bind(this), INTERVAL_MS);
   },
 
diff --git a/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.html b/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.html
index b8f359e..12dfc7f 100644
--- a/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.html
+++ b/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.html
@@ -23,6 +23,7 @@
         color: var(--cr-icon-button-color);
         cursor: pointer;
         display: inline-flex;
+        flex-shrink: 0;
         height: var(--cr-icon-button-height);
         margin-inline-end: var(--cr-icon-button-margin-end,
             var(--cr-icon-ripple-margin));
diff --git a/ui/webui/resources/js/chromeos/onc_mojo.js b/ui/webui/resources/js/chromeos/onc_mojo.js
index 4662fa0..accbd8d 100644
--- a/ui/webui/resources/js/chromeos/onc_mojo.js
+++ b/ui/webui/resources/js/chromeos/onc_mojo.js
@@ -231,5 +231,3 @@
 
 /** @typedef {chromeos.networkConfig.mojom.NetworkStateProperties} */
 OncMojo.NetworkStateProperties;
-
-OncMojo.NetworkType = chromeos.networkConfig.mojom.NetworkType;