diff --git a/core/modules/system/lib/Drupal/system/Controller/AdminController.php b/core/modules/system/lib/Drupal/system/Controller/AdminController.php
index 032eab0..cf78b69 100644
--- a/core/modules/system/lib/Drupal/system/Controller/AdminController.php
+++ b/core/modules/system/lib/Drupal/system/Controller/AdminController.php
@@ -55,8 +55,6 @@ public function index() {
       $module_info[$module]->info = $info;
     }
 
-    $this->moduleHandler->loadInclude('system', 'admin.inc');
-
     uasort($module_info, 'system_sort_modules_by_info_name');
     $menu_items = array();
 
diff --git a/core/modules/system/lib/Drupal/system/Controller/SystemController.php b/core/modules/system/lib/Drupal/system/Controller/SystemController.php
index 597471e..41825c8 100644
--- a/core/modules/system/lib/Drupal/system/Controller/SystemController.php
+++ b/core/modules/system/lib/Drupal/system/Controller/SystemController.php
@@ -10,6 +10,9 @@
 use Drupal\Core\Controller\ControllerBase;
 use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
 use Drupal\Core\Entity\Query\QueryFactory;
+use Drupal\Core\Theme\ThemeAccessCheck;
+use Drupal\system\Form\ThemeAdminForm;
+use Drupal\Core\Access\CsrfTokenGenerator;
 use Drupal\system\SystemManager;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpFoundation\RedirectResponse;
@@ -34,16 +37,36 @@ class SystemController extends ControllerBase implements ContainerInjectionInter
   protected $systemManager;
 
   /**
+   * The Csrf token generator service.
+   *
+   * @var \Drupal\Core\Access\CsrfTokenGenerator
+   */
+  protected $tokenGenerator;
+
+  /**
+   * The theme access checker service.
+   *
+   * @var \Drupal\Core\Theme\ThemeAccessCheck
+   */
+  protected $themeAccess;
+
+  /**
    * Constructs a new SystemController.
    *
    * @param \Drupal\system\SystemManager $systemManager
    *   System manager service.
    * @param \Drupal\Core\Entity\Query\QueryFactory $queryFactory
    *   The entity query object.
+   * @param \Drupal\Core\Access\CsrfTokenGenerator $token_generator
+   *   The token generator service.
+   * @param \Drupal\Core\Theme\ThemeAccessCheck $theme_access
+   *   The theme access checker service.
    */
-  public function __construct(SystemManager $systemManager, QueryFactory $queryFactory) {
+  public function __construct(SystemManager $systemManager, QueryFactory $queryFactory, CsrfTokenGenerator $token_generator, ThemeAccessCheck $theme_access) {
     $this->systemManager = $systemManager;
     $this->queryFactory = $queryFactory;
+    $this->tokenGenerator = $token_generator;
+    $this->themeAccess = $theme_access;
   }
 
   /**
@@ -52,7 +75,9 @@ public function __construct(SystemManager $systemManager, QueryFactory $queryFac
   public static function create(ContainerInterface $container) {
     return new static(
       $container->get('system.manager'),
-      $container->get('entity.query')
+      $container->get('entity.query'),
+      $container->get('csrf_token'),
+      $container->get('access_check.theme')
     );
   }
 
@@ -146,11 +171,152 @@ public function systemAdminMenuBlockPage() {
   }
 
   /**
-   * @todo Remove system_themes_page().
+   * Returns a theme listing.
+   *
+   * @return string
+   *   An HTML string of the theme listing page.
    */
   public function themesPage() {
-    module_load_include('admin.inc', 'system');
-    return system_themes_page();
+    $config = $this->config('system.theme');
+    // Get current list of themes.
+    $themes = system_rebuild_theme_data();
+    uasort($themes, 'system_sort_modules_by_info_name');
+
+    $theme_default = $config->get('default');
+    $theme_groups  = array();
+    $admin_theme = $config->get('admin');
+
+    foreach ($themes as &$theme) {
+      if (!empty($theme->info['hidden'])) {
+        continue;
+      }
+      $theme->is_default = ($theme->name == $theme_default);
+
+      // Identify theme screenshot.
+      $theme->screenshot = NULL;
+      // Create a list which includes the current theme and all its base themes.
+      if (isset($themes[$theme->name]->base_themes)) {
+        $theme_keys = array_keys($themes[$theme->name]->base_themes);
+        $theme_keys[] = $theme->name;
+      }
+      else {
+        $theme_keys = array($theme->name);
+      }
+      // Look for a screenshot in the current theme or in its closest ancestor.
+      foreach (array_reverse($theme_keys) as $theme_key) {
+        if (isset($themes[$theme_key]) && file_exists($themes[$theme_key]->info['screenshot'])) {
+          $theme->screenshot = array(
+            'uri' => $themes[$theme_key]->info['screenshot'],
+            'alt' => $this->t('Screenshot for !theme theme', array('!theme' => $theme->info['name'])),
+            'title' => $this->t('Screenshot for !theme theme', array('!theme' => $theme->info['name'])),
+            'attributes' => array('class' => array('screenshot')),
+          );
+          break;
+        }
+      }
+
+      if (empty($theme->status)) {
+        // Ensure this theme is compatible with this version of core.
+        // Require the 'content' region to make sure the main page
+        // content has a common place in all themes.
+        $theme->incompatible_core = !isset($theme->info['core']) || ($theme->info['core'] != \DRUPAL::CORE_COMPATIBILITY) || !isset($theme->info['regions']['content']);
+        $theme->incompatible_php = version_compare(phpversion(), $theme->info['php']) < 0;
+        // Confirmed that the base theme is available.
+        $theme->incompatible_base = isset($theme->info['base theme']) && !isset($themes[$theme->info['base theme']]);
+        // Confirm that the theme engine is available.
+        $theme->incompatible_engine = isset($theme->info['engine']) && !isset($theme->owner);
+      }
+      $query['token'] = $this->tokenGenerator->get('system-theme-operation-link');
+      $theme->operations = array();
+      if (!empty($theme->status) || !$theme->incompatible_core && !$theme->incompatible_php && !$theme->incompatible_base && !$theme->incompatible_engine) {
+        // Create the operations links.
+        $query['theme'] = $theme->name;
+        if ($this->themeAccess->checkAccess($theme->name)) {
+          $theme->operations[] = array(
+            'title' => $this->t('Settings'),
+            'href' => 'admin/appearance/settings/' . $theme->name,
+            'attributes' => array('title' => $this->t('Settings for !theme theme', array('!theme' => $theme->info['name']))),
+          );
+        }
+        if (!empty($theme->status)) {
+          if (!$theme->is_default) {
+            if ($theme->name != $admin_theme) {
+              $theme->operations[] = array(
+                'title' => $this->t('Disable'),
+                'href' => 'admin/appearance/disable',
+                'query' => $query,
+                'attributes' => array('title' => $this->t('Disable !theme theme', array('!theme' => $theme->info['name']))),
+              );
+            }
+            $theme->operations[] = array(
+              'title' => $this->t('Set default'),
+              'href' => 'admin/appearance/default',
+              'query' => $query,
+              'attributes' => array('title' => $this->t('Set !theme as default theme', array('!theme' => $theme->info['name']))),
+            );
+          }
+          $admin_theme_options[$theme->name] = $theme->info['name'];
+        }
+        else {
+          $theme->operations[] = array(
+            'title' => $this->t('Enable'),
+            'href' => 'admin/appearance/enable',
+            'query' => $query,
+            'attributes' => array('title' => $this->t('Enable !theme theme', array('!theme' => $theme->info['name']))),
+          );
+          $theme->operations[] = array(
+            'title' => $this->t('Enable and set default'),
+            'href' => 'admin/appearance/default',
+            'query' => $query,
+            'attributes' => array('title' => $this->t('Enable !theme as default theme', array('!theme' => $theme->info['name']))),
+          );
+        }
+      }
+
+      // Add notes to default and administration theme.
+      $theme->notes = array();
+      $theme->classes = array();
+      if ($theme->is_default) {
+        $theme->classes[] = 'theme-default';
+        $theme->notes[] = $this->t('default theme');
+      }
+      if ($theme->name == $admin_theme || ($theme->is_default && $admin_theme == '0')) {
+        $theme->classes[] = 'theme-admin';
+        $theme->notes[] = $this->t('admin theme');
+      }
+
+      // Sort enabled and disabled themes into their own groups.
+      $theme_groups[$theme->status ? 'enabled' : 'disabled'][] = $theme;
+    }
+
+    // There are two possible theme groups.
+    $theme_group_titles = array(
+      'enabled' => format_plural(count($theme_groups['enabled']), 'Enabled theme', 'Enabled themes'),
+    );
+    if (!empty($theme_groups['disabled'])) {
+      $theme_group_titles['disabled'] = format_plural(count($theme_groups['disabled']), 'Disabled theme', 'Disabled themes');
+    }
+
+    uasort($theme_groups['enabled'], function($a, $b) {
+      if ($a->is_default) {
+        return -1;
+      }
+      if ($b->is_default) {
+        return 1;
+      }
+      return strcasecmp($a->info['name'], $b->info['name']);
+    });
+    $this->moduleHandler()->alter('system_themes_page', $theme_groups);
+
+    $build = array();
+    $build[] = array(
+      '#theme' => 'system_themes_page',
+      '#theme_groups' => $theme_groups,
+      '#theme_group_titles' => $theme_group_titles,
+    );
+    $build[] = \Drupal::formBuilder()->getForm(new ThemeAdminForm(), $admin_theme_options);
+
+    return $build;
   }
 
   /**
diff --git a/core/modules/system/lib/Drupal/system/Form/ModulesUninstallForm.php b/core/modules/system/lib/Drupal/system/Form/ModulesUninstallForm.php
index 711f934..93bf906 100644
--- a/core/modules/system/lib/Drupal/system/Form/ModulesUninstallForm.php
+++ b/core/modules/system/lib/Drupal/system/Form/ModulesUninstallForm.php
@@ -85,7 +85,6 @@ public function buildForm(array $form, array &$form_state) {
     $profile = drupal_get_profile();
 
     // Sort all modules by their name.
-    $this->moduleHandler->loadInclude('system', 'inc', 'system.admin');
     uasort($uninstallable, 'system_sort_modules_by_info_name');
 
     $form['uninstall'] = array('#tree' => TRUE);
diff --git a/core/modules/system/lib/Drupal/system/Form/ThemeAdminForm.php b/core/modules/system/lib/Drupal/system/Form/ThemeAdminForm.php
new file mode 100644
index 0000000..8bb44ef
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Form/ThemeAdminForm.php
@@ -0,0 +1,57 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\system\Form\ThemeAdminForm
+ */
+
+namespace Drupal\system\Form;
+
+use Drupal\Core\Form\FormBase;
+
+/**
+ * Form to select the administration theme.
+ *
+ * @ingroup forms
+ */
+class ThemeAdminForm extends FormBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormID() {
+    return 'system_themes_admin_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, array &$form_state, array $theme_options = NULL) {
+    // Administration theme settings.
+    $form['admin_theme'] = array(
+      '#type' => 'details',
+      '#title' => $this->t('Administration theme'),
+    );
+    $form['admin_theme']['admin_theme'] = array(
+      '#type' => 'select',
+      '#options' => array(0 => $this->t('Default theme')) + $theme_options,
+      '#title' => $this->t('Administration theme'),
+      '#description' => $this->t('Choose "Default theme" to always use the same theme as the rest of the site.'),
+      '#default_value' => $this->config('system.theme')->get('admin'),
+    );
+    $form['admin_theme']['actions'] = array('#type' => 'actions');
+    $form['admin_theme']['actions']['submit'] = array(
+      '#type' => 'submit',
+      '#value' => $this->t('Save configuration'),
+    );
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, array &$form_state) {
+    drupal_set_message($this->t('The configuration options have been saved.'));
+    $this->config('system.theme')->set('admin', $form_state['values']['admin_theme'])->save();
+  }
+
+}
diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc
index 29237fd..30d1c67 100644
--- a/core/modules/system/system.admin.inc
+++ b/core/modules/system/system.admin.inc
@@ -11,181 +11,6 @@
 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
 
 /**
- * Menu callback; displays a listing of all themes.
- *
- * @deprecated Use \Drupal\system\Controller\SystemController::themesPage()
- */
-function system_themes_page() {
-  // Get current list of themes.
-  $themes = system_rebuild_theme_data();
-  uasort($themes, 'system_sort_modules_by_info_name');
-
-  $theme_default = \Drupal::config('system.theme')->get('default');
-  $theme_groups  = array();
-  $admin_theme = \Drupal::config('system.theme')->get('admin');
-
-  foreach ($themes as &$theme) {
-    if (!empty($theme->info['hidden'])) {
-      continue;
-    }
-    $theme->is_default = ($theme->name == $theme_default);
-
-    // Identify theme screenshot.
-    $theme->screenshot = NULL;
-    // Create a list which includes the current theme and all its base themes.
-    if (isset($themes[$theme->name]->base_themes)) {
-      $theme_keys = array_keys($themes[$theme->name]->base_themes);
-      $theme_keys[] = $theme->name;
-    }
-    else {
-      $theme_keys = array($theme->name);
-    }
-    // Look for a screenshot in the current theme or in its closest ancestor.
-    foreach (array_reverse($theme_keys) as $theme_key) {
-      if (isset($themes[$theme_key]) && file_exists($themes[$theme_key]->info['screenshot'])) {
-        $theme->screenshot = array(
-          'uri' => $themes[$theme_key]->info['screenshot'],
-          'alt' => t('Screenshot for !theme theme', array('!theme' => $theme->info['name'])),
-          'title' => t('Screenshot for !theme theme', array('!theme' => $theme->info['name'])),
-          'attributes' => array('class' => array('screenshot')),
-        );
-        break;
-      }
-    }
-
-    if (empty($theme->status)) {
-     // Ensure this theme is compatible with this version of core.
-     // Require the 'content' region to make sure the main page
-     // content has a common place in all themes.
-      $theme->incompatible_core = !isset($theme->info['core']) || ($theme->info['core'] != \Drupal::CORE_COMPATIBILITY) || (!isset($theme->info['regions']['content']));
-      $theme->incompatible_php = version_compare(phpversion(), $theme->info['php']) < 0;
-      // Confirmed that the base theme is available.
-      $theme->incompatible_base = (isset($theme->info['base theme']) && !isset($themes[$theme->info['base theme']]));
-      // Confirm that the theme engine is available.
-      $theme->incompatible_engine = (isset($theme->info['engine']) && !isset($theme->owner));
-    }
-    $query['token'] = drupal_get_token('system-theme-operation-link');
-    $theme->operations = array();
-    if (!empty($theme->status) || !$theme->incompatible_core && !$theme->incompatible_php && !$theme->incompatible_base && !$theme->incompatible_engine) {
-      // Create the operations links.
-      $query['theme'] = $theme->name;
-      if (drupal_theme_access($theme)) {
-        $theme->operations[] = array(
-          'title' => t('Settings'),
-          'href' => 'admin/appearance/settings/' . $theme->name,
-          'attributes' => array('title' => t('Settings for !theme theme', array('!theme' => $theme->info['name']))),
-        );
-      }
-      if (!empty($theme->status)) {
-        if (!$theme->is_default) {
-          if ($theme->name != $admin_theme) {
-            $theme->operations[] = array(
-              'title' => t('Disable'),
-              'href' => 'admin/appearance/disable',
-              'query' => $query,
-              'attributes' => array('title' => t('Disable !theme theme', array('!theme' => $theme->info['name']))),
-            );
-          }
-          $theme->operations[] = array(
-            'title' => t('Set default'),
-            'href' => 'admin/appearance/default',
-            'query' => $query,
-            'attributes' => array('title' => t('Set !theme as default theme', array('!theme' => $theme->info['name']))),
-          );
-        }
-        $admin_theme_options[$theme->name] = $theme->info['name'];
-      }
-      else {
-        $theme->operations[] = array(
-          'title' => t('Enable'),
-          'href' => 'admin/appearance/enable',
-          'query' => $query,
-          'attributes' => array('title' => t('Enable !theme theme', array('!theme' => $theme->info['name']))),
-        );
-        $theme->operations[] = array(
-          'title' => t('Enable and set default'),
-          'href' => 'admin/appearance/default',
-          'query' => $query,
-          'attributes' => array('title' => t('Enable !theme as default theme', array('!theme' => $theme->info['name']))),
-        );
-      }
-    }
-
-    // Add notes to default and administration theme.
-    $theme->notes = array();
-    $theme->classes = array();
-    if ($theme->is_default) {
-      $theme->classes[] = 'theme-default';
-      $theme->notes[] = t('default theme');
-    }
-    if ($theme->name == $admin_theme || ($theme->is_default && $admin_theme == '0')) {
-      $theme->classes[] = 'theme-admin';
-      $theme->notes[] = t('admin theme');
-    }
-
-    // Sort enabled and disabled themes into their own groups.
-    $theme_groups[$theme->status ? 'enabled' : 'disabled'][] = $theme;
-  }
-
-  // There are two possible theme groups.
-  $theme_group_titles = array(
-    'enabled' => format_plural(count($theme_groups['enabled']), 'Enabled theme', 'Enabled themes'),
-  );
-  if (!empty($theme_groups['disabled'])) {
-    $theme_group_titles['disabled'] = format_plural(count($theme_groups['disabled']), 'Disabled theme', 'Disabled themes');
-  }
-
-  uasort($theme_groups['enabled'], 'system_sort_themes');
-  drupal_alter('system_themes_page', $theme_groups);
-
-  $build = array(
-    '#sorted' => TRUE,
-  );
-  $build['system_themes_page'] = array(
-    '#theme' => 'system_themes_page',
-    '#theme_groups' => $theme_groups,
-    '#theme_group_titles' => $theme_group_titles,
-  );
-  $build['admin_form'] = drupal_get_form('system_themes_admin_form', $admin_theme_options);
-  return $build;
-}
-
-/**
- * Form to select the administration theme.
- *
- * @ingroup forms
- * @see system_themes_admin_form_submit()
- */
-function system_themes_admin_form($form, &$form_state, $theme_options) {
-  // Administration theme settings.
-  $form['admin_theme'] = array(
-    '#type' => 'details',
-    '#title' => t('Administration theme'),
-  );
-  $form['admin_theme']['admin_theme'] = array(
-    '#type' => 'select',
-    '#options' => array(0 => t('Default theme')) + $theme_options,
-    '#title' => t('Administration theme'),
-    '#description' => t('Choose "Default theme" to always use the same theme as the rest of the site.'),
-    '#default_value' => \Drupal::config('system.theme')->get('admin'),
-  );
-  $form['admin_theme']['actions'] = array('#type' => 'actions');
-  $form['admin_theme']['actions']['submit'] = array(
-    '#type' => 'submit',
-    '#value' => t('Save configuration'),
-  );
-  return $form;
-}
-
-/**
- * Process system_themes_admin_form form submissions.
- */
-function system_themes_admin_form_submit($form, &$form_state) {
-  drupal_set_message(t('The configuration options have been saved.'));
-  \Drupal::config('system.theme')->set('admin', $form_state['values']['admin_theme'])->save();
-}
-
-/**
  * Menu callback; Set the default theme.
  */
 function system_theme_default() {
@@ -266,26 +91,6 @@ function _system_is_incompatible(&$incompatible, $files, $file) {
 }
 
 /**
- * Array sorting callback; sorts modules or themes by their name.
- */
-function system_sort_modules_by_info_name($a, $b) {
-  return strcasecmp($a->info['name'], $b->info['name']);
-}
-
-/**
- * Array sorting callback; sorts modules or themes by their name.
- */
-function system_sort_themes($a, $b) {
-  if ($a->is_default) {
-    return -1;
-  }
-  if ($b->is_default) {
-    return 1;
-  }
-  return strcasecmp($a->info['name'], $b->info['name']);
-}
-
-/**
  * Returns HTML for an administrative block for display.
  *
  * @param $variables
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 40c3234..effaf9a 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -2687,6 +2687,13 @@ function system_region_list($theme_key, $show = REGIONS_ALL) {
 }
 
 /**
+ * Array sorting callback; sorts modules by their name.
+ */
+function system_sort_modules_by_info_name($a, $b) {
+  return strcasecmp($a->info['name'], $b->info['name']);
+}
+
+/**
  * Implements hook_system_info_alter().
  */
 function system_system_info_alter(&$info, $file, $type) {
