diff --git a/core/includes/module.inc b/core/includes/module.inc
index ff11244..97638fa 100644
--- a/core/includes/module.inc
+++ b/core/includes/module.inc
@@ -20,7 +20,7 @@
  *   For $type 'theme', the array values are objects representing the
  *   respective database row, with the 'info' property already unserialized.
  *
- * @see list_themes()
+ * @see \Drupal\Core\Extension\ThemeHandler::listInfo()
  */
 function system_list($type) {
   $lists = &drupal_static(__FUNCTION__);
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index c89b734..a7f9de5 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -231,7 +231,7 @@ function drupal_find_theme_templates($cache, $extension, $path) {
   // used for filtering. This allows base themes to have sub-themes in its
   // folder hierarchy without affecting the base themes template discovery.
   $theme_paths = array();
-  foreach (list_themes() as $theme_info) {
+  foreach (\Drupal::service('theme_handler')->listInfo() as $theme_info) {
     if (!empty($theme_info->base_theme)) {
       $theme_paths[$theme_info->base_theme][$theme_info->getName()] = $theme_info->getPath();
     }
@@ -352,6 +352,8 @@ function theme_get_setting($setting_name, $theme = NULL) {
     // Get the global settings from configuration.
     $cache[$theme]->setData(\Drupal::config('system.theme.global')->get());
 
+    // Get the values for the theme-specific settings from the .info.yml files
+    // of the theme and all its base themes.
     $themes = \Drupal::service('theme_handler')->listInfo();
     if (isset($themes[$theme])) {
       $theme_object = $themes[$theme];
diff --git a/core/includes/theme.maintenance.inc b/core/includes/theme.maintenance.inc
index 965cccd..aca0a53 100644
--- a/core/includes/theme.maintenance.inc
+++ b/core/includes/theme.maintenance.inc
@@ -70,7 +70,7 @@ function _drupal_maintenance_theme() {
     $module_handler->load('system');
   }
 
-  $themes = list_themes();
+  $themes = \Drupal::service('theme_handler')->listInfo();
 
   // If no themes are installed yet, or if the requested custom theme is not
   // installed, retrieve all available themes.
@@ -83,10 +83,11 @@ function _drupal_maintenance_theme() {
     \Drupal::theme()->setActiveTheme($theme_init->getActiveTheme($themes[$custom_theme], array()));
   }
 
-  // list_themes() triggers a \Drupal\Core\Extension\ModuleHandler::alter() in
-  // maintenance mode, but we can't let themes alter the .info.yml data until
-  // we know a theme's base themes. So don't set active theme until after
-  // list_themes() builds its cache.
+  // \Drupal\Core\Extension\ThemeHandlerInterface::listInfo() triggers a
+  // \Drupal\Core\Extension\ModuleHandler::alter() in maintenance mode, but we
+  // can't let themes alter the .info.yml data until we know a theme's base
+  // themes. So don't set active theme until after
+  // \Drupal\Core\Extension\ThemeHandlerInterface::listInfo() builds its cache.
   $theme = $custom_theme;
 
   // Find all our ancestor themes and put them in an array.
diff --git a/core/lib/Drupal/Core/Theme/Registry.php b/core/lib/Drupal/Core/Theme/Registry.php
index ff4f678..784abd3 100644
--- a/core/lib/Drupal/Core/Theme/Registry.php
+++ b/core/lib/Drupal/Core/Theme/Registry.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\DestructableInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Extension\ThemeHandlerInterface;
 use Drupal\Core\Lock\LockBackendInterface;
 use Drupal\Core\Utility\ThemeRegistry;
 
@@ -137,6 +138,13 @@ class Registry implements DestructableInterface {
   protected $root;
 
   /**
+   * The theme handler.
+   *
+   * @var \Drupal\Core\Extension\ThemeHandlerInterface
+   */
+  protected $themeHandler;
+
+  /**
    * Constructs a \Drupal\Core\\Theme\Registry object.
    *
    * @param string $root
@@ -149,13 +157,16 @@ class Registry implements DestructableInterface {
    *   The module handler to use to load modules.
    * @param string $theme_name
    *   (optional) The name of the theme for which to construct the registry.
+   * @param $theme_handler
+   *   The theme handler.
    */
-  public function __construct($root, CacheBackendInterface $cache, LockBackendInterface $lock, ModuleHandlerInterface $module_handler, $theme_name = NULL) {
+  public function __construct($root, CacheBackendInterface $cache, LockBackendInterface $lock, ModuleHandlerInterface $module_handler, $theme_name = NULL, ThemeHandlerInterface $theme_handler) {
     $this->root = $root;
     $this->cache = $cache;
     $this->lock = $lock;
     $this->moduleHandler = $module_handler;
     $this->themeName = $theme_name;
+    $this->themeHandler = $theme_handler;
   }
 
   /**
@@ -180,7 +191,7 @@ protected function init($theme_name = NULL) {
     }
     // Instead of the active theme, a specific theme was requested.
     else {
-      $themes = $this->listThemes();
+      $themes = $this->themeHandler->listInfo();
       $this->theme = $themes[$theme_name];
 
       // Find all base themes.
@@ -403,14 +414,15 @@ protected function build() {
    *   example, if a theme hook is both defined by a module and a theme, then
    *   the definition in the theme will be used.
    * @param \stdClass $theme
-   *   The loaded $theme object as returned from list_themes().
+   *   The loaded $theme object as returned from
+   *   ThemeHandlerInterface::listInfo().
    * @param string $path
    *   The directory where $name is. For example, modules/system or
    *   themes/bartik.
    *
    * @see _theme()
    * @see hook_theme()
-   * @see list_themes()
+   * @see \Drupal\Core\Extension\ThemeHandler::listInfo()
    * @see twig_render_template()
    *
    * @throws \BadFunctionCallException
@@ -605,14 +617,4 @@ public function destruct() {
   protected function getPath($module) {
     return drupal_get_path('module', $module);
   }
-
-  /**
-   * Wraps list_themes().
-   *
-   * @return array
-   */
-  protected function listThemes() {
-    return list_themes();
-  }
-
 }
diff --git a/core/lib/Drupal/Core/Theme/ThemeAccessCheck.php b/core/lib/Drupal/Core/Theme/ThemeAccessCheck.php
index 78ffd26..323721d 100644
--- a/core/lib/Drupal/Core/Theme/ThemeAccessCheck.php
+++ b/core/lib/Drupal/Core/Theme/ThemeAccessCheck.php
@@ -39,7 +39,7 @@ public function access($theme) {
    *   TRUE if the theme is installed, FALSE otherwise.
    */
   public function checkAccess($theme) {
-    $themes = list_themes();
+    $themes = \Drupal::service('theme_handler')->listInfo();
     return !empty($themes[$theme]->status);
   }
 
diff --git a/core/modules/block/block.module b/core/modules/block/block.module
index 85d295e..d7335c9 100644
--- a/core/modules/block/block.module
+++ b/core/modules/block/block.module
@@ -40,7 +40,7 @@ function block_help($route_name, RouteMatchInterface $route_match) {
   }
   if ($route_name == 'block.admin_display' || $route_name == 'block.admin_display_theme') {
     $demo_theme = $route_match->getParameter('theme') ?: \Drupal::config('system.theme')->get('default');
-    $themes = list_themes();
+    $themes = \Drupal::service('theme_handler')->listInfo();
     $output = '<p>' . t('This page provides a drag-and-drop interface for adding a block to a region, and for controlling the order of blocks within regions. To add a block to a region, or to configure its specific title and visibility settings, click the block title under <em>Place blocks</em>. Since not all themes implement the same regions, or display regions in the same way, blocks are positioned on a per-theme basis. Remember that your changes will not be saved until you click the <em>Save blocks</em> button at the bottom of the page.') . '</p>';
     $output .= '<p>' . \Drupal::l(t('Demonstrate block regions (!theme)', array('!theme' => $themes[$demo_theme]->info['name'])), new Url('block.admin_demo', array('theme' => $demo_theme))) . '</p>';
     return $output;
@@ -176,7 +176,7 @@ function block_theme_initialize($theme) {
  * Implements hook_rebuild().
  */
 function block_rebuild() {
-  foreach (list_themes() as $name => $data) {
+  foreach (\Drupal::service('theme_handler')->listInfo() as $name => $data) {
     if ($data->status) {
       _block_rehash($name);
     }
diff --git a/core/modules/block/src/BlockForm.php b/core/modules/block/src/BlockForm.php
index fd8eeab..93ab1d8 100644
--- a/core/modules/block/src/BlockForm.php
+++ b/core/modules/block/src/BlockForm.php
@@ -13,6 +13,7 @@
 use Drupal\Core\Entity\EntityForm;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Executable\ExecutableManagerInterface;
+use Drupal\Core\Extension\ThemeHandlerInterface;
 use Drupal\Core\Form\FormState;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Language\LanguageManagerInterface;
@@ -61,6 +62,13 @@ class BlockForm extends EntityForm {
   protected $language;
 
   /**
+   * The theme handler.
+   *
+   * @var \Drupal\Core\Extension\ThemeHandler
+   */
+  protected $themeHandler;
+
+  /**
    * Constructs a BlockForm object.
    *
    * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
@@ -71,12 +79,15 @@ class BlockForm extends EntityForm {
    *   The EventDispatcher for gathering administrative contexts.
    * @param \Drupal\Core\Language\LanguageManagerInterface $language
    *   The language manager.
+   * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
+   * The theme handler.
    */
-  public function __construct(EntityManagerInterface $entity_manager, ExecutableManagerInterface $manager, EventDispatcherInterface $dispatcher, LanguageManagerInterface $language) {
+  public function __construct(EntityManagerInterface $entity_manager, ExecutableManagerInterface $manager, EventDispatcherInterface $dispatcher, LanguageManagerInterface $language, ThemeHandlerInterface $theme_handler) {
     $this->storage = $entity_manager->getStorage('block');
     $this->manager = $manager;
     $this->dispatcher = $dispatcher;
     $this->language = $language;
+    $this->themeHandler = $theme_handler;
   }
 
   /**
@@ -87,7 +98,8 @@ public static function create(ContainerInterface $container) {
       $container->get('entity.manager'),
       $container->get('plugin.manager.condition'),
       $container->get('event_dispatcher'),
-      $container->get('language_manager')
+      $container->get('language_manager'),
+      $container->get('theme_handler')
     );
   }
 
@@ -135,7 +147,7 @@ public function form(array $form, FormStateInterface $form_state) {
     }
     else {
       $theme_options = array();
-      foreach (list_themes() as $theme_name => $theme_info) {
+      foreach ($this->themeHandler->listInfo() as $theme_name => $theme_info) {
         if (!empty($theme_info->status)) {
           $theme_options[$theme_name] = $theme_info->info['name'];
         }
diff --git a/core/modules/block/tests/src/Unit/BlockFormTest.php b/core/modules/block/tests/src/Unit/BlockFormTest.php
index 4f563db..8acff20 100644
--- a/core/modules/block/tests/src/Unit/BlockFormTest.php
+++ b/core/modules/block/tests/src/Unit/BlockFormTest.php
@@ -44,6 +44,14 @@ class BlockFormTest extends UnitTestCase {
    */
   protected $language;
 
+
+  /**
+   * The theme handler.
+   *
+   * @var \Drupal\Core\Extension\ThemeHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $themeHandler;
+
   /**
    * The entity manager.
    *
@@ -63,6 +71,7 @@ protected function setUp() {
 
     $this->entityManager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
     $this->storage = $this->getMock('Drupal\Core\Config\Entity\ConfigEntityStorageInterface');
+    $this->themeHandler = $this->getMock('Drupal\Core\Extension\ThemeHandlerInterface');
     $this->entityManager->expects($this->any())
       ->method('getStorage')
       ->will($this->returnValue($this->storage));
@@ -95,7 +104,7 @@ public function testGetUniqueMachineName() {
       ->method('getQuery')
       ->will($this->returnValue($query));
 
-    $block_form_controller = new BlockForm($this->entityManager, $this->conditionManager, $this->dispatcher, $this->language);
+    $block_form_controller = new BlockForm($this->entityManager, $this->conditionManager, $this->dispatcher, $this->language, $this->themeHandler);
 
     // Ensure that the block with just one other instance gets the next available
     // name suggestion.
diff --git a/core/modules/block_content/src/Controller/BlockContentController.php b/core/modules/block_content/src/Controller/BlockContentController.php
index 4716bba..855250a 100644
--- a/core/modules/block_content/src/Controller/BlockContentController.php
+++ b/core/modules/block_content/src/Controller/BlockContentController.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Controller\ControllerBase;
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\block_content\BlockContentTypeInterface;
+use Drupal\Core\Extension\ThemeHandlerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpFoundation\Request;
 
@@ -31,13 +32,21 @@ class BlockContentController extends ControllerBase {
   protected $blockContentTypeStorage;
 
   /**
+   * The theme handler.
+   *
+   * @var \Drupal\Core\Extension\ThemeHandlerInterface
+   */
+  protected $themeHandler;
+
+  /**
    * {@inheritdoc}
    */
   public static function create(ContainerInterface $container) {
     $entity_manager = $container->get('entity.manager');
     return new static(
       $entity_manager->getStorage('block_content'),
-      $entity_manager->getStorage('block_content_type')
+      $entity_manager->getStorage('block_content_type'),
+      $container->get('theme_handler')
     );
   }
 
@@ -48,10 +57,13 @@ public static function create(ContainerInterface $container) {
    *   The custom block storage.
    * @param \Drupal\Core\Entity\EntityStorageInterface $block_content_type_storage
    *   The custom block type storage.
+   * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
+   * The theme handler.
    */
-  public function __construct(EntityStorageInterface $block_content_storage, EntityStorageInterface $block_content_type_storage) {
+  public function __construct(EntityStorageInterface $block_content_storage, EntityStorageInterface $block_content_type_storage, ThemeHandlerInterface $theme_handler) {
     $this->blockContentStorage = $block_content_storage;
     $this->blockContentTypeStorage = $block_content_type_storage;
+    $this->themeHandler = $theme_handler;
   }
 
   /**
@@ -90,7 +102,7 @@ public function addForm(BlockContentTypeInterface $block_content_type, Request $
     $block = $this->blockContentStorage->create(array(
       'type' => $block_content_type->id()
     ));
-    if (($theme = $request->query->get('theme')) && in_array($theme, array_keys(list_themes()))) {
+    if (($theme = $request->query->get('theme')) && in_array($theme, array_keys($this->themeHandler->listInfo()))) {
       // We have navigated to this page from the block library and will keep track
       // of the theme for redirecting the user to the configuration page for the
       // newly created block in the given theme.
diff --git a/core/modules/system/module.api.php b/core/modules/system/module.api.php
index 2c3cbde..75bc64d 100644
--- a/core/modules/system/module.api.php
+++ b/core/modules/system/module.api.php
@@ -86,9 +86,9 @@ function hook_module_implements_alter(&$implementations, $hook) {
  * Alter the information parsed from module and theme .info.yml files
  *
  * This hook is invoked in _system_rebuild_module_data() and in
- * _system_rebuild_theme_data(). A module may implement this hook in order to
- * add to or alter the data generated by reading the .info.yml file with
- * \Drupal\Core\Extension\InfoParser.
+ * \Drupal\Core\Extension\ThemeHandlerInterface::rebuildThemeData(). A module
+ * may implement this hook in order to add to or alter the data generated by
+ * reading the .info.yml file with \Drupal\Core\Extension\InfoParser.
  *
  * @param array $info
  *   The .info.yml file contents, passed by reference so that it can be altered.
diff --git a/core/modules/system/src/Form/ThemeSettingsForm.php b/core/modules/system/src/Form/ThemeSettingsForm.php
index 8e72246..36bf64a 100644
--- a/core/modules/system/src/Form/ThemeSettingsForm.php
+++ b/core/modules/system/src/Form/ThemeSettingsForm.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\system\Form;
 
+use Drupal\Core\Extension\ThemeHandlerInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Render\Element;
 use Drupal\Core\StreamWrapper\PublicStream;
@@ -30,17 +31,27 @@ class ThemeSettingsForm extends ConfigFormBase {
   protected $moduleHandler;
 
   /**
+   * The theme handler.
+   *
+   * @var \Drupal\Core\Extension\ThemeHandlerInterface
+   */
+  protected $themeHandler;
+
+  /**
    * Constructs a ThemeSettingsForm object.
    *
    * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
    *   The factory for configuration objects.
    * @param \Drupal\Core\Extension\ModuleHandlerInterface
    *   The module handler instance to use.
+   * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
+   * The theme handler.
    */
-  public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler) {
+  public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler) {
     parent::__construct($config_factory);
 
     $this->moduleHandler = $module_handler;
+    $this->themeHandler = $theme_handler;
   }
 
   /**
@@ -49,7 +60,8 @@ public function __construct(ConfigFactoryInterface $config_factory, ModuleHandle
   public static function create(ContainerInterface $container) {
     return new static(
       $container->get('config.factory'),
-      $container->get('module_handler')
+      $container->get('module_handler'),
+      $container->get('theme_handler')
     );
   }
 
@@ -69,7 +81,7 @@ public function getFormId() {
   public function buildForm(array $form, FormStateInterface $form_state, $theme = '') {
     $form = parent::buildForm($form, $form_state);
 
-    $themes = list_themes();
+    $themes = $this->themeHandler->listInfo();
 
     // Deny access if the theme is not installed or not found.
     if (!empty($theme) && (empty($themes[$theme]) || !$themes[$theme]->status)) {
@@ -80,7 +92,7 @@ public function buildForm(array $form, FormStateInterface $form_state, $theme =
     if ($theme) {
       $var = 'theme_' . $theme . '_settings';
       $config_key = $theme . '.settings';
-      $themes = list_themes();
+      $themes = $this->themeHandler->listInfo();
       $features = $themes[$theme]->info['features'];
     }
     else {
diff --git a/core/modules/system/src/Tests/Theme/ThemeTest.php b/core/modules/system/src/Tests/Theme/ThemeTest.php
index 129c8b3..9dc3f97 100644
--- a/core/modules/system/src/Tests/Theme/ThemeTest.php
+++ b/core/modules/system/src/Tests/Theme/ThemeTest.php
@@ -200,17 +200,20 @@ function testFunctionOverride() {
   }
 
   /**
-   * Test the list_themes() function.
+   * Test the listInfo() function.
    */
   function testListThemes() {
     $theme_handler = $this->container->get('theme_handler');
     $theme_handler->install(array('test_subtheme'));
     $themes = $theme_handler->listInfo();
 
-    // Check if drupal_theme_access() retrieves installed themes properly from
-    // list_themes().
+    $themes = \Drupal::service('theme_handler')->listInfo();
+    // Check if drupal_theme_access() retrieves enabled themes properly from
+    // ThemeHandlerInterface::listInfo().
     $this->assertTrue(drupal_theme_access('test_theme'), 'Installed theme detected');
 
+    $this->assertTrue(drupal_theme_access('test_theme'), 'Enabled theme detected');
+    // Check if ThemeHandlerInterface::listInfo() returns disabled themes.
     // Check for base theme and subtheme lists.
     $base_theme_list = array('test_basetheme' => 'Theme test base theme');
     $sub_theme_list = array('test_subtheme' => 'Theme test subtheme');
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index 0ca834a..c8d5273 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -491,7 +491,7 @@ function hook_cache_flush() {
  * @see drupal_flush_all_caches()
  */
 function hook_rebuild() {
-  $themes = list_themes();
+  $themes = \Drupal::service('theme_handler')->listInfo();
   foreach ($themes as $theme) {
     _block_rehash($theme->getName());
   }
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 8f2a8ab..6ada5b8 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -100,7 +100,7 @@ function system_help($route_name, RouteMatchInterface $route_match) {
       return $output;
 
     case 'system.theme_settings_theme':
-      $theme_list = list_themes();
+      $theme_list = \Drupal::service('theme_handler')->listInfo();
       $theme = $theme_list[$route_match->getParameter('theme')];
       return '<p>' . t('These options control the display settings for the %name theme. When your site is displayed using this theme, these settings will be used.', array('%name' => $theme->info['name'])) . '</p>';
 
diff --git a/core/modules/views_ui/src/Form/BasicSettingsForm.php b/core/modules/views_ui/src/Form/BasicSettingsForm.php
index 621f1a4..557745b 100644
--- a/core/modules/views_ui/src/Form/BasicSettingsForm.php
+++ b/core/modules/views_ui/src/Form/BasicSettingsForm.php
@@ -7,8 +7,11 @@
 
 namespace Drupal\views_ui\Form;
 
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Extension\ThemeHandlerInterface;
 use Drupal\Core\Form\ConfigFormBase;
 use Drupal\Core\Form\FormStateInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Form builder for the admin display defaults page.
@@ -16,6 +19,37 @@
 class BasicSettingsForm extends ConfigFormBase {
 
   /**
+   * The theme handler.
+   *
+   * @var \Drupal\Core\Extension\ThemeHandlerInterface
+   */
+  protected $themeHandler;
+
+  /**
+   * Constructs a \Drupal\views_ui\Form\BasicSettingsForm object.
+   *
+   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
+   *   The factory for configuration objects.
+   * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
+   *   The theme handler.
+   */
+  public function __construct(ConfigFactoryInterface $config_factory, ThemeHandlerInterface $theme_handler) {
+    parent::__construct($config_factory);
+
+    $this->themeHandler = $theme_handler;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('config.factory'),
+      $container->get('theme_handler')
+    );
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function getFormId() {
@@ -30,7 +64,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
 
     $config = $this->config('views.settings');
     $options = array();
-    foreach (list_themes() as $name => $theme) {
+    foreach ($this->themeHandler->listInfo() as $name => $theme) {
       if ($theme->status) {
         $options[$name] = $theme->info['name'];
       }
